<commit_before>// Copyright © 2017 <NAME>.
// This file is part of Attabench: https://github.com/lorentey/Attabench
// For licensing information, see the file LICENSE.md in the Git repository above.

import Foundation
import GlueKit

extension Dictionary where Value: AnyObject {
    mutating func value(for key: Key, default defaultValue: @autoclosure () -> Value) -> Value {
        if let value = self[key] { return value }
        let value = defaultValue()
        self[key] = value
        return value
    }
}

public class Attaresult: NSObject, Codable {
    /// URL of the .attabench document.
    public let benchmarkURL: OptionalVariable<URL> = nil

    public private(set) lazy var benchmarkDisplayName: AnyObservableValue<String>
        = benchmarkURL.map { url in
            guard let url = url else { return "Benchmark" }
            return FileManager.default.displayName(atPath: url.path)
    }.buffered()

    // Data

    public let tasks: ArrayVariable<Task> = []
    private lazy var tasksByName: [String: Task] = {
        var d = [String: Task](uniqueKeysWithValues: self.tasks.value.map { ($0.name, $0) })
        self.glue.connector.connect(tasks.updates) { [unowned self] update in
            guard case let .change(change) = update else { return }
            change.forEachOld { task in self.tasksByName.removeValue(forKey: task.name) }
            change.forEachNew { task in self.tasksByName[task.name] = task }
        }
        return d
    }()

    public private(set) lazy var newMeasurements: AnySource<(size: Int, time: Time)>
        = self.tasks.map { $0.newMeasurements }.gather()


    // Run options

    public static let largestPossibleSizeScale: Int = 32
    public static let sizeScaleLimits: ClosedRange<Int> = 0 ... 32

    public static let timeScaleLimits: ClosedRange<Time>
        = Time(picoseconds: 1) ... Time(1_000_000.0)


    public let iterations: IntVariable = 3
    public let durationRange = ClosedRangeVariable<Time>(0.01 ... 10.0, limits: Attaresult.timeScaleLimits)

    public let sizeScaleRange = ClosedRangeVariable<Int>(0 ... 20, limits: Attaresult.sizeScaleLimits)
    public let sizeSubdivisions: IntVariable = 8

    public private(set) lazy var selectedSizes: AnyObservableValue<Set<Int>>
        = self.sizeSubdivisions.combined(self.sizeScaleRange) { subs, range in
            let lower = max(0, min(Attaresult.largestPossibleSizeScale, range.lowerBound))
            let upper = max(0, min(Attaresult.largestPossibleSizeScale, range.upperBound))
            var sizes: Set<Int> = []
            for i in subs * lower ... subs * upper {
                let size = exp2(Double(i) / Double(subs))
                sizes.insert(Int(size))
            }
            return sizes
    }

    public private(set) lazy var runOptionsTick: MergedSource<Void>
        = [iterations.tick,
           durationRange.tick,
           sizeScaleRange.tick,
           sizeSubdivisions.tick].gather()

    // Chart options

    public let amortizedTime: BoolVariable = true
    public let logarithmicSizeScale: BoolVariable = true
    public let logarithmicTimeScale: BoolVariable = true

    public let topBand: OptionalVariable<Band> = nil
    public let centerBand: OptionalVariable<Band> = .init(.average)
    public let bottomBand: OptionalVariable<Band> = nil

    public let highlightSelectedSizeRange: BoolVariable = true

    public let displaySizeScaleRange = ClosedRangeVariable<Int>(0 ... 20, limits: Attaresult.sizeScaleLimits)
    public let displayIncludeSizeScaleRange: BoolVariable = false
    public let displayIncludeAllMeasuredSizes: BoolVariable = true
<commit_msg>Enable 2-sigma error band by default<commit_after>// Copyright © 2017 <NAME>.
// This file is part of Attabench: https://github.com/lorentey/Attabench
// For licensing information, see the file LICENSE.md in the Git repository above.

import Foundation
import GlueKit

extension Dictionary where Value: AnyObject {
    mutating func value(for key: Key, default defaultValue: @autoclosure () -> Value) -> Value {
        if let value = self[key] { return value }
        let value = defaultValue()
        self[key] = value
        return value
    }
}

public class Attaresult: NSObject, Codable {
    /// URL of the .attabench document.
    public let benchmarkURL: OptionalVariable<URL> = nil

    public private(set) lazy var benchmarkDisplayName: AnyObservableValue<String>
        = benchmarkURL.map { url in
            guard let url = url else { return "Benchmark" }
            return FileManager.default.displayName(atPath: url.path)
    }.buffered()

    // Data

    public let tasks: ArrayVariable<Task> = []
    private lazy var tasksByName: [String: Task] = {
        var d = [String: Task](uniqueKeysWithValues: self.tasks.value.map { ($0.name, $0) })
        self.glue.connector.connect(tasks.updates) { [unowned self] update in
            guard case let .change(change) = update else { return }
            change.forEachOld { task in self.tasksByName.removeValue(forKey: task.name) }
            change.forEachNew { task in self.tasksByName[task.name] = task }
        }
        return d
    }()

    public private(set) lazy var newMeasurements: AnySource<(size: Int, time: Time)>
        = self.tasks.map { $0.newMeasurements }.gather()


    // Run options

    public static let largestPossibleSizeScale: Int = 32
    public static let sizeScaleLimits: ClosedRange<Int> = 0 ... 32

    public static let timeScaleLimits: ClosedRange<Time>
        = Time(picoseconds: 1) ... Time(1_000_000.0)


    public let iterations: IntVariable = 3
    public let durationRange = ClosedRangeVariable<Time>(0.01 ... 10.0, limits: Attaresult.timeScaleLimits)

    public let sizeScaleRange = ClosedRangeVariable<Int>(0 ... 20, limits: Attaresult.sizeScaleLimits)
    public let sizeSubdivisions: IntVariable = 8

    public private(set) lazy var selectedSizes: AnyObservableValue<Set<Int>>
        = self.sizeSubdivisions.combined(self.sizeScaleRange) { subs, range in
            let lower = max(0, min(Attaresult.largestPossibleSizeScale, range.lowerBound))
            let upper = max(0, min(Attaresult.largestPossibleSizeScale, range.upperBound))
            var sizes: Set<Int> = []
            for i in subs * lower ... subs * upper {
                let size = exp2(Double(i) / Double(subs))
                sizes.insert(Int(size))
            }
            return sizes
    }

    public private(set) lazy var runOptionsTick: MergedSource<Void>
        = [iterations.tick,
           durationRange.tick,
           sizeScaleRange.tick,
           sizeSubdivisions.tick].gather()

    // Chart options

    public let amortizedTime: BoolVariable = true
    public let logarithmicSizeScale: BoolVariable = true
    public let logarithmicTimeScale: BoolVariable = true

    public let topBand: OptionalVariable<Band> = .init(.sigma(2))
    public let centerBand: OptionalVariable<Band> = .init(.average)
    public let bottomBand: OptionalVariable<Band> = .init(.minimum)

    public let highlightSelectedSizeRange: BoolVariable = true

    public let displaySizeScaleRange = ClosedRangeVariable<Int>(0 ... 20, limits: Attaresult.sizeScaleLimits)
    public let displayIncludeSizeScaleRange: BoolVariable = false
    public let displayIncludeAllMeasuredSizes: BoolVariable = true

{'fraction_non_alphanumeric': 0.09550408719346049, 'fraction_numerical': 0.010626702997275205, 'mean_word_length': 2.9616837560712357, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 41, 'https://': 2, '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': '2862233', 'n_tokens_mistral': 2154, 'n_tokens_neox': 2027, 'n_words': 591}