--- phase: 01-semantic-position-model plan: 01 type: execute wave: 1 depends_on: [] files_modified: - SportsTime/Core/Models/Domain/SortOrderProvider.swift - SportsTime/Core/Models/Domain/Trip.swift autonomous: true must_haves: truths: - "Games sort by schedule time within each day" - "Items can be inserted at any position (before, between, after existing items)" - "Items can be assigned to any trip day by date calculation" artifacts: - path: "SportsTime/Core/Models/Domain/SortOrderProvider.swift" provides: "sortOrder calculation utilities" exports: ["initialSortOrder(forGameTime:)", "sortOrderBetween(_:_:)", "sortOrderBefore(_:)", "sortOrderAfter(_:)", "needsNormalization(_:)", "normalize(_:)"] - path: "SportsTime/Core/Models/Domain/Trip.swift" provides: "Day derivation methods" contains: "func dayNumber(for date: Date) -> Int" key_links: [] --- Create the sortOrder calculation utilities and day derivation methods that Phase 1 depends on. Purpose: Establish the foundational utilities for semantic position assignment. Games need sortOrder derived from time, travel/custom items need midpoint insertion, and items need day derivation from trip dates. Output: `SortOrderProvider.swift` with all sortOrder utilities, `Trip.swift` extended with day derivation methods. @~/.claude/get-shit-done/workflows/execute-plan.md @~/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/01-semantic-position-model/01-RESEARCH.md # Existing source files @SportsTime/Core/Models/Domain/ItineraryItem.swift @SportsTime/Core/Models/Domain/Trip.swift Task 1: Create SortOrderProvider utility SportsTime/Core/Models/Domain/SortOrderProvider.swift Create a new file `SortOrderProvider.swift` with an enum containing static methods for sortOrder calculation. Include these methods (as specified in 01-RESEARCH.md): 1. `initialSortOrder(forGameTime: Date) -> Double` - Extract hour and minute from game time - Calculate minutes since midnight - Return 100.0 + minutesSinceMidnight (range: 100-1540) - This ensures games sort by time and leaves room for negative sortOrder items 2. `sortOrderBetween(_ above: Double, _ below: Double) -> Double` - Return (above + below) / 2.0 - Simple midpoint calculation 3. `sortOrderBefore(_ first: Double) -> Double` - Return first - 1.0 - Creates space before the first item 4. `sortOrderAfter(_ last: Double) -> Double` - Return last + 1.0 - Creates space after the last item 5. `needsNormalization(_ items: [ItineraryItem]) -> Bool` - Sort items by sortOrder - Check if any adjacent gap is less than 1e-10 - Return true if normalization needed 6. `normalize(_ items: inout [ItineraryItem])` - Sort by current sortOrder - Reassign sortOrder as 1.0, 2.0, 3.0... (integer spacing) - Updates items in place Use `Calendar.current` for date component extraction. Import Foundation only. File exists at `SportsTime/Core/Models/Domain/SortOrderProvider.swift` with all 6 methods. Build succeeds: ```bash xcodebuild -project SportsTime.xcodeproj -scheme SportsTime -destination 'platform=iOS Simulator,name=iPhone 17,OS=26.2' build 2>&1 | tail -20 ``` SortOrderProvider.swift exists with all 6 static methods, project builds without errors Task 2: Add day derivation methods to Trip SportsTime/Core/Models/Domain/Trip.swift Extend the existing Trip struct with day derivation methods in a new extension at the bottom of the file. Add these methods: 1. `func dayNumber(for date: Date) -> Int` - Use Calendar.current to get startOfDay for both startDate and target date - Calculate days between using dateComponents([.day], from:to:) - Return days + 1 (1-indexed) 2. `func date(forDay dayNumber: Int) -> Date?` - Use Calendar.current to add (dayNumber - 1) days to startDate - Return the resulting date Add a comment block explaining: - Day 1 = trip.startDate - Day 2 = startDate + 1 calendar day - Games belong to their start date (even if running past midnight) These methods complement the existing `itineraryDays()` method but work with raw Date values rather than the Trip's stops structure. Build succeeds and new methods are callable: ```bash xcodebuild -project SportsTime.xcodeproj -scheme SportsTime -destination 'platform=iOS Simulator,name=iPhone 17,OS=26.2' build 2>&1 | tail -20 ``` Trip.swift has dayNumber(for:) and date(forDay:) methods, project builds without errors 1. Both files exist and contain expected methods 2. `xcodebuild build` succeeds with no errors 3. SortOrderProvider methods are static and accessible as `SortOrderProvider.methodName()` 4. Trip extension methods are instance methods callable on any Trip value - SortOrderProvider.swift exists with 6 static methods for sortOrder calculation - Trip.swift extended with dayNumber(for:) and date(forDay:) methods - Project builds successfully - No changes to existing ItineraryItem.swift (model already has correct fields) After completion, create `.planning/phases/01-semantic-position-model/01-01-SUMMARY.md`