<commit_before>//
//  Quickly
//

public final class QJalousieViewControllerInteractiveAnimation : IQJalousieViewControllerInteractiveAnimation {
    
    public var contentView: UIView!
    public var currentState: QJalousieViewControllerState
    public var targetState: QJalousieViewControllerState
    
    public var contentViewController: IQJalousieViewController?
    public var contentFullscreenFrame: CGRect!
    public var contentShowedFrame: CGRect!
    public var contentClosedFrame: CGRect!
    
    public var detailViewController: IQJalousieViewController?
    public var detailFullscreenSize: CGFloat
    public var detailFullscreenFrame: CGRect!
    public var detailShowedSize: CGFloat
    public var detailShowedFrame: CGRect!
    public var detailClosedFrame: CGRect!

    public var position: CGPoint
    public var deltaPosition: CGFloat
    public var velocity: CGPoint
    public var acceleration: CGFloat
    public var finishDistanceRate: CGFloat
    public var ease: IQAnimationEase
    public var canFinish: Bool
    
    public init(
        contentShadow: QViewShadow = QViewShadow(color: UIColor.black, opacity: 0.45, radius: 6, offset: CGSize.zero),
        detailFullscreenSize: CGFloat = UIScreen.main.bounds.height,
        detailShowedSize: CGFloat = UIScreen.main.bounds.height * 0.5,
        acceleration: CGFloat = 1200,
        finishDistanceRate: CGFloat = 0.4,
        ease: IQAnimationEase = QAnimationEaseLinear()
    ) {
        self.currentState = .closed
        self.targetState = .closed
        self.detailFullscreenSize = detailFullscreenSize
        self.detailShowedSize = detailShowedSize
        self.position = CGPoint.zero
        self.deltaPosition = 0
        self.velocity = CGPoint.zero
        self.acceleration = acceleration
        self.finishDistanceRate = finishDistanceRate
        self.ease = ease
        self.canFinish = false
    }
    
    public func prepare(
        contentView: UIView,
        state: QJalousieViewControllerState,
        contentViewController: IQJalousieViewController?,
        detailViewController: IQJalousieViewController?,
        position: CGPoint,
        velocity: CGPoint
    ) {
        self.contentView = contentView
        self.currentState = state
        self.targetState = state
        self.contentViewController = contentViewController
        self.contentFullscreenFrame = self._contentFrame(contentView: contentView, state: .fullscreen)
        self.contentShowedFrame = self._contentFrame(contentView: contentView, state: .showed)
        self.contentClosedFrame = self._contentFrame(contentView: contentView, state: .closed)
        self.detailViewController = detailViewController
        self.detailFullscreenFrame = self._detailFrame(contentView: contentView, state: .fullscreen)
        self.detailShowedFrame = self._detailFrame(contentView: contentView, state: .showed)
        self.detailClosedFrame = self._detailFrame(contentView: contentView, state: .closed)
        self.position = position
        self.velocity = velocity
        
        if let vc = self.detailViewController {
            switch state {
            case .closed: vc.view.frame = self.detailClosedFrame
            case .showed: vc.view.frame = self.detailShowedFrame
            case .fullscreen: vc.view.frame = self.detailFullscreenFrame
            }
            self.contentView.bringSubviewToFront(vc.view)
        }
    }
    
    public func update(position: CGPoint, velocity: CGPoint) {
        var positionDelta: CGFloat = position.y - self.position.y
        let contentBeginFrame, contentEndFrame: CGRect
        let detailBeginFrame, detailEndFrame: CGRect
        switch self.currentState {
        case .fullscreen:
            if positionDelta < 0 {
                positionDelta = -positionDelta
                contentBeginFrame = self.contentFullscreenFrame
                contentEndFrame = self.contentFullscreenFrame
                detailBeginFrame = self.detailFullscreenFrame
                detailEndFrame = self.detailFullscreenFrame
                self.targetState = .fullscreen
            } else if positionDelta > self.detailShowedSize {
                contentBeginFrame = self.contentFullscreenFrame
                contentEndFrame = self.contentClosedFrame
                detailBeginFrame = self.detailFullscreenFrame
                detailEndFrame = self.detailClosedFrame
                self.targetState = .closed
            } else if positionDelta > 0 {
                contentBeginFrame = self.contentFullscreenFrame
                contentEndFrame = self.contentShowedFrame
                detailBeginFrame = self.detailFullscreenFrame
                detailEndFrame = self.detailShowedFrame
                self.targetState = .showed
            } else {
                contentBeginFrame = self.contentFullscreenFrame
                contentEndFrame = self.contentFullscreenFrame
                detailBeginFrame = self.detailFullscreenFrame
                detailEndFrame = self.detailFullscreenFrame
                self.targetState = .fullscreen
            }
        case .showed:
            if positionDelta < 0 {
                positionDelta = -positionDelta
                contentBeginFrame = self.contentShowedFrame
                contentEndFrame = self.contentFullscreenFrame
                detailBeginFrame = self.detailShowedFrame
                detailEndFrame = self.detailFullscreenFrame
                self.targetState = .fullscreen
            } else if positionDelta > 0 {
                contentBeginFrame = self.contentShowedFrame
                contentEndFrame = self.contentClosedFrame
                detailBeginFrame = self.detailShowedFrame
                detailEndFrame = self.detailClosedFrame
                self.targetState = .closed
            } else {
                contentBeginFrame = self.contentShowedFrame
                contentEndFrame = self.contentShowedFrame
                detailBeginFrame = self.detailShowedFrame
                detailEndFrame = self.detailShowedFrame
                self.targetState = .showed
            }
        case .closed:
            contentBeginFrame = self.contentClosedFrame
            contentEndFrame = self.contentClosedFrame
            detailBeginFrame = self.detailClosedFrame
            detailEndFrame = self.detailClosedFrame
            self.targetState = .closed
        }
        if contentBeginFrame != contentEndFrame || detailBeginFrame != detailEndFrame {
            let detailDelta = detailBeginFrame.topPoint.distance(to: detailEndFrame.topPoint)
            self.deltaPosition = self.ease.lerp(positionDelta, from: 0, to: detailDelta)
            let progress = max(0, min(self.deltaPosition / detailDelta, 1))
            self.contentViewController?.view.frame = contentBeginFrame.lerp(contentEndFrame, progress: progress)
            self.detailViewController?.view.frame = detailBeginFrame.lerp(detailEndFrame, progress: progress)
            self.canFinish = self.deltaPosition > (detailDelta * self.finishDistanceRate)
        }
    }
    
    public func finish(_ complete: @escaping (_ state: QJalousieViewControllerState) -> Void) {
        let contentEndFrame, detailBeginFrame, detailEndFrame: CGRect
        switch self.currentState {
        case .fullscreen: detailBeginFrame = self.detailFullscreenFrame
        case .showed: detailBeginFrame = self.detailShowedFrame
        case .closed: detailBeginFrame = self.detailClosedFrame
        }
        switch self.targetState {
        case .fullscreen: contentEndFrame = self.contentFullscreenFrame; detailEndFrame = self.detailFullscreenFrame
        case .showed: contentEndFrame = self.contentShowedFrame; detailEndFrame = self.detailShowedFrame
        case .closed: contentEndFrame = self.contentClosedFrame; detailEndFrame = self.detailClosedFrame<commit_msg>Refactoring & Stabilization<commit_after>//
//  Quickly
//

public final class QJalousieViewControllerInteractiveAnimation : IQJalousieViewControllerInteractiveAnimation {
    
    public var contentView: UIView!
    public var currentState: QJalousieViewControllerState
    public var targetState: QJalousieViewControllerState
    
    public var contentViewController: IQJalousieViewController?
    public var contentFullscreenFrame: CGRect!
    public var contentShowedFrame: CGRect!
    public var contentClosedFrame: CGRect!
    
    public var detailViewController: IQJalousieViewController?
    public var detailFullscreenSize: CGFloat
    public var detailFullscreenFrame: CGRect!
    public var detailShowedSize: CGFloat
    public var detailShowedFrame: CGRect!
    public var detailClosedFrame: CGRect!

    public var position: CGPoint
    public var deltaPosition: CGFloat
    public var velocity: CGPoint
    public var acceleration: CGFloat
    public var ease: IQAnimationEase
    public var canFinish: Bool
    
    public init(
        contentShadow: QViewShadow = QViewShadow(color: UIColor.black, opacity: 0.45, radius: 6, offset: CGSize.zero),
        detailFullscreenSize: CGFloat = UIScreen.main.bounds.height,
        detailShowedSize: CGFloat = UIScreen.main.bounds.height * 0.5,
        acceleration: CGFloat = 1200,
        ease: IQAnimationEase = QAnimationEaseLinear()
    ) {
        self.currentState = .closed
        self.targetState = .closed
        self.detailFullscreenSize = detailFullscreenSize
        self.detailShowedSize = detailShowedSize
        self.position = CGPoint.zero
        self.deltaPosition = 0
        self.velocity = CGPoint.zero
        self.acceleration = acceleration
        self.ease = ease
        self.canFinish = false
    }
    
    public func prepare(
        contentView: UIView,
        state: QJalousieViewControllerState,
        contentViewController: IQJalousieViewController?,
        detailViewController: IQJalousieViewController?,
        position: CGPoint,
        velocity: CGPoint
    ) {
        self.contentView = contentView
        self.currentState = state
        self.targetState = state
        self.contentViewController = contentViewController
        self.contentFullscreenFrame = self._contentFrame(contentView: contentView, state: .fullscreen)
        self.contentShowedFrame = self._contentFrame(contentView: contentView, state: .showed)
        self.contentClosedFrame = self._contentFrame(contentView: contentView, state: .closed)
        self.detailViewController = detailViewController
        self.detailFullscreenFrame = self._detailFrame(contentView: contentView, state: .fullscreen)
        self.detailShowedFrame = self._detailFrame(contentView: contentView, state: .showed)
        self.detailClosedFrame = self._detailFrame(contentView: contentView, state: .closed)
        self.position = position
        self.velocity = velocity
        
        if let vc = self.detailViewController {
            switch state {
            case .closed: vc.view.frame = self.detailClosedFrame
            case .showed: vc.view.frame = self.detailShowedFrame
            case .fullscreen: vc.view.frame = self.detailFullscreenFrame
            }
            self.contentView.bringSubviewToFront(vc.view)
        }
    }
    
    public func update(position: CGPoint, velocity: CGPoint) {
        var positionDelta: CGFloat = position.y - self.position.y
        let contentBeginFrame, contentEndFrame: CGRect
        let detailBeginFrame, detailEndFrame: CGRect
        let deviation: CGFloat
        switch self.currentState {
        case .fullscreen:
            if positionDelta < 0 {
                positionDelta = -positionDelta
                contentBeginFrame = self.contentFullscreenFrame
                contentEndFrame = self.contentFullscreenFrame
                detailBeginFrame = self.detailFullscreenFrame
                detailEndFrame = self.detailFullscreenFrame
                deviation = 0
                self.targetState = .fullscreen
            } else if positionDelta > self.detailShowedSize {
                contentBeginFrame = self.contentShowedFrame
                contentEndFrame = self.contentClosedFrame
                detailBeginFrame = self.detailShowedFrame
                detailEndFrame = self.detailClosedFrame
                deviation = self.detailShowedSize
                self.targetState = .closed
            } else if positionDelta > 0 {
                contentBeginFrame = self.contentFullscreenFrame
                contentEndFrame = self.contentShowedFrame
                detailBeginFrame = self.detailFullscreenFrame
                detailEndFrame = self.detailShowedFrame
                deviation = 0
                self.targetState = .showed
            } else {
                contentBeginFrame = self.contentFullscreenFrame
                contentEndFrame = self.contentFullscreenFrame
                detailBeginFrame = self.detailFullscreenFrame
                detailEndFrame = self.detailFullscreenFrame
                deviation = 0
                self.targetState = .fullscreen
            }
        case .showed:
            if positionDelta < 0 {
                positionDelta = -positionDelta
                contentBeginFrame = self.contentShowedFrame
                contentEndFrame = self.contentFullscreenFrame
                detailBeginFrame = self.detailShowedFrame
                detailEndFrame = self.detailFullscreenFrame
                deviation = 0
                self.targetState = .fullscreen
            } else if positionDelta > 0 {
                contentBeginFrame = self.contentShowedFrame
                contentEndFrame = self.contentClosedFrame
                detailBeginFrame = self.detailShowedFrame
                detailEndFrame = self.detailClosedFrame
                deviation = 0
                self.targetState = .closed
            } else {
                contentBeginFrame = self.contentShowedFrame
                contentEndFrame = self.contentShowedFrame
                detailBeginFrame = self.detailShowedFrame
                detailEndFrame = self.detailShowedFrame
                deviation = 0
                self.targetState = .showed
            }
        case .closed:
            contentBeginFrame = self.contentClosedFrame
            contentEndFrame = self.contentClosedFrame
            detailBeginFrame = self.detailClosedFrame
            detailEndFrame = self.detailClosedFrame
            deviation = 0
            self.targetState = .closed
        }
        if contentBeginFrame != contentEndFrame || detailBeginFrame != detailEndFrame {
            let detailDelta = detailBeginFrame.topPoint.distance(to: detailEndFrame.topPoint)
            self.deltaPosition = self.ease.lerp(positionDelta, from: 0, to: detailDelta + deviation)
            let progress = max(0, min((self.deltaPosition - deviation) / detailDelta, 1))
            self.contentViewController?.view.frame = contentBeginFrame.lerp(contentEndFrame, progress: progress)
            self.detailViewController?.view.frame = detailBeginFrame.lerp(detailEndFrame, progress: progress)
            self.canFinish = self.currentState != self.targetState
        }
    }
    
    public func finish(_ complete: @escaping (_ state: QJalousieViewControllerState) -> Void) {
        let contentEndFrame, detailBeginFrame, detailEndFrame: CGRect
        switch self.currentState {
        case .fullscreen: detailBeginFrame = self.detailFullscreenFrame
        case .showed: detailBeginFrame = self.detailShowedFrame
        case .closed: detailBeginFrame = self.detailClosedFrame
        }
        switch self.targetState {
        case .fullscreen: contentEndFrame = self.contentFullscreenFrame; detailEndFrame = self.detailFullscreenFrame
        case .showed: contentEndFrame = self.contentShowedFrame; detailEndFrame = self.detailShowedFrame
        case .closed: contentEndFrame = self.contentClosedFrame; detailEndFrame = self.detailClosedFrame
{'fraction_non_alphanumeric': 0.06009177195298259, 'fraction_numerical': 0.002828587591929097, 'mean_word_length': 2.404665097367858, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5111596', 'n_tokens_mistral': 4069, 'n_tokens_neox': 3798, 'n_words': 863}