73 lines
2.1 KiB
Swift
73 lines
2.1 KiB
Swift
//
|
|
// ScheduleDetailVM.swift
|
|
// QuickLocation
|
|
//
|
|
// Created by 八条 on 2026/6/25.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
enum ScheduleTimelineRole {
|
|
case start
|
|
case waypoint
|
|
case end
|
|
}
|
|
|
|
struct ScheduleTimelineItem {
|
|
let point: SchedulePointModel
|
|
let role: ScheduleTimelineRole
|
|
let durationToNext: Int64?
|
|
let isFirst: Bool
|
|
let isLast: Bool
|
|
}
|
|
|
|
struct ScheduleDetailViewModel {
|
|
let routeId: String
|
|
let scheduModel: ScheduleModel?
|
|
let orderedPoints: [SchedulePointModel]
|
|
let timelineItems: [ScheduleTimelineItem]
|
|
|
|
init(routeId: String, model: ScheduleModel?) {
|
|
self.scheduModel = model
|
|
self.routeId = routeId.isEmpty ? (model?.id ?? "") : routeId
|
|
|
|
let points = Self.order(model?.points ?? [])
|
|
self.orderedPoints = points
|
|
self.timelineItems = points.enumerated().map { index, point in
|
|
let role: ScheduleTimelineRole
|
|
if points.count == 1 {
|
|
role = point.type == 2 ? .end : .start
|
|
} else if index == 0 {
|
|
role = .start
|
|
} else if index == points.count - 1 {
|
|
role = .end
|
|
} else {
|
|
role = .waypoint
|
|
}
|
|
|
|
var duration: Int64?
|
|
if index + 1 < points.count {
|
|
let nextTimestamp = points[index + 1].expected_timestamp
|
|
if point.expected_timestamp > 0, nextTimestamp > point.expected_timestamp {
|
|
duration = nextTimestamp - point.expected_timestamp
|
|
}
|
|
}
|
|
|
|
return ScheduleTimelineItem(
|
|
point: point,
|
|
role: role,
|
|
durationToNext: duration,
|
|
isFirst: index == 0,
|
|
isLast: index == points.count - 1
|
|
)
|
|
}
|
|
}
|
|
|
|
private static func order(_ points: [SchedulePointModel]) -> [SchedulePointModel] {
|
|
guard points.count > 1 else { return points }
|
|
let sequences = points.map(\.sequence)
|
|
guard Set(sequences).count == points.count else { return points }
|
|
return points.sorted { $0.sequence < $1.sequence }
|
|
}
|
|
}
|