<commit_before>//
//  Created by <NAME> on 2017-08-18.
//  Copyright © 2017 Gavrix. All rights reserved.
//

import Foundation

public struct KeyPointsAnimation<T: Interpolatable>: PropertyAnimation {
    
    fileprivate struct NextKeyPoint {
        var point: T
        var time: Float
        var timingFunction: TimingFunction
    }
    
    fileprivate struct InterpolationSegment {
        
        let startTime: RelativeTimeInterval
        let endTime: RelativeTimeInterval
        
        let startPoint: T
        let endPoint: T
        
        var timingFunction: TimingFunction
        
        func contains(time: RelativeTimeInterval) -> Bool {
            return startTime < time && endTime >= time
        }
        
        func interpolate(at time: RelativeTimeInterval) -> T {
            let state = timingFunction(time)
            return startPoint.interpolate(to: endPoint, by: state)
        }
        
        var duration: RelativeTimeInterval {
            return endTime - startTime
        }
    }
    
    public class PointsBuilder {
        fileprivate var points: [NextKeyPoint] = []
        public func add(point: T, at time: Float, timingFunction: @escaping TimingFunction) {
            points.append(NextKeyPoint(point:point, time: time, timingFunction: timingFunction))
        }
        
        fileprivate func build(startingWith point: T) -> [InterpolationSegment] {
            var segmentStartPoint = point
            var segmentStartTime: RelativeTimeInterval = .zero
            
            
            var segments: [InterpolationSegment] = []
            
            for nextPoint in points {
                segments.append(InterpolationSegment(
                    startTime: segmentStartTime,
                    endTime: RelativeTimeInterval(interval: TimeInterval(nextPoint.time), maxInterval: 1.0),
                    startPoint: segmentStartPoint,
                    endPoint: nextPoint.point,
                    timingFunction: nextPoint.timingFunction)
                )
                segmentStartPoint = nextPoint.point
                segmentStartTime = RelativeTimeInterval(interval: TimeInterval(nextPoint.time), maxInterval: 1.0)
            }
            return segments
            
        }
    }
    
    
    public var duration: TimeInterval
    
    public var animatableProperty: AnimatableProperty<T>
    
    private var segments: [InterpolationSegment]
    private var startingPoint: T
    
    public init(initial point: T, animatableProperty: AnimatableProperty<T>, duration: TimeInterval, buildPoints: (PointsBuilder) -> Void) {
        
        let pointsBuilder = PointsBuilder()
        buildPoints(pointsBuilder)
        
        segments = pointsBuilder.build(startingWith: point)
        
        dump(segments)
        self.startingPoint = point
        self.duration = duration
        self.animatableProperty = animatableProperty
    }
  
    public func interpolatedValue(at globalTime: RelativeTimeInterval) -> T {
        for segment in segments {
            guard segment.contains(time: globalTime) else { continue }
            
            let localTime = RelativeTimeInterval(interval: globalTime - segment.startTime, maxInterval: segment.duration)
            return segment.interpolate(at: localTime)
        }
        return startingPoint
    }
    
}

<commit_msg>Remove debug code<commit_after>//
//  Created by <NAME> on 2017-08-18.
//  Copyright © 2017 Gavrix. All rights reserved.
//

import Foundation

public struct KeyPointsAnimation<T: Interpolatable>: PropertyAnimation {
    
    fileprivate struct NextKeyPoint {
        var point: T
        var time: Float
        var timingFunction: TimingFunction
    }
    
    fileprivate struct InterpolationSegment {
        
        let startTime: RelativeTimeInterval
        let endTime: RelativeTimeInterval
        
        let startPoint: T
        let endPoint: T
        
        var timingFunction: TimingFunction
        
        func contains(time: RelativeTimeInterval) -> Bool {
            return startTime < time && endTime >= time
        }
        
        func interpolate(at time: RelativeTimeInterval) -> T {
            let state = timingFunction(time)
            return startPoint.interpolate(to: endPoint, by: state)
        }
        
        var duration: RelativeTimeInterval {
            return endTime - startTime
        }
    }
    
    public class PointsBuilder {
        fileprivate var points: [NextKeyPoint] = []
        public func add(point: T, at time: Float, timingFunction: @escaping TimingFunction) {
            points.append(NextKeyPoint(point:point, time: time, timingFunction: timingFunction))
        }
        
        fileprivate func build(startingWith point: T) -> [InterpolationSegment] {
            var segmentStartPoint = point
            var segmentStartTime: RelativeTimeInterval = .zero
            
            
            var segments: [InterpolationSegment] = []
            
            for nextPoint in points {
                segments.append(InterpolationSegment(
                    startTime: segmentStartTime,
                    endTime: RelativeTimeInterval(interval: TimeInterval(nextPoint.time), maxInterval: 1.0),
                    startPoint: segmentStartPoint,
                    endPoint: nextPoint.point,
                    timingFunction: nextPoint.timingFunction)
                )
                segmentStartPoint = nextPoint.point
                segmentStartTime = RelativeTimeInterval(interval: TimeInterval(nextPoint.time), maxInterval: 1.0)
            }
            return segments
            
        }
    }
    
    
    public var duration: TimeInterval
    
    public var animatableProperty: AnimatableProperty<T>
    
    private var segments: [InterpolationSegment]
    private var startingPoint: T
    
    public init(initial point: T, animatableProperty: AnimatableProperty<T>, duration: TimeInterval, buildPoints: (PointsBuilder) -> Void) {
        
        let pointsBuilder = PointsBuilder()
        buildPoints(pointsBuilder)
        
        segments = pointsBuilder.build(startingWith: point)
        
        self.startingPoint = point
        self.duration = duration
        self.animatableProperty = animatableProperty
    }
  
    public func interpolatedValue(at globalTime: RelativeTimeInterval) -> T {
        for segment in segments {
            guard segment.contains(time: globalTime) else { continue }
            
            let localTime = RelativeTimeInterval(interval: globalTime - segment.startTime, maxInterval: segment.duration)
            return segment.interpolate(at: localTime)
        }
        return startingPoint
    }
    
}


{'fraction_non_alphanumeric': 0.06683499183127878, 'fraction_numerical': 0.004752710530224268, 'mean_word_length': 1.9743816254416962, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 23, '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': '4423968', 'n_tokens_mistral': 1674, 'n_tokens_neox': 1614, 'n_words': 423}