import Charts import SwiftUI /// Full-game win probability line chart using Swift Charts struct WinProbabilityChartView: View { let entries: [WinProbabilityEntry] let homeCode: String let awayCode: String private var homeColor: Color { TeamAssets.color(for: homeCode) } private var awayColor: Color { TeamAssets.color(for: awayCode) } var body: some View { DataPanel(.standard) { VStack(alignment: .leading, spacing: 12) { HStack { Text("WIN PROBABILITY") .dataLabelStyle() Spacer() if let latest = entries.last { HStack(spacing: 12) { probLabel(code: awayCode, value: latest.awayTeamWinProbability) probLabel(code: homeCode, value: latest.homeTeamWinProbability) } } } Chart { ForEach(Array(entries.enumerated()), id: \.offset) { index, entry in if let wp = entry.homeTeamWinProbability { LineMark( x: .value("AB", index), y: .value("WP", wp) ) .foregroundStyle(homeColor) .interpolationMethod(.catmullRom) AreaMark( x: .value("AB", index), yStart: .value("Base", 50), yEnd: .value("WP", wp) ) .foregroundStyle( wp >= 50 ? homeColor.opacity(0.15) : awayColor.opacity(0.15) ) .interpolationMethod(.catmullRom) } } RuleMark(y: .value("Even", 50)) .foregroundStyle(DS.Colors.textQuaternary) .lineStyle(StrokeStyle(lineWidth: 0.5, dash: [4, 4])) } .chartYScale(domain: 0...100) .chartYAxis { AxisMarks(values: [0, 25, 50, 75, 100]) { value in AxisGridLine(stroke: StrokeStyle(lineWidth: 0.3)) .foregroundStyle(DS.Colors.textQuaternary) AxisValueLabel { Text("\(value.as(Int.self) ?? 0)%") .font(DS.Fonts.caption) .foregroundStyle(DS.Colors.textTertiary) } } } .chartXAxis(.hidden) .frame(height: chartHeight) } } } @ViewBuilder private func probLabel(code: String, value: Double?) -> some View { HStack(spacing: 4) { RoundedRectangle(cornerRadius: 2) .fill(TeamAssets.color(for: code)) .frame(width: 3, height: 14) Text(code) .font(DS.Fonts.caption) .foregroundStyle(DS.Colors.textTertiary) Text(value.map { "\(Int($0))%" } ?? "-") .font(DS.Fonts.dataValueCompact) .foregroundStyle(DS.Colors.textPrimary) } } #if os(tvOS) private var chartHeight: CGFloat { 180 } #else private var chartHeight: CGFloat { 140 } #endif }