From 0159ec926fa365383fb8a9dbc7d1a1da11085a0e Mon Sep 17 00:00:00 2001 From: AppGoni Date: Sun, 23 Aug 2026 14:24:12 +0900 Subject: [PATCH 01/14] =?UTF-8?q?feat:=20AtchaV2=20Phase=2014=20=E2=80=94?= =?UTF-8?q?=20=EC=9E=AC=EC=8B=A4=ED=96=89=20=EC=A0=95=ED=95=A9=EC=84=B1=20?= =?UTF-8?q?(=EC=8A=A4=EB=83=85=EC=83=B7=20+=20=EA=B3=A0=EC=95=84=20LA=20?= =?UTF-8?q?=EC=9E=AC=EB=B6=80=EC=B0=A9=20+=20=EB=8F=84=EB=B3=B4=20?= =?UTF-8?q?=EC=8B=9C=EA=B0=84)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Domain: AlarmSessionSnapshot(info·도보 초·표시명·수단·확인·만료) + AlarmSessionSnapshotStore 포트 신설, AlarmInfo·TransportMode Codable, LastRoute 세션 파생값(첫 도보 초·탑승 구간· 표시명 — LA 어댑터의 표시명 로직을 Domain 순수 계산으로 이동) - 도보 시간 반영(미확정 #7 클라 임시안 확정): AlarmTiming.alarmFireDate(departureTime: firstWalkSeconds:) — 기본값 없이 등록/refresh 재스케줄/LA alarmTime/홈 배너 4곳이 같은 기준을 강제로 탄다(이중 시각 금지). refresh의 도보 출처는 스냅샷(routeId 일치 시) - RegisterAlarmUseCase: 과거 fireDate 사전 가드(AlarmError.tooLate — 권한 팝업·서버 등록 전 차단) + 등록 성공 시 스냅샷 저장. Cancel: clear. 홈 토스트 "이미 출발 시간이 지난 경로예요" - AlarmSyncService: 첫 sync 진입 시 스냅샷 시딩(diff 휘발 해소 — lastInfo 복원 + 구독자 전파로 오프라인 재실행 복원, expired 톰스톤은 2차 방어 복원) / sync 성공 시 병합 저장 + 죽은 세션 LA 로컬 재시작 위임 / 만료 확정 시 톰스톤(expired=true), 서버 sessionEnded 시 clear / "당겨짐" 배지 만료 보존(조용한 갱신이 10분을 못 채우고 지우던 문제) - LA 어댑터: 부트스트랩 직후 Activity.activities 스캔 — 스냅샷 일치+미만료+미dismiss는 adopt(관찰 재개), 그 외 즉시 정리. sync 성공 후 죽은 세션(활성 LA 없음·미확인·미dismiss) 로컬 재시작(8시간 한도·시작 실패 커버, push-to-start 무관). 최초 start 긴급도를 알람 시각 기준으로 통일 - 홈: alarmSynced 수신 시 카드 없으면 GetLastRouteDetailUseCase(신설 — 기존 미사용 detail 엔드포인트 재활용)로 카드 복원 + 도보 반영 배너 재시작. 변경 분 표기 .up 통일 - 위젯: Attributes에 수단·도보 필드(optional — 구버전 LA 재부착 디코딩 안전) → DI 컴팩트 지하철/버스 아이콘 분기 + 잠금화면 3행 "HH:mm 출발 · 정류장 도보 N분" - stopIntent 확인 기록 영속화(Phase 13 연동) — 확인된 세션은 LA 재시작 금지 - DEV: 데모 경로에 도보 leg(120초) 추가(검수 ③ 재료), 변경 시뮬레이터 기준 세션 영속화 (재실행 후 주입 diff·카드 복원 시각 정합) Co-Authored-By: Claude Fable 5 --- .../AlarmSessionSnapshotStoreAdapter.swift | 29 +++ .../Sources/Adapters/DevDemoFallbacks.swift | 60 ++++- .../LastTrainLiveActivityAdapter.swift | 132 +++++++++-- .../AlarmSessionLifecycleService.swift | 20 +- Projects/App/Sources/AlarmSyncService.swift | 129 +++++++++- Projects/App/Sources/AppDIContainer.swift | 50 +++- Projects/App/Sources/AppDelegate.swift | 5 + .../Sources/LastTrainLiveActivityWidget.swift | 48 ++-- .../Sources/LastTrainActivityAttributes.swift | 23 +- .../LastTrainActivityAttributesTests.swift | 28 ++- .../Domain/Sources/Entities/AlarmError.swift | 3 + .../Domain/Sources/Entities/AlarmInfo.swift | 3 +- .../Entities/AlarmSessionSnapshot.swift | 61 +++++ .../Domain/Sources/Entities/AlarmTiming.swift | 14 +- .../Domain/Sources/Entities/LastRoute.swift | 4 +- .../Entities/LastRouteSessionDerivation.swift | 38 +++ .../Sources/UseCases/CancelAlarmUseCase.swift | 8 +- .../UseCases/GetLastRouteDetailUseCase.swift | 17 ++ .../UseCases/RefreshAlarmUseCase.swift | 20 +- .../UseCases/RegisterAlarmUseCase.swift | 48 +++- .../Tests/AlarmSessionSnapshotTests.swift | 65 ++++++ Projects/Domain/Tests/AlarmTimingTests.swift | 22 +- .../DefaultCancelAlarmUseCaseTests.swift | 39 ++++ ...efaultGetLastRouteDetailUseCaseTests.swift | 40 ++++ .../DefaultRefreshAlarmUseCaseTests.swift | 87 ++++++- .../DefaultRegisterAlarmUseCaseTests.swift | 149 +++++++++++- .../LastRouteSessionDerivationTests.swift | 99 ++++++++ .../LastTrainActivityLifecycleTests.swift | 22 +- .../Feature/Home/Example/ExampleApp.swift | 13 +- .../Home/Sources/HomeDIContainer.swift | 6 +- .../Home/Sources/HomeViewController.swift | 2 + .../Feature/Home/Sources/HomeViewModel.swift | 85 ++++++- .../Home/Tests/HomeViewModelTests.swift | 221 +++++++++++++++++- 33 files changed, 1462 insertions(+), 128 deletions(-) create mode 100644 Projects/App/Sources/Adapters/AlarmSessionSnapshotStoreAdapter.swift create mode 100644 Projects/Domain/Sources/Entities/AlarmSessionSnapshot.swift create mode 100644 Projects/Domain/Sources/Entities/LastRouteSessionDerivation.swift create mode 100644 Projects/Domain/Sources/UseCases/GetLastRouteDetailUseCase.swift create mode 100644 Projects/Domain/Tests/AlarmSessionSnapshotTests.swift create mode 100644 Projects/Domain/Tests/DefaultGetLastRouteDetailUseCaseTests.swift create mode 100644 Projects/Domain/Tests/LastRouteSessionDerivationTests.swift diff --git a/Projects/App/Sources/Adapters/AlarmSessionSnapshotStoreAdapter.swift b/Projects/App/Sources/Adapters/AlarmSessionSnapshotStoreAdapter.swift new file mode 100644 index 0000000..3826317 --- /dev/null +++ b/Projects/App/Sources/Adapters/AlarmSessionSnapshotStoreAdapter.swift @@ -0,0 +1,29 @@ +import CoreStorage +import Domain +import Foundation + +/// Domain `AlarmSessionSnapshotStore` → CoreStorage(UserDefaults 백엔드) 어댑터 (Phase 14). +/// 스냅샷은 재실행 브리지이지 정본이 아니다 — 저장·삭제 실패는 조용히 흡수하고(다음 +/// 등록/sync가 자가치유), 필드 추가 등으로 인한 디코딩 실패도 nil로 무해화한다 +/// (최근 검색 저장소의 자가치유 패턴 재사용). +struct AlarmSessionSnapshotStoreAdapter: AlarmSessionSnapshotStore { + private static let storageKey = "alarm.sessionSnapshot" + + private let store: any KeyValueStore + + init(store: any KeyValueStore = UserDefaultsKeyValueStore()) { + self.store = store + } + + func load() async -> AlarmSessionSnapshot? { + (try? store.value(AlarmSessionSnapshot.self, forKey: Self.storageKey)) ?? nil + } + + func save(_ snapshot: AlarmSessionSnapshot) async { + try? store.setValue(snapshot, forKey: Self.storageKey) + } + + func clear() async { + try? store.removeValue(forKey: Self.storageKey) + } +} diff --git a/Projects/App/Sources/Adapters/DevDemoFallbacks.swift b/Projects/App/Sources/Adapters/DevDemoFallbacks.swift index 918744b..ea2f75f 100644 --- a/Projects/App/Sources/Adapters/DevDemoFallbacks.swift +++ b/Projects/App/Sources/Adapters/DevDemoFallbacks.swift @@ -61,9 +61,13 @@ struct DevDemoFallbackLastRouteRepository: LastRouteRepository { do { return try await base.lastRoute(id: id) } catch { print("⚠️ [DEV 우회] 경로 상세 실패 → 데모 경로 반환: \(error)") + // 카드 복원(Phase 14) 검수 정합: 알려진 세션(재실행 후에도 영속)의 출발 시각을 + // 재사용해야 배너·LA와 카드의 시각이 어긋나지 않는다. 모르면 새 데모 시각. + let knownDeparture = await DevChangeSimulator.shared.knownSessionDeparture(routeId: id) let route = Self.demoRoute( start: Coordinate(latitude: 37.4979, longitude: 127.0276), - end: Coordinate(latitude: 37.4853, longitude: 126.9015) + end: Coordinate(latitude: 37.4853, longitude: 126.9015), + departure: knownDeparture ) await DevChangeSimulator.shared.noteKnownSession( routeId: route.id, departureTime: route.departureTime @@ -72,10 +76,13 @@ struct DevDemoFallbackLastRouteRepository: LastRouteRepository { } } - /// 출발 시각은 8분 뒤 — 알람이 버퍼(−3분) 반영으로 +5분 시점에 걸린다. - /// (3분이면 알람 시각 ≈ now라 등록 탭 시점에 이미 과거가 되어 AlarmKit이 거부한다.) - private static func demoRoute(start: Coordinate, end: Coordinate) -> LastRoute { - let departure = Date().addingTimeInterval(8 * 60) + /// 출발 시각은 8분 뒤 — 알람이 도보(첫 walk leg 120초)+버퍼(180초) 반영으로 +3분 + /// 시점에 걸린다(Phase 14 검수 ③: 배너·LA·발화가 전부 "출발 − 도보 − 3분" 기준). + /// 더 이르면 등록 탭 시점에 이미 과거가 되어 tooLate 가드·AlarmKit 거부에 걸린다. + private static func demoRoute( + start: Coordinate, end: Coordinate, departure: Date? = nil + ) -> LastRoute { + let departure = departure ?? Date().addingTimeInterval(8 * 60) return LastRoute( id: "dev-demo-route", departureTime: departure, @@ -85,6 +92,20 @@ struct DevDemoFallbackLastRouteRepository: LastRouteRepository { totalDistance: 14200, totalWalkDistance: 700, legs: [ + TransportLeg( + mode: .walk, + sectionTime: 120, + distance: 150, + departureTime: nil, + routeName: nil, + lineType: nil, + start: nil, + end: RoutePoint(name: "강남역", coordinate: start), + subwayFinalStation: nil, + subwayDirection: nil, + isExpressSubway: false, + isLastSubway: false + ), TransportLeg( mode: .subway, sectionTime: 1500, @@ -168,12 +189,21 @@ final class DevChangeSimulator { case end } + /// 알려진 세션의 UserDefaults 키 (Phase 14 검수) — 강제 종료·재실행 검수에서 + /// 기준 출발 시각을 잃으면 주입 diff·카드 복원 시각이 어긋나므로 DEV 한정 영속화한다. + private static let knownRouteIdKey = "dev.sim.knownRouteId" + private static let knownDepartureKey = "dev.sim.knownDeparture" + private var pending: Injection? /// 마지막으로 알려진 세션 — 데모 경로 생성·등록·refresh 성공·주입 적용 시 갱신된다. private var knownRouteId: String? private var knownDepartureTime: Date? - private init() {} + private init() { + knownRouteId = UserDefaults.standard.string(forKey: Self.knownRouteIdKey) + let epoch = UserDefaults.standard.double(forKey: Self.knownDepartureKey) + knownDepartureTime = epoch > 0 ? Date(timeIntervalSince1970: epoch) : nil + } /// 주입 예약 — 다음 refresh() 1회가 소비한다. func inject(_ injection: Injection) { @@ -184,7 +214,18 @@ final class DevChangeSimulator { /// departureTime이 nil이면 routeId만 갱신한다(등록 경로는 출발 시각을 모른다). func noteKnownSession(routeId: String, departureTime: Date?) { knownRouteId = routeId - if let departureTime { knownDepartureTime = departureTime } + UserDefaults.standard.set(routeId, forKey: Self.knownRouteIdKey) + if let departureTime { + knownDepartureTime = departureTime + UserDefaults.standard.set( + departureTime.timeIntervalSince1970, forKey: Self.knownDepartureKey + ) + } + } + + /// 알려진 세션의 출발 시각 — routeId가 일치할 때만 (데모 상세의 시각 정합용). + func knownSessionDeparture(routeId: String) -> Date? { + knownRouteId == routeId ? knownDepartureTime : nil } /// 보류 중 주입을 소비해 변형된 AlarmInfo를 만든다. 주입이 없으면 nil. @@ -204,6 +245,11 @@ final class DevChangeSimulator { case .end: departure = nil } knownDepartureTime = departure + if let departure { + UserDefaults.standard.set( + departure.timeIntervalSince1970, forKey: Self.knownDepartureKey + ) + } return AlarmInfo( lastRouteId: routeId, departureTime: departure, diff --git a/Projects/App/Sources/Adapters/LastTrainLiveActivityAdapter.swift b/Projects/App/Sources/Adapters/LastTrainLiveActivityAdapter.swift index 8223944..a76d94d 100644 --- a/Projects/App/Sources/Adapters/LastTrainLiveActivityAdapter.swift +++ b/Projects/App/Sources/Adapters/LastTrainLiveActivityAdapter.swift @@ -28,6 +28,21 @@ nonisolated protocol LastTrainDepartureEnding: Sendable { func endAsDeparted() async } +/// Phase 14 재실행 정합성 경로 — 고아 LA 재부착과 죽은 세션 재시작. Domain 포트는 +/// 시그니처 고정 계약이라 App 내부 확장 포트로 둔다(재부착은 어댑터 내부 동작). +nonisolated protocol LastTrainSessionRestoring: Sendable { + /// 부트스트랩 직후 1회 — 프로세스가 죽는 사이 잠금화면에 남은 + /// `Activity.activities`를 스캔해, 스냅샷과 routeId가 일치하고 미만료인 세션은 + /// **adopt**(보관 + 상태 관찰 재개 — 이후 update/end가 정상 동작)하고, + /// 불일치·만료·스냅샷 없음은 즉시 정리한다. + func reattachOrphans(snapshot: AlarmSessionSnapshot?, now: Date) async + /// sync 성공 후 — 스냅샷은 살아 있는데(미만료·미확인) 활성 activity가 없고 dismiss + /// 기록도 없으면 LA를 로컬 재시작한다. 8시간 한도로 시스템이 내린 세션·시작 실패 + /// 세션 커버 — push-to-start 금지 정책과 무관(그 정책은 유저가 지운 LA의 재생성 금지, + /// dismiss 기록이 있으면 여기서도 재시작하지 않는다). + func restartIfNeeded(snapshot: AlarmSessionSnapshot, now: Date) async +} + /// ActivityKit → Domain `LastTrainActivityPort` 어댑터. ActivityKit을 import하는 곳은 App에서 이 파일뿐. /// 단일 알람 정책과 동일하게 Live Activity도 단일 세션만 유지한다(새 start가 기존 세션을 교체). /// 포트 계약대로 어떤 실패도 밖으로 던지지 않는다 — LA 실패가 알람 등록·취소를 실패시키면 안 된다. @@ -36,7 +51,7 @@ nonisolated protocol LastTrainDepartureEnding: Sendable { /// MainActor 클래스의 격리 멤버로는 적합성이 성립하지 않는다(Sendable 경계를 넘는 격리 적합성 불가). /// ActivityKit의 `Activity`는 Sendable 미표기이나 스레드 안전 설계라 `@preconcurrency`로 완화한다. actor LastTrainLiveActivityAdapter: LastTrainActivityPort, LastTrainChangeAlerting, - LastTrainDepartureEnding { + LastTrainDepartureEnding, LastTrainSessionRestoring { /// 유저 스와이프 dismiss 기록 키 — 앱 재실행 후에도 남아야 Phase 12 폴백 트리거 재료가 된다. private static let dismissedDefaultsKey = "la.dismissedByUser" @@ -79,12 +94,18 @@ actor LastTrainLiveActivityAdapter: LastTrainActivityPort, LastTrainChangeAlerti } let departureTime = session.departureTime ?? route.departureTime + // 로컬 알람 발화 시각 — register/refresh와 동일 기준(출발 − 도보 − 버퍼, Phase 14). + let alarmTime = AlarmTiming.alarmFireDate( + departureTime: departureTime, + firstWalkSeconds: route.firstWalkSectionSeconds + ) let initialState = LastTrainActivityState( departureTime: departureTime, - // 로컬 알람 발화 시각 — register/refresh와 동일한 버퍼 반영값(출발 − 3분). - alarmTime: AlarmTiming.alarmFireDate(departureTime: departureTime), + alarmTime: alarmTime, + // 긴급도는 이후 갱신과 같은 척도인 **알람 시각** 기준(Phase 14 정합 — 최초 + // start만 출발 시각 기준이던 불일치 제거). urgency: Domain.LastTrainUrgency.forTimeRemaining( - departureTime.timeIntervalSinceNow + alarmTime.timeIntervalSinceNow ), changeBadgeExpiry: nil, phase: .active @@ -94,7 +115,9 @@ actor LastTrainLiveActivityAdapter: LastTrainActivityPort, LastTrainChangeAlerti let requested = try Activity.request( attributes: LastTrainActivityAttributes( routeId: route.id, - routeName: Self.displayRouteName(for: route) + routeName: route.sessionDisplayName, + transportKind: Self.transportKind(from: route.boardingLeg?.mode), + firstWalkSeconds: route.firstWalkSectionSeconds ), // staleDate = 출발 시각: 갱신이 끊긴 LA가 출발 시각이 지난 뒤에도 // 오래된 정보를 신선한 것처럼 보이지 않게 시스템이 stale 처리하도록 방어. @@ -110,6 +133,76 @@ actor LastTrainLiveActivityAdapter: LastTrainActivityPort, LastTrainChangeAlerti } } + // MARK: - LastTrainSessionRestoring (Phase 14) + + func reattachOrphans(snapshot: AlarmSessionSnapshot?, now: Date) async { + // 살아 있는 세션을 이미 보관 중이면(이론상 재부착 전 start 경합) 손대지 않는다. + var adopted = activity != nil + for orphan in Activity.activities { + if !adopted, + // dismiss 기록이 있는 세션은 재부착도 하지 않는다 — 유저가 지운 LA는 + // 어떤 경로로도 되살리지 않는 정책과 한 몸(정상 흐름에선 지워진 LA가 + // 목록에 없지만, 기록·상태가 어긋난 경우에도 지운 의사가 이긴다). + !dismissedByUser, + let snapshot, !snapshot.expired, + orphan.attributes.routeId == snapshot.info.lastRouteId, + let departure = snapshot.info.departureTime, + !AlarmTiming.isSessionExpired(departureTime: departure, now: now), + orphan.activityState == .active || orphan.activityState == .stale { + // adopt — 보관 + 상태 관찰 재개. 이후 update/end가 정상 동작한다. + activity = orphan + observeActivityState(orphan) + adopted = true + } else { + // 불일치·만료·스냅샷 없음(고아) — 잠금화면에서 즉시 정리한다. + await orphan.end(nil, dismissalPolicy: .immediate) + } + } + } + + func restartIfNeeded(snapshot: AlarmSessionSnapshot, now: Date) async { + // dismiss 존중(유저가 지운 LA 재생성 금지)·확인된 세션(departed 소멸 예약 완료) + // 재시작 금지. 활성 activity가 있으면 당연히 재시작하지 않는다 — adopt된 세션 포함. + guard activity == nil, + !dismissedByUser, + !snapshot.expired, + !snapshot.acknowledged, + let departure = snapshot.info.departureTime, + !AlarmTiming.isSessionExpired(departureTime: departure, now: now), + ActivityAuthorizationInfo().areActivitiesEnabled + else { return } + + let alarmTime = AlarmTiming.alarmFireDate( + departureTime: departure, + firstWalkSeconds: snapshot.firstWalkSeconds + ) + let state = LastTrainActivityState( + departureTime: departure, + alarmTime: alarmTime, + urgency: Domain.LastTrainUrgency.forTimeRemaining(alarmTime.timeIntervalSince(now)), + changeBadgeExpiry: nil, + phase: .active + ) + do { + let requested = try Activity.request( + attributes: LastTrainActivityAttributes( + routeId: snapshot.info.lastRouteId, + routeName: snapshot.routeDisplayName.isEmpty ? "막차" : snapshot.routeDisplayName, + transportKind: Self.transportKind(from: snapshot.transportMode), + firstWalkSeconds: snapshot.firstWalkSeconds + ), + content: ActivityContent( + state: Self.contentState(from: state), + staleDate: departure + ) + ) + activity = requested + observeActivityState(requested) + } catch { + // 재시작 실패도 흡수한다 — 알람·홈 배너만으로 동작(포트 계약과 동일 태도). + } + } + func update(state: LastTrainActivityState, alert: Bool) async { // 문구 없는 Bool 경로(Domain 포트) — alert=true면 범용 폴백 문구로 위임한다. // Phase 11 훅은 이 경로 대신 LastTrainChangeAlerting으로 변경 유형별 문구를 싣는다. @@ -260,26 +353,15 @@ actor LastTrainLiveActivityAdapter: LastTrainActivityPort, LastTrainChangeAlerti ) } - /// 노선 표시명 — 막차 탑승 구간(departureTime이 있는 첫 대중교통 구간, 없으면 첫 대중교통 구간) 기준. - /// 버스 routeName은 "타입:번호"(예: "간선:472") → "472번 버스", 지하철은 노선명 그대로(급행이면 " 급행"). - private nonisolated static func displayRouteName(for route: LastRoute) -> String { - let transitLegs = route.legs.filter { $0.mode == .bus || $0.mode == .subway } - guard let leg = transitLegs.first(where: { $0.departureTime != nil }) ?? transitLegs.first - else { return "막차" } - - switch leg.mode { - case .subway: - guard let name = leg.routeName else { return "지하철" } - return leg.isExpressSubway ? "\(name) 급행" : name - case .bus: - guard let routeName = leg.routeName else { return "버스" } - guard let colonIndex = routeName.firstIndex(of: ":") else { - return "\(routeName)번 버스" - } - let number = String(routeName[routeName.index(after: colonIndex)...]) - return "\(number)번 버스" - case .walk, .unknown: - return "막차" + /// Domain 수단 → 위젯 계약 수단 키 (Phase 14 DI 아이콘 분기). + private nonisolated static func transportKind( + from mode: TransportMode? + ) -> LastTrainTransportKind? { + switch mode { + case .bus: .bus + case .subway: .subway + case .walk, .unknown: .other + case nil: nil } } } diff --git a/Projects/App/Sources/AlarmSessionLifecycleService.swift b/Projects/App/Sources/AlarmSessionLifecycleService.swift index e9c4dac..d13be02 100644 --- a/Projects/App/Sources/AlarmSessionLifecycleService.swift +++ b/Projects/App/Sources/AlarmSessionLifecycleService.swift @@ -1,3 +1,4 @@ +import Domain import Foundation import os @@ -8,19 +9,25 @@ import os final class AlarmSessionLifecycleService { /// departed 전환·예약 소멸 경로 — LA 어댑터가 구현한다(실패 전부 흡수, non-throwing). private let liveActivity: any LastTrainDepartureEnding + /// 확인 기록 영속화 (Phase 14) — 강제 종료·재실행 후에도 남아 재시작 판정 + /// (확인된 세션 재시작 금지)의 재료가 된다. + private let snapshotStore: any AlarmSessionSnapshotStore private static let logger = Logger( subsystem: "com.atcha.iOS.v2", category: "SessionLifecycle" ) - /// stopIntent 확인 기록 — Phase 14 스냅샷 `acknowledged` 필드의 인메모리 선행. - /// 프로세스가 죽으면 사라진다(강제 종료 케이스의 영속화는 Phase 14 몫). + /// stopIntent 확인 기록 — 스냅샷 영속화의 인메모리 미러. private(set) var isAcknowledged = false - init(liveActivity: any LastTrainDepartureEnding) { + init( + liveActivity: any LastTrainDepartureEnding, + snapshotStore: any AlarmSessionSnapshotStore + ) { self.liveActivity = liveActivity + self.snapshotStore = snapshotStore } - /// 알람 "확인" 탭(stopIntent 실행) — ① 확인 기록 ② LA departed 전환 + /// 알람 "확인" 탭(stopIntent 실행) — ① 확인 기록(스냅샷 영속화) ② LA departed 전환 /// ③ 출발+10분 자동 소멸 예약. ②③은 어댑터의 end 한 번으로 구현된다 /// (final content = departed, dismissalPolicy = .after) — 앱이 다시 깨지 /// 않아도 잠금화면에서 시스템이 내린다. @@ -28,6 +35,11 @@ final class AlarmSessionLifecycleService { // 로그는 자동 검수 ②(강제 종료 후 인텐트 실행 여부 판정)의 증적 채널이다. Self.logger.info("알람 확인(stopIntent) 수신 — departed 전환 + 자동 소멸 예약") isAcknowledged = true + // 세션 스냅샷이 있을 때만 기록한다 — 스냅샷 없는 확인(이론상 경합)은 남길 곳이 없고, + // 그 경우의 정리는 wake 시점 리컨실이 맡는다. + if let snapshot = await snapshotStore.load() { + await snapshotStore.save(snapshot.updating(acknowledged: true)) + } await liveActivity.endAsDeparted() } } diff --git a/Projects/App/Sources/AlarmSyncService.swift b/Projects/App/Sources/AlarmSyncService.swift index a5bc009..7c5b44a 100644 --- a/Projects/App/Sources/AlarmSyncService.swift +++ b/Projects/App/Sources/AlarmSyncService.swift @@ -24,6 +24,13 @@ import os /// 성공해 **미래 출발 시각**을 반환하면 서버 우선(만료 취소, 정상 갱신 경로). /// 만료 확정 세션은 기록해 이후 refresh가 같은 과거 세션으로 배너를 되살리지 못하게 /// 한다(홈의 미래 시각 가드가 1차 방어, 이 기록이 2차). +/// +/// Phase 14 재실행 정합성: 첫 sync 진입 시 스냅샷을 시딩해 ⑤ `lastInfo`(diff의 "이전 +/// 값")가 재실행 후에도 살아 종료 중 발생한 변경을 실제로 판정하고, 만료 판정도 프로세스 +/// 수명과 무관하게 성립한다(expired 톰스톤은 2차 방어 복원). ⑥ sync 성공 시 스냅샷을 +/// 병합 저장하고, 스냅샷은 살아 있는데 활성 LA가 없는 죽은 세션은 로컬 재시작을 +/// 위임한다(dismiss·확인 기록 존중은 어댑터 몫). 도보 초는 스냅샷에서 읽어 LA 알람 +/// 시각 계산이 등록/refresh와 같은 기준을 탄다(이중 시각 금지). // Sendable 프로토콜(AlarmSyncEvents 등) 채택이 기본 MainActor 격리를 nonisolated로 // 추론시키므로 명시한다 — 상태(subscribers 등)는 전부 메인 액터에서만 만진다. @MainActor @@ -37,6 +44,11 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { private let localNotification: any LocalNotificationPort /// sessionEnded 시 로컬 알람 취소용(Phase 12) — 등록/갱신 UseCase와 같은 스케줄러를 공유한다. private let alarmScheduler: any AlarmScheduler + /// 세션 스냅샷(Phase 14) — 재실행 브리지. sync 성공 시 병합 저장, 만료 확정 시 톰스톤, + /// 서버 sessionEnded 시 clear. + private let snapshotStore: any AlarmSessionSnapshotStore + /// 죽은 세션 LA 재시작 경로(Phase 14) — dismiss·확인 기록 판정은 어댑터가 한다. + private let sessionRestorer: any LastTrainSessionRestoring private static let logger = Logger(subsystem: "com.atcha.iOS.v2", category: "AlarmSync") /// "⚠ 당겨짐" 배지 유지 시간 — 정책: 표출 시점 + 10분. @@ -51,6 +63,15 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { /// Phase 13 만료 2차 방어 — 로컬 만료를 확정한 세션. 이후 refresh가 같은 routeId의 /// 과거 세션을 반환해도 무시한다(미래 출발이 오면 서버 우선으로 해제). private var locallyExpiredSession: AlarmInfo? + /// Phase 14 스냅샷 시딩 1회 게이트 — 첫 sync 진입 전에 반드시 시딩이 끝나야 + /// diff·만료 판정이 재실행 전 세션을 본다(트리거 3경로 공용이라 sync 안에서 게이트). + private var isSeededFromSnapshot = false + /// 현재 세션의 첫 도보 구간(초) — LA 알람 시각 계산용(등록/refresh와 같은 기준, + /// 이중 시각 금지). 스냅샷 시딩·병합 저장 시 갱신된다. + private var sessionWalkSeconds: Int? + /// "⚠ 당겨짐" 배지의 현재 만료 시각 — 조용한 갱신(unchanged/delayed)이 배지를 10분 + /// 정책보다 일찍 지우지 않도록 보존한다(Phase 14 정합). + private var changeBadgeExpiry: Date? /// 진행 중 동기화 — 트리거가 겹치면(예: 앱 시작 직후 포그라운드 노티) 합류한다. private var inFlight: Task? private var foregroundObserver: (any NSObjectProtocol)? @@ -61,13 +82,17 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { evaluateChangeUseCase: any EvaluateAlarmChangeUseCase, liveActivity: any LastTrainChangeAlerting, localNotification: any LocalNotificationPort, - alarmScheduler: any AlarmScheduler + alarmScheduler: any AlarmScheduler, + snapshotStore: any AlarmSessionSnapshotStore, + sessionRestorer: any LastTrainSessionRestoring ) { self.refreshAlarmUseCase = refreshAlarmUseCase self.evaluateChangeUseCase = evaluateChangeUseCase self.liveActivity = liveActivity self.localNotification = localNotification self.alarmScheduler = alarmScheduler + self.snapshotStore = snapshotStore + self.sessionRestorer = sessionRestorer } /// 인증 부트스트랩 완료 후 1회 호출: 즉시 동기화(앱 시작 경로) + 포그라운드 @@ -98,6 +123,9 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { return await inFlight.value } Self.logger.info("알람 동기화 시작") + // Phase 14 시딩 — 첫 진입에서 스냅샷을 lastInfo(diff 이전 값)·만료 기록으로 복원. + // 만료 선행 판정보다 먼저여야 재실행 직후의 과거 세션도 리컨실에 걸린다. + await seedFromSnapshotIfNeeded() // Phase 13 선행 판정 — 확정은 refresh 결과를 본 뒤(미래 출발이면 서버 우선 취소). let expiryCandidate = expireLocallyIfNeeded(now: Date()) let task = Task { [refreshAlarmUseCase] () -> AlarmInfo? in @@ -137,15 +165,68 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { Self.logger.info("알람 동기화 성공: route=\(info.lastRouteId, privacy: .public)") let previous = lastInfo lastInfo = info + // Phase 14 — sync 성공은 스냅샷 저장 시점. 도보·표시명은 같은 세션이면 보존한다. + let snapshot = await persistSyncedSnapshot(for: info) for continuation in subscribers.values { continuation.yield(info) } + // Phase 14 죽은 세션 재시작 — 스냅샷은 살아 있는데 활성 LA가 없고 dismiss·확인 + // 기록도 없으면 로컬 재시작(판정은 어댑터). 8시간 한도·시작 실패 세션 커버. + await sessionRestorer.restartIfNeeded(snapshot: snapshot, now: Date()) // Phase 11 피기백 — 이 시점에 알람 재스케줄은 이미 완료돼 있다 // (RefreshAlarmUseCase.execute 반환 = 재스케줄 포함). 표출은 그 뒤에만 덧붙는다. await propagateChange(previous: previous, latest: info) return info } + // MARK: - Phase 14 스냅샷 시딩·병합 + + /// 첫 sync 진입 전 1회 — 재실행 브리지 복원. expired 톰스톤은 2차 방어로, + /// 살아 있는 스냅샷은 diff의 "이전 값"으로 시딩하고 **구독자에게도 흘린다** — + /// refresh가 실패해도(오프라인·실서버 미인증) 홈이 배너·해제 버튼·카드를 복원할 + /// 수 있어야 재실행이 정보를 잃지 않는다. 직후의 만료 판정·refresh가 이 값을 + /// 즉시 교정하므로(서버 우선) 스냅샷이 정본 행세를 하는 창은 한 sync 이내다. + private func seedFromSnapshotIfNeeded() async { + guard !isSeededFromSnapshot else { return } + isSeededFromSnapshot = true + guard let snapshot = await snapshotStore.load() else { return } + sessionWalkSeconds = snapshot.firstWalkSeconds + if snapshot.expired { + locallyExpiredSession = snapshot.info + } else if lastInfo == nil { + lastInfo = snapshot.info + Self.logger.info( + "스냅샷 시딩: route=\(snapshot.info.lastRouteId, privacy: .public)" + ) + for continuation in subscribers.values { + continuation.yield(snapshot.info) + } + } + } + + /// sync 성공 시 스냅샷 병합 저장 — 같은 세션(routeId 일치)이면 등록 시점 사실 + /// (도보·표시명·수단·확인 기록)을 보존하고 info만 갱신, 다른 세션이면 아는 것만 담는다 + /// (표시명 공백은 LA 재시작 시 "막차" 폴백, 카드는 상세 재조회가 채운다). + private func persistSyncedSnapshot(for info: AlarmInfo) async -> AlarmSessionSnapshot { + let existing = await snapshotStore.load() + let snapshot: AlarmSessionSnapshot + if let existing, existing.info.lastRouteId == info.lastRouteId { + snapshot = existing.updating(info: info, expired: false) + } else { + snapshot = AlarmSessionSnapshot( + info: info, + firstWalkSeconds: nil, + routeDisplayName: "", + transportMode: nil, + acknowledged: false, + expired: false + ) + } + await snapshotStore.save(snapshot) + sessionWalkSeconds = snapshot.firstWalkSeconds + return snapshot + } + // MARK: - Phase 13 클라 자체 만료 (wake 시점 판정) /// sync 진입 선행 판정 — 보유 세션이 만료 유예(출발+60초, AlarmTiming 단일 기준)를 @@ -167,6 +248,22 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { locallyExpiredSession = session // replay-1이 죽은 세션을 재구독자에게 되살리지 않도록 비운다. lastInfo = nil + // Phase 14 — 만료 기록을 톰스톤(expired=true)으로 영속화: 재실행 후에도 같은 + // 과거 세션의 refresh가 배너·재부착·재시작을 되살리지 못한다(2차 방어의 영속화). + // clear가 아니라 톰스톤인 이유: 지워 버리면 다음 실행의 2차 방어가 사라진다. + let existing = await snapshotStore.load() + if let existing, existing.info.lastRouteId == session.lastRouteId { + await snapshotStore.save(existing.updating(expired: true)) + } else { + await snapshotStore.save(AlarmSessionSnapshot( + info: session, + firstWalkSeconds: sessionWalkSeconds, + routeDisplayName: "", + transportMode: nil, + acknowledged: false, + expired: true + )) + } await presentSessionEnded(previous: session, now: Date()) yieldChange(.sessionEnded) } @@ -207,6 +304,9 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { case .sessionEnded: // 운행 종료·경로 소멸 — LA 최종 상태 종료 + 로컬 알람 취소. // 배너 정리는 changes yield를 받은 홈의 몫. + // 서버가 세션 종료를 확정했으므로 재실행 브리지(스냅샷)도 지운다(Phase 14). + await snapshotStore.clear() + sessionWalkSeconds = nil await presentSessionEnded(previous: previous, now: now) yieldChange(verdict) } @@ -220,8 +320,12 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { now: Date ) async { guard let departure = latest.departureTime else { return } - let alarmTime = AlarmTiming.alarmFireDate(departureTime: departure) + let alarmTime = AlarmTiming.alarmFireDate( + departureTime: departure, firstWalkSeconds: sessionWalkSeconds + ) let badgeExpiry = now.addingTimeInterval(Self.changeBadgeDuration) + // 조용한 후속 갱신(unchanged/delayed)이 배지를 10분보다 일찍 지우지 않도록 보존한다. + changeBadgeExpiry = badgeExpiry guard alarmTime > now else { // 새 알람 시각이 이미 과거(출발은 미래) — 마지노선 침범. 원래 울렸어야 할 알람 @@ -285,9 +389,13 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { private func presentMissed(latest: AlarmInfo, now: Date) async { // actionable=false 판정은 departureTime이 있을 때만 나온다(없으면 sessionEnded). guard let departure = latest.departureTime else { return } + // 실패 상태로 내려가면 "당겨짐" 배지는 의미를 잃는다 — 보존 기록도 접는다. + changeBadgeExpiry = nil let state = LastTrainActivityState( departureTime: departure, - alarmTime: AlarmTiming.alarmFireDate(departureTime: departure), + alarmTime: AlarmTiming.alarmFireDate( + departureTime: departure, firstWalkSeconds: sessionWalkSeconds + ), urgency: .imminent, changeBadgeExpiry: nil, phase: .missed @@ -315,6 +423,7 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { private func presentSessionEnded(previous: AlarmInfo?, now: Date) async { // 더는 울리면 안 되는 것이 정책의 핵심 — 표출(LA 종료)보다 알람 취소를 먼저 한다. await alarmScheduler.cancelAlarm() + changeBadgeExpiry = nil // sessionEnded 응답에는 departureTime이 없다 — 종료 시각 정보용으로 직전 스냅샷 // (previous = 갱신 전 lastInfo)의 마지막 출발 시각을 쓰고, 그것도 없으면 now. @@ -323,7 +432,9 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { // 로컬 노티 폴백도 없다(배너 정리는 changes 스트림을 받은 홈이 한다). await liveActivity.end(final: LastTrainActivityState( departureTime: departure, - alarmTime: AlarmTiming.alarmFireDate(departureTime: departure), + alarmTime: AlarmTiming.alarmFireDate( + departureTime: departure, firstWalkSeconds: sessionWalkSeconds + ), // 위젯은 serviceEnded phase 키로 그린다 — urgency는 종료 화면에선 의미 없는 방어값. urgency: .imminent, changeBadgeExpiry: nil, @@ -332,14 +443,20 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { } /// 갱신된 AlarmInfo → LA 상태. departureTime이 없으면(세션 종료 등) 만들 수 없다. + /// 조용한 갱신도 살아 있는 "당겨짐" 배지는 그대로 싣는다 — 10분 정책 보존(Phase 14). private func activityState(for info: AlarmInfo, now: Date) -> LastTrainActivityState? { guard let departure = info.departureTime else { return nil } - let alarmTime = AlarmTiming.alarmFireDate(departureTime: departure) + let alarmTime = AlarmTiming.alarmFireDate( + departureTime: departure, firstWalkSeconds: sessionWalkSeconds + ) + if let badgeExpiry = changeBadgeExpiry, badgeExpiry <= now { + changeBadgeExpiry = nil // 만료된 배지 기록은 정리한다. + } return LastTrainActivityState( departureTime: departure, alarmTime: alarmTime, urgency: LastTrainUrgency.forTimeRemaining(alarmTime.timeIntervalSince(now)), - changeBadgeExpiry: nil, + changeBadgeExpiry: changeBadgeExpiry, phase: .active ) } diff --git a/Projects/App/Sources/AppDIContainer.swift b/Projects/App/Sources/AppDIContainer.swift index dd143bf..3484abf 100644 --- a/Projects/App/Sources/AppDIContainer.swift +++ b/Projects/App/Sources/AppDIContainer.swift @@ -27,13 +27,18 @@ final class AppDIContainer { // 로컬 노티도 1회 생성 공유 — 권한 요청 훅(등록 UseCase)과 dismiss 폴백 발송(AlarmSyncService)이 // 같은 요청 이력을 봐야 한다. UNUserNotificationCenter를 아는 곳은 이 어댑터뿐. private let localNotificationPort: any LocalNotificationPort + // 구체 어댑터 보유 — 고아 LA 재부착(부트스트랩 직후, Phase 14)과 DEV 검수 토글의 통로. + private let liveActivityAdapter: LastTrainLiveActivityAdapter + /// 세션 스냅샷(Phase 14 재실행 브리지) — 등록/취소/refresh UseCase·수명 서비스· + /// 동기화 서비스가 같은 저장소를 봐야 한다(1회 생성 공유). + private let alarmSessionSnapshotStore: any AlarmSessionSnapshotStore let alarmSyncService: AlarmSyncService /// Phase 13 발화 이후 세션 수명 — stopIntent(AlarmAcknowledgeIntent)가 조합 루트를 /// 거쳐 도달하는 지점. AppDelegate 경유로 인텐트 perform()이 접근한다. let alarmSessionLifecycle: AlarmSessionLifecycleService #if DEV /// DEV 플로팅 디버그 메뉴가 dismiss 기록 강제 토글에 접근하는 유일한 통로 (Phase 12 검수). - let devLiveActivityAdapter: LastTrainLiveActivityAdapter + var devLiveActivityAdapter: LastTrainLiveActivityAdapter { liveActivityAdapter } #endif init() { @@ -93,29 +98,45 @@ final class AppDIContainer { scheduling: AlarmKitScheduler(stopIntent: AlarmAcknowledgeIntent()) ) self.alarmScheduler = alarmScheduler - // 구체 어댑터로 들고 있다가 세 얼굴로 나눠 준다 — Domain 포트(등록/해제 UseCase), + // 구체 어댑터로 들고 있다가 네 얼굴로 나눠 준다 — Domain 포트(등록/해제 UseCase), // App 내부 변경 표출 경로(LastTrainChangeAlerting, Phase 11 훅), - // 발화 확인 경로(LastTrainDepartureEnding, Phase 13). + // 발화 확인 경로(LastTrainDepartureEnding, Phase 13), + // 재실행 복원 경로(LastTrainSessionRestoring, Phase 14). let liveActivityAdapter = LastTrainLiveActivityAdapter() + self.liveActivityAdapter = liveActivityAdapter self.liveActivityPort = liveActivityAdapter - self.alarmSessionLifecycle = AlarmSessionLifecycleService(liveActivity: liveActivityAdapter) - #if DEV - self.devLiveActivityAdapter = liveActivityAdapter - #endif + let snapshotStore = AlarmSessionSnapshotStoreAdapter() + self.alarmSessionSnapshotStore = snapshotStore + self.alarmSessionLifecycle = AlarmSessionLifecycleService( + liveActivity: liveActivityAdapter, + snapshotStore: snapshotStore + ) let localNotificationAdapter = LocalNotificationAdapter() self.localNotificationPort = localNotificationAdapter self.alarmSyncService = AlarmSyncService( refreshAlarmUseCase: DefaultRefreshAlarmUseCase( repository: alarmRepository, - scheduler: alarmScheduler + scheduler: alarmScheduler, + // refresh 응답에는 도보 정보가 없다 — 등록 시점 스냅샷이 도보 초의 출처. + snapshotStore: snapshotStore ), evaluateChangeUseCase: DefaultEvaluateAlarmChangeUseCase(), liveActivity: liveActivityAdapter, localNotification: localNotificationAdapter, - alarmScheduler: alarmScheduler + alarmScheduler: alarmScheduler, + snapshotStore: snapshotStore, + sessionRestorer: liveActivityAdapter ) } + /// 부트스트랩 직후 1회(AppDelegate) — 프로세스가 죽는 사이 잠금화면에 남은 고아 LA를 + /// 스냅샷과 대조해 재부착하거나 정리한다(Phase 14). 인증·네트워크와 무관한 로컬 + /// 리컨실이라 앱 시작 최전선에서 수행한다(부트스트랩 실패로 고아가 방치되지 않게). + func reattachOrphanLiveActivities() async { + let snapshot = await alarmSessionSnapshotStore.load() + await liveActivityAdapter.reattachOrphans(snapshot: snapshot, now: Date()) + } + func makeHomeDIContainer() -> any HomeCoordinatorBuildable { let recentSearchRepository = RecentSearchRepositoryImpl(store: UserDefaultsKeyValueStore()) let locationService = CoreLocationServiceAdapter() @@ -137,15 +158,22 @@ final class AppDIContainer { scheduler: alarmScheduler, activityPort: liveActivityPort, // 알림 권한 요청의 유일한 시점(등록 성공 직후) — UseCase 내부 훅이 호출한다. - notificationPort: localNotificationPort + notificationPort: localNotificationPort, + // 등록 성공 = 스냅샷 저장 시점(Phase 14). + snapshotStore: alarmSessionSnapshotStore ), cancelAlarmUseCase: DefaultCancelAlarmUseCase( repository: alarmRepository, scheduler: alarmScheduler, - activityPort: liveActivityPort + activityPort: liveActivityPort, + snapshotStore: alarmSessionSnapshotStore ), observeAlarmUseCase: DefaultObserveAlarmUseCase(events: alarmSyncService), observeAlarmChangeUseCase: DefaultObserveAlarmChangeUseCase(events: alarmSyncService), + // 재실행 카드 복원(Phase 14) — 기존 미사용 자산(detail 엔드포인트) 재활용. + getLastRouteDetailUseCase: DefaultGetLastRouteDetailUseCase( + repository: lastRouteRepository + ), searchCoordinatorBuildable: searchContainer ) } diff --git a/Projects/App/Sources/AppDelegate.swift b/Projects/App/Sources/AppDelegate.swift index 034e602..5e4d2df 100644 --- a/Projects/App/Sources/AppDelegate.swift +++ b/Projects/App/Sources/AppDelegate.swift @@ -19,6 +19,11 @@ final class AppDelegate: UIResponder, UIApplicationDelegate { _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil ) -> Bool { + // 고아 LA 재부착/정리 (Phase 14) — 인증 부트스트랩과 무관한 로컬 리컨실이라 + // 앱 시작 최전선에서 1회. 첫 sync보다 먼저 끝나는 것이 보통이지만, 늦어도 + // 어댑터(actor)가 직렬화하므로 안전하다. + let container = container + Task { await container.reattachOrphanLiveActivities() } configureFirebaseIfAvailable() if isFirebaseEnabled { Messaging.messaging().delegate = self diff --git a/Projects/App/Widget/Sources/LastTrainLiveActivityWidget.swift b/Projects/App/Widget/Sources/LastTrainLiveActivityWidget.swift index afe9f53..5f4dce1 100644 --- a/Projects/App/Widget/Sources/LastTrainLiveActivityWidget.swift +++ b/Projects/App/Widget/Sources/LastTrainLiveActivityWidget.swift @@ -21,7 +21,7 @@ struct LastTrainLiveActivityWidget: Widget { var body: some WidgetConfiguration { ActivityConfiguration(for: LastTrainActivityAttributes.self) { context in LastTrainLockScreenView( - routeName: context.attributes.routeName, + attributes: context.attributes, state: context.state, isStale: context.isStale ) @@ -35,7 +35,7 @@ struct LastTrainLiveActivityWidget: Widget { return DynamicIsland { DynamicIslandExpandedRegion(.leading) { HStack(spacing: DSSpacing.xs) { - Image(systemName: "bus.fill") + Image(systemName: context.attributes.transportSymbolName) .font(.subheadline) .foregroundStyle(state.glanceColor) Text(context.attributes.routeName) @@ -83,8 +83,8 @@ struct LastTrainLiveActivityWidget: Widget { } } } compactLeading: { - // 노선 수단(버스/지하철) 구분 필드가 계약에 없어 버스 아이콘 고정. - Image(systemName: "bus.fill") + // 수단 필드(Phase 14) 기준 지하철/버스 아이콘 분기 — 구버전 LA(필드 없음)는 버스 폴백. + Image(systemName: context.attributes.transportSymbolName) .foregroundStyle(state.glanceColor) } compactTrailing: { switch state.status { @@ -117,7 +117,7 @@ struct LastTrainLiveActivityWidget: Widget { .foregroundStyle(state.glanceColor) } } minimal: { - Image(systemName: "bus.fill") + Image(systemName: context.attributes.transportSymbolName) .foregroundStyle(state.glanceColor) } .keylineTint(Color(ds: DSColor.Accent.default)) @@ -138,10 +138,10 @@ struct LastTrainLiveActivityWidget: Widget { /// glance는 0.5초 — 숫자보다 색·상태가 먼저 읽히도록 카운트다운 /// 숫자·아이콘에 긴급도 색을 상시 적용한다. private struct LastTrainLockScreenView: View { - let routeName: String + let attributes: LastTrainActivityAttributes let state: LastTrainActivityAttributes.ContentState /// staleDate(=출발 시각)가 지나도록 갱신이 없었다 — 강제 종료·고아 케이스의 UI 완충 - /// (Phase 13). 근본 해소(재부착)는 Phase 14 몫. + /// (Phase 13). 근본 해소는 Phase 14 재부착 — 이 분기는 최후 방어선으로 유지. let isStale: Bool var body: some View { @@ -156,10 +156,10 @@ private struct LastTrainLockScreenView: View { /// 1행: 노선명 + "⚠ 당겨짐" 배지 슬롯. private var headerRow: some View { HStack(spacing: DSSpacing.xs) { - Image(systemName: "bus.fill") + Image(systemName: attributes.transportSymbolName) .font(.subheadline) .foregroundStyle(Color(ds: DSColor.Icon.default)) - Text("\(routeName) 막차") + Text("\(attributes.routeName) 막차") .font(.subheadline.weight(.semibold)) .foregroundStyle(Color(ds: DSColor.Text.primary)) .lineLimit(1) @@ -205,16 +205,36 @@ private struct LastTrainLockScreenView: View { } } - /// 3행: 출발 시각. 목업의 "정류장 도보 8분" 자리는 비워둔다 — - /// ContentState에 도보 필드가 없고 Phase 9 wire 계약은 고정이라 - /// attributes/state 확장 금지. Phase 11 미확정 #7(도보 소요 데이터) - /// 해소 시 "HH:mm 출발 · 정류장 도보 N분" 형태로 재검토. + /// 3행: 출발 시각 + 정류장 도보 소요 (Phase 14 — 미확정 #7 클라 임시안으로 목업 공석 해소). + /// 도보 데이터가 없는 세션(구버전 LA·도보 없는 경로)은 출발 시각만 표시한다. private var departureRow: some View { - Text("\(LastTrainTimeFormat.hhmm(state.departureTime)) 출발") + Text(departureRowText) .font(.footnote) .foregroundStyle(Color(ds: DSColor.Text.secondary)) .lineLimit(1) } + + private var departureRowText: String { + let departureText = "\(LastTrainTimeFormat.hhmm(state.departureTime)) 출발" + guard let walkSeconds = attributes.firstWalkSeconds, walkSeconds > 0 else { + return departureText + } + // 올림 표기 — 변경 분 표기와 같은 방향(.up), "0분 도보"는 존재하지 않는다. + let walkMinutes = max(1, Int((Double(walkSeconds) / 60).rounded(.up))) + return "\(departureText) · 정류장 도보 \(walkMinutes)분" + } +} + +// MARK: - Attributes presentation helpers + +private extension LastTrainActivityAttributes { + /// 수단 → SF Symbol. 필드가 없는 구버전 LA는 버스 폴백(기존 표시 유지). + var transportSymbolName: String { + switch transportKind { + case .subway: "tram.fill" + case .bus, .other, nil: "bus.fill" + } + } } /// "⚠ 당겨짐" 배지 — 변경 직후 10분 노출 정책의 표시 슬롯. diff --git a/Projects/Core/LiveActivity/Sources/LastTrainActivityAttributes.swift b/Projects/Core/LiveActivity/Sources/LastTrainActivityAttributes.swift index 2e3019c..8ee2dc9 100644 --- a/Projects/Core/LiveActivity/Sources/LastTrainActivityAttributes.swift +++ b/Projects/Core/LiveActivity/Sources/LastTrainActivityAttributes.swift @@ -10,10 +10,22 @@ public struct LastTrainActivityAttributes: ActivityAttributes, Sendable { public let routeId: String /// 노선명 (예: "9호선 급행") — 잠금화면·다이나믹 아일랜드 타이틀. public let routeName: String + /// 탑승 수단 (Phase 14) — DI 컴팩트 아이콘 분기용. 고정 정보라 Attributes가 맞는 자리. + /// optional인 이유: 구버전이 남긴 활성 LA의 재부착 디코딩이 새 키 부재로 깨지면 안 된다. + public let transportKind: LastTrainTransportKind? + /// 등록 시점 경로의 첫 도보 구간(초, Phase 14) — 잠금화면 3행 "정류장 도보 N분" 표시용. + public let firstWalkSeconds: Int? - public init(routeId: String, routeName: String) { + public init( + routeId: String, + routeName: String, + transportKind: LastTrainTransportKind?, + firstWalkSeconds: Int? + ) { self.routeId = routeId self.routeName = routeName + self.transportKind = transportKind + self.firstWalkSeconds = firstWalkSeconds } /// Mutable snapshot pushed on every update. @@ -45,6 +57,15 @@ public struct LastTrainActivityAttributes: ActivityAttributes, Sendable { } } +/// 탑승 수단 (Phase 14) — 위젯 아이콘 키. 세분류(간선/지선 등)는 표시에 불필요해 +/// 버스/지하철 2종 + 방어값(other)만 둔다. 미지 rawValue 디코딩 실패는 어댑터가 +/// optional 필드로 무해화한다(위젯은 nil이면 버스 아이콘 폴백). +public enum LastTrainTransportKind: String, Codable, Hashable, Sendable { + case bus + case subway + case other +} + /// 긴급도 3단계 (여유/주의/임박). public enum LastTrainUrgency: String, Codable, Hashable, Sendable { case relaxed diff --git a/Projects/Core/LiveActivity/Tests/LastTrainActivityAttributesTests.swift b/Projects/Core/LiveActivity/Tests/LastTrainActivityAttributesTests.swift index 69473d1..bf22b19 100644 --- a/Projects/Core/LiveActivity/Tests/LastTrainActivityAttributesTests.swift +++ b/Projects/Core/LiveActivity/Tests/LastTrainActivityAttributesTests.swift @@ -35,11 +35,37 @@ struct LastTrainActivityAttributesTests { @Test func attributes_roundTripCodable_preservesFixedSessionInfo() throws { - let attributes = LastTrainActivityAttributes(routeId: "route-42", routeName: "9호선 급행") + let attributes = LastTrainActivityAttributes( + routeId: "route-42", + routeName: "9호선 급행", + transportKind: .subway, + firstWalkSeconds: 120 + ) let data = try JSONEncoder().encode(attributes) let decoded = try JSONDecoder().decode(LastTrainActivityAttributes.self, from: data) #expect(decoded.routeId == "route-42") #expect(decoded.routeName == "9호선 급행") + #expect(decoded.transportKind == .subway) + #expect(decoded.firstWalkSeconds == 120) + } + + @Test + func attributes_legacyPayloadWithoutPhase14Fields_stillDecodes() throws { + // 재부착(Phase 14)은 구버전 앱이 남긴 활성 LA의 attributes를 디코딩한다 — + // 새 필드(수단·도보)가 없는 payload가 실패하면 재부착 자체가 불가능해진다. + let legacy = Data(#"{"routeId":"route-42","routeName":"9호선 급행"}"#.utf8) + let decoded = try JSONDecoder().decode(LastTrainActivityAttributes.self, from: legacy) + #expect(decoded.routeId == "route-42") + #expect(decoded.transportKind == nil) + #expect(decoded.firstWalkSeconds == nil) + } + + @Test + func transportKind_rawValuesAreStable() { + // Raw values ride inside ActivityKit's persisted attributes — wire 계약. + #expect(LastTrainTransportKind.bus.rawValue == "bus") + #expect(LastTrainTransportKind.subway.rawValue == "subway") + #expect(LastTrainTransportKind.other.rawValue == "other") } @Test diff --git a/Projects/Domain/Sources/Entities/AlarmError.swift b/Projects/Domain/Sources/Entities/AlarmError.swift index aca3ae3..a22a408 100644 --- a/Projects/Domain/Sources/Entities/AlarmError.swift +++ b/Projects/Domain/Sources/Entities/AlarmError.swift @@ -2,4 +2,7 @@ public enum AlarmError: Error, Equatable, Sendable { /// AlarmKit 권한 거부 — 서버 등록을 보류하고 설정 이동을 안내한다. case permissionDenied + /// 알람 발화 시각(출발 − 도보 − 버퍼)이 이미 과거 — 서버 등록 성공 후 로컬 스케줄이 + /// 실패하는 서버/로컬 불일치를 사전 차단한다(등록 자체를 시작하지 않는다). + case tooLate } diff --git a/Projects/Domain/Sources/Entities/AlarmInfo.swift b/Projects/Domain/Sources/Entities/AlarmInfo.swift index 41acf7c..adfe5a2 100644 --- a/Projects/Domain/Sources/Entities/AlarmInfo.swift +++ b/Projects/Domain/Sources/Entities/AlarmInfo.swift @@ -2,7 +2,8 @@ import Foundation // TODO: [미확정] 서버 계산 "알람 시각" 필드는 refresh 응답에 없다(실측: departureTime뿐) — // 알람 시각 스펙이 확정되면 여기에 추가한다. -public struct AlarmInfo: Equatable, Sendable { +/// Codable: 세션 스냅샷(`AlarmSessionSnapshot`) 영속화용 — 재실행 브리지이지 정본이 아니다. +public struct AlarmInfo: Equatable, Sendable, Codable { public let lastRouteId: String /// 막차 출발 시각 (서버 재계산 값) public let departureTime: Date? diff --git a/Projects/Domain/Sources/Entities/AlarmSessionSnapshot.swift b/Projects/Domain/Sources/Entities/AlarmSessionSnapshot.swift new file mode 100644 index 0000000..9790b5d --- /dev/null +++ b/Projects/Domain/Sources/Entities/AlarmSessionSnapshot.swift @@ -0,0 +1,61 @@ +import Foundation + +/// 알람 세션의 재실행 브리지 (Phase 14) — 앱 프로세스 수명과 알람 세션 수명을 분리한다. +/// 정본은 여전히 서버(refresh)다: 스냅샷만으로 알람을 새로 만들지 않고, 서버 결과와 +/// 충돌하면 항상 서버가 이긴다. 기록 시점: 등록 성공·sync 성공 시 save, +/// 취소·서버 sessionEnded 시 clear, 로컬 만료 확정 시 expired=true 톰스톤 +/// (재실행 후에도 같은 과거 세션의 refresh가 배너를 되살리지 못하게 하는 2차 방어). +public struct AlarmSessionSnapshot: Sendable, Equatable, Codable { + public let info: AlarmInfo + /// 등록 시점 경로의 첫 도보 구간(초) — 알람 기준 시각 계산용 (없으면 nil). + public let firstWalkSeconds: Int? + /// LA·카드 복원용 표시명 (예: "6411번 버스"). + public let routeDisplayName: String + /// 탑승 수단 — LA 재시작 시 아이콘 분기용 (확정 결정: 스냅샷 = 표시명·수단 포함). + public let transportMode: TransportMode? + /// stopIntent 확인 기록 (Phase 13 연동) — 확인된 세션은 LA를 재시작하지 않는다 + /// (departed 소멸 예약이 이미 잡혀 있다). + public let acknowledged: Bool + /// 로컬 만료 기록 (Phase 13 연동) — true면 죽은 세션 톰스톤. + public let expired: Bool + + public init( + info: AlarmInfo, + firstWalkSeconds: Int?, + routeDisplayName: String, + transportMode: TransportMode?, + acknowledged: Bool, + expired: Bool + ) { + self.info = info + self.firstWalkSeconds = firstWalkSeconds + self.routeDisplayName = routeDisplayName + self.transportMode = transportMode + self.acknowledged = acknowledged + self.expired = expired + } + + /// 세션 사실(도보·표시명·수단)은 유지하고 기록 필드만 바꾼 사본. + public func updating( + info: AlarmInfo? = nil, + acknowledged: Bool? = nil, + expired: Bool? = nil + ) -> AlarmSessionSnapshot { + AlarmSessionSnapshot( + info: info ?? self.info, + firstWalkSeconds: firstWalkSeconds, + routeDisplayName: routeDisplayName, + transportMode: transportMode, + acknowledged: acknowledged ?? self.acknowledged, + expired: expired ?? self.expired + ) + } +} + +/// 스냅샷 영속화 포트 — 어댑터(UserDefaults 백엔드)는 App에 둔다. +/// 디코딩 실패는 어댑터가 nil로 무해화한다(자가치유 — 다음 save가 덮어쓴다). +public protocol AlarmSessionSnapshotStore: Sendable { + func load() async -> AlarmSessionSnapshot? + func save(_ snapshot: AlarmSessionSnapshot) async + func clear() async +} diff --git a/Projects/Domain/Sources/Entities/AlarmTiming.swift b/Projects/Domain/Sources/Entities/AlarmTiming.swift index a3c8d4c..178a036 100644 --- a/Projects/Domain/Sources/Entities/AlarmTiming.swift +++ b/Projects/Domain/Sources/Entities/AlarmTiming.swift @@ -1,14 +1,18 @@ import Foundation /// 버퍼 = 스누즈 예산 (정책 5). 알람은 기준 시각 − 버퍼에 울린다. 버퍼 고정 3분, 설정 없음(v1). -/// TODO(미확정 #7): 기준 시각 = departureTime − 첫 도보 구간 시간이 원칙이나, refresh 응답에 -/// 도보 정보가 없어 register/refresh 이중 시각이 생기므로 확정 전까지 버퍼만 균일 적용한다. +/// 기준 시각(미확정 #7 클라 임시안, Phase 14 확정) = departureTime − 첫 도보 구간 시간 — +/// 도보 초는 등록 시점 경로에서 취득해 스냅샷에 저장하고, 서버 필드가 생기면 대체한다. public enum AlarmTiming { public static let bufferSeconds: TimeInterval = 180 - /// 로컬 알람 발화 시각 = departureTime − bufferSeconds. - public static func alarmFireDate(departureTime: Date) -> Date { - departureTime.addingTimeInterval(-bufferSeconds) + /// 로컬 알람 발화 시각 = departureTime − firstWalkSeconds − bufferSeconds. + /// 등록/refresh 재스케줄/LA alarmTime/홈 배너 4곳이 전부 이 함수를 탄다(이중 시각 금지) — + /// 기본값을 두지 않아 콜사이트가 도보 초의 출처(경로·스냅샷·없음)를 명시하게 강제한다. + public static func alarmFireDate(departureTime: Date, firstWalkSeconds: Int?) -> Date { + departureTime.addingTimeInterval( + -(TimeInterval(firstWalkSeconds ?? 0) + bufferSeconds) + ) } /// 클라 자체 만료 유예 — 출발 시각 + 60초가 지나면 세션을 로컬 만료로 판정한다 diff --git a/Projects/Domain/Sources/Entities/LastRoute.swift b/Projects/Domain/Sources/Entities/LastRoute.swift index cbefa7a..23fa5e6 100644 --- a/Projects/Domain/Sources/Entities/LastRoute.swift +++ b/Projects/Domain/Sources/Entities/LastRoute.swift @@ -1,6 +1,8 @@ import Foundation -public enum TransportMode: Equatable, Sendable { +/// Codable: 세션 스냅샷의 수단 기록용(LA 재시작 아이콘 분기) — 미지 케이스 디코딩 실패는 +/// 스냅샷 어댑터가 nil로 무해화한다. +public enum TransportMode: Equatable, Sendable, Codable { case walk case bus case subway diff --git a/Projects/Domain/Sources/Entities/LastRouteSessionDerivation.swift b/Projects/Domain/Sources/Entities/LastRouteSessionDerivation.swift new file mode 100644 index 0000000..544b1e8 --- /dev/null +++ b/Projects/Domain/Sources/Entities/LastRouteSessionDerivation.swift @@ -0,0 +1,38 @@ +import Foundation + +// 알람 세션이 경로에서 취하는 파생값 — 등록(스냅샷 저장)·LA 어댑터·홈이 같은 계산을 +// 봐야 하므로 Domain 순수 계산으로 둔다(이중 계산 금지, 미확정 #7 클라 임시안). +public extension LastRoute { + /// 알람 기준 시각에 반영하는 첫 도보 구간 시간(초) — legs의 **첫 `.walk` leg**의 + /// sectionTime. 도보 구간이 없으면 nil(호출자는 버퍼만 적용으로 폴백). + var firstWalkSectionSeconds: Int? { + legs.first(where: { $0.mode == .walk })?.sectionTime + } + + /// 막차 탑승 구간 — departureTime이 있는 첫 대중교통 구간, 없으면 첫 대중교통 구간. + var boardingLeg: TransportLeg? { + let transitLegs = legs.filter { $0.mode == .bus || $0.mode == .subway } + return transitLegs.first(where: { $0.departureTime != nil }) ?? transitLegs.first + } + + /// 노선 표시명 — LA 타이틀·스냅샷(재실행 복원)용. + /// 버스 routeName은 "타입:번호"(예: "간선:472") → "472번 버스", 지하철은 노선명 + /// 그대로(급행이면 " 급행"). 탑승 구간이 없으면 "막차". + var sessionDisplayName: String { + guard let leg = boardingLeg else { return "막차" } + switch leg.mode { + case .subway: + guard let name = leg.routeName else { return "지하철" } + return leg.isExpressSubway ? "\(name) 급행" : name + case .bus: + guard let routeName = leg.routeName else { return "버스" } + guard let colonIndex = routeName.firstIndex(of: ":") else { + return "\(routeName)번 버스" + } + let number = String(routeName[routeName.index(after: colonIndex)...]) + return "\(number)번 버스" + case .walk, .unknown: + return "막차" + } + } +} diff --git a/Projects/Domain/Sources/UseCases/CancelAlarmUseCase.swift b/Projects/Domain/Sources/UseCases/CancelAlarmUseCase.swift index f0a1cc2..2c6ac94 100644 --- a/Projects/Domain/Sources/UseCases/CancelAlarmUseCase.swift +++ b/Projects/Domain/Sources/UseCases/CancelAlarmUseCase.swift @@ -9,20 +9,26 @@ public struct DefaultCancelAlarmUseCase: CancelAlarmUseCase { private let scheduler: any AlarmScheduler /// Live Activity 포트 — nil이면 LA 없이 동작한다(Example·기존 콜사이트 호환). private let activityPort: (any LastTrainActivityPort)? + /// 세션 스냅샷(Phase 14) — 취소는 clear 시점이다. nil이면 영속화 없이 동작한다. + private let snapshotStore: (any AlarmSessionSnapshotStore)? public init( repository: any AlarmRepository, scheduler: any AlarmScheduler, - activityPort: (any LastTrainActivityPort)? = nil + activityPort: (any LastTrainActivityPort)? = nil, + snapshotStore: (any AlarmSessionSnapshotStore)? = nil ) { self.repository = repository self.scheduler = scheduler self.activityPort = activityPort + self.snapshotStore = snapshotStore } public func execute(lastRouteId: String) async throws { try await repository.cancel(lastRouteId: lastRouteId) await scheduler.cancelAlarm() + // 세션이 유저 의사로 끝났다 — 재실행 브리지(스냅샷)도 함께 지운다. + await snapshotStore?.clear() // 수명 정책: 알람 세션이 끝나면 LA도 끝낸다. 유저 취소는 실패 상태가 아니므로 // phase는 .active로 종료한다. end는 즉시 닫는 경로라 시각 값은 표시에 쓰이지 않는다. if let activityPort { diff --git a/Projects/Domain/Sources/UseCases/GetLastRouteDetailUseCase.swift b/Projects/Domain/Sources/UseCases/GetLastRouteDetailUseCase.swift new file mode 100644 index 0000000..c964daa --- /dev/null +++ b/Projects/Domain/Sources/UseCases/GetLastRouteDetailUseCase.swift @@ -0,0 +1,17 @@ +/// 경로 상세 재조회 (Phase 14 카드 복원) — 재실행 후 "알람은 있는데 무슨 경로인지 +/// 모르는" 상태를 해소한다. 홈은 alarmSynced 수신 시 카드가 없으면 이걸로 복원한다. +public protocol GetLastRouteDetailUseCase: Sendable { + func execute(routeId: String) async throws -> LastRoute +} + +public struct DefaultGetLastRouteDetailUseCase: GetLastRouteDetailUseCase { + private let repository: any LastRouteRepository + + public init(repository: any LastRouteRepository) { + self.repository = repository + } + + public func execute(routeId: String) async throws -> LastRoute { + try await repository.lastRoute(id: routeId) + } +} diff --git a/Projects/Domain/Sources/UseCases/RefreshAlarmUseCase.swift b/Projects/Domain/Sources/UseCases/RefreshAlarmUseCase.swift index 2c76034..2a604c5 100644 --- a/Projects/Domain/Sources/UseCases/RefreshAlarmUseCase.swift +++ b/Projects/Domain/Sources/UseCases/RefreshAlarmUseCase.swift @@ -7,25 +7,39 @@ public protocol RefreshAlarmUseCase: Sendable { public struct DefaultRefreshAlarmUseCase: RefreshAlarmUseCase { private let repository: any AlarmRepository private let scheduler: any AlarmScheduler + /// 도보 초의 출처(Phase 14) — refresh 응답에는 도보 정보가 없으므로 등록 시점 + /// 스냅샷에서 읽는다. nil이면 버퍼만 적용(등록 경로와 같은 폴백). + private let snapshotStore: (any AlarmSessionSnapshotStore)? private let now: @Sendable () -> Date public init( repository: any AlarmRepository, scheduler: any AlarmScheduler, + snapshotStore: (any AlarmSessionSnapshotStore)? = nil, now: @escaping @Sendable () -> Date = { Date() } ) { self.repository = repository self.scheduler = scheduler + self.snapshotStore = snapshotStore self.now = now } public func execute() async throws -> AlarmInfo { let info = try await repository.refresh() // 시각 변경 시(로컬 알람이 사라진 경우 포함) 재스케줄한다. - // 기대 발화 시각은 버퍼 반영값(AlarmTiming) — register와 동일한 기준으로 비교해야 - // 변경이 없어도 매 refresh마다 재스케줄되는 헛돎을 막는다. + // 기대 발화 시각은 register와 같은 기준(출발 − 도보 − 버퍼)으로 비교해야 + // 변경이 없어도 매 refresh마다 재스케줄되는 헛돎이 없다(이중 시각 금지). if let departure = info.departureTime { - let expectedFireDate = AlarmTiming.alarmFireDate(departureTime: departure) + let snapshot = await snapshotStore?.load() + // 스냅샷의 도보 초는 같은 세션(routeId 일치)일 때만 유효하다 — + // 서버가 다른 경로로 갈아탔으면 그 경로의 도보를 모른다(버퍼만 적용). + let firstWalkSeconds = snapshot?.info.lastRouteId == info.lastRouteId + ? snapshot?.firstWalkSeconds + : nil + let expectedFireDate = AlarmTiming.alarmFireDate( + departureTime: departure, + firstWalkSeconds: firstWalkSeconds + ) // 새 알람 시각이 이미 과거면 재스케줄하지 않는다 — 과거 fixed 스케줄은 AlarmKit이 // 거부해 refresh 전체를 실패시킬 수 있다. 이 경우의 인지는 갱신 성공 이후 // 훅의 즉시 최후통첩이 담당한다(정책 4 "알람 발화 후 변경"). diff --git a/Projects/Domain/Sources/UseCases/RegisterAlarmUseCase.swift b/Projects/Domain/Sources/UseCases/RegisterAlarmUseCase.swift index 8f2e7f7..129c996 100644 --- a/Projects/Domain/Sources/UseCases/RegisterAlarmUseCase.swift +++ b/Projects/Domain/Sources/UseCases/RegisterAlarmUseCase.swift @@ -1,3 +1,5 @@ +import Foundation + public protocol RegisterAlarmUseCase: Sendable { func execute(route: LastRoute) async throws } @@ -9,21 +11,38 @@ public struct DefaultRegisterAlarmUseCase: RegisterAlarmUseCase { private let activityPort: (any LastTrainActivityPort)? /// 로컬 노티 포트 — nil이면 알림 권한 요청 없이 동작한다(Example·기존 콜사이트 호환). private let notificationPort: (any LocalNotificationPort)? + /// 세션 스냅샷(Phase 14 재실행 브리지) — nil이면 영속화 없이 동작한다(Example 호환). + private let snapshotStore: (any AlarmSessionSnapshotStore)? + private let now: @Sendable () -> Date public init( repository: any AlarmRepository, scheduler: any AlarmScheduler, activityPort: (any LastTrainActivityPort)? = nil, - notificationPort: (any LocalNotificationPort)? = nil + notificationPort: (any LocalNotificationPort)? = nil, + snapshotStore: (any AlarmSessionSnapshotStore)? = nil, + now: @escaping @Sendable () -> Date = { Date() } ) { self.repository = repository self.scheduler = scheduler self.activityPort = activityPort self.notificationPort = notificationPort + self.snapshotStore = snapshotStore + self.now = now } public func execute(route: LastRoute) async throws { - // 권한 요청이 최초 진입점 — 거부면 서버 등록까지 전부 보류한다. + // 발화 시각(출발 − 도보 − 버퍼, 미확정 #7 클라 임시안)이 이미 과거면 시작조차 + // 하지 않는다 — 서버 등록이 성공한 뒤 로컬 스케줄(AlarmKit 과거 fixed 거부)이 + // 실패하는 서버/로컬 불일치의 사전 가드. 권한 팝업보다도 앞선다(죽은 경로에 + // 권한을 묻지 않는다). + let fireDate = AlarmTiming.alarmFireDate( + departureTime: route.departureTime, + firstWalkSeconds: route.firstWalkSectionSeconds + ) + guard fireDate > now() else { throw AlarmError.tooLate } + + // 권한 요청이 다음 진입점 — 거부면 서버 등록까지 전부 보류한다. guard await scheduler.requestAuthorization() else { throw AlarmError.permissionDenied } @@ -34,21 +53,30 @@ public struct DefaultRegisterAlarmUseCase: RegisterAlarmUseCase { } try await repository.register(lastRouteId: route.id) // 단일 알람 정책: 서버 등록이 성공한 뒤에만 로컬 알람을 교체한다. - // TODO: [미확정] 서버 계산 알람 시각 스펙 확정 전까지 막차 출발 시각 − 버퍼로 스케줄한다. try await scheduler.replaceAlarm( id: route.id, - fireDate: AlarmTiming.alarmFireDate(departureTime: route.departureTime), + fireDate: fireDate, title: AlarmSchedulingDefaults.title ) + let session = AlarmInfo( + lastRouteId: route.id, + departureTime: route.departureTime, + updatedAt: nil, // 등록 직후라 서버 재계산 값이 아직 없다 — refresh가 갱신한다. + isReal: true + ) + // 등록 성공 = 스냅샷 저장 시점(Phase 14) — 재실행 시 diff 기준·LA 재부착·카드 + // 복원의 재료. 도보 초·표시명·수단은 등록 시점 경로에서만 얻을 수 있다. + await snapshotStore?.save(AlarmSessionSnapshot( + info: session, + firstWalkSeconds: route.firstWalkSectionSeconds, + routeDisplayName: route.sessionDisplayName, + transportMode: route.boardingLeg?.mode, + acknowledged: false, + expired: false + )) // 수명 정책: 알람 등록(서버+로컬)이 전부 성공한 뒤에만 LA를 시작한다. // start는 throws가 아니므로 LA 실패가 알람 등록을 실패시킬 수 없다. if let activityPort { - let session = AlarmInfo( - lastRouteId: route.id, - departureTime: route.departureTime, - updatedAt: nil, // 등록 직후라 서버 재계산 값이 아직 없다 — refresh가 갱신한다. - isReal: true - ) await activityPort.start(session: session, route: route) } // 알림 권한 요청 — [미확정 #8 임시] 알람 등록 성공 직후가 유일한 요청 시점. diff --git a/Projects/Domain/Tests/AlarmSessionSnapshotTests.swift b/Projects/Domain/Tests/AlarmSessionSnapshotTests.swift new file mode 100644 index 0000000..fc85562 --- /dev/null +++ b/Projects/Domain/Tests/AlarmSessionSnapshotTests.swift @@ -0,0 +1,65 @@ +@testable import Domain +import Foundation +import Testing + +struct AlarmSessionSnapshotTests { + private let snapshot = AlarmSessionSnapshot( + info: AlarmInfo( + lastRouteId: "route-1", + departureTime: Date(timeIntervalSince1970: 1_756_000_000), + updatedAt: Date(timeIntervalSince1970: 1_755_990_000), + isReal: true + ), + firstWalkSeconds: 120, + routeDisplayName: "6411번 버스", + transportMode: .bus, + acknowledged: false, + expired: false + ) + + @Test + func roundTripsCodable() throws { + let data = try JSONEncoder().encode(snapshot) + let decoded = try JSONDecoder().decode(AlarmSessionSnapshot.self, from: data) + #expect(decoded == snapshot) + } + + @Test + func nilOptionalFields_roundTripCodable() throws { + let sparse = AlarmSessionSnapshot( + info: AlarmInfo(lastRouteId: "r", departureTime: nil, updatedAt: nil, isReal: false), + firstWalkSeconds: nil, + routeDisplayName: "", + transportMode: nil, + acknowledged: true, + expired: true + ) + let data = try JSONEncoder().encode(sparse) + let decoded = try JSONDecoder().decode(AlarmSessionSnapshot.self, from: data) + #expect(decoded == sparse) + #expect(decoded.firstWalkSeconds == nil) + #expect(decoded.transportMode == nil) + } + + @Test + func updating_replacesOnlyGivenFields() { + let newInfo = AlarmInfo( + lastRouteId: "route-1", + departureTime: Date(timeIntervalSince1970: 1_756_000_600), + updatedAt: nil, + isReal: true + ) + let updated = snapshot.updating(info: newInfo, acknowledged: true) + // 세션 사실(도보·표시명·수단)은 유지된다. + #expect(updated.info == newInfo) + #expect(updated.acknowledged) + #expect(!updated.expired) + #expect(updated.firstWalkSeconds == 120) + #expect(updated.routeDisplayName == "6411번 버스") + #expect(updated.transportMode == .bus) + + let tombstone = snapshot.updating(expired: true) + #expect(tombstone.expired) + #expect(tombstone.info == snapshot.info) + } +} diff --git a/Projects/Domain/Tests/AlarmTimingTests.swift b/Projects/Domain/Tests/AlarmTimingTests.swift index a5a9b02..b7bceef 100644 --- a/Projects/Domain/Tests/AlarmTimingTests.swift +++ b/Projects/Domain/Tests/AlarmTimingTests.swift @@ -4,9 +4,27 @@ import Testing struct AlarmTimingTests { @Test - func alarmFireDate_isDepartureMinusBuffer() { + func alarmFireDate_withoutWalk_isDepartureMinusBuffer() { let departure = Date(timeIntervalSince1970: 1_000) - #expect(AlarmTiming.alarmFireDate(departureTime: departure) == Date(timeIntervalSince1970: 820)) + #expect( + AlarmTiming.alarmFireDate(departureTime: departure, firstWalkSeconds: nil) + == Date(timeIntervalSince1970: 820) + ) + } + + @Test + func alarmFireDate_withWalk_subtractsWalkAndBuffer() { + // Phase 14 (미확정 #7 클라 임시안): 기준 시각 = 출발 − 도보 − 버퍼. + let departure = Date(timeIntervalSince1970: 1_000) + #expect( + AlarmTiming.alarmFireDate(departureTime: departure, firstWalkSeconds: 120) + == Date(timeIntervalSince1970: 700) + ) + // 0초 도보는 없음과 동일하다. + #expect( + AlarmTiming.alarmFireDate(departureTime: departure, firstWalkSeconds: 0) + == Date(timeIntervalSince1970: 820) + ) } @Test diff --git a/Projects/Domain/Tests/DefaultCancelAlarmUseCaseTests.swift b/Projects/Domain/Tests/DefaultCancelAlarmUseCaseTests.swift index 2b23a32..ad53443 100644 --- a/Projects/Domain/Tests/DefaultCancelAlarmUseCaseTests.swift +++ b/Projects/Domain/Tests/DefaultCancelAlarmUseCaseTests.swift @@ -44,6 +44,14 @@ private struct SpyAlarmScheduler: AlarmScheduler { func scheduledFireDate() async -> Date? { nil } } +private actor SpySnapshotStore: AlarmSessionSnapshotStore { + private(set) var clearCount = 0 + + func load() async -> AlarmSessionSnapshot? { nil } + func save(_ snapshot: AlarmSessionSnapshot) async {} + func clear() async { clearCount += 1 } +} + struct DefaultCancelAlarmUseCaseTests { @Test func execute_serverCancelSucceeds_thenCancelsLocalAlarm() async throws { @@ -68,4 +76,35 @@ struct DefaultCancelAlarmUseCaseTests { } #expect(await log.events == ["cancel:route-1"]) } + + // MARK: - 세션 스냅샷 (Phase 14) + + @Test + func execute_success_clearsSnapshot() async throws { + let log = CallLog() + let store = SpySnapshotStore() + let sut = DefaultCancelAlarmUseCase( + repository: SpyAlarmRepository(log: log), + scheduler: SpyAlarmScheduler(log: log), + snapshotStore: store + ) + try await sut.execute(lastRouteId: "route-1") + #expect(await store.clearCount == 1) + } + + @Test + func execute_serverCancelFails_keepsSnapshot() async { + // 세션은 아직 살아 있다 — 실패한 취소가 재실행 브리지를 지우면 안 된다. + let log = CallLog() + let store = SpySnapshotStore() + let sut = DefaultCancelAlarmUseCase( + repository: SpyAlarmRepository(log: log, cancelError: StubError()), + scheduler: SpyAlarmScheduler(log: log), + snapshotStore: store + ) + await #expect(throws: StubError.self) { + try await sut.execute(lastRouteId: "route-1") + } + #expect(await store.clearCount == 0) + } } diff --git a/Projects/Domain/Tests/DefaultGetLastRouteDetailUseCaseTests.swift b/Projects/Domain/Tests/DefaultGetLastRouteDetailUseCaseTests.swift new file mode 100644 index 0000000..ba4007c --- /dev/null +++ b/Projects/Domain/Tests/DefaultGetLastRouteDetailUseCaseTests.swift @@ -0,0 +1,40 @@ +@testable import Domain +import Foundation +import Testing + +private struct StubError: Error {} + +private struct StubLastRouteRepository: LastRouteRepository { + var result: Result + + func searchLastRoutes(start: Coordinate, end: Coordinate) async throws -> [LastRoute] { [] } + + func lastRoute(id: String) async throws -> LastRoute { + try result.get() + } +} + +private let fixture = LastRoute( + id: "route-1", departureTime: Date(timeIntervalSince1970: 1_000), totalTime: 0, + totalWalkTime: 0, transferCount: 0, totalDistance: 0, totalWalkDistance: 0, legs: [] +) + +struct DefaultGetLastRouteDetailUseCaseTests { + @Test + func execute_returnsRepositoryDetail() async throws { + let sut = DefaultGetLastRouteDetailUseCase( + repository: StubLastRouteRepository(result: .success(fixture)) + ) + #expect(try await sut.execute(routeId: "route-1") == fixture) + } + + @Test + func execute_repositoryFails_rethrows() async { + let sut = DefaultGetLastRouteDetailUseCase( + repository: StubLastRouteRepository(result: .failure(StubError())) + ) + await #expect(throws: StubError.self) { + _ = try await sut.execute(routeId: "route-1") + } + } +} diff --git a/Projects/Domain/Tests/DefaultRefreshAlarmUseCaseTests.swift b/Projects/Domain/Tests/DefaultRefreshAlarmUseCaseTests.swift index ec6243d..dd8979a 100644 --- a/Projects/Domain/Tests/DefaultRefreshAlarmUseCaseTests.swift +++ b/Projects/Domain/Tests/DefaultRefreshAlarmUseCaseTests.swift @@ -51,6 +51,25 @@ private func makeInfo(departureTime: Date?) -> AlarmInfo { AlarmInfo(lastRouteId: "route-1", departureTime: departureTime, updatedAt: nil, isReal: true) } +private struct StubSnapshotStore: AlarmSessionSnapshotStore { + let snapshot: AlarmSessionSnapshot? + + func load() async -> AlarmSessionSnapshot? { snapshot } + func save(_ snapshot: AlarmSessionSnapshot) async {} + func clear() async {} +} + +private func makeSnapshot(routeId: String, firstWalkSeconds: Int?) -> AlarmSessionSnapshot { + AlarmSessionSnapshot( + info: AlarmInfo(lastRouteId: routeId, departureTime: nil, updatedAt: nil, isReal: true), + firstWalkSeconds: firstWalkSeconds, + routeDisplayName: "6411번 버스", + transportMode: .bus, + acknowledged: false, + expired: false + ) +} + /// 픽스처가 1970 부근의 작은 epoch를 쓰므로, "기대 발화 시각이 미래일 때만 재스케줄" 가드를 /// 통과시키려면 now도 그보다 이른 고정값으로 주입한다. private let fixedNow: @Sendable () -> Date = { Date(timeIntervalSince1970: 0) } @@ -78,7 +97,12 @@ struct DefaultRefreshAlarmUseCaseTests { let sut = DefaultRefreshAlarmUseCase( repository: StubAlarmRepository(log: log, refreshResult: .success(makeInfo(departureTime: departure))), // 로컬 알람은 버퍼 반영값으로 스케줄돼 있으므로, 같은 기준으로 비교해야 헛재스케줄이 없다. - scheduler: SpyAlarmScheduler(log: log, scheduledDate: AlarmTiming.alarmFireDate(departureTime: departure)), + scheduler: SpyAlarmScheduler( + log: log, + scheduledDate: AlarmTiming.alarmFireDate( + departureTime: departure, firstWalkSeconds: nil + ) + ), now: fixedNow ) _ = try await sut.execute() @@ -127,6 +151,67 @@ struct DefaultRefreshAlarmUseCaseTests { #expect(await log.events == ["refresh"]) } + // MARK: - 도보 반영 (Phase 14 — 스냅샷이 도보 초의 출처) + + @Test + func execute_snapshotWalkSeconds_rescheduleUsesWalkAwareFireDate() async throws { + let log = CallLog() + let departure = Date(timeIntervalSince1970: 2_000) + let sut = DefaultRefreshAlarmUseCase( + repository: StubAlarmRepository( + log: log, refreshResult: .success(makeInfo(departureTime: departure)) + ), + scheduler: SpyAlarmScheduler(log: log, scheduledDate: nil), + snapshotStore: StubSnapshotStore( + snapshot: makeSnapshot(routeId: "route-1", firstWalkSeconds: 120) + ), + now: fixedNow + ) + _ = try await sut.execute() + // 기대 발화 시각 = 2000 − 120(도보) − 180(버퍼) = 1700 — 등록 경로와 같은 기준. + #expect(await log.events == ["refresh", "scheduledFireDate", "replaceAlarm:route-1@1700"]) + } + + @Test + func execute_snapshotWalkMatchingSchedule_doesNotReschedule() async throws { + // 로컬 알람이 이미 도보 반영값으로 걸려 있으면 재스케줄하지 않는다(헛돎 금지). + let log = CallLog() + let departure = Date(timeIntervalSince1970: 2_000) + let sut = DefaultRefreshAlarmUseCase( + repository: StubAlarmRepository( + log: log, refreshResult: .success(makeInfo(departureTime: departure)) + ), + scheduler: SpyAlarmScheduler( + log: log, scheduledDate: Date(timeIntervalSince1970: 1_700) + ), + snapshotStore: StubSnapshotStore( + snapshot: makeSnapshot(routeId: "route-1", firstWalkSeconds: 120) + ), + now: fixedNow + ) + _ = try await sut.execute() + #expect(await log.events == ["refresh", "scheduledFireDate"]) + } + + @Test + func execute_snapshotForDifferentRoute_ignoresItsWalkSeconds() async throws { + // 서버가 다른 경로로 갈아탔으면 옛 경로의 도보 초는 무효 — 버퍼만 적용한다. + let log = CallLog() + let departure = Date(timeIntervalSince1970: 2_000) + let sut = DefaultRefreshAlarmUseCase( + repository: StubAlarmRepository( + log: log, refreshResult: .success(makeInfo(departureTime: departure)) + ), + scheduler: SpyAlarmScheduler(log: log, scheduledDate: nil), + snapshotStore: StubSnapshotStore( + snapshot: makeSnapshot(routeId: "other-route", firstWalkSeconds: 120) + ), + now: fixedNow + ) + _ = try await sut.execute() + #expect(await log.events == ["refresh", "scheduledFireDate", "replaceAlarm:route-1@1820"]) + } + @Test func execute_refreshFails_throwsWithoutScheduling() async { let log = CallLog() diff --git a/Projects/Domain/Tests/DefaultRegisterAlarmUseCaseTests.swift b/Projects/Domain/Tests/DefaultRegisterAlarmUseCaseTests.swift index a313622..6a27986 100644 --- a/Projects/Domain/Tests/DefaultRegisterAlarmUseCaseTests.swift +++ b/Projects/Domain/Tests/DefaultRegisterAlarmUseCaseTests.swift @@ -50,8 +50,26 @@ private struct SpyAlarmScheduler: AlarmScheduler { func scheduledFireDate() async -> Date? { nil } } +private actor SpySnapshotStore: AlarmSessionSnapshotStore { + private(set) var saved: [AlarmSessionSnapshot] = [] + private(set) var clearCount = 0 + var stored: AlarmSessionSnapshot? + + func load() async -> AlarmSessionSnapshot? { stored } + + func save(_ snapshot: AlarmSessionSnapshot) async { + saved.append(snapshot) + stored = snapshot + } + + func clear() async { + clearCount += 1 + stored = nil + } +} + private extension LastRoute { - static func fixture(id: String) -> LastRoute { + static func fixture(id: String, legs: [TransportLeg] = []) -> LastRoute { LastRoute( id: id, departureTime: Date(timeIntervalSince1970: 1_000), @@ -60,11 +78,33 @@ private extension LastRoute { transferCount: 0, totalDistance: 0, totalWalkDistance: 0, - legs: [] + legs: legs ) } } +private func walkLeg(sectionTime: Int) -> TransportLeg { + TransportLeg( + mode: .walk, sectionTime: sectionTime, distance: 100, departureTime: nil, + routeName: nil, lineType: nil, start: nil, end: nil, + subwayFinalStation: nil, subwayDirection: nil, + isExpressSubway: false, isLastSubway: false + ) +} + +private func busLeg(routeName: String) -> TransportLeg { + TransportLeg( + mode: .bus, sectionTime: 900, distance: 4_000, departureTime: nil, + routeName: routeName, lineType: "11", start: nil, end: nil, + subwayFinalStation: nil, subwayDirection: nil, + isExpressSubway: false, isLastSubway: false + ) +} + +/// 픽스처가 1970 부근의 작은 epoch를 쓰므로, tooLate 사전 가드(발화 시각 > now)를 +/// 통과시키려면 now도 그보다 이른 고정값으로 주입한다. +private let fixedNow: @Sendable () -> Date = { Date(timeIntervalSince1970: 0) } + struct DefaultRegisterAlarmUseCaseTests { @Test func execute_existingAlarm_cancelsThenRegistersThenSchedules() async throws { @@ -72,7 +112,8 @@ struct DefaultRegisterAlarmUseCaseTests { let existing = AlarmInfo(lastRouteId: "old", departureTime: nil, updatedAt: nil, isReal: false) let sut = DefaultRegisterAlarmUseCase( repository: SpyAlarmRepository(log: log, existing: existing), - scheduler: SpyAlarmScheduler(log: log) + scheduler: SpyAlarmScheduler(log: log), + now: fixedNow ) try await sut.execute(route: .fixture(id: "new")) // 스케줄 시각은 버퍼 반영값: 출발 1000 − 180 = 820 @@ -84,18 +125,33 @@ struct DefaultRegisterAlarmUseCaseTests { let log = CallLog() let sut = DefaultRegisterAlarmUseCase( repository: SpyAlarmRepository(log: log), - scheduler: SpyAlarmScheduler(log: log) + scheduler: SpyAlarmScheduler(log: log), + now: fixedNow ) try await sut.execute(route: .fixture(id: "new")) #expect(await log.events == ["auth:true", "refresh", "register:new", "replaceAlarm:new@820"]) } + @Test + func execute_routeWithWalkLeg_schedulesWalkAwareFireDate() async throws { + // Phase 14: 발화 시각 = 출발 − 첫 도보 − 버퍼 = 1000 − 120 − 180 = 700. + let log = CallLog() + let sut = DefaultRegisterAlarmUseCase( + repository: SpyAlarmRepository(log: log), + scheduler: SpyAlarmScheduler(log: log), + now: fixedNow + ) + try await sut.execute(route: .fixture(id: "new", legs: [walkLeg(sectionTime: 120)])) + #expect(await log.events == ["auth:true", "refresh", "register:new", "replaceAlarm:new@700"]) + } + @Test func execute_serverRegisterFails_doesNotSchedule() async { let log = CallLog() let sut = DefaultRegisterAlarmUseCase( repository: SpyAlarmRepository(log: log, registerError: StubError()), - scheduler: SpyAlarmScheduler(log: log) + scheduler: SpyAlarmScheduler(log: log), + now: fixedNow ) await #expect(throws: StubError.self) { try await sut.execute(route: .fixture(id: "new")) @@ -108,7 +164,8 @@ struct DefaultRegisterAlarmUseCaseTests { let log = CallLog() let sut = DefaultRegisterAlarmUseCase( repository: SpyAlarmRepository(log: log), - scheduler: SpyAlarmScheduler(log: log, authorizationGranted: false) + scheduler: SpyAlarmScheduler(log: log, authorizationGranted: false), + now: fixedNow ) await #expect(throws: AlarmError.permissionDenied) { try await sut.execute(route: .fixture(id: "new")) @@ -116,4 +173,84 @@ struct DefaultRegisterAlarmUseCaseTests { // 권한 거부 시 서버 등록·삭제·로컬 스케줄 어디에도 도달하면 안 된다. #expect(await log.events == ["auth:false"]) } + + // MARK: - tooLate 사전 가드 (Phase 14) + + @Test + func execute_fireDateAlreadyPast_throwsTooLateBeforeAnySideEffect() async { + let log = CallLog() + let store = SpySnapshotStore() + // 발화 시각 820 ≤ now 820 — 경계 포함 과거로 본다. + let sut = DefaultRegisterAlarmUseCase( + repository: SpyAlarmRepository(log: log), + scheduler: SpyAlarmScheduler(log: log), + snapshotStore: store, + now: { Date(timeIntervalSince1970: 820) } + ) + await #expect(throws: AlarmError.tooLate) { + try await sut.execute(route: .fixture(id: "new")) + } + // 권한 팝업·서버 등록·스케줄·스냅샷 어디에도 도달하지 않는다(사전 가드). + #expect(await log.events == []) + #expect(await store.saved.isEmpty) + } + + @Test + func execute_walkMakesFireDatePast_throwsTooLate() async { + // 도보 반영으로 발화 시각(700)이 now(750)보다 과거가 되는 경우도 가드에 걸린다. + let log = CallLog() + let sut = DefaultRegisterAlarmUseCase( + repository: SpyAlarmRepository(log: log), + scheduler: SpyAlarmScheduler(log: log), + now: { Date(timeIntervalSince1970: 750) } + ) + await #expect(throws: AlarmError.tooLate) { + try await sut.execute(route: .fixture(id: "new", legs: [walkLeg(sectionTime: 120)])) + } + #expect(await log.events == []) + } + + // MARK: - 세션 스냅샷 (Phase 14) + + @Test + func execute_success_savesSnapshotWithRouteFacts() async throws { + let log = CallLog() + let store = SpySnapshotStore() + let route = LastRoute.fixture( + id: "new", legs: [walkLeg(sectionTime: 120), busLeg(routeName: "간선:6411")] + ) + let sut = DefaultRegisterAlarmUseCase( + repository: SpyAlarmRepository(log: log), + scheduler: SpyAlarmScheduler(log: log), + snapshotStore: store, + now: fixedNow + ) + try await sut.execute(route: route) + + let saved = await store.saved + #expect(saved.count == 1) + #expect(saved.first?.info.lastRouteId == "new") + #expect(saved.first?.info.departureTime == route.departureTime) + #expect(saved.first?.firstWalkSeconds == 120) + #expect(saved.first?.routeDisplayName == "6411번 버스") + #expect(saved.first?.transportMode == .bus) + #expect(saved.first?.acknowledged == false) + #expect(saved.first?.expired == false) + } + + @Test + func execute_serverRegisterFails_doesNotSaveSnapshot() async { + let log = CallLog() + let store = SpySnapshotStore() + let sut = DefaultRegisterAlarmUseCase( + repository: SpyAlarmRepository(log: log, registerError: StubError()), + scheduler: SpyAlarmScheduler(log: log), + snapshotStore: store, + now: fixedNow + ) + await #expect(throws: StubError.self) { + try await sut.execute(route: .fixture(id: "new")) + } + #expect(await store.saved.isEmpty) + } } diff --git a/Projects/Domain/Tests/LastRouteSessionDerivationTests.swift b/Projects/Domain/Tests/LastRouteSessionDerivationTests.swift new file mode 100644 index 0000000..384eb13 --- /dev/null +++ b/Projects/Domain/Tests/LastRouteSessionDerivationTests.swift @@ -0,0 +1,99 @@ +@testable import Domain +import Foundation +import Testing + +private func leg( + mode: TransportMode, + sectionTime: Int = 600, + departureTime: Date? = nil, + routeName: String? = nil, + isExpressSubway: Bool = false +) -> TransportLeg { + TransportLeg( + mode: mode, sectionTime: sectionTime, distance: 100, departureTime: departureTime, + routeName: routeName, lineType: nil, start: nil, end: nil, + subwayFinalStation: nil, subwayDirection: nil, + isExpressSubway: isExpressSubway, isLastSubway: false + ) +} + +private func route(legs: [TransportLeg]) -> LastRoute { + LastRoute( + id: "r", departureTime: Date(timeIntervalSince1970: 1_000), totalTime: 0, + totalWalkTime: 0, transferCount: 0, totalDistance: 0, totalWalkDistance: 0, legs: legs + ) +} + +struct LastRouteSessionDerivationTests { + @Test + func firstWalkSectionSeconds_takesFirstWalkLegOnly() { + // 첫 .walk leg의 sectionTime — 뒤쪽 도보(환승·하차)는 반영하지 않는다. + let sut = route(legs: [ + leg(mode: .walk, sectionTime: 120), + leg(mode: .subway, routeName: "2호선"), + leg(mode: .walk, sectionTime: 300), + ]) + #expect(sut.firstWalkSectionSeconds == 120) + } + + @Test + func firstWalkSectionSeconds_noWalkLeg_isNil() { + #expect(route(legs: [leg(mode: .bus, routeName: "간선:6411")]).firstWalkSectionSeconds == nil) + #expect(route(legs: []).firstWalkSectionSeconds == nil) + } + + @Test + func firstWalkSectionSeconds_walkAfterTransit_stillCounts() { + // "첫 .walk leg"는 위치와 무관하게 목록에서 처음 나오는 도보 구간이다 — + // 문서 명세(route.legs의 첫 .walk leg sectionTime) 그대로. + let sut = route(legs: [ + leg(mode: .subway, routeName: "2호선"), + leg(mode: .walk, sectionTime: 240), + ]) + #expect(sut.firstWalkSectionSeconds == 240) + } + + @Test + func boardingLeg_prefersLegWithDepartureTime() { + let departure = Date(timeIntervalSince1970: 1_000) + let sut = route(legs: [ + leg(mode: .walk), + leg(mode: .bus, routeName: "간선:472"), + leg(mode: .subway, departureTime: departure, routeName: "9호선"), + ]) + #expect(sut.boardingLeg?.routeName == "9호선") + } + + @Test + func boardingLeg_fallsBackToFirstTransitLeg() { + let sut = route(legs: [ + leg(mode: .walk), + leg(mode: .bus, routeName: "간선:472"), + leg(mode: .subway, routeName: "9호선"), + ]) + #expect(sut.boardingLeg?.routeName == "간선:472") + } + + @Test + func sessionDisplayName_busParsesTypePrefix() { + #expect(route(legs: [leg(mode: .bus, routeName: "간선:6411")]).sessionDisplayName == "6411번 버스") + #expect(route(legs: [leg(mode: .bus, routeName: "472")]).sessionDisplayName == "472번 버스") + #expect(route(legs: [leg(mode: .bus)]).sessionDisplayName == "버스") + } + + @Test + func sessionDisplayName_subwayKeepsLineName() { + #expect(route(legs: [leg(mode: .subway, routeName: "2호선")]).sessionDisplayName == "2호선") + #expect( + route(legs: [leg(mode: .subway, routeName: "9호선", isExpressSubway: true)]) + .sessionDisplayName == "9호선 급행" + ) + #expect(route(legs: [leg(mode: .subway)]).sessionDisplayName == "지하철") + } + + @Test + func sessionDisplayName_noTransitLeg_fallsBack() { + #expect(route(legs: [leg(mode: .walk)]).sessionDisplayName == "막차") + #expect(route(legs: []).sessionDisplayName == "막차") + } +} diff --git a/Projects/Domain/Tests/LastTrainActivityLifecycleTests.swift b/Projects/Domain/Tests/LastTrainActivityLifecycleTests.swift index deb808c..eb26ece 100644 --- a/Projects/Domain/Tests/LastTrainActivityLifecycleTests.swift +++ b/Projects/Domain/Tests/LastTrainActivityLifecycleTests.swift @@ -91,6 +91,10 @@ private struct SpyLocalNotificationPort: LocalNotificationPort { } } +/// 픽스처가 1970 부근의 작은 epoch를 쓰므로, tooLate 사전 가드(발화 시각 > now)를 +/// 통과시키려면 now도 그보다 이른 고정값으로 주입한다. +private let fixedNow: @Sendable () -> Date = { Date(timeIntervalSince1970: 0) } + private extension LastRoute { static func fixture(id: String) -> LastRoute { LastRoute( @@ -115,7 +119,8 @@ struct LastTrainActivityLifecycleTests { let sut = DefaultRegisterAlarmUseCase( repository: SpyAlarmRepository(log: log), scheduler: SpyAlarmScheduler(log: log), - activityPort: SpyActivityPort(log: log, box: box) + activityPort: SpyActivityPort(log: log, box: box), + now: fixedNow ) try await sut.execute(route: route) // 순서 계약: 알람(서버 등록 → 로컬 교체)이 항상 LA 시작에 선행한다. @@ -135,7 +140,8 @@ struct LastTrainActivityLifecycleTests { let sut = DefaultRegisterAlarmUseCase( repository: SpyAlarmRepository(log: log, registerError: StubError()), scheduler: SpyAlarmScheduler(log: log), - activityPort: SpyActivityPort(log: log, box: box) + activityPort: SpyActivityPort(log: log, box: box), + now: fixedNow ) await #expect(throws: StubError.self) { try await sut.execute(route: .fixture(id: "new")) @@ -152,7 +158,8 @@ struct LastTrainActivityLifecycleTests { let sut = DefaultRegisterAlarmUseCase( repository: SpyAlarmRepository(log: log), scheduler: SpyAlarmScheduler(log: log, authorizationGranted: false), - activityPort: SpyActivityPort(log: log, box: box) + activityPort: SpyActivityPort(log: log, box: box), + now: fixedNow ) await #expect(throws: AlarmError.permissionDenied) { try await sut.execute(route: .fixture(id: "new")) @@ -169,7 +176,8 @@ struct LastTrainActivityLifecycleTests { repository: SpyAlarmRepository(log: log), scheduler: SpyAlarmScheduler(log: log), activityPort: SpyActivityPort(log: log, box: box), - notificationPort: SpyLocalNotificationPort(log: log) + notificationPort: SpyLocalNotificationPort(log: log), + now: fixedNow ) try await sut.execute(route: .fixture(id: "new")) // 순서 계약: 알림 권한 요청은 흐름의 맨 끝 — LA 시작 뒤에 정확히 1회. @@ -186,7 +194,8 @@ struct LastTrainActivityLifecycleTests { repository: SpyAlarmRepository(log: log, registerError: StubError()), scheduler: SpyAlarmScheduler(log: log), activityPort: SpyActivityPort(log: log, box: box), - notificationPort: SpyLocalNotificationPort(log: log) + notificationPort: SpyLocalNotificationPort(log: log), + now: fixedNow ) await #expect(throws: StubError.self) { try await sut.execute(route: .fixture(id: "new")) @@ -203,7 +212,8 @@ struct LastTrainActivityLifecycleTests { repository: SpyAlarmRepository(log: log), scheduler: SpyAlarmScheduler(log: log, authorizationGranted: false), activityPort: SpyActivityPort(log: log, box: box), - notificationPort: SpyLocalNotificationPort(log: log) + notificationPort: SpyLocalNotificationPort(log: log), + now: fixedNow ) await #expect(throws: AlarmError.permissionDenied) { try await sut.execute(route: .fixture(id: "new")) diff --git a/Projects/Feature/Home/Example/ExampleApp.swift b/Projects/Feature/Home/Example/ExampleApp.swift index 3102c72..0b35925 100644 --- a/Projects/Feature/Home/Example/ExampleApp.swift +++ b/Projects/Feature/Home/Example/ExampleApp.swift @@ -41,6 +41,7 @@ final class SceneDelegate: UIResponder, UIWindowSceneDelegate { cancelAlarmUseCase: PreviewCancelAlarmUseCase(), observeAlarmUseCase: PreviewObserveAlarmUseCase(), observeAlarmChangeUseCase: PreviewObserveAlarmChangeUseCase(), + getLastRouteDetailUseCase: PreviewGetLastRouteDetailUseCase(), searchCoordinatorBuildable: PreviewSearchCoordinatorBuildable() ) let coordinator = container.makeHomeCoordinator(navigationController: navigationController) @@ -96,6 +97,15 @@ struct PreviewObserveAlarmChangeUseCase: ObserveAlarmChangeUseCase { } } +/// 재실행 카드 복원 경로 스텁 — 동기화 이벤트가 없어 호출되지 않지만, 호출돼도 +/// canned 경로를 돌려줘 플로우가 성립한다. +struct PreviewGetLastRouteDetailUseCase: GetLastRouteDetailUseCase { + func execute(routeId: String) async throws -> LastRoute { + try? await Task.sleep(for: .milliseconds(300)) + return PreviewSearchCoordinator.makeCannedRoute() + } +} + /// 검색 플로우 스텁: 화면 전환 없이 canned 경로를 즉시 반환한다. /// 실제 검색 UX 시연은 SearchFeatureExample이 담당한다. struct PreviewSearchCoordinatorBuildable: SearchCoordinatorBuildable { @@ -122,7 +132,8 @@ final class PreviewSearchCoordinator: Coordinator { finish() } - private static func makeCannedRoute() -> LastRoute { + // nonisolated: 상세 재조회 스텁(nonisolated async)에서도 공유한다. + nonisolated static func makeCannedRoute() -> LastRoute { let departure = Date().addingTimeInterval(42 * 60) return LastRoute( id: "preview-route", diff --git a/Projects/Feature/Home/Sources/HomeDIContainer.swift b/Projects/Feature/Home/Sources/HomeDIContainer.swift index 4d86076..5cfdc10 100644 --- a/Projects/Feature/Home/Sources/HomeDIContainer.swift +++ b/Projects/Feature/Home/Sources/HomeDIContainer.swift @@ -14,6 +14,7 @@ public final class HomeDIContainer: HomeCoordinatorBuildable { private let cancelAlarmUseCase: any CancelAlarmUseCase private let observeAlarmUseCase: any ObserveAlarmUseCase private let observeAlarmChangeUseCase: any ObserveAlarmChangeUseCase + private let getLastRouteDetailUseCase: any GetLastRouteDetailUseCase private let searchCoordinatorBuildable: any SearchCoordinatorBuildable public init( @@ -23,6 +24,7 @@ public final class HomeDIContainer: HomeCoordinatorBuildable { cancelAlarmUseCase: any CancelAlarmUseCase, observeAlarmUseCase: any ObserveAlarmUseCase, observeAlarmChangeUseCase: any ObserveAlarmChangeUseCase, + getLastRouteDetailUseCase: any GetLastRouteDetailUseCase, searchCoordinatorBuildable: any SearchCoordinatorBuildable ) { self.getCurrentLocationUseCase = getCurrentLocationUseCase @@ -31,6 +33,7 @@ public final class HomeDIContainer: HomeCoordinatorBuildable { self.cancelAlarmUseCase = cancelAlarmUseCase self.observeAlarmUseCase = observeAlarmUseCase self.observeAlarmChangeUseCase = observeAlarmChangeUseCase + self.getLastRouteDetailUseCase = getLastRouteDetailUseCase self.searchCoordinatorBuildable = searchCoordinatorBuildable } @@ -47,7 +50,8 @@ public final class HomeDIContainer: HomeCoordinatorBuildable { registerAlarmUseCase: registerAlarmUseCase, cancelAlarmUseCase: cancelAlarmUseCase, observeAlarmUseCase: observeAlarmUseCase, - observeAlarmChangeUseCase: observeAlarmChangeUseCase + observeAlarmChangeUseCase: observeAlarmChangeUseCase, + getLastRouteDetailUseCase: getLastRouteDetailUseCase ) viewModel.onSearchRequested = onSearchRequested return HomeViewController(viewModel: viewModel) diff --git a/Projects/Feature/Home/Sources/HomeViewController.swift b/Projects/Feature/Home/Sources/HomeViewController.swift index 9e1e005..bb7ff40 100644 --- a/Projects/Feature/Home/Sources/HomeViewController.swift +++ b/Projects/Feature/Home/Sources/HomeViewController.swift @@ -220,6 +220,8 @@ final class HomeViewController: UIViewController { ) case .alarmRegisterFailed: DSToast.show("알람 등록에 실패했어요. 다시 시도해 주세요.", in: view) + case .alarmTooLate: + DSToast.show("이미 출발 시간이 지난 경로예요", in: view) case .alarmCancelFailed: DSToast.show("알람 해제에 실패했어요. 다시 시도해 주세요.", in: view) case let .lastTrainAdvanced(minutes): diff --git a/Projects/Feature/Home/Sources/HomeViewModel.swift b/Projects/Feature/Home/Sources/HomeViewModel.swift index db9bcb1..01af5d6 100644 --- a/Projects/Feature/Home/Sources/HomeViewModel.swift +++ b/Projects/Feature/Home/Sources/HomeViewModel.swift @@ -40,6 +40,8 @@ final class HomeViewModel { case alarmPermissionNeeded case alarmRegisterFailed case alarmCancelFailed + /// 발화 시각이 이미 과거인 경로의 등록 시도(사전 가드, Phase 14) — 서버 등록 전에 차단됐다. + case alarmTooLate /// 포그라운드 인앱 채널: 막차가 당겨졌다는 판정 — VC가 토스트 + 배너 강조로 표출한다. case lastTrainAdvanced(minutes: Int) /// 이미 못 타는 앞당김(actionable=false) — 배너는 실패 문구로 고정되고 원샷 안내만 나간다. @@ -64,6 +66,7 @@ final class HomeViewModel { private let cancelAlarmUseCase: any CancelAlarmUseCase private let observeAlarmUseCase: any ObserveAlarmUseCase private let observeAlarmChangeUseCase: any ObserveAlarmChangeUseCase + private let getLastRouteDetailUseCase: any GetLastRouteDetailUseCase private let now: @Sendable () -> Date private let bannerTickInterval: Duration @@ -75,6 +78,7 @@ final class HomeViewModel { private var observeTask: Task? private var changeTask: Task? private var bannerTask: Task? + private var restoreCardTask: Task? init( getCurrentLocationUseCase: any GetCurrentLocationUseCase, @@ -83,6 +87,7 @@ final class HomeViewModel { cancelAlarmUseCase: any CancelAlarmUseCase, observeAlarmUseCase: any ObserveAlarmUseCase, observeAlarmChangeUseCase: any ObserveAlarmChangeUseCase, + getLastRouteDetailUseCase: any GetLastRouteDetailUseCase, now: @escaping @Sendable () -> Date = { Date() }, bannerTickInterval: Duration = .seconds(60) ) { @@ -92,6 +97,7 @@ final class HomeViewModel { self.cancelAlarmUseCase = cancelAlarmUseCase self.observeAlarmUseCase = observeAlarmUseCase self.observeAlarmChangeUseCase = observeAlarmChangeUseCase + self.getLastRouteDetailUseCase = getLastRouteDetailUseCase self.now = now self.bannerTickInterval = bannerTickInterval } @@ -102,6 +108,7 @@ final class HomeViewModel { observeTask?.cancel() changeTask?.cancel() bannerTask?.cancel() + restoreCardTask?.cancel() } // MARK: - 입력 @@ -146,11 +153,18 @@ final class HomeViewModel { self?.registeredRouteId = route.id self?.state.isAlarmBusy = false self?.refreshAlarmButton() - self?.startBannerTimer(departure: route.departureTime) + self?.startBannerTimer( + departure: route.departureTime, + firstWalkSeconds: route.firstWalkSectionSeconds + ) } catch AlarmError.permissionDenied { guard !Task.isCancelled else { return } self?.state.isAlarmBusy = false self?.onToast?(.alarmPermissionNeeded) + } catch AlarmError.tooLate { + guard !Task.isCancelled else { return } + self?.state.isAlarmBusy = false + self?.onToast?(.alarmTooLate) } catch { guard !Task.isCancelled else { return } self?.state.isAlarmBusy = false @@ -213,7 +227,47 @@ final class HomeViewModel { // 창의 "지금 출발하세요"(2단계)도 동기화 복원 대상이다. if let departure = info.departureTime, !AlarmTiming.isSessionExpired(departureTime: departure, now: now()) { - startBannerTimer(departure: departure) + // 도보 초는 등록 시점 경로에서만 안다 — 같은 경로가 화면에 있으면 그 값, + // 재실행 복원(카드 없음)이면 상세 재조회가 끝난 뒤 재시작하며 반영한다. + startBannerTimer( + departure: departure, + firstWalkSeconds: selectedRoute?.id == info.lastRouteId + ? selectedRoute?.firstWalkSectionSeconds + : nil + ) + } + restoreRouteCardIfNeeded(info) + } + + /// 재실행 복원 (Phase 14): 알람은 있는데 카드가 없으면 경로 상세를 재조회해 카드를 + /// 복원한다 — "무슨 경로인지 모르는 해제 버튼" 상태 해소. 실패는 현행 폴백(카드 없이 + /// 해제 버튼)으로 조용히 남는다 — 만료 정리가 있어 유령이 오래가지 않는다. + private func restoreRouteCardIfNeeded(_ info: AlarmInfo) { + guard state.routeCard == nil, restoreCardTask == nil else { return } + restoreCardTask = Task { [weak self] in + defer { self?.restoreCardTask = nil } + guard let useCase = self?.getLastRouteDetailUseCase else { return } + guard let route = try? await useCase.execute(routeId: info.lastRouteId) else { return } + guard !Task.isCancelled, let self else { return } + // 복원 도중 상태가 변했으면(새 경로 선택·세션 종료) 낡은 복원을 버린다. + guard self.registeredRouteId == info.lastRouteId, + self.state.routeCard == nil else { return } + self.selectedRoute = route + var newState = self.state + newState.routeCard = RouteCardViewData(entity: route) + newState.alarmButton = Self.alarmButtonMode( + selectedRouteId: route.id, + registeredRouteId: self.registeredRouteId + ) + self.state = newState + // 배너를 도보 반영 기준으로 재시작한다(등록/refresh/LA와 같은 값 — 이중 시각 금지). + if let departure = info.departureTime, + !AlarmTiming.isSessionExpired(departureTime: departure, now: self.now()) { + self.startBannerTimer( + departure: departure, + firstWalkSeconds: route.firstWalkSectionSeconds + ) + } } } @@ -234,8 +288,9 @@ final class HomeViewModel { private func alarmChanged(_ verdict: AlarmChangeVerdict) { switch verdict { case let .advanced(by: interval, actionable: true): - // 반올림하되 최소 1분 — "0분 당겨졌어요"는 말이 안 된다. - let minutes = max(1, Int((interval / 60).rounded())) + // 올림 + 최소 1분 — LA 잠금화면 문구(.up)와 같은 분으로 읽혀야 한다(표기 통일, + // Phase 14). "0분 당겨졌어요"도 자연히 존재하지 않는다. + let minutes = max(1, Int((interval / 60).rounded(.up))) onToast?(.lastTrainAdvanced(minutes: minutes)) case .advanced(by: _, actionable: false): // 이미 못 타는 앞당김 — 카운트다운을 멈추고 배너를 실패 문구로 고정한다. @@ -295,13 +350,15 @@ final class HomeViewModel { ) } - private func startBannerTimer(departure: Date) { + private func startBannerTimer(departure: Date, firstWalkSeconds: Int?) { bannerTask?.cancel() // 매 틱 departure 기준으로 재계산 — 누적 드리프트가 없다. bannerTask = Task { [weak self] in while !Task.isCancelled { guard let now = self?.now() else { return } - guard let banner = Self.makeBanner(departure: departure, now: now) else { + guard let banner = Self.makeBanner( + departure: departure, firstWalkSeconds: firstWalkSeconds, now: now + ) else { // 유예 경과(3단계) — 배너·버튼을 내리고 카드를 "지난 막차"로 전환, // 틱 종료. 알람·LA·서버 정리는 App(AlarmSyncService)의 wake 판정 몫. self?.sessionExpired(departure: departure) @@ -345,19 +402,25 @@ final class HomeViewModel { max(0, Int(ceil(departure.timeIntervalSince(now) / 60))) } - /// 카운트다운·긴급도 모두 **버퍼 포함 알람 발화 시각**(AlarmTiming) 기준 — LA와 기준을 - /// 통일한다(이중 시각 금지). 그래서 문구도 "막차 출발까지"가 아니라 사용자가 출발해야 - /// 할 시각 기준의 "출발까지"다. + /// 카운트다운·긴급도 모두 **도보·버퍼 포함 알람 발화 시각**(AlarmTiming) 기준 — 등록/ + /// refresh/LA와 기준을 통일한다(이중 시각 금지). 그래서 문구도 "막차 출발까지"가 + /// 아니라 사용자가 출발해야 할 시각 기준의 "출발까지"다. /// /// Phase 13 배너 3단계 전이: /// 1) now < 알람 시각: "출발까지 N분" /// 2) 알람 시각 ≤ now < 출발+유예: "지금 출발하세요" (imminent 고정 — "출발까지 0분" 제거) /// 3) 유예 경과: nil — 호출자가 배너를 내리고 카드를 "지난 막차"로 전환할 시점. - nonisolated static func makeBanner(departure: Date, now: Date) -> BannerViewData? { + nonisolated static func makeBanner( + departure: Date, + firstWalkSeconds: Int?, + now: Date + ) -> BannerViewData? { guard !AlarmTiming.isSessionExpired(departureTime: departure, now: now) else { return nil } - let alarmDate = AlarmTiming.alarmFireDate(departureTime: departure) + let alarmDate = AlarmTiming.alarmFireDate( + departureTime: departure, firstWalkSeconds: firstWalkSeconds + ) guard now < alarmDate else { return BannerViewData(text: "지금 출발하세요", urgency: .imminent) } diff --git a/Projects/Feature/Home/Tests/HomeViewModelTests.swift b/Projects/Feature/Home/Tests/HomeViewModelTests.swift index b72d7a7..7607ac0 100644 --- a/Projects/Feature/Home/Tests/HomeViewModelTests.swift +++ b/Projects/Feature/Home/Tests/HomeViewModelTests.swift @@ -35,6 +35,11 @@ private struct StubObserveAlarmChangeUseCase: ObserveAlarmChangeUseCase { func execute() -> AsyncStream { handler() } } +private struct StubGetLastRouteDetailUseCase: GetLastRouteDetailUseCase { + let handler: @Sendable (String) async throws -> LastRoute + func execute(routeId: String) async throws -> LastRoute { try await handler(routeId) } +} + /// 테스트 도중 `now()`를 전진시키기 위한 가변 시계. private nonisolated final class NowBox: @unchecked Sendable { private let lock = NSLock() @@ -121,6 +126,9 @@ private func makeSUT( alarmChanges: @escaping @Sendable () -> AsyncStream = { AsyncStream { $0.finish() } }, + routeDetail: @escaping @Sendable (String) async throws -> LastRoute = { _ in + throw StubError() + }, now: @escaping @Sendable () -> Date = { fixedNow }, bannerTickInterval: Duration = .seconds(60) ) -> HomeViewModel { @@ -131,6 +139,7 @@ private func makeSUT( cancelAlarmUseCase: StubCancelAlarmUseCase(handler: cancel), observeAlarmUseCase: StubObserveAlarmUseCase(handler: alarmUpdates), observeAlarmChangeUseCase: StubObserveAlarmChangeUseCase(handler: alarmChanges), + getLastRouteDetailUseCase: StubGetLastRouteDetailUseCase(handler: routeDetail), now: now, bannerTickInterval: bannerTickInterval ) @@ -261,19 +270,19 @@ struct HomeViewModelTests { // 카운트다운·긴급도 모두 알람 발화 시각(출발 − 3분 버퍼) 기준 — 이중 시각 금지. // 출발까지 13분 = 알람까지 정확히 600초: imminent 경계. #expect(HomeViewModel.makeBanner( - departure: fixedNow.addingTimeInterval(13 * 60), now: fixedNow + departure: fixedNow.addingTimeInterval(13 * 60), firstWalkSeconds: nil, now: fixedNow ) == .init(text: "출발까지 10분", urgency: .imminent)) // 알람까지 601초: caution으로 넘어간다. #expect(HomeViewModel.makeBanner( - departure: fixedNow.addingTimeInterval(13 * 60 + 1), now: fixedNow + departure: fixedNow.addingTimeInterval(13 * 60 + 1), firstWalkSeconds: nil, now: fixedNow )?.urgency == .caution) // 출발까지 33분 = 알람까지 정확히 1800초: caution 경계. #expect(HomeViewModel.makeBanner( - departure: fixedNow.addingTimeInterval(33 * 60), now: fixedNow + departure: fixedNow.addingTimeInterval(33 * 60), firstWalkSeconds: nil, now: fixedNow ) == .init(text: "출발까지 30분", urgency: .caution)) // 알람까지 1801초: relaxed. #expect(HomeViewModel.makeBanner( - departure: fixedNow.addingTimeInterval(33 * 60 + 1), now: fixedNow + departure: fixedNow.addingTimeInterval(33 * 60 + 1), firstWalkSeconds: nil, now: fixedNow )?.urgency == .relaxed) } @@ -282,22 +291,22 @@ struct HomeViewModelTests { // Phase 13: 1단계(카운트다운) → 2단계(지금 출발하세요) → 3단계(nil = 지난 막차). // 알람 직전(출발 3분 1초 전): 아직 1단계 — "출발까지 1분". #expect(HomeViewModel.makeBanner( - departure: fixedNow.addingTimeInterval(181), now: fixedNow + departure: fixedNow.addingTimeInterval(181), firstWalkSeconds: nil, now: fixedNow ) == .init(text: "출발까지 1분", urgency: .imminent)) // 알람 시각 정각(출발 3분 전): 2단계 진입 — "출발까지 0분"은 존재하지 않는다. #expect(HomeViewModel.makeBanner( - departure: fixedNow.addingTimeInterval(180), now: fixedNow + departure: fixedNow.addingTimeInterval(180), firstWalkSeconds: nil, now: fixedNow ) == .init(text: "지금 출발하세요", urgency: .imminent)) // 출발 정각·유예 마지막 초까지 2단계 유지. #expect(HomeViewModel.makeBanner( - departure: fixedNow, now: fixedNow + departure: fixedNow, firstWalkSeconds: nil, now: fixedNow ) == .init(text: "지금 출발하세요", urgency: .imminent)) #expect(HomeViewModel.makeBanner( - departure: fixedNow.addingTimeInterval(-59), now: fixedNow + departure: fixedNow.addingTimeInterval(-59), firstWalkSeconds: nil, now: fixedNow ) == .init(text: "지금 출발하세요", urgency: .imminent)) // 유예 경계(출발+60초)부터 3단계 — nil. #expect(HomeViewModel.makeBanner( - departure: fixedNow.addingTimeInterval(-60), now: fixedNow + departure: fixedNow.addingTimeInterval(-60), firstWalkSeconds: nil, now: fixedNow ) == nil) } @@ -624,7 +633,199 @@ struct HomeViewModelTests { from: DateComponents(year: 2026, month: 8, day: 23, hour: 0, minute: 10) )! - #expect(HomeViewModel.makeBanner(departure: departure, now: now) + #expect(HomeViewModel.makeBanner(departure: departure, firstWalkSeconds: nil, now: now) == .init(text: "출발까지 27분", urgency: .caution)) } + + // MARK: - 도보 시간 반영 (Phase 14) + + @Test + func makeBanner_walkSeconds_shiftAlarmBase() { + // 기준 = 출발 − 도보 − 버퍼: 출발 42분 뒤, 도보 120초면 알람까지 37분. + #expect(HomeViewModel.makeBanner( + departure: fixedNow.addingTimeInterval(42 * 60), firstWalkSeconds: 120, now: fixedNow + ) == .init(text: "출발까지 37분", urgency: .relaxed)) + // 도보 반영으로 알람 시각이 이미 지났으면(출발 5분 전, 도보 120초 → 알람 정각) + // 2단계 "지금 출발하세요"에 진입한다. + #expect(HomeViewModel.makeBanner( + departure: fixedNow.addingTimeInterval(5 * 60), firstWalkSeconds: 120, now: fixedNow + ) == .init(text: "지금 출발하세요", urgency: .imminent)) + } + + @Test + func registerAlarm_routeWithWalk_bannerUsesWalkAwareBase() async { + // 등록 배너도 등록/LA와 같은 기준(출발 − 도보 − 버퍼)을 쓴다 — 이중 시각 금지. + let route = makeWalkRoute( + id: "r1", departure: fixedNow.addingTimeInterval(42 * 60), walkSeconds: 120 + ) + let sut = makeSUT() + let recorder = StateRecorder() + recorder.attach(to: sut) + + sut.routeSelected(route) + sut.registerAlarmTapped() + await recorder.waitUntilLast { $0.banner != nil } + + #expect(sut.state.banner == .init(text: "출발까지 37분", urgency: .relaxed)) + } + + // MARK: - tooLate 사전 가드 (Phase 14) + + @Test + func registerAlarm_tooLate_emitsToastAndKeepsRegisterButton() async { + let route = makeRoute(id: "r1", departure: fixedNow.addingTimeInterval(60)) + let sut = makeSUT(register: { _ in throw AlarmError.tooLate }) + let recorder = StateRecorder() + recorder.attach(to: sut) + + sut.routeSelected(route) + sut.registerAlarmTapped() + while recorder.toasts.isEmpty { await Task.yield() } + + #expect(recorder.toasts == [.alarmTooLate]) + #expect(sut.state.banner == nil) + #expect(!sut.state.isAlarmBusy) + #expect(sut.state.alarmButton == .register) + } + + // MARK: - 변경 분 표기 올림 통일 (Phase 14) + + @Test + func changeStream_advancedToast_roundsMinutesUp() async { + // 61초 앞당김 → 올림 2분 — LA 잠금화면 문구(.up)와 같은 분으로 읽힌다. + let (stream, continuation) = AsyncStream.makeStream() + let sut = makeSUT(alarmChanges: { stream }) + let recorder = StateRecorder() + recorder.attach(to: sut) + + sut.viewDidLoad() + continuation.yield(.advanced(by: 61, actionable: true)) + while recorder.toasts.isEmpty { await Task.yield() } + + #expect(recorder.toasts == [.lastTrainAdvanced(minutes: 2)]) + } + + // MARK: - 재실행 카드 복원 (Phase 14) + + @Test + func alarmSync_withoutCard_restoresCardFromRouteDetail() async { + // 재실행 복원: 카드 없이 동기화가 도착하면 상세를 재조회해 카드·해제 버튼· + // 도보 반영 배너까지 복원한다 — "무슨 경로인지 모르는 해제 버튼" 해소. + let departure = fixedNow.addingTimeInterval(42 * 60) + let route = makeWalkRoute(id: "r1", departure: departure, walkSeconds: 120) + let (stream, continuation) = AsyncStream.makeStream() + let sut = makeSUT( + alarmUpdates: { stream }, + routeDetail: { routeId in + #expect(routeId == "r1") + return route + } + ) + let recorder = StateRecorder() + recorder.attach(to: sut) + + sut.viewDidLoad() + continuation.yield( + AlarmInfo(lastRouteId: "r1", departureTime: departure, updatedAt: nil, isReal: true) + ) + await recorder.waitUntilLast { $0.routeCard != nil } + + #expect(sut.state.routeCard == RouteCardViewData(entity: route)) + #expect(sut.state.alarmButton == .cancel) + // 배너도 상세의 도보 초 반영 기준으로 재시작됐다 (42분 − 2분 도보 − 3분 버퍼 = 37분). + await recorder.waitUntilLast { $0.banner?.text == "출발까지 37분" } + } + + @Test + func alarmSync_detailFails_keepsCancelButtonWithoutCard() async { + // 복원 실패는 현행 폴백 — 카드 없이 해제 버튼·배너만. (기본 routeDetail 스텁이 throw) + let departure = fixedNow.addingTimeInterval(30 * 60) + let (stream, continuation) = AsyncStream.makeStream() + let sut = makeSUT(alarmUpdates: { stream }) + let recorder = StateRecorder() + recorder.attach(to: sut) + + sut.viewDidLoad() + continuation.yield( + AlarmInfo(lastRouteId: "r1", departureTime: departure, updatedAt: nil, isReal: true) + ) + await recorder.waitUntilLast { $0.banner != nil } + for _ in 0..<20 { await Task.yield() } + + #expect(sut.state.routeCard == nil) + #expect(sut.state.alarmButton == .cancel) + } + + @Test + func alarmSync_cardAlreadyVisible_doesNotFetchDetail() async { + // 등록 직후의 동기화 — 카드가 이미 있으면 상세 재조회를 하지 않는다. + let route = makeRoute(id: "r1", departure: fixedNow.addingTimeInterval(42 * 60)) + let fetched = FetchFlag() + let (stream, continuation) = AsyncStream.makeStream() + let sut = makeSUT( + alarmUpdates: { stream }, + routeDetail: { _ in + fetched.mark() + throw StubError() + } + ) + let recorder = StateRecorder() + recorder.attach(to: sut) + sut.viewDidLoad() + sut.routeSelected(route) + sut.registerAlarmTapped() + await recorder.waitUntilLast { $0.banner != nil } + + continuation.yield( + AlarmInfo( + lastRouteId: "r1", + departureTime: fixedNow.addingTimeInterval(42 * 60), + updatedAt: nil, + isReal: true + ) + ) + for _ in 0..<20 { await Task.yield() } + + #expect(!fetched.value) + #expect(sut.state.routeCard == RouteCardViewData(entity: route)) + } +} + +/// 상세 재조회 호출 여부 기록용 — 스텁 클로저가 @Sendable이라 클래스 박스로 관찰한다. +private nonisolated final class FetchFlag: @unchecked Sendable { + private let lock = NSLock() + private var flag = false + + var value: Bool { + lock.lock() + defer { lock.unlock() } + return flag + } + + func mark() { + lock.lock() + defer { lock.unlock() } + flag = true + } +} + +/// 첫 구간이 도보인 경로 픽스처 (Phase 14 도보 반영 검증용). +private nonisolated func makeWalkRoute(id: String, departure: Date, walkSeconds: Int) -> LastRoute { + let base = makeRoute(id: id, departure: departure) + let walk = TransportLeg( + mode: .walk, sectionTime: walkSeconds, distance: 150, departureTime: nil, + routeName: nil, lineType: nil, start: nil, end: nil, + subwayFinalStation: nil, subwayDirection: nil, + isExpressSubway: false, isLastSubway: false + ) + return LastRoute( + id: base.id, + departureTime: base.departureTime, + totalTime: base.totalTime, + totalWalkTime: base.totalWalkTime, + transferCount: base.transferCount, + totalDistance: base.totalDistance, + totalWalkDistance: base.totalWalkDistance, + legs: [walk] + base.legs + ) } From 5e3e07395db2f11b81b26587b95e06b78968ff75 Mon Sep 17 00:00:00 2001 From: AppGoni Date: Sun, 23 Aug 2026 22:05:28 +0900 Subject: [PATCH 02/14] =?UTF-8?q?docs:=20AtchaV2=20Phase=2015=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20=ED=94=84=EB=A1=AC=ED=94=84=ED=8A=B8=20=E2=80=94=20?= =?UTF-8?q?=EC=9D=B8=EC=A7=80=20=EC=B1=84=EB=84=90=20=EB=B0=A9=EC=96=B4?= =?UTF-8?q?=EC=84=A0=20(=EC=9E=90=EB=8F=99=20=EA=B2=80=EC=88=98=20?= =?UTF-8?q?=EA=B7=9C=EC=95=BD=20=EA=B8=B0=EC=A4=80)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- .../atcha-v2-channel-defense-prompt.md | 156 ++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 docs/prompts/atcha-v2-channel-defense-prompt.md diff --git a/docs/prompts/atcha-v2-channel-defense-prompt.md b/docs/prompts/atcha-v2-channel-defense-prompt.md new file mode 100644 index 0000000..2108e14 --- /dev/null +++ b/docs/prompts/atcha-v2-channel-defense-prompt.md @@ -0,0 +1,156 @@ +# AtchaV2 인지 채널 방어선 구현 프롬프트 — 폴백 확대 + time-sensitive + 노티 라우팅 + 권한 회복 + +> **사용법**: 이 문서 전체를 Claude Code에 컨텍스트로 전달하고 `"Phase 15를 진행해"`라고 지시한다. +> 실행 에이전트는 [마스터 프롬프트](atcha-v2-master-prompt.md)의 **진행 프로토콜·공통 규칙·공통 acceptance를 그대로 상속**하며, 한 번에 한 Phase만 수행한다. +> 갭 분석·우선순위 정본은 [Post-12 로드맵](../planning/atcha-v2-post12-roadmap.md)의 "Phase 15 — 인지 채널 방어선" 절. 충돌 시 **CLAUDE.md > 마스터 프롬프트 > [LA 프롬프트](atcha-v2-live-activity-prompt.md) > [세션 수명주기 프롬프트](atcha-v2-session-lifecycle-prompt.md) > 이 문서** 순. +> **검수는 사람 검수가 아니라 [자동 검수 규약](atcha-v2-auto-verification.md)을 따른다** — 실행 에이전트가 computer use로 직접 수행·증적 보고하고, 실기기 잔여 항목만 사용자에게 이관한다. +> 작성일: 2026-08-23. + +--- + +## Goal (최상위) + +**Phase 12의 폴백이 실전에서 뚫리는 지점을 막는다 — 어떤 설정의 유저에게도 인지 채널이 0이 되지 않게.** + +Phase 10~12의 인지 계층은 "LA가 살아 있는 유저"를 전제로 설계됐고, 폴백 트리거는 dismiss 기록 하나뿐이다. 그래서 LA를 설정에서 꺼 둔 유저는 변경 alert를 어떤 채널로도 받지 못하고, 폴백 노티가 오더라도 심야에 흔한 집중 모드가 그것을 억제하며, 노티를 탭해도 시스템 기본 동작 외의 랜딩이 없고, 알림 권한을 거부한 유저는 자신이 무엇을 잃었는지 안내받지 못한다. 위치 권한을 설정에서 되살려도 홈은 `viewDidLoad` 1회 조회뿐이라 출발지가 돌아오지 않는다. 이 문서는 그 구멍들을 막는다. Phase 번호는 세션 수명주기 프롬프트의 13~14에 이어 **15**. + +인지 채널 방어선의 완성 상태 (이 문서가 만드는 판정): + +``` +변경 판정(advanced/missed) 표출 시점 + ├─ 앱 포그라운드 ──► 인앱 채널 단일 (배너 강조 + 토스트) — LA alert·노티 없음 (이중 알림 0) + └─ 앱 백그라운드 + ├─ LA alert 도달 가능 ──► LA alert (기존 경로) + └─ LA alert 도달 불가 ──► 로컬 노티 (time-sensitive — 집중 모드 관통) + = dismissed ∨ 활성 activity 없음 ∨ areActivitiesEnabled false + + 노티 탭 ──► 홈 랜딩 (검색 플로우가 떠 있으면 접는다) + 알림 권한 거부 ──► 1회 안내 토스트 (재요청·재안내 스팸 없음) + 위치 권한 회복 ──► didBecomeActive 재확인 → 출발지 자동 재조회 +``` + +확정된 제품 결정사항 (변경하려면 사용자에게 먼저 물을 것 — [로드맵](../planning/atcha-v2-post12-roadmap.md) 2026-08-23 확정): + +| 항목 | 결정 | +|---|---| +| 폴백 조건 | `isDismissedByUser` 단일 → **"LA alert 도달 불가"** 3조건 합집합(dismissed ∨ 활성 activity 없음 ∨ `areActivitiesEnabled` false). 판정은 **어댑터의 단일 게터**로 — 호출자(AlarmSyncService)가 조건을 조립하지 않는다 | +| 폴백 확대의 의미 | **채널 갈아타기이지 LA 재생성이 아니다** — push-to-start 금지·dismiss 존중 정책 전부 불변 | +| 노티 강도 | 폴백 노티 전부 `.timeSensitive` interruptionLevel + time-sensitive entitlement — 집중 모드(심야에 흔함) 관통 | +| 노티 탭 랜딩 | **홈 랜딩** — 새 화면·딥링크·payload 파싱 없음. presented 정리 + 검색 플로우 접기. 앱 종료 상태에서의 탭은 스플래시 → 홈 자연 랜딩이 곧 목적지라 라우터가 할 일이 없다 | +| 포그라운드 표시 정책 | `willPresent` **`[.banner, .sound]` 명시** — 포그라운드에서는 애초에 노티를 발송하지 않는 것(표출 분기의 applicationState 선행 검사)이 1차 방어라 이중 알림은 구조적으로 없고, 이 정책은 "백그라운드 발송 → 활성화 직후 도달" 경합에서 유일한 가시 채널을 살리는 안전망이다 | +| 알림 권한 거부 안내 | **이번 호출로 최초 요청이 이뤄졌고 거부됐을 때만** 1회 토스트("막차 변경 알림을 받으려면 설정에서 알림을 허용해주세요"). 기존 재요청 금지 가드(요청 이력 키) 불변 — 이력이 있으면 요청도 안내도 없다 | +| 최후통첩 이중 알림 | 마지노선 침범 분기에 **applicationState 선행 검사** — 포그라운드면 조용한 LA 상태 갱신 + 인앱 채널 단일(일반 advanced 분기와 동일 구조). "포그라운드 여부와 무관하게 즉시"는 **백그라운드 한정**으로 정정한다 | +| 위치 권한 재확인 | `didBecomeActive` 시 출발지가 `needsSearch`일 때만 재조회. 재확인 경로는 **loading 전환·거부 토스트 없이** 조용히 — 성공 시에만 상태를 바꾼다(거부 유지 유저의 매 포그라운드 깜빡임·토스트 스팸 방지) | + +--- + +## 이 문서가 다시 정의하지 않는 것 (중복 금지) + +아래는 기존 Phase 산출물이다. **계약을 바꾸지 않고 명시된 지점만 확장한다.** 이 목록의 계약을 깨고 싶어지면 멈추고 사용자에게 물을 것. + +| 산출물 | 소속 | 이 문서에서의 취급 | +|---|---|---| +| `LastTrainActivityPort` (Domain 문서 고정 계약) | Phase 10 | **시그니처 불변** (`isDismissedByUser` 포함). 도달 가능성 게터는 App 내부 확장 포트(`LastTrainChangeAlerting`)에만 추가 | +| `EvaluateAlarmChangeUseCase` / `AlarmChangeVerdict` | Phase 11 | 그대로 사용. 케이스 추가 금지 | +| 방향 비대칭(앞당김 alert/늦춤 조용)·배지 10분·행동 중심 문구 | Phase 11 | 불변 — 바뀌는 것은 **채널 선택 분기**뿐 | +| `LocalNotificationAdapter` 권한 요청 시점(등록 성공 직후 1곳)·재요청 금지 가드 | Phase 12 | 시점·가드 불변. **반환값만 확장**해 거부 사실을 위로 전달 | +| dismiss 감지·push-to-start 금지·사일런트 푸시 경로 requestAuthorization 금지 | Phase 8·10·12 | 그대로 유지 | +| 만료 판정·departed·스냅샷·고아 재부착·죽은 세션 재시작 | Phase 13·14 | 불변. 재시작이 `propagateChange`보다 선행하므로 재시작 성공 세션은 자연히 "도달 가능"으로 판정된다 | +| `AlarmSyncService` 3경로 일원화 구조·판정 훅 | Phase 8·11 | 구조 불변 — 폴백 분기의 **조건식 교체**와 최후통첩 분기의 **applicationState 선행 검사**만 | +| 서버 계약 전체 | 마스터 공통 규칙 | **서버 변경 0.** 이 문서의 전 작업은 클라 단독 | + +## 전제 조건 + +1. **Phase 14 완료가 전제** (`feat/v2-phase14-relaunch-consistency` 기준). 이 문서 내부의 병렬 없음 — Phase 15 단일. +2. 서버 트랙(로드맵 S1~S4)과 **완전 독립** — 미확정 입력을 새로 요구하지 않는다. 검수는 [자동 검수 규약](atcha-v2-auto-verification.md)에 따라 DEV 데모 폴백·변경 시뮬레이터(플로팅 "변경" 버튼·dismiss 토글)를 재료로 에이전트가 직접 수행한다. +3. time-sensitive entitlement(`com.apple.developer.usernotifications.time-sensitive`)는 개발 서명·시뮬레이터에서 프로비저닝 없이 동작하는 것이 통례지만, 시뮬레이터 렌더가 라벨을 생략하면 판정을 "자동화 불가"로 기록하고 실기기 잔여로 이관한다(규약의 불가 시 분기). + +--- + +## Phase 15 — 인지 채널 방어선 + +### Goal +LA alert가 도달할 수 없는 모든 상태에서 로컬 노티가 대신 서고, 그 노티가 집중 모드를 관통하며, 탭하면 홈에 내려앉고, 권한을 잃은 유저에게는 회복 경로(안내 토스트·설정 복귀 재조회)가 열리게 한다. 포그라운드 이중 알림은 구조적으로 제거한다. + +### Requirements + +- **폴백 조건 확대 (App — `LastTrainChangeAlerting` 확장)**: App 내부 확장 포트에 도달 가능성 게터를 추가하고, 어댑터(`LastTrainLiveActivityAdapter`)가 3조건을 단일 판정한다: + ```swift + /// Phase 15 — LA alert 도달 가능성 단일 판정. + /// 보유 activity 있음 ∧ ActivityAuthorizationInfo().areActivitiesEnabled ∧ ¬dismissedByUser. + /// false면 update(alert:)가 no-op이거나 잠금화면에 표면이 없다 — 호출자는 로컬 노티로 갈아탄다. + var isAlertReachable: Bool { get async } + ``` + `AlarmSyncService`의 alert 채널 분기 3곳(최후통첩·일반 advanced 백그라운드·missed)의 `isDismissedByUser` 조회를 전부 `!isAlertReachable`로 교체한다. Domain 포트의 `isDismissedByUser`는 시그니처 불변(문서 고정 계약)이고, dismiss 기록의 의미(재부착·재시작 금지 판정)도 그대로다. `sessionEnded`·`delayed`·`unchanged`의 조용한 경로는 폴백 대상이 아니다(행동을 요구하지 않는다 — 기존 정책 불변). +- **폴백 노티 time-sensitive (App 어댑터 + 매니페스트)**: `LocalNotificationAdapter.post`의 content에 `interruptionLevel = .timeSensitive`를 설정하고, `Projects/App/Project.swift`의 앱 타겟 entitlements DSL에 `com.apple.developer.usernotifications.time-sensitive: true`를 추가한다(기존 `aps-environment`와 병기 — 덮어쓰기 금지). 위젯 익스텐션은 노티를 발송하지 않으므로 대상 아님. 권한 요청 옵션(`[.alert, .sound]`)은 불변 — time-sensitive는 별도 런타임 권한이 없고, 유저가 설정에서 앱별로 끌 수 있는 것은 수용한다. +- **`UNUserNotificationCenterDelegate` 도입 (App 신규 파일)**: 델리게이트 어댑터를 App에 신설하고 `AppDelegate.didFinishLaunching`에서 `UNUserNotificationCenter.current().delegate`로 등록한다(탭이 앱을 cold start시키는 경우까지 잡으려면 launch 완료 전 등록이 필수). + - `willPresent` → `[.banner, .sound]` 반환 (결정사항 — 근거 포함 주석 명시). + - `didReceive`(탭) → 메인 액터 복귀 후 홈 랜딩 훅 호출. 훅은 SceneDelegate가 배선한다(`AppCoordinator`에 `returnToHome()` 신설 — presented가 있으면 dismiss, 내비게이션 스택을 홈 루트로 pop). payload 파싱·identifier 분기 없음 — 이 앱의 모든 노티는 폴백 노티 하나뿐이다. + - 앱 종료 상태에서의 탭(훅 미배선 시점)은 버린다 — 스플래시 → 홈이 곧 랜딩이라 의미가 같다(주석 명시). + - 프로그램적 pop은 `SearchCoordinator`의 `closeFlow()`를 타지 않아 자식 코디네이터가 잔존할 수 있다 — 스와이프 백 누수(Phase 17 몫)와 같은 계열이므로 **여기서 고치지 않고** 랜딩 지점 주석에 Phase 17 참조로 명시만 한다. + - "UserNotifications import는 App에서 `LocalNotificationAdapter` 한 파일뿐" 주석 규칙은 "App 한정(어댑터 + 델리게이트)"으로 갱신한다 — Feature·Domain 유입 금지는 불변. +- **알림 권한 거부 1회 안내 (Domain 반환값 확장 + 홈 토스트)**: 포트·UseCase의 반환값을 확장해 "이번에 거부됨"을 위로 전달한다: + ```swift + public enum LocalNotificationAuthorizationOutcome: Sendable, Equatable { + case granted // 이번 호출로 요청이 이뤄졌고 허용됨 + case deniedNow // 이번 호출로 최초 요청이 이뤄졌고 거부됨 — 1회 안내의 유일한 트리거 + case alreadySettled // 요청 이력 있음(결과 무관) — 요청도 안내도 없다 + } + // LocalNotificationPort + @discardableResult + func requestAuthorizationIfNeeded() async -> LocalNotificationAuthorizationOutcome + // RegisterAlarmUseCase — 등록 성공의 후속 안내 신호(등록 실패 경로는 기존 throw 그대로) + @discardableResult + func execute(route: LastRoute) async throws -> LocalNotificationAuthorizationOutcome + ``` + `DefaultRegisterAlarmUseCase`는 기존 훅 위치(등록 성공 마지막)에서 포트 결과를 그대로 반환한다(포트 nil이면 `.alreadySettled`). `HomeViewModel`은 등록 성공 시 `.deniedNow`일 때만 신규 `ToastEvent.notificationPermissionDenied`를 발화하고, VC는 "막차 변경 알림을 받으려면 설정에서 알림을 허용해주세요" 토스트를 띄운다. 요청 이력 키·"요청했음만 기록" 어댑터 가드는 불변 — 시스템 요청이 평생 1회이므로 안내도 구조적으로 최대 1회다. `@discardableResult`라 기존 콜사이트는 무변경, 스텁(Tests/Example)만 시그니처를 따라간다. +- **최후통첩 포그라운드 이중 알림 제거 (App — `AlarmSyncService.presentAdvanced` 마지노선 분기)**: 새 알람 시각이 이미 과거인 분기에 `UIApplication.shared.applicationState == .active` 검사를 선행한다 — 포그라운드면 LA alert·로컬 노티 없이 조용한 상태 갱신(imminent + 배지)만 하고, 사용자 주의는 인앱 채널(changes 스트림 → 배너 강조 + 토스트)이 단독으로 맡는다(일반 advanced·missed 분기와 동일 구조). 백그라운드면 기존대로 즉시 최후통첩(도달 가능 → LA alert / 불가 → 로컬 노티). 주석의 "포그라운드 여부와 무관하게"는 이 정정에 맞게 고친다. +- **위치 권한 `didBecomeActive` 재확인 (HomeFeature)**: `HomeViewController`가 `UIApplication.didBecomeActiveNotification`을 관찰해 `viewModel.didBecomeActive()`를 호출한다(관찰 해제는 기존 VC 수명 관례). ViewModel은 출발지가 `.needsSearch`(사유 무관)일 때만 재조회하고, 재확인 경로는: + - `.loading` 전환 없이 기존 표시를 유지한 채 조회, **성공 시에만** `.current`로 갱신(깜빡임 방지). + - 실패(여전히 거부·불가) 시 상태 유지 + **`locationPermissionNeeded` 토스트 재발화 금지** — 그 토스트는 최초 진입(viewDidLoad) 경로 1회뿐(스팸 방지). + - `.loading`·`.current` 상태면 no-op(진행 중 재진입·불필요 재조회 방지 — 권한 팝업 닫힘도 didBecomeActive를 울리므로 이 가드가 필수다). + `LocationError` 세분화(denied/restricted/전역 OFF)는 Phase 17 몫 — 기존 2케이스 그대로 쓴다. + +### Constraints +- 알람 재스케줄·안전망 경로에 회귀 금지 — 채널 분기는 표출 계층에서만 바뀐다(재스케줄은 `RefreshAlarmUseCase.execute` 안에서 이미 끝난 뒤라는 기존 구조 불변). +- `UNUserNotificationCenter`·ActivityKit 심볼의 Domain·Feature 유출 금지(`tuist graph` + import 검사 — 기존 규약). 신규 델리게이트 파일 포함 전부 App. +- 알림 권한 요청 지점은 여전히 등록 성공 직후 한 곳 — 델리게이트·재확인 어디에도 새 요청 지점을 만들지 않는다(미확정 #8 유지). 사일런트 푸시 경로 requestAuthorization 금지도 그대로. +- `AlarmChangeVerdict` 케이스 추가 금지. `LastTrainActivityPort` 시그니처 불변. +- 판정·전이는 순수 함수/시각·상태 주입으로 테스트(실 `Date()`·실 UserDefaults 금지 — 기존 `now` 주입·인메모리 스텁 패턴 재사용). `isAlertReachable`·델리게이트 자체는 시스템 프레임워크 직결이라 단위 테스트 대상이 아니다 — 분기 정책(UseCase·ViewModel)을 스텁으로 테스트한다. +- Phase 16~18 선취 금지: pull-to-refresh·타임아웃·신선도 스탬프(16), `LocationError` 세분화·SearchCoordinator 누수 수정·arrivalField(17), 최근 경로 칩(18)은 이 문서 밖. + +### Acceptance +공통 acceptance + `-scheme Domain test`(RegisterAlarmUseCase 반환값·outcome 정책) + `-scheme HomeFeature test`(권한 거부 토스트·didBecomeActive 재확인·재발화 금지). + +### 자동 검수 (블로킹 — [자동 검수 규약](atcha-v2-auto-verification.md)) +iOS 26 시뮬레이터에서 에이전트가 직접 수행하고 단계별 스크린샷 증적으로 보고: +① **LA 비활성 폴백**: 설정 앱에서 앗차의 Live Activity OFF → 알람 등록(LA 시작 no-op) → 백그라운드 전환 + DEV "변경" 버튼 앞당김 주입 → **로컬 노티 도달** 스크린샷("인지 채널 0" 해소의 직접 증명). 회귀 확인: LA ON + DEV dismiss 토글 ON 경로도 여전히 노티 폴백. +② **time-sensitive**: ①의 노티 배너에 "시간 민감형" 라벨 확인 스크린샷. 가능하면 집중 모드(방해금지) ON 상태에서 도달까지 — 시뮬레이터가 라벨·집중 모드 semantics를 렌더하지 않으면 "자동화 불가"로 기록하고 실기기 잔여로 이관(규약의 불가 시 분기). +③ **노티 탭 → 홈 랜딩**: 검색 화면 진입 상태로 백그라운드 → 폴백 노티 발생 → 노티 탭 → 검색 플로우가 접히고 홈(카드·배너)으로 복귀하는 스크린샷. 참고: 앱 `simctl terminate` 후 노티 탭 → 스플래시 → 홈 cold start 랜딩도 1회 확인. +④ **권한 거부 1회 안내**: `simctl uninstall` 후 재설치(요청 이력 초기화) → 등록 → AlarmKit 팝업 허용 → 알림 권한 팝업 **"허용 안 함" AXPress** → 안내 토스트 스크린샷 → 알람 해제 후 재등록 → 권한 팝업·토스트 **재발화 없음** 확인. +⑤ **최후통첩 이중 알림 제거**: 포그라운드 유지 상태에서 마지노선 침범 앞당김(데모 경로 기준 "5분 앞당김", 지연 0에 준하게) 주입 → 인앱 토스트 + 배너 "지금 출발하세요"만 표출되고 LA alert 경로를 타지 않았음을 화면 + 로그로 증적. 백그라운드 재주입 시 기존 최후통첩(LA alert 또는 노티)이 유지되는지 회귀 확인. +⑥ **위치 권한 재확인**: 위치 팝업 "허용 안 함" → 홈 `needsSearch` 상태 스크린샷 → 설정 앱에서 위치 허용 → 앱 복귀 → 출발지 라벨 자동 복원 스크린샷. 스팸 확인: 거부 유지 상태로 백/포그라운드 2회 반복 → 거부 토스트·출발지 깜빡임 재발 없음. + +**실기기 잔여**: 집중 모드에서의 time-sensitive 노티 실표시(②가 시뮬레이터에서 판정 불가로 판명된 경우 — 판명 결과를 이 문서에 기록). 사일런트 푸시 실수신 경로의 폴백 동작(기존 항상-잔여 항목의 연장 — DEV 주입은 같은 `syncFromPush` 경로라 로직 검증은 시뮬레이터로 충분). + +--- + +## 진행 프로토콜 + +[마스터 프롬프트의 진행 프로토콜](atcha-v2-master-prompt.md#진행-프로토콜) 1~6을 그대로 상속한다. 추가 규칙: + +1. 이 문서는 **Phase 15 단일** — 내부 병렬 없음. Phase 14 완료 커밋 위에서 진행한다. +2. ["이 문서가 다시 정의하지 않는 것"](#이-문서가-다시-정의하지-않는-것-중복-금지) 표의 계약을 바꾸고 싶어지면 멈추고 사용자에게 물을 것. +3. Phase 16~18 산출물(pull-to-refresh, 타임아웃·오프라인 구분, 신선도 스탬프, App 테스트 타겟, `LocationError` 세분화, SearchCoordinator 누수 수정, 최근 경로 칩)을 **선취하지 않는다** — [로드맵](../planning/atcha-v2-post12-roadmap.md)의 몫. +4. 검수는 [자동 검수 규약](atcha-v2-auto-verification.md)을 따른다 — "자동 검수 (블로킹)"는 에이전트가 computer use로 수행·증적 보고를 마쳐야 다음 진행, "실기기 잔여"만 사용자에게 이관한다. +5. time-sensitive의 시뮬레이터 판정 불가가 확정되면 결과를 **이 문서 자동 검수 절에 기록**하고 실기기 잔여로 이관한다. 확정 전까지는 entitlement + interruptionLevel 설정을 코드 사실로 보고한다. + +## 미확정 입력 (참조) + +이 문서는 새 미확정 입력을 만들지 않는다. 관련 기존 항목의 취급: + +| # | 항목 | 이 문서에서의 취급 | +|---|---|---| +| 8 | 알림 권한 요청 시점 | **시점 불변**(알람 등록 성공 직후) — 이 문서는 거부 이후의 안내만 추가한다. 시점 확정 시에도 안내 구조는 재사용된다 | +| 5·6·10 | FCM 토큰 전달·plist | 이 문서 밖(S2) — 폴백 노티는 로컬 발송이라 FCM 무관, plist 부재 상태에서 전 기능 성립(기존 기본선 유지) | +| 원장 전체 | [Post-12 로드맵](../planning/atcha-v2-post12-roadmap.md)의 "미확정 입력 원장" 절 참조 | | From 87c7fa1a430cdf0027f5b029cac48cb88c1a60d9 Mon Sep 17 00:00:00 2001 From: AppGoni Date: Sun, 23 Aug 2026 22:05:28 +0900 Subject: [PATCH 03/14] =?UTF-8?q?feat:=20AtchaV2=20Phase=2015=20=E2=80=94?= =?UTF-8?q?=20=EC=9D=B8=EC=A7=80=20=EC=B1=84=EB=84=90=20=EB=B0=A9=EC=96=B4?= =?UTF-8?q?=EC=84=A0=20(=ED=8F=B4=EB=B0=B1=20=ED=99=95=EB=8C=80=20+=20time?= =?UTF-8?q?-sensitive=20+=20=EB=85=B8=ED=8B=B0=20=EB=9D=BC=EC=9A=B0?= =?UTF-8?q?=ED=8C=85=20+=20=EA=B6=8C=ED=95=9C=20=ED=9A=8C=EB=B3=B5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - LA alert 도달 불가 판정(isAlertReachable: activity ∧ areActivitiesEnabled ∧ ¬dismissed)으로 폴백 조건 확대 - 폴백 노티 .timeSensitive + time-sensitive entitlement (집중 모드 관통) - UNUserNotificationCenterDelegate 도입 — 노티 탭 → 홈 랜딩, willPresent [.banner,.sound] 명시 - 알림 권한 deniedNow 1회 안내 토스트 (요청 이력 가드 불변, RegisterAlarmUseCase 반환값 확장) - 최후통첩 분기 applicationState 선행 검사 — 포그라운드 이중 알림 제거 - 위치 권한 didBecomeActive 재확인 — needsSearch 한정, 깜빡임·토스트 스팸 없음 Co-Authored-By: Claude Fable 5 --- Projects/App/Project.swift | 2 + .../LastTrainLiveActivityAdapter.swift | 16 +++ .../Adapters/LocalNotificationAdapter.swift | 33 +++-- .../NotificationTapRoutingDelegate.swift | 41 ++++++ Projects/App/Sources/AlarmSyncService.swift | 56 +++++--- Projects/App/Sources/AppCoordinator.swift | 11 ++ Projects/App/Sources/AppDIContainer.swift | 3 + Projects/App/Sources/AppDelegate.swift | 3 + Projects/App/Sources/SceneDelegate.swift | 4 + .../Interfaces/LocalNotificationPort.swift | 17 ++- .../UseCases/RegisterAlarmUseCase.swift | 12 +- .../DefaultRegisterAlarmUseCaseTests.swift | 47 ++++++ .../LastTrainActivityLifecycleTests.swift | 5 +- .../Feature/Home/Example/ExampleApp.swift | 4 +- .../Home/Sources/HomeViewController.swift | 22 +++ .../Feature/Home/Sources/HomeViewModel.swift | 30 +++- .../Home/Tests/HomeViewModelTests.swift | 135 +++++++++++++++++- 17 files changed, 399 insertions(+), 42 deletions(-) create mode 100644 Projects/App/Sources/Adapters/NotificationTapRoutingDelegate.swift diff --git a/Projects/App/Project.swift b/Projects/App/Project.swift index 5a1e26b..d25407f 100644 --- a/Projects/App/Project.swift +++ b/Projects/App/Project.swift @@ -35,6 +35,8 @@ let appTarget = Target.target( // 배포 서명 시 프로비저닝이 production으로 치환한다. entitlements: .dictionary([ "aps-environment": "development", + // 폴백 노티의 .timeSensitive interruptionLevel용(Phase 15) — 집중 모드 관통. + "com.apple.developer.usernotifications.time-sensitive": true, ]), dependencies: [ .target(name: "AtchaWidget"), diff --git a/Projects/App/Sources/Adapters/LastTrainLiveActivityAdapter.swift b/Projects/App/Sources/Adapters/LastTrainLiveActivityAdapter.swift index a76d94d..89ddfe3 100644 --- a/Projects/App/Sources/Adapters/LastTrainLiveActivityAdapter.swift +++ b/Projects/App/Sources/Adapters/LastTrainLiveActivityAdapter.swift @@ -14,6 +14,11 @@ nonisolated protocol LastTrainChangeAlerting: Sendable { /// Phase 12 dismiss 폴백 트리거 — 유저가 잠금화면에서 LA를 스와이프로 지운 기록. /// true면 LA alert는 도달 불가(update가 no-op)라 호출자가 로컬 노티로 갈아탄다. var isDismissedByUser: Bool { get async } + /// Phase 15 — LA alert 도달 가능성 단일 판정: + /// 보유 activity 있음 ∧ areActivitiesEnabled ∧ ¬dismissedByUser. + /// false면 update(alert:)가 no-op이거나 잠금화면에 표면이 없다 — 호출자는 로컬 노티로 + /// 갈아탄다(채널 갈아타기이지 LA 재생성이 아니다 — push-to-start 금지 정책 불변). + var isAlertReachable: Bool { get async } /// Phase 12 종료 표출 — missed/serviceEnded 최종 상태로 LA를 내린다(Domain 포트와 동일 구현). func end(final state: LastTrainActivityState) async } @@ -233,6 +238,17 @@ actor LastTrainLiveActivityAdapter: LastTrainActivityPort, LastTrainChangeAlerti var isDismissedByUser: Bool { dismissedByUser } + /// Phase 15 폴백 조건 확대 — dismiss 기록 하나로는 "LA를 설정에서 꺼둔 유저"(start가 + /// no-op이라 activity 자체가 없다)와 "시작 실패·시스템 종료 후 재시작도 막힌 세션"이 + /// 전부 인지 채널 0으로 남는다. 세 조건을 어댑터가 한 번에 판정한다 — 호출자 + /// (AlarmSyncService)는 조건을 조립하지 않는다. 죽은 세션 재시작(restartIfNeeded)이 + /// 표출(propagateChange)보다 선행하므로, 재시작에 성공한 세션은 자연히 도달 가능이다. + var isAlertReachable: Bool { + activity != nil + && ActivityAuthorizationInfo().areActivitiesEnabled + && !dismissedByUser + } + // MARK: - LastTrainDepartureEnding (Phase 13) /// 정책: departed 상태는 잠금화면에 남았다가 출발 + 10분에 자동 소멸한다(.after) — diff --git a/Projects/App/Sources/Adapters/LocalNotificationAdapter.swift b/Projects/App/Sources/Adapters/LocalNotificationAdapter.swift index 034b28f..8466889 100644 --- a/Projects/App/Sources/Adapters/LocalNotificationAdapter.swift +++ b/Projects/App/Sources/Adapters/LocalNotificationAdapter.swift @@ -3,13 +3,19 @@ import Foundation @preconcurrency import UserNotifications /// UNUserNotificationCenter → Domain `LocalNotificationPort` 어댑터. -/// UserNotifications를 import하는 곳은 App에서 이 파일뿐(디바이스 프레임워크 App 한정 규칙). +/// UserNotifications import는 App 한정(이 어댑터 + 노티 탭 라우팅 델리게이트) — +/// Feature·Domain 유입 금지 규칙은 불변. /// -/// 역할은 Phase 12의 두 가지뿐: +/// 역할은 두 가지뿐: /// ① 권한 요청 — 명시된 한 시점(알람 등록 성공 직후, `DefaultRegisterAlarmUseCase` 훅)에서만 /// 불린다. 사일런트 푸시 경로에는 requestAuthorization이 절대 없다 — `post()`는 권한을 /// 묻지 않고 현재 상태만 조회해 authorized가 아니면 조용히 no-op한다. -/// ② dismiss 폴백 발송 — 유저가 LA를 스와이프로 지운 뒤의 변경 표출을 로컬 노티로 대신한다. +/// 반환값(Phase 15): 이번 호출로 최초 요청이 이뤄졌고 거부됐을 때만 `deniedNow` — +/// 홈이 1회 안내 토스트를 띄울 유일한 트리거다(이력이 있으면 요청도 안내도 없다). +/// ② 폴백 발송 — LA alert가 도달할 수 없는 상태(dismissed ∨ 활성 activity 없음 ∨ LA 비활성, +/// Phase 15 확대)의 변경 표출을 로컬 노티로 대신한다. 집중 모드(심야에 흔함)에서 억제되지 +/// 않도록 `.timeSensitive` interruptionLevel을 싣는다(time-sensitive entitlement 필요 — +/// 앱 타겟 매니페스트에 선언, 유저가 설정에서 앱별로 끄는 것은 수용). /// /// actor인 이유: LastTrainLiveActivityAdapter와 동일 — 포트가 nonisolated async 요구사항을 /// 가진 Sendable 프로토콜이라 MainActor 클래스의 격리 멤버로는 적합성이 성립하지 않는다. @@ -27,17 +33,24 @@ actor LocalNotificationAdapter: LocalNotificationPort { // MARK: - LocalNotificationPort - func requestAuthorizationIfNeeded() async { - guard !userDefaults.bool(forKey: Self.authRequestedDefaultsKey) else { return } + @discardableResult + func requestAuthorizationIfNeeded() async -> LocalNotificationAuthorizationOutcome { + guard !userDefaults.bool(forKey: Self.authRequestedDefaultsKey) else { + return .alreadySettled + } + // 허용·거부·에러 무관하게 "요청했음"을 기록한다 — 발송 가능 여부는 post()가 매번 + // notificationSettings()로 실시간 조회하므로 결과까지 저장할 필요가 없고, + // 안내 토스트도 이 1회 요청의 결과(deniedNow)에만 매달리므로 구조적으로 1회다. + userDefaults.set(true, forKey: Self.authRequestedDefaultsKey) do { - _ = try await UNUserNotificationCenter.current() + let granted = try await UNUserNotificationCenter.current() .requestAuthorization(options: [.alert, .sound]) + return granted ? .granted : .deniedNow } catch { // 실패 흡수(포트 계약) — 권한 요청 실패가 알람 등록 결과에 영향을 줄 수 없다. + // 거부 "확정"이 아니므로 안내 토스트 대상도 아니다. + return .alreadySettled } - // 허용·거부·에러 무관하게 "요청했음"만 기록한다 — 발송 가능 여부는 post()가 매번 - // notificationSettings()로 실시간 조회하므로 결과까지 저장할 필요가 없다. - userDefaults.set(true, forKey: Self.authRequestedDefaultsKey) } func post(title: String, body: String) async { @@ -50,6 +63,8 @@ actor LocalNotificationAdapter: LocalNotificationPort { content.title = title content.body = body content.sound = .default + // 막차 변경은 즉시 행동이 필요한 정보다 — 집중 모드를 관통한다(Phase 15). + content.interruptionLevel = .timeSensitive let request = UNNotificationRequest( // 폴백 노티는 변경 이벤트당 1건으로 드물다 — 교체(고정 id) 없이 개별 발송. identifier: UUID().uuidString, diff --git a/Projects/App/Sources/Adapters/NotificationTapRoutingDelegate.swift b/Projects/App/Sources/Adapters/NotificationTapRoutingDelegate.swift new file mode 100644 index 0000000..b28389c --- /dev/null +++ b/Projects/App/Sources/Adapters/NotificationTapRoutingDelegate.swift @@ -0,0 +1,41 @@ +import Foundation +@preconcurrency import UserNotifications + +/// UNUserNotificationCenter 델리게이트 (Phase 15) — 포그라운드 표시 정책과 노티 탭 라우팅. +/// UserNotifications import는 App 한정(LocalNotificationAdapter + 이 파일) — Feature·Domain +/// 유입 금지 규칙은 불변. 이 앱의 노티는 폴백 노티 하나뿐이라 payload 파싱·identifier 분기가 없다. +/// +/// 클래스는 App 기본 격리(MainActor)를 그대로 쓴다 — 시스템이 부르는 델리게이트 메서드만 +/// nonisolated witness로 두고 내부에서 메인 액터로 복귀한다. +final class NotificationTapRoutingDelegate: NSObject, UNUserNotificationCenterDelegate { + /// 노티 탭 → 홈 랜딩 훅 — SceneDelegate가 AppCoordinator.returnToHome()으로 배선한다. + /// 앱 종료 상태에서의 탭(훅 미배선 시점)은 버린다 — 스플래시 → 홈이 곧 랜딩이라 의미가 같다. + var onTap: (() -> Void)? + + /// AppDelegate launch 완료 전에 호출해야 한다 — 탭이 앱을 cold start시키는 경우의 + /// didReceive까지 시스템이 이 델리게이트로 전달한다. UN 타입을 노출하지 않는 등록 + /// 메서드라 AppDelegate에 UserNotifications import가 생기지 않는다. + func attachToNotificationCenter() { + UNUserNotificationCenter.current().delegate = self + } + + /// 포그라운드 표시 정책 명시(Phase 15 결정): 표출 분기가 applicationState를 선행 검사해 + /// 포그라운드에서는 애초에 노티를 발송하지 않는 것이 1차 방어라 이중 알림은 구조적으로 + /// 없다. 이 정책은 "백그라운드 발송 → 활성화 직후 도달" 경합에서 인앱 토스트가 이미 + /// 지나갔을 때 유일한 가시 채널을 살리는 안전망이다. + nonisolated func userNotificationCenter( + _ center: UNUserNotificationCenter, + willPresent notification: UNNotification + ) async -> UNNotificationPresentationOptions { + [.banner, .sound] + } + + nonisolated func userNotificationCenter( + _ center: UNUserNotificationCenter, + didReceive response: UNNotificationResponse + ) async { + // 기본 탭만 라우팅한다 — 커스텀 액션·dismiss 액션은 없다(만들지도 않았다). + guard response.actionIdentifier == UNNotificationDefaultActionIdentifier else { return } + await MainActor.run { self.onTap?() } + } +} diff --git a/Projects/App/Sources/AlarmSyncService.swift b/Projects/App/Sources/AlarmSyncService.swift index 7c5b44a..7baff5c 100644 --- a/Projects/App/Sources/AlarmSyncService.swift +++ b/Projects/App/Sources/AlarmSyncService.swift @@ -13,8 +13,9 @@ import os /// 홈 배너 강조·토스트)을 덧붙인다. 알람 재스케줄은 `RefreshAlarmUseCase.execute()` 안에서 /// 이미 끝난 뒤라(반환 = 재스케줄 완료) LA·인앱 표출 실패가 알람을 막을 구조 자체가 없다. /// -/// Phase 12 폴백·종료: ③ 유저가 LA를 스와이프로 지운 기록(`isDismissedByUser`)이 있으면 -/// 백그라운드 alert 채널을 로컬 노티(같은 문구)로 갈아탄다 — 피기백 시점엔 앱이 깨어 있으므로 +/// Phase 12 폴백·종료(15에서 조건 확대): ③ LA alert가 도달 불가한 상태(dismissed ∨ 활성 +/// activity 없음 ∨ LA 비활성 — 어댑터의 `isAlertReachable` 단일 판정)면 백그라운드 alert +/// 채널을 로컬 노티(같은 문구, time-sensitive)로 갈아탄다 — 피기백 시점엔 앱이 깨어 있으므로 /// 서버 무관여로 가능하고, push-to-start 재생성은 하지 않는다(지운 의사 존중). /// ④ advanced(actionable: false)는 LA를 missed 상태로, sessionEnded는 serviceEnded 최종 /// 상태로 내리고 로컬 알람을 취소한다. 배너 정리는 changes 스트림을 받은 홈의 몫. @@ -329,24 +330,32 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { guard alarmTime > now else { // 새 알람 시각이 이미 과거(출발은 미래) — 마지노선 침범. 원래 울렸어야 할 알람 - // 시점이 지나 있으므로 조용한 채널로는 늦다: 포그라운드 여부와 무관하게 즉시 최후통첩. + // 시점이 지나 있으므로 조용한 채널로는 늦다: 백그라운드면 즉시 최후통첩. + let ultimatumState = LastTrainActivityState( + departureTime: departure, + alarmTime: alarmTime, + urgency: .imminent, + changeBadgeExpiry: badgeExpiry, + phase: .active + ) + if UIApplication.shared.applicationState == .active { + // 포그라운드 — LA alert 소리·로컬 노티 없이 조용한 상태 갱신만(Phase 15 + // 이중 알림 제거). 사용자 주의는 인앱 채널(changes 스트림 → 배너 강조 + + // 토스트)이 단독으로 맡는다 — 일반 advanced·missed 분기와 동일 구조. + await liveActivity.update(state: ultimatumState, alert: nil) + return + } let alert = ( title: LastTrainChangeMessages.ultimatumTitle, body: LastTrainChangeMessages.ultimatumBody(latestDeparture: departure) ) - if await liveActivity.isDismissedByUser { - // dismiss 폴백(Phase 12) — LA는 유저가 지웠다: alert를 실을 update는 no-op이고 - // push-to-start 재생성은 하지 않는다(어차피 세션도 없고, 지운 의사 존중이 정책). + if await liveActivity.isAlertReachable { + await liveActivity.update(state: ultimatumState, alert: alert) + } else { + // 도달 불가 폴백(Phase 12→15 확대) — dismissed·activity 없음·LA 비활성 + // 전부 로컬 노티로 갈아탄다. push-to-start 재생성은 하지 않는다(정책 불변). // 피기백 시점엔 앱이 깨어 있으므로 서버 무관여 로컬 노티로 같은 문구를 보낸다. await localNotification.post(title: alert.title, body: alert.body) - } else { - await liveActivity.update(state: LastTrainActivityState( - departureTime: departure, - alarmTime: alarmTime, - urgency: .imminent, - changeBadgeExpiry: badgeExpiry, - phase: .active - ), alert: alert) } return } @@ -373,13 +382,13 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { title: LastTrainChangeMessages.advancedAlertTitle(minutesEarlier: minutesEarlier), body: LastTrainChangeMessages.advancedAlertBody(from: previousDeparture, to: departure) ) - if await liveActivity.isDismissedByUser { - // dismiss 폴백(Phase 12) — LA alert 대신 같은 행동 중심 문구의 로컬 노티. - // push-to-start 재생성 금지(정책) — 지워진 LA를 되살리지 않는다. - await localNotification.post(title: alert.title, body: alert.body) - } else { + if await liveActivity.isAlertReachable { // 잠금화면 alert + "당겨짐" 배지(만료 now+10분). await liveActivity.update(state: state, alert: alert) + } else { + // 도달 불가 폴백(Phase 12→15 확대) — LA alert 대신 같은 행동 중심 문구의 + // 로컬 노티. push-to-start 재생성 금지(정책) — 지워진 LA를 되살리지 않는다. + await localNotification.post(title: alert.title, body: alert.body) } } @@ -408,11 +417,12 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { if UIApplication.shared.applicationState == .active { // 포그라운드 — 상태 전환만 조용히. 사용자 주의는 인앱 채널이 맡는다(이중 알림 방지). await liveActivity.update(state: state, alert: nil) - } else if await liveActivity.isDismissedByUser { - // dismiss 폴백(Phase 12) — push-to-start 재생성 금지, 같은 문구의 로컬 노티로 대신한다. - await localNotification.post(title: alert.title, body: alert.body) - } else { + } else if await liveActivity.isAlertReachable { await liveActivity.update(state: state, alert: alert) + } else { + // 도달 불가 폴백(Phase 12→15 확대) — push-to-start 재생성 금지, 같은 문구의 + // 로컬 노티로 대신한다. + await localNotification.post(title: alert.title, body: alert.body) } } diff --git a/Projects/App/Sources/AppCoordinator.swift b/Projects/App/Sources/AppCoordinator.swift index a8ddddc..431255d 100644 --- a/Projects/App/Sources/AppCoordinator.swift +++ b/Projects/App/Sources/AppCoordinator.swift @@ -59,6 +59,17 @@ final class AppCoordinator: Coordinator, CoordinatorFinishDelegate { } } + /// 노티 탭 랜딩(Phase 15) — presented를 접고 내비게이션을 홈 루트로 되돌린다. + /// 이 앱의 노티는 폴백 노티뿐이고 목적지는 항상 홈(배너·카드가 최신 상태를 말한다). + /// 스플래시 단계의 탭이면 popToRoot가 스플래시에 머무를 뿐 — 부트스트랩 후 홈 자연 랜딩. + func returnToHome() { + navigationController.presentedViewController?.dismiss(animated: false) + // 프로그램적 pop은 SearchCoordinator.closeFlow()를 타지 않아 자식 코디네이터가 + // 잔존할 수 있다 — 스와이프 백 누수와 같은 계열이라 Phase 17 + // (UINavigationControllerDelegate 정리)이 일괄 해소한다. 여기서 선취하지 않는다. + navigationController.popToRootViewController(animated: false) + } + func coordinatorDidFinish(_ coordinator: any Coordinator) { removeChild(coordinator) } diff --git a/Projects/App/Sources/AppDIContainer.swift b/Projects/App/Sources/AppDIContainer.swift index 3484abf..87438cd 100644 --- a/Projects/App/Sources/AppDIContainer.swift +++ b/Projects/App/Sources/AppDIContainer.swift @@ -36,6 +36,9 @@ final class AppDIContainer { /// Phase 13 발화 이후 세션 수명 — stopIntent(AlarmAcknowledgeIntent)가 조합 루트를 /// 거쳐 도달하는 지점. AppDelegate 경유로 인텐트 perform()이 접근한다. let alarmSessionLifecycle: AlarmSessionLifecycleService + /// 노티 탭 라우팅 델리게이트(Phase 15) — AppDelegate가 launch 시 등록하고, + /// SceneDelegate가 홈 랜딩 훅(onTap)을 배선한다. + let notificationTapDelegate = NotificationTapRoutingDelegate() #if DEV /// DEV 플로팅 디버그 메뉴가 dismiss 기록 강제 토글에 접근하는 유일한 통로 (Phase 12 검수). var devLiveActivityAdapter: LastTrainLiveActivityAdapter { liveActivityAdapter } diff --git a/Projects/App/Sources/AppDelegate.swift b/Projects/App/Sources/AppDelegate.swift index 5e4d2df..c9a391e 100644 --- a/Projects/App/Sources/AppDelegate.swift +++ b/Projects/App/Sources/AppDelegate.swift @@ -24,6 +24,9 @@ final class AppDelegate: UIResponder, UIApplicationDelegate { // 어댑터(actor)가 직렬화하므로 안전하다. let container = container Task { await container.reattachOrphanLiveActivities() } + // 노티 탭 라우팅(Phase 15) — launch 완료 전에 등록해야 탭이 앱을 cold start시키는 + // 경우의 didReceive까지 잡는다. 홈 랜딩 훅 배선은 SceneDelegate 몫. + container.notificationTapDelegate.attachToNotificationCenter() configureFirebaseIfAvailable() if isFirebaseEnabled { Messaging.messaging().delegate = self diff --git a/Projects/App/Sources/SceneDelegate.swift b/Projects/App/Sources/SceneDelegate.swift index 5e1db59..de37ac4 100644 --- a/Projects/App/Sources/SceneDelegate.swift +++ b/Projects/App/Sources/SceneDelegate.swift @@ -25,6 +25,10 @@ final class SceneDelegate: UIResponder, UIWindowSceneDelegate { self.window = window appCoordinator = coordinator coordinator.start() + // 노티 탭 → 홈 랜딩 배선(Phase 15). 델리게이트 등록은 AppDelegate(launch 시점) 몫. + container.notificationTapDelegate.onTap = { [weak coordinator] in + coordinator?.returnToHome() + } #if DEV installDevChangeButton(in: window, container: container) diff --git a/Projects/Domain/Sources/Interfaces/LocalNotificationPort.swift b/Projects/Domain/Sources/Interfaces/LocalNotificationPort.swift index 8602701..b1100bf 100644 --- a/Projects/Domain/Sources/Interfaces/LocalNotificationPort.swift +++ b/Projects/Domain/Sources/Interfaces/LocalNotificationPort.swift @@ -1,8 +1,21 @@ +/// 알림 권한 요청의 결과 — "이번 호출로 무엇이 일어났는가"를 담는다 (Phase 15). +/// 홈이 1회 안내 토스트를 띄울 유일한 트리거는 `deniedNow`다 — 요청 이력이 있으면 +/// 시스템 요청도 안내도 다시 일어나지 않는다(재요청·재안내 스팸 금지). +public enum LocalNotificationAuthorizationOutcome: Sendable, Equatable { + /// 이번 호출로 요청이 이뤄졌고 허용됨. + case granted + /// 이번 호출로 최초 요청이 이뤄졌고 거부됨 — 1회 안내의 유일한 트리거. + case deniedNow + /// 요청 이력 있음(결과 무관) 또는 요청 불가 — 요청도 안내도 없다. + case alreadySettled +} + /// 로컬 노티 포트 — 구현은 App 어댑터(UNUserNotificationCenter는 App 한정 규칙). /// 권한 요청은 명시된 한 시점(알람 등록 성공 직후)에서만 호출된다. /// 거부 상태 기록·재요청 금지는 구현(어댑터) 책임. 실패는 밖으로 던지지 않는다. public protocol LocalNotificationPort: Sendable { - func requestAuthorizationIfNeeded() async - /// LA dismiss 폴백용 즉시 발송. 권한 없으면 조용히 no-op. + @discardableResult + func requestAuthorizationIfNeeded() async -> LocalNotificationAuthorizationOutcome + /// LA alert 도달 불가 폴백용 즉시 발송. 권한 없으면 조용히 no-op. func post(title: String, body: String) async } diff --git a/Projects/Domain/Sources/UseCases/RegisterAlarmUseCase.swift b/Projects/Domain/Sources/UseCases/RegisterAlarmUseCase.swift index 129c996..a70808a 100644 --- a/Projects/Domain/Sources/UseCases/RegisterAlarmUseCase.swift +++ b/Projects/Domain/Sources/UseCases/RegisterAlarmUseCase.swift @@ -1,7 +1,10 @@ import Foundation public protocol RegisterAlarmUseCase: Sendable { - func execute(route: LastRoute) async throws + /// 반환값은 등록 성공의 후속 안내 신호(Phase 15) — 알림 권한이 이번에 거부됐는지. + /// 등록 실패는 기존대로 throw로 표현한다(반환값에 실패가 실리지 않는다). + @discardableResult + func execute(route: LastRoute) async throws -> LocalNotificationAuthorizationOutcome } public struct DefaultRegisterAlarmUseCase: RegisterAlarmUseCase { @@ -31,7 +34,8 @@ public struct DefaultRegisterAlarmUseCase: RegisterAlarmUseCase { self.now = now } - public func execute(route: LastRoute) async throws { + @discardableResult + public func execute(route: LastRoute) async throws -> LocalNotificationAuthorizationOutcome { // 발화 시각(출발 − 도보 − 버퍼, 미확정 #7 클라 임시안)이 이미 과거면 시작조차 // 하지 않는다 — 서버 등록이 성공한 뒤 로컬 스케줄(AlarmKit 과거 fixed 거부)이 // 실패하는 서버/로컬 불일치의 사전 가드. 권한 팝업보다도 앞선다(죽은 경로에 @@ -84,6 +88,8 @@ public struct DefaultRegisterAlarmUseCase: RegisterAlarmUseCase { // 사이에 서버 등록·로컬 스케줄·LA 시작이 끼어 있어 연속 팝업이 완화된다. // 등록 실패·권한 거부 경로에서는 위에서 throw로 빠져나가므로 여기까지 오지 않는다. // 거부 기록·재요청 스팸 방지는 어댑터 책임이고, 실패는 던지지 않는다(등록 결과에 영향 없음). - await notificationPort?.requestAuthorizationIfNeeded() + // 결과는 그대로 위로 전달한다(Phase 15) — deniedNow일 때만 홈이 1회 안내 토스트를 띄운다. + guard let notificationPort else { return .alreadySettled } + return await notificationPort.requestAuthorizationIfNeeded() } } diff --git a/Projects/Domain/Tests/DefaultRegisterAlarmUseCaseTests.swift b/Projects/Domain/Tests/DefaultRegisterAlarmUseCaseTests.swift index 6a27986..61bb6b2 100644 --- a/Projects/Domain/Tests/DefaultRegisterAlarmUseCaseTests.swift +++ b/Projects/Domain/Tests/DefaultRegisterAlarmUseCaseTests.swift @@ -50,6 +50,21 @@ private struct SpyAlarmScheduler: AlarmScheduler { func scheduledFireDate() async -> Date? { nil } } +private struct StubLocalNotificationPort: LocalNotificationPort { + let log: CallLog + var authorizationOutcome: LocalNotificationAuthorizationOutcome = .alreadySettled + + @discardableResult + func requestAuthorizationIfNeeded() async -> LocalNotificationAuthorizationOutcome { + await log.append("requestNotiAuth") + return authorizationOutcome + } + + func post(title: String, body: String) async { + await log.append("postNoti:\(title)") + } +} + private actor SpySnapshotStore: AlarmSessionSnapshotStore { private(set) var saved: [AlarmSessionSnapshot] = [] private(set) var clearCount = 0 @@ -174,6 +189,38 @@ struct DefaultRegisterAlarmUseCaseTests { #expect(await log.events == ["auth:false"]) } + // MARK: - 알림 권한 후속 신호 (Phase 15) + + @Test + func execute_notificationDeniedNow_propagatesOutcome() async throws { + // 포트가 "이번 호출로 최초 요청·거부"를 답하면 그대로 위로 전달한다 — + // 홈이 1회 안내 토스트를 띄울 유일한 트리거. + let log = CallLog() + let sut = DefaultRegisterAlarmUseCase( + repository: SpyAlarmRepository(log: log), + scheduler: SpyAlarmScheduler(log: log), + notificationPort: StubLocalNotificationPort(log: log, authorizationOutcome: .deniedNow), + now: fixedNow + ) + let outcome = try await sut.execute(route: .fixture(id: "new")) + #expect(outcome == .deniedNow) + // 요청 시점은 여전히 등록 성공 마지막 한 곳이다(미확정 #8 유지). + #expect(await log.events.last == "requestNotiAuth") + } + + @Test + func execute_withoutNotificationPort_returnsAlreadySettled() async throws { + // 포트 미주입(Example·스텁 조립)이면 요청 자체가 없다 — 안내도 없다. + let log = CallLog() + let sut = DefaultRegisterAlarmUseCase( + repository: SpyAlarmRepository(log: log), + scheduler: SpyAlarmScheduler(log: log), + now: fixedNow + ) + let outcome = try await sut.execute(route: .fixture(id: "new")) + #expect(outcome == .alreadySettled) + } + // MARK: - tooLate 사전 가드 (Phase 14) @Test diff --git a/Projects/Domain/Tests/LastTrainActivityLifecycleTests.swift b/Projects/Domain/Tests/LastTrainActivityLifecycleTests.swift index eb26ece..f391f5a 100644 --- a/Projects/Domain/Tests/LastTrainActivityLifecycleTests.swift +++ b/Projects/Domain/Tests/LastTrainActivityLifecycleTests.swift @@ -81,9 +81,12 @@ private struct SpyActivityPort: LastTrainActivityPort { private struct SpyLocalNotificationPort: LocalNotificationPort { let log: CallLog + var authorizationOutcome: LocalNotificationAuthorizationOutcome = .alreadySettled - func requestAuthorizationIfNeeded() async { + @discardableResult + func requestAuthorizationIfNeeded() async -> LocalNotificationAuthorizationOutcome { await log.append("requestNotiAuth") + return authorizationOutcome } func post(title: String, body: String) async { diff --git a/Projects/Feature/Home/Example/ExampleApp.swift b/Projects/Feature/Home/Example/ExampleApp.swift index 0b35925..2667d95 100644 --- a/Projects/Feature/Home/Example/ExampleApp.swift +++ b/Projects/Feature/Home/Example/ExampleApp.swift @@ -72,8 +72,10 @@ struct PreviewReverseGeocodeUseCase: ReverseGeocodeUseCase { } struct PreviewRegisterAlarmUseCase: RegisterAlarmUseCase { - func execute(route: LastRoute) async throws { + @discardableResult + func execute(route: LastRoute) async throws -> LocalNotificationAuthorizationOutcome { try? await Task.sleep(for: .milliseconds(500)) + return .alreadySettled } } diff --git a/Projects/Feature/Home/Sources/HomeViewController.swift b/Projects/Feature/Home/Sources/HomeViewController.swift index bb7ff40..9318a6e 100644 --- a/Projects/Feature/Home/Sources/HomeViewController.swift +++ b/Projects/Feature/Home/Sources/HomeViewController.swift @@ -47,6 +47,19 @@ final class HomeViewController: UIViewController { configureUI() bind() viewModel.viewDidLoad() + // 설정을 다녀온 뒤의 위치 권한 회복 재확인(Phase 15) — 재조회 여부는 VM이 판정한다. + // 셀렉터 기반 관찰: 해제가 자동(iOS 9+)이라 deinit 정리가 필요 없고, 알림은 + // 메인 스레드에서 발송되므로 MainActor VC 메서드 직결로 충분하다. + NotificationCenter.default.addObserver( + self, + selector: #selector(handleDidBecomeActive), + name: UIApplication.didBecomeActiveNotification, + object: nil + ) + } + + @objc private func handleDidBecomeActive() { + viewModel.didBecomeActive() } override func viewWillAppear(_ animated: Bool) { @@ -222,6 +235,15 @@ final class HomeViewController: UIViewController { DSToast.show("알람 등록에 실패했어요. 다시 시도해 주세요.", in: view) case .alarmTooLate: DSToast.show("이미 출발 시간이 지난 경로예요", in: view) + case .notificationPermissionDenied: + DSToast.show( + "막차 변경 알림을 받으려면 설정에서 알림을 허용해주세요", + in: view, + action: .init(title: "설정으로 이동") { + guard let url = URL(string: UIApplication.openSettingsURLString) else { return } + UIApplication.shared.open(url) + } + ) case .alarmCancelFailed: DSToast.show("알람 해제에 실패했어요. 다시 시도해 주세요.", in: view) case let .lastTrainAdvanced(minutes): diff --git a/Projects/Feature/Home/Sources/HomeViewModel.swift b/Projects/Feature/Home/Sources/HomeViewModel.swift index 01af5d6..5635341 100644 --- a/Projects/Feature/Home/Sources/HomeViewModel.swift +++ b/Projects/Feature/Home/Sources/HomeViewModel.swift @@ -42,6 +42,9 @@ final class HomeViewModel { case alarmCancelFailed /// 발화 시각이 이미 과거인 경로의 등록 시도(사전 가드, Phase 14) — 서버 등록 전에 차단됐다. case alarmTooLate + /// 알림 권한이 이번 등록에서 최초 요청됐고 거부됨(Phase 15) — 폴백 노티를 잃었다는 + /// 1회 안내. 요청이 평생 1회(어댑터 가드)라 이 안내도 구조적으로 최대 1회다. + case notificationPermissionDenied /// 포그라운드 인앱 채널: 막차가 당겨졌다는 판정 — VC가 토스트 + 배너 강조로 표출한다. case lastTrainAdvanced(minutes: Int) /// 이미 못 타는 앞당김(actionable=false) — 배너는 실패 문구로 고정되고 원샷 안내만 나간다. @@ -119,6 +122,26 @@ final class HomeViewModel { observeAlarmChanges() } + /// 설정을 다녀온 뒤(didBecomeActive) 위치 권한 회복을 재확인한다(Phase 15). + /// `needsSearch`일 때만 — `.loading`/`.current`면 no-op(권한 팝업 닫힘도 이 노티를 + /// 울리므로 이 가드가 진행 중 재진입·불필요 재조회를 막는다). 재확인 경로는 기존 + /// 표시를 유지한 채 조용히 조회하고 **성공 시에만** 상태를 바꾼다 — 거부 유지 유저의 + /// 매 포그라운드 깜빡임·거부 토스트 재발화(스팸)를 만들지 않는다. + func didBecomeActive() { + guard case .needsSearch = state.departure else { return } + locationTask?.cancel() + locationTask = Task { [weak self] in + guard let locationUseCase = self?.getCurrentLocationUseCase, + let coordinate = try? await locationUseCase.execute() else { return } + guard !Task.isCancelled, + let geocodeUseCase = self?.reverseGeocodeUseCase, + let place = try? await geocodeUseCase.execute(coordinate: coordinate) + else { return } + guard !Task.isCancelled else { return } + self?.state.departure = .current(name: place.name) + } + } + /// 출발지/도착지 어느 필드를 탭해도 동일하게 검색 플로우로 진입한다. func searchFieldTapped() { onSearchRequested? { [weak self] route in @@ -148,7 +171,7 @@ final class HomeViewModel { alarmTask = Task { [weak self] in guard let useCase = self?.registerAlarmUseCase else { return } do { - try await useCase.execute(route: route) + let followUp = try await useCase.execute(route: route) guard !Task.isCancelled else { return } self?.registeredRouteId = route.id self?.state.isAlarmBusy = false @@ -157,6 +180,11 @@ final class HomeViewModel { departure: route.departureTime, firstWalkSeconds: route.firstWalkSectionSeconds ) + // 등록은 성공했고 폴백 노티만 잃었다 — 1회 안내(Phase 15). deniedNow는 + // 이번 호출로 최초 요청이 이뤄졌고 거부된 경우뿐이라 재등록 시 반복되지 않는다. + if followUp == .deniedNow { + self?.onToast?(.notificationPermissionDenied) + } } catch AlarmError.permissionDenied { guard !Task.isCancelled else { return } self?.state.isAlarmBusy = false diff --git a/Projects/Feature/Home/Tests/HomeViewModelTests.swift b/Projects/Feature/Home/Tests/HomeViewModelTests.swift index 7607ac0..e00594a 100644 --- a/Projects/Feature/Home/Tests/HomeViewModelTests.swift +++ b/Projects/Feature/Home/Tests/HomeViewModelTests.swift @@ -17,7 +17,14 @@ private struct StubReverseGeocodeUseCase: ReverseGeocodeUseCase { private struct StubRegisterAlarmUseCase: RegisterAlarmUseCase { let handler: @Sendable (LastRoute) async throws -> Void - func execute(route: LastRoute) async throws { try await handler(route) } + /// 알림 권한 후속 신호(Phase 15) — 기본은 "요청·안내 없음". + var authorizationOutcome: LocalNotificationAuthorizationOutcome = .alreadySettled + + @discardableResult + func execute(route: LastRoute) async throws -> LocalNotificationAuthorizationOutcome { + try await handler(route) + return authorizationOutcome + } } private struct StubCancelAlarmUseCase: CancelAlarmUseCase { @@ -40,6 +47,26 @@ private struct StubGetLastRouteDetailUseCase: GetLastRouteDetailUseCase { func execute(routeId: String) async throws -> LastRoute { try await handler(routeId) } } +/// 테스트 도중 스텁 동작을 바꾸거나 호출 횟수를 세기 위한 가변 박스 (NowBox와 동일 패턴). +private nonisolated final class ValueBox: @unchecked Sendable { + private let lock = NSLock() + private var value: Value + + init(_ value: Value) { self.value = value } + + func get() -> Value { + lock.lock() + defer { lock.unlock() } + return value + } + + func update(_ transform: (Value) -> Value) { + lock.lock() + defer { lock.unlock() } + value = transform(value) + } +} + /// 테스트 도중 `now()`를 전진시키기 위한 가변 시계. private nonisolated final class NowBox: @unchecked Sendable { private let lock = NSLock() @@ -119,6 +146,7 @@ private func makeSUT( Place(name: "강남역", address: "서울 강남구", coordinate: $0) }, register: @escaping @Sendable (LastRoute) async throws -> Void = { _ in }, + registerOutcome: LocalNotificationAuthorizationOutcome = .alreadySettled, cancel: @escaping @Sendable (String) async throws -> Void = { _ in }, alarmUpdates: @escaping @Sendable () -> AsyncStream = { AsyncStream { $0.finish() } @@ -135,7 +163,9 @@ private func makeSUT( HomeViewModel( getCurrentLocationUseCase: StubGetCurrentLocationUseCase(handler: location), reverseGeocodeUseCase: StubReverseGeocodeUseCase(handler: geocode), - registerAlarmUseCase: StubRegisterAlarmUseCase(handler: register), + registerAlarmUseCase: StubRegisterAlarmUseCase( + handler: register, authorizationOutcome: registerOutcome + ), cancelAlarmUseCase: StubCancelAlarmUseCase(handler: cancel), observeAlarmUseCase: StubObserveAlarmUseCase(handler: alarmUpdates), observeAlarmChangeUseCase: StubObserveAlarmChangeUseCase(handler: alarmChanges), @@ -187,6 +217,73 @@ struct HomeViewModelTests { #expect(recorder.toasts.isEmpty) } + // MARK: - 위치 권한 재확인 (Phase 15) + + @Test + func didBecomeActive_needsSearch_recoversDepartureWithoutLoadingFlicker() async { + // 최초 진입은 거부 → needsSearch. 설정에서 허용하고 돌아온(didBecomeActive) 상황. + let granted = ValueBox(false) + let sut = makeSUT(location: { + guard granted.get() else { throw LocationError.permissionDenied } + return Coordinate(latitude: 37.4979, longitude: 127.0276) + }) + let recorder = StateRecorder() + recorder.attach(to: sut) + sut.viewDidLoad() + await recorder.waitUntilLast { $0.departure == .needsSearch(deniedPermission: true) } + let statesBefore = recorder.states.count + + granted.update { _ in true } + sut.didBecomeActive() + await recorder.waitUntilLast { $0.departure == .current(name: "강남역") } + + // 재확인 경로는 .loading을 거치지 않는다 — 성공 상태로만 전이(깜빡임 방지). + #expect(!recorder.states.dropFirst(statesBefore).contains { $0.departure == .loading }) + // 거부 토스트는 최초 진입 1회뿐 — 재확인이 재발화하지 않는다. + #expect(recorder.toasts == [.locationPermissionNeeded]) + } + + @Test + func didBecomeActive_stillDenied_keepsStateAndEmitsNoToast() async { + let calls = ValueBox(0) + let sut = makeSUT(location: { + calls.update { $0 + 1 } + throw LocationError.permissionDenied + }) + let recorder = StateRecorder() + recorder.attach(to: sut) + sut.viewDidLoad() + await recorder.waitUntilLast { $0.departure == .needsSearch(deniedPermission: true) } + let statesBefore = recorder.states.count + + sut.didBecomeActive() + // 실패 경로는 상태 신호가 없다 — 재조회 호출을 확인한 뒤 후처리를 드레인한다. + while calls.get() < 2 { await Task.yield() } + for _ in 0..<20 { await Task.yield() } + + #expect(recorder.states.count == statesBefore) + #expect(recorder.toasts == [.locationPermissionNeeded]) + } + + @Test + func didBecomeActive_departureResolved_doesNotRequery() async { + let calls = ValueBox(0) + let sut = makeSUT(location: { + calls.update { $0 + 1 } + return Coordinate(latitude: 37.4979, longitude: 127.0276) + }) + let recorder = StateRecorder() + recorder.attach(to: sut) + sut.viewDidLoad() + await recorder.waitUntilLast { $0.departure == .current(name: "강남역") } + + // 권한 팝업 닫힘도 didBecomeActive를 울린다 — 이미 해결된 출발지는 재조회하지 않는다. + sut.didBecomeActive() + for _ in 0..<20 { await Task.yield() } + + #expect(calls.get() == 1) + } + @Test func routeSelected_populatesCard() async { let route = makeRoute(id: "r1", departure: fixedNow.addingTimeInterval(42 * 60)) @@ -219,6 +316,40 @@ struct HomeViewModelTests { #expect(sut.state.alarmButton == .cancel) } + // MARK: - 알림 권한 거부 1회 안내 (Phase 15) + + @Test + func registerAlarm_notificationDeniedNow_emitsOneTimeGuidanceToast() async { + let route = makeRoute(id: "r1", departure: fixedNow.addingTimeInterval(42 * 60)) + let sut = makeSUT(registerOutcome: .deniedNow) + let recorder = StateRecorder() + recorder.attach(to: sut) + + sut.routeSelected(route) + sut.registerAlarmTapped() + while recorder.toasts.isEmpty { await Task.yield() } + // 배너는 틱 태스크가 비동기로 채운다 — 토스트와 별도로 기다린다. + await recorder.waitUntilLast { $0.banner != nil } + + // 등록 자체는 성공 — 배너·버튼은 정상 전이하고 안내 토스트만 덧붙는다. + #expect(recorder.toasts == [.notificationPermissionDenied]) + #expect(sut.state.alarmButton == .cancel) + } + + @Test + func registerAlarm_notificationAlreadySettled_emitsNoGuidanceToast() async { + let route = makeRoute(id: "r1", departure: fixedNow.addingTimeInterval(42 * 60)) + let sut = makeSUT(registerOutcome: .alreadySettled) + let recorder = StateRecorder() + recorder.attach(to: sut) + + sut.routeSelected(route) + sut.registerAlarmTapped() + await recorder.waitUntilLast { $0.banner != nil } + + #expect(recorder.toasts.isEmpty) + } + @Test func registerAlarm_failure_emitsToastAndKeepsBannerHidden() async { let route = makeRoute(id: "r1", departure: fixedNow.addingTimeInterval(42 * 60)) From a666e1e955b82b5862c6bb36c2c4617c4a313a8a Mon Sep 17 00:00:00 2001 From: AppGoni Date: Sun, 23 Aug 2026 22:40:31 +0900 Subject: [PATCH 04/14] =?UTF-8?q?docs:=20AtchaV2=20Phase=2016=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20=ED=94=84=EB=A1=AC=ED=94=84=ED=8A=B8=20=E2=80=94=20?= =?UTF-8?q?=EA=B0=B1=EC=8B=A0=20=EC=8B=A0=EB=A2=B0=EC=84=B1=20(=EC=88=98?= =?UTF-8?q?=EB=8F=99=20=EA=B0=B1=EC=8B=A0=20+=20=ED=83=80=EC=9E=84?= =?UTF-8?q?=EC=95=84=EC=9B=83=C2=B7=EC=9E=AC=EC=8B=9C=EB=8F=84=20+=20?= =?UTF-8?q?=EC=98=A4=ED=94=84=EB=9D=BC=EC=9D=B8=20=EA=B5=AC=EB=B6=84=20+?= =?UTF-8?q?=20=EC=8B=A0=EC=84=A0=EB=8F=84=20=EC=8A=A4=ED=83=AC=ED=94=84=20?= =?UTF-8?q?+=20App=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=ED=83=80=EA=B2=9F)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- .../atcha-v2-refresh-reliability-prompt.md | 210 ++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 docs/prompts/atcha-v2-refresh-reliability-prompt.md diff --git a/docs/prompts/atcha-v2-refresh-reliability-prompt.md b/docs/prompts/atcha-v2-refresh-reliability-prompt.md new file mode 100644 index 0000000..6227c15 --- /dev/null +++ b/docs/prompts/atcha-v2-refresh-reliability-prompt.md @@ -0,0 +1,210 @@ +# AtchaV2 갱신 신뢰성 구현 프롬프트 — 수동 갱신 + 타임아웃·재시도 + 오프라인 구분 + 신선도 스탬프 + App 테스트 타겟 + +> **사용법**: 이 문서 전체를 Claude Code에 컨텍스트로 전달하고 `"Phase 16을 진행해"`라고 지시한다. +> 실행 에이전트는 [마스터 프롬프트](atcha-v2-master-prompt.md)의 **진행 프로토콜·공통 규칙·공통 acceptance를 그대로 상속**하며, 한 번에 한 Phase만 수행한다. +> 갭 분석·우선순위 정본은 [Post-12 로드맵](../planning/atcha-v2-post12-roadmap.md)의 "Phase 16 — 갱신 신뢰성" 절. 충돌 시 **CLAUDE.md > 마스터 프롬프트 > [LA 프롬프트](atcha-v2-live-activity-prompt.md) > [세션 수명주기 프롬프트](atcha-v2-session-lifecycle-prompt.md) > [인지 채널 방어선 프롬프트](atcha-v2-channel-defense-prompt.md) > 이 문서** 순. +> **검수는 사람 검수가 아니라 [자동 검수 규약](atcha-v2-auto-verification.md)을 따른다** — 실행 에이전트가 computer use로 직접 수행·증적 보고하고, 실기기 잔여 항목만 사용자에게 이관한다. +> 작성일: 2026-08-23. + +--- + +## Goal (최상위) + +**갱신이 조용히 실패해도 앱이 거짓말하지 않게 한다 — 사용자에게 수동 갱신 수단을 주고, 네트워크가 빨리 실패하게 하고, 화면의 숫자가 언제 확인된 값인지 말한다.** + +Phase 8의 갱신 채널은 자동 트리거 3경로(앱 시작·포그라운드 복귀·푸시)뿐이라 사용자가 지금 값을 의심해도 할 수 있는 일이 없고, Stage/Release의 URLSession은 기본 60초 타임아웃이라 심야의 약한 연결에서 스플래시·갱신이 1분을 침묵하며, 실패 문구는 원인 불문 "네트워크 연결을 확인해주세요" 하나고, sync 실패는 완전한 무음이라 배너·카드가 언제 값인지 아무도 모른다. 그리고 이 모든 판정·폴백 분기의 심장인 `AlarmSyncService`는 App 타겟에 테스트 타겟이 없어 **무테스트**다. 이 문서는 그 다섯 구멍을 막는다. Phase 번호는 인지 채널 방어선(15)에 이어 **16**. + +[신뢰 UX 원칙](../planning/atcha-v2-post12-roadmap.md#신뢰-ux-원칙-전-phase-공통) 3("신선도 스탬프 — 갱신 실패를 토스트로 소음화하지 않고 조용히 정직하게")·4("안전망 약속의 문장화")의 직접 구현이다. + +갱신 신뢰성의 완성 상태 (이 문서가 만드는 구조): + +``` +갱신 트리거 4경로 — 전부 같은 sync() 한 곳으로 (기존 3 + 수동 1, inFlight 합류) + 앱 시작 ────────────┐ + 포그라운드 복귀 ─────┤──► AlarmSyncService.sync() + 사일런트 푸시 ───────┤ ├─ 성공 ──► updates(AlarmSyncUpdate: info + checkedAt) + 홈 pull-to-refresh ──┘ │ └─► 배너·카드 + "HH:mm 확인 기준" 스탬프 + (신설 — AlarmSyncRequesting) └─ 실패 ──► 무음 — 스탬프가 낡은 시각을 정직하게 유지 + + 네트워크 요청 1회의 수명 + Stage/Release 타임아웃 10초(기본 60초 해소) ──► GET + transport 실패면 1회 재시도 + 연결 자체가 없음 ──► NetworkError.offline ──► 스플래시 실패 문구 분기 + + App 타겟 테스트 타겟(AtchaV2Tests) ──► AlarmSyncService 판정·폴백·만료 분기 회귀 방어 + (UIApplication.shared·Date() 직접 참조 → isAppActive·now 주입으로 교체) +``` + +확정된 제품 결정사항 (변경하려면 사용자에게 먼저 물을 것 — [로드맵](../planning/atcha-v2-post12-roadmap.md) 2026-08-23 확정): + +| 항목 | 결정 | +|---|---| +| 수동 갱신 표면 | **홈 pull-to-refresh 단일** (새 버튼·화면 없음). Domain 포트 `AlarmSyncRequesting` + `RequestAlarmSyncUseCase` — 홈은 UseCase만 본다(Observe 계열과 같은 패턴). `AlarmSyncService`가 4번째 트리거로 순응하되 **기존 inFlight 합류를 재사용** — 당김·포그라운드 복귀가 겹쳐도 refresh는 1회다 | +| 수동 갱신 실패 | **무음** — 실패 토스트 금지(원칙 3: 소음화 지양). 스피너 종료 + 스탬프가 낡은 시각을 유지하는 것이 실패의 표면이다 | +| 스탬프 문구·위치 | **"HH:mm 확인 기준"** — 배너 보조 라인(`DSBanner` detailText) + 카드 푸터(`DSRouteCard` footnoteText) 두 서피스, 값은 단일 소스(State 필드 1개). 표출 조건: **등록 세션 존재 ∧ 확인 시각 존재**. 세션 정리(해제·만료·sessionEnded)와 함께 사라진다 — "지난 막차" 카드에는 스탬프가 없다 | +| 스탬프의 원천 | **서버가 값을 확인해준 시각만** — 등록 성공 시각·refresh 성공 시각. 홈이 수신 시각으로 찍지 않는다(스냅샷 시딩 복원값이 "지금 확인됨"으로 둔갑하는 거짓 방지). 시딩은 스냅샷에 영속화된 마지막 확인 시각(`syncedAt`)을 나른다 — 재실행·오프라인에서도 "마지막으로 확인된 그 시각"이 표시된다 | +| 타임아웃 | Stage/Release `URLSessionConfiguration.default` 기반 **request 10초 · resource 30초**. DEV의 3/5초는 검수용 임시 우회로 불변(제거 조건은 DevDemoFallbacks와 동반 — 기존 주석) | +| 재시도 | **멱등 GET 1회**, `URLSessionNetworkClient` 내부. 대상은 transport 계열(타임아웃·연결 끊김)만 — offline(즉시 재실패라 무의미)·취소(사용자 의사)·HTTP 상태·디코딩은 제외. **POST/DELETE 재시도 금지**(알람 등록·해제 이중 발사 방지) | +| 오프라인 구분 | `NetworkError.offline` 신설 — URLError `.notConnectedToInternet`·`.dataNotAllowed`만. `.networkConnectionLost`는 일시 장애로 transport 유지(재시도로 살리는 쪽이 맞다) | +| 스플래시 문구 | offline → "네트워크 연결을 확인해주세요"(기존 문구 유지) / 그 외 → **"일시적인 문제가 생겼어요. 잠시 후 다시 시도해주세요"**. 매핑은 App의 순수 헬퍼 함수로(테스트 대상). 현 DEV는 `bootstrap()`이 `issuerNotConfigured`를 삼켜 재시도 화면 자체가 안 뜬다 — 실표출은 S1(익명 인증) 이후이므로 **이 분기의 검수는 단위 테스트**다 | +| App 테스트 타겟 | `AtchaV2Tests` 신설(**host app 방식** — 앱 타겟 의존으로 internal 심볼 `@testable` 접근) + `AtchaV2` 스킴에 testAction. `AlarmSyncService`의 `UIApplication.shared` 직접 참조 3곳·`Date()` 직접 호출 5곳을 **주입(isAppActive·now)으로 교체** — 판정·폴백·만료 분기의 회귀 방어가 이 Phase의 핵심 산출물이다. 테스트 진입점은 `syncNow()`(수동 갱신과 동일 경로 — 부수 효과로 NotificationCenter 없이 전 분기 도달) | + +--- + +## 이 문서가 다시 정의하지 않는 것 (중복 금지) + +아래는 기존 Phase 산출물이다. **계약을 바꾸지 않고 명시된 지점만 확장한다.** 이 목록의 계약을 깨고 싶어지면 멈추고 사용자에게 물을 것. + +| 산출물 | 소속 | 이 문서에서의 취급 | +|---|---|---| +| `AlarmSyncService` 3경로 일원화 구조·판정 훅·폴백 조건(`isAlertReachable`)·최후통첩 applicationState 선행 검사 | Phase 8·11·15 | **구조·조건 불변** — 수동 트리거가 같은 `sync()`에 합류하고, `UIApplication`/`Date()` 참조가 주입으로 바뀔 뿐 분기 의미는 그대로다. 분기들은 이제 회귀 테스트의 대상이 된다 | +| `LastTrainActivityPort`(문서 고정 계약) / `AlarmChangeVerdict` / `LocalNotificationPort` | Phase 10·11·12·15 | **시그니처 불변.** 케이스 추가 금지 | +| 스냅샷 = 재실행 브리지, 정본은 서버 | Phase 14 | 성격 불변 — `syncedAt` 필드 1개만 추가(Codable 하위호환: 구 스냅샷은 nil로 디코딩된다 — `decodeIfPresent` 합성) | +| `AlarmSyncEvents` replay-1·실패 무음 정책 | Phase 8 | 정책 불변 — **방출 타입만** `AlarmSyncUpdate`(info + checkedAt)로 확장. 실패는 여전히 스트림에 흐르지 않는다 | +| DEV 데모 폴백·변경 시뮬레이터·DEV 3/5초 타임아웃 | Phase 11·14 | 불변 — 검수 재료. **DEV refresh가 주입 없이는 실서버 실패를 그대로 실패시키는 동작**이 "무음 실패 시 스탬프 유지" 검수의 재료가 된다 | +| 서버 계약 전체 | 마스터 공통 규칙 | **서버 변경 0.** 미확정 #11("등록된 알람 없음" 표현)을 이 Phase가 해소하지 않는다 — pull-to-refresh도 알람 없음을 정리하지 않는다(기존 TODO 유지) | + +## 전제 조건 + +1. **Phase 15 완료가 전제** (`feat/v2-phase15-channel-defense` 기준). 이 문서 내부의 병렬 없음 — Phase 16 단일. +2. 서버 트랙(로드맵 S1~S4)과 **완전 독립** — 미확정 입력을 새로 요구하지 않는다. 검수는 [자동 검수 규약](atcha-v2-auto-verification.md)에 따라 DEV 데모 폴백·변경 시뮬레이터를 재료로 에이전트가 직접 수행한다. +3. pull-to-refresh의 **당김 제스처** 자동화는 실측 제약(AX 액션 기반 조작만 신뢰)에 걸릴 수 있다 — 불가로 판명되면 규약의 불가 시 분기를 따른다(자동 검수 절에 명시). + +--- + +## Phase 16 — 갱신 신뢰성 + +### Goal +사용자가 원할 때 갱신할 수 있고(당김), 갱신이 빨리 실패하고(타임아웃·재시도), 실패의 원인이 구분되고(오프라인), 화면의 숫자가 언제 확인된 값인지 항상 말하며(스탬프), 그 전 과정을 회귀 테스트가 지키게 한다(App 테스트 타겟). + +### Requirements + +- **수동 갱신 경로 (Domain 포트 + App 순응 + 홈 pull-to-refresh)**: Domain에 요청 포트와 UseCase를 신설한다: + ```swift + /// 수동 동기화 요청 포트(Phase 16) — 구현은 App의 AlarmSyncService(4번째 트리거). + public protocol AlarmSyncRequesting: Sendable { + /// 동기화 1회를 요청하고 완료까지 기다린다. 진행 중 동기화가 있으면 합류한다. + /// 실패를 던지지 않는다 — 결과는 AlarmSyncEvents.updates()로만 흐른다(무음 정책 공유). + func syncNow() async + } + // RequestAlarmSyncUseCase (프로토콜 + Default) — Observe 계열과 동일 패턴. + ``` + `AlarmSyncService`는 `AlarmSyncRequesting`을 채택한다(`nonisolated func syncNow() async`가 메인 액터의 `sync()`로 hop — inFlight 합류가 이미 있어 재진입 무해). `HomeViewController`는 contentStack을 `UIScrollView`(alwaysBounceVertical)로 감싸고 `UIRefreshControl`을 부착한다 — 시각 레이아웃은 불변. `HomeViewModel.refreshPulled()`는 진행 중 재진입을 no-op으로 가드하고, 완료 시 `onManualSyncFinished` 훅으로 VC가 `endRefreshing()`한다. 수동 경로가 **새 표출 채널을 만들지 않는다** — 시각·상태 갱신은 기존 updates()/changes() 스트림이 그대로 담당한다. +- **Stage/Release 타임아웃 (App — `AppDIContainer`)**: `#else`(비-DEV) 분기의 `URLSessionNetworkClient`에 `URLSessionConfiguration.default` 기반 `timeoutIntervalForRequest = 10`, `timeoutIntervalForResource = 30` 세션을 주입한다. DEV의 3/5초 임시 우회 분기는 불변. +- **멱등 GET 1회 재시도 (CoreNetwork — `URLSessionNetworkClient`)**: `data(for:)`에서 `endpoint.method == .get`이고 첫 시도가 **transport로 분류되는** 실패면 즉시 1회 재시도한다. offline 분류·취소(`URLError.cancelled`/`CancellationError`)·HTTP 상태·디코딩 실패는 재시도하지 않는다. GET 외 메서드는 재시도 없음. +- **오프라인 구분 + 스플래시 문구 분기 (CoreNetwork + App)**: `NetworkError`에 케이스를 신설하고 분류를 전송 계층 한 곳에서 한다: + ```swift + public enum NetworkError: Error, Sendable { + case invalidURL + /// 연결 자체가 없음(URLError .notConnectedToInternet/.dataNotAllowed) — 재시도 무의미. + /// .networkConnectionLost는 일시 장애로 transport 유지(재시도 대상). + case offline(underlying: any Error) + case transport(underlying: any Error) + case invalidResponse + case unacceptableStatus(code: Int, data: Data) + case decoding(underlying: any Error) + } + ``` + `isOffline` 편의 게터를 함께 둔다. App에는 순수 매핑 헬퍼(예: `BootstrapFailureMessage.text(for: any Error) -> String`)를 신설해 `AppCoordinator.bootstrap()`의 catch가 `SplashViewController.showRetry(message:)`(시그니처 확장 — 기본 문구 유지)로 전달한다: offline → "네트워크 연결을 확인해주세요" / 그 외 → "일시적인 문제가 생겼어요. 잠시 후 다시 시도해주세요". 헬퍼는 `AtchaV2Tests` 대상 — 현 DEV에선 재시도 화면이 도달 불가(전제 조건 참고)라 UI 검수 항목이 아니다. +- **신선도 스탬프 (Domain 방출 확장 + 스냅샷 영속화 + 홈·DS 표출)**: + - Domain: `AlarmSyncEvents.updates()`의 방출 타입을 확장한다(정책 불변 — 값에 확인 시각만 동봉): + ```swift + /// 동기화 성공 방출값 — info에 "언제 서버로 확인했는가"를 동봉한다(신선도 스탬프의 원천). + public struct AlarmSyncUpdate: Sendable, Equatable { + public let info: AlarmInfo + /// 서버 확인 시각. 스냅샷 시딩 복원이면 직전 세션의 마지막 확인 시각, 그것도 없으면 nil(스탬프 없음). + public let checkedAt: Date? + } + public protocol AlarmSyncEvents: Sendable { + func updates() -> AsyncStream + } + ``` + `ObserveAlarmUseCase`·`DefaultObserveAlarmUseCase`가 따라간다. `AlarmSessionSnapshot`에 `syncedAt: Date?`를 추가한다(init 기본값 nil + `updating`에 갱신 파라미터 — 구 스냅샷은 nil 디코딩으로 하위호환). + - App: `AlarmSyncService`가 sync 성공 시 `checkedAt = now()`로 방출·스냅샷 병합 저장에 `syncedAt` 기록, 시딩 방출은 `snapshot.syncedAt`을 나른다. `DefaultRegisterAlarmUseCase`는 등록 성공 스냅샷 저장 시 `syncedAt = now()`(등록도 서버 확인이다). + - HomeFeature: `State`에 `freshnessText: String?` 단일 필드 — "HH:mm 확인 기준"(기존 캐시 포매터 재사용). 표출 조건은 등록 세션 존재 ∧ 확인 시각 존재이고, 등록 성공 시 `now()` 기준으로 세팅, updates 수신 시 `checkedAt`으로 갱신(nil이면 유지하지 않고 nil — 낡음을 숨기지 않는다), 해제·만료·sessionEnded 정리 시 nil. 배너 틱은 스탬프를 건드리지 않는다(배너 텍스트와 독립). + - DesignSystem(추가만 — 기존 API 파괴 금지): `DSBanner.configure(text:style:detailText: String? = nil)` — 스타일별 보조 톤의 caption 라인, nil이면 기존 렌더와 동일. `DSRouteCard.Content`에 `footnoteText: String? = nil` — caption·tertiary 푸터, muted 톤 대응. 색·폰트는 기존 토큰 경유(신규 토큰 불필요 판단이 기본). + - VC: `render()`가 `state.freshnessText`를 배너 detailText와 카드 footnote 두 서피스에 반영한다(`RouteCardViewData.dsContent`는 footnote 주입 형태로 조정). +- **App 테스트 타겟 신설 (Tuist 매니페스트 + `AlarmSyncService` 주입 + 회귀 테스트)**: + - `Projects/App/Project.swift`에 유닛 테스트 타겟을 추가하고 스킴에 연결한다: + ```swift + let testTarget = Target.target( + name: "AtchaV2Tests", + destinations: Atcha.destinations, + product: .unitTests, + bundleId: "\(Atcha.v2BundleID).tests", + deploymentTargets: Atcha.v2Deployment, + infoPlist: .default, + sources: ["Tests/**"], + dependencies: [.target(name: "AtchaV2")], // host app — internal 심볼 @testable 접근 + settings: .atchaV2() + ) + // AtchaV2 스킴: testAction: .targets(["AtchaV2Tests"]) 추가 (Debug 기본) + ``` + Workspace.swift 변경 없음(기존 프로젝트에 타겟 추가). `tuist generate` 필수. + - `AlarmSyncService`의 시스템 직결 지점을 주입으로 교체한다(기본값이 현 동작 — 콜사이트 무변경): + ```swift + init( + ..., + /// 표출 채널 분기용 앱 활성 판정(Phase 16) — UIApplication 직접 참조를 걷어내 테스트가 상태를 주입한다. + isAppActive: @escaping @MainActor () -> Bool = { UIApplication.shared.applicationState == .active }, + /// 만료·판정·스탬프의 시각 주입 — 실 Date() 직접 호출 제거(기존 UseCase·VM 관례와 동일). + now: @escaping @Sendable () -> Date = { Date() } + ) + ``` + 본문의 `UIApplication.shared.applicationState == .active` 3곳 → `isAppActive()`, `Date()` 5곳 → `now()`. + - `Projects/App/Tests/`에 Swift Testing으로 회귀 테스트를 작성한다(스텁: 큐잉 `RefreshAlarmUseCase`, 고정 판정 `EvaluateAlarmChangeUseCase`, reachable 제어 가능한 `LastTrainChangeAlerting` 스파이, `LocalNotificationPort`·`AlarmScheduler`·`LastTrainSessionRestoring` 스파이, 인메모리 `AlarmSessionSnapshotStore` — Tests/Example 스텁 중복은 기존 트레이드오프). 진입은 `syncNow()`. 최소 커버 목록: + 1. advanced(actionable) **백그라운드 + reachable** → LA alert 1회, 로컬 노티 0 + 2. advanced **백그라운드 + unreachable** → 로컬 노티 1회, LA alert 0 (Phase 15 폴백 회귀) + 3. advanced **포그라운드** → 조용한 update(alert nil)만 + verdict yield (인앱 채널 단독) + 4. **최후통첩**(새 알람 시각 과거·출발 미래) 포그라운드 → 조용한 update만, alert·노티 0 (Phase 15 이중 알림 제거 회귀) + 5. 최후통첩 백그라운드 reachable → LA alert / unreachable → 로컬 노티 + 6. missed(actionable=false) 3분기(포그라운드 조용 / reachable alert / unreachable 노티) + 7. sessionEnded → 알람 취소 + 스냅샷 clear + LA end (배지 정리 포함) + 8. **클라 자체 만료**: 시딩된 과거 세션 + refresh 실패 → 알람 취소·expired 톰스톤·sessionEnded yield (Phase 13 회귀 — now 주입으로 시각 고정) + 9. **서버 우선**: 만료 후보 상태에서 refresh가 미래 출발 반환 → 만료 취소·정상 갱신 + 10. **신선도**: sync 성공 → `checkedAt` = 주입 now / 시딩 → `snapshot.syncedAt` / 실패 → yield 없음 + - `BootstrapFailureMessage` 매핑 테스트(offline/기타/비 NetworkError)도 같은 타겟에 둔다. + +### Constraints +- 알람 재스케줄·안전망 경로에 회귀 금지 — 이 Phase는 트리거 1개 추가·주입 교체·표출 확장뿐, `RefreshAlarmUseCase` 내부 정책과 판정·폴백 분기의 의미를 바꾸지 않는다. +- 수동 갱신 실패에 토스트·알럿 금지(결정사항). 오프라인 구분을 홈 표출에 쓰지 않는다 — 이번 스코프의 오프라인 분기는 스플래시 문구뿐. +- `UNUserNotificationCenter`·ActivityKit·`UIApplication` 심볼의 Domain·Feature 유입 금지(기존 규약 — `AlarmSyncRequesting`·`AlarmSyncUpdate`는 순수 타입). `tuist graph`로 의존 방향 확인. +- 테스트는 Swift Testing, 실 `Date()`·실 UserDefaults 금지(주입·인메모리 스텁 — 기존 관례). AtchaV2Tests는 host app에서 돌지만 **서비스 단독 인스턴스**를 만들어 테스트한다(앱이 띄운 전역 상태에 의존·간섭 금지). +- `Tuist/Package.swift`·`Package.resolved` 무변경. 레거시 무변경. +- Phase 17~18 선취 금지: 검색·홈 빈 상태, `arrivalField` 바인딩, `LocationError` 세분화, 오늘/내일 라벨, SearchCoordinator 누수 수정(17), 최근 경로 칩(18)은 이 문서 밖. 미확정 #11(알람 없음 표현) 해소 시도 금지 — 기존 TODO 유지. + +### Acceptance +공통 acceptance + `-scheme Domain test`(AlarmSyncUpdate·RequestAlarmSyncUseCase·스냅샷 syncedAt) + `-scheme CoreNetwork test`(offline 분류·GET 재시도·비멱등 무재시도·취소 무재시도) + `-scheme DesignSystem test` + `-scheme HomeFeature test`(refreshPulled 가드·완료 훅·스탬프 표출/유지/정리) + **`-scheme AtchaV2 test`(신설 — App 타겟 회귀)**. + +### 자동 검수 (블로킹 — [자동 검수 규약](atcha-v2-auto-verification.md)) +iOS 26 시뮬레이터(Debug/DEV)에서 에이전트가 직접 수행하고 단계별 스크린샷 증적으로 보고. DEV refresh는 변경 주입이 없으면 실서버 실패를 그대로 실패시킨다 — 이 동작이 ②의 재료다. +① **스탬프 표출**: 데모 경로 알람 등록 → 배너 보조 라인·카드 푸터에 "HH:mm 확인 기준"(등록 시각) 표출 스크린샷. +② **무음 실패 정직성**: 1분 이상 경과 후 pull-to-refresh(주입 없음 → refresh 실패) → 스피너 종료 + **스탬프 시각 불변**(등록 시각 유지) + 실패 토스트 없음 스크린샷 — "낡았다고 말한다"의 직접 증명. +③ **수동 갱신 성공**: DEV "변경" 버튼으로 늦춤 주입 → pull-to-refresh → 배너 시각 갱신(조용한 delayed) + **스탬프가 현재 시각으로 갱신** 스크린샷 — 당김이 실동작하는 수동 갱신 수단이라는 직접 증명. +④ **재실행 복원**: `simctl terminate` → 재실행 → 시딩 스탬프가 **마지막 확인 시각을 유지**(재실행 시각으로 둔갑하지 않음) 스크린샷 (직후 자동 sync는 주입 없으면 실패하므로 관찰 가능). +⑤ **회귀**: 앞당김 주입 + 포그라운드 → 기존 인앱 채널(토스트 + 배너 강조) 동작 유지 + 스탬프 갱신. 스피너 진행 중 재당김 → 재진입 no-op(로그 증적). +당김 제스처 자동화가 불가로 판명되면(AX 기반 조작 한계): 판정을 "자동화 불가"로 기록하고, VM 경로는 단위 테스트로 검증돼 있으므로 **DEV 플로팅 디버그 메뉴에 검수용 "수동 갱신" 항목(syncNow 직결, DEV 한정 — 변경 시뮬레이터와 동일 취급)을 추가**해 ②·③의 스탬프 판정을 대체 수행하고, 실제 당김 제스처만 실기기 잔여로 이관한다. + +**실기기 잔여**: 실서버 오프라인·타임아웃 실측(스플래시 문구 분기 실표출 포함 — 현 DEV는 issuerNotConfigured 삼킴으로 재시도 화면 도달 불가, S1 이후 확인). 사일런트 푸시 실수신 경로(기존 항상-잔여 항목). (해당 시) pull-to-refresh 당김 제스처 실동작. + +--- + +## 진행 프로토콜 + +[마스터 프롬프트의 진행 프로토콜](atcha-v2-master-prompt.md#진행-프로토콜) 1~6을 그대로 상속한다. 추가 규칙: + +1. 이 문서는 **Phase 16 단일** — 내부 병렬 없음. Phase 15 완료 커밋 위에서 진행한다. +2. ["이 문서가 다시 정의하지 않는 것"](#이-문서가-다시-정의하지-않는-것-중복-금지) 표의 계약을 바꾸고 싶어지면 멈추고 사용자에게 물을 것. +3. Phase 17~18 산출물을 **선취하지 않는다** — [로드맵](../planning/atcha-v2-post12-roadmap.md)의 몫. +4. 검수는 [자동 검수 규약](atcha-v2-auto-verification.md)을 따른다 — "자동 검수 (블로킹)"는 에이전트가 computer use로 수행·증적 보고를 마쳐야 다음 진행, "실기기 잔여"만 사용자에게 이관한다. +5. 당김 제스처 자동화 불가가 확정되면 결과를 **이 문서 자동 검수 절에 기록**하고 명시된 대체 수단(DEV 메뉴 항목)으로 검수를 완료한다. + +## 미확정 입력 (참조) + +이 문서는 새 미확정 입력을 만들지 않는다. 관련 기존 항목의 취급: + +| # | 항목 | 이 문서에서의 취급 | +|---|---|---| +| 11 | 서버의 "등록된 알람 없음" 표현 | **미해소 유지** — pull-to-refresh도 실패 무음 정책을 공유하므로 유령 알람을 정리하지 않는다(기존 `HomeViewModel` TODO 그대로). 표현 확정 시 정리 이벤트가 이 스트림 위에 얹힌다 | +| 1 | Stage 전용 호스트 | 이 문서 밖 — 타임아웃 설정은 호스트와 무관하게 유효하다 | +| 2 | 익명 인증 발급 엔드포인트 | 이 문서 밖(S1) — 스플래시 문구 분기는 S1 이후 실표출되지만 매핑·테스트는 지금 완성한다 | +| 원장 전체 | [Post-12 로드맵](../planning/atcha-v2-post12-roadmap.md)의 "미확정 입력 원장" 절 참조 | | From c9a517a60b1a8397b0ec537d56b003c9b36802aa Mon Sep 17 00:00:00 2001 From: AppGoni Date: Sun, 23 Aug 2026 23:09:46 +0900 Subject: [PATCH 05/14] =?UTF-8?q?feat:=20AtchaV2=20Phase=2016=20=E2=80=94?= =?UTF-8?q?=20=EA=B0=B1=EC=8B=A0=20=EC=8B=A0=EB=A2=B0=EC=84=B1=20(pull-to-?= =?UTF-8?q?refresh=20+=20=ED=83=80=EC=9E=84=EC=95=84=EC=9B=83=C2=B7?= =?UTF-8?q?=EC=9E=AC=EC=8B=9C=EB=8F=84=20+=20=EC=98=A4=ED=94=84=EB=9D=BC?= =?UTF-8?q?=EC=9D=B8=20=EA=B5=AC=EB=B6=84=20+=20=EC=8B=A0=EC=84=A0?= =?UTF-8?q?=EB=8F=84=20=EC=8A=A4=ED=83=AC=ED=94=84=20+=20App=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=ED=83=80=EA=B2=9F)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 수동 갱신: Domain AlarmSyncRequesting/RequestAlarmSyncUseCase + AlarmSyncService.syncNow(4번째 트리거, inFlight 합류) + 홈 스크롤 래핑·UIRefreshControl(실패 무음) - Stage/Release URLSession 타임아웃 10/30초 + CoreNetwork 멱등 GET 1회 재시도(transport 한정) - NetworkError.offline 신설(notConnectedToInternet·dataNotAllowed) + 스플래시 실패 문구 분기(BootstrapFailureMessage) - 신선도 스탬프: AlarmSyncUpdate(info+checkedAt) 방출 + 스냅샷 syncedAt 영속화 + 배너 보조 라인·카드 푸터 "HH:mm 확인 기준" - App 테스트 타겟(AtchaV2Tests) 신설 — AlarmSyncService UIApplication·Date() 직접 참조를 isAppActive·now 주입으로 교체, 판정·폴백·만료 분기 회귀 테스트 11건 + 스플래시 매핑 테스트 Co-Authored-By: Claude Fable 5 --- Projects/App/Project.swift | 17 +- Projects/App/Sources/AlarmSyncService.swift | 81 +++- Projects/App/Sources/AppCoordinator.swift | 5 +- Projects/App/Sources/AppDIContainer.swift | 10 +- .../App/Sources/BootstrapFailureMessage.swift | 14 + .../App/Sources/SplashViewController.swift | 5 +- .../App/Tests/AlarmSyncServiceTests.swift | 391 ++++++++++++++++++ .../Tests/BootstrapFailureMessageTests.swift | 26 ++ .../Core/Network/Sources/NetworkError.swift | 20 + .../Sources/URLSessionNetworkClient.swift | 17 +- .../URLSessionNetworkClientRetryTests.swift | 149 +++++++ .../Sources/Components/DSBanner.swift | 30 +- .../Sources/Components/DSRouteCard.swift | 13 +- .../Entities/AlarmSessionSnapshot.swift | 15 +- .../Sources/Interfaces/AlarmSyncEvents.swift | 22 +- .../Interfaces/AlarmSyncRequesting.swift | 10 + .../UseCases/ObserveAlarmUseCase.swift | 4 +- .../UseCases/RegisterAlarmUseCase.swift | 4 +- .../UseCases/RequestAlarmSyncUseCase.swift | 20 + .../Tests/AlarmSessionSnapshotTests.swift | 38 +- .../DefaultObserveAlarmUseCaseTests.swift | 28 +- .../DefaultRegisterAlarmUseCaseTests.swift | 2 + .../DefaultRequestAlarmSyncUseCaseTests.swift | 22 + .../Feature/Home/Example/ExampleApp.swift | 10 +- .../Home/Sources/HomeDIContainer.swift | 4 + .../Home/Sources/HomeViewController.swift | 42 +- .../Feature/Home/Sources/HomeViewData.swift | 14 +- .../Feature/Home/Sources/HomeViewModel.swift | 69 +++- .../Home/Tests/HomeViewModelTests.swift | 242 +++++++++-- 29 files changed, 1228 insertions(+), 96 deletions(-) create mode 100644 Projects/App/Sources/BootstrapFailureMessage.swift create mode 100644 Projects/App/Tests/AlarmSyncServiceTests.swift create mode 100644 Projects/App/Tests/BootstrapFailureMessageTests.swift create mode 100644 Projects/Core/Network/Tests/URLSessionNetworkClientRetryTests.swift create mode 100644 Projects/Domain/Sources/Interfaces/AlarmSyncRequesting.swift create mode 100644 Projects/Domain/Sources/UseCases/RequestAlarmSyncUseCase.swift create mode 100644 Projects/Domain/Tests/DefaultRequestAlarmSyncUseCaseTests.swift diff --git a/Projects/App/Project.swift b/Projects/App/Project.swift index d25407f..68fe0fc 100644 --- a/Projects/App/Project.swift +++ b/Projects/App/Project.swift @@ -65,6 +65,20 @@ let appTarget = Target.target( ]) ) +// App 타겟 테스트 타겟(Phase 16) — host app 방식: 앱 타겟 의존으로 internal 심볼을 +// @testable 접근한다. AlarmSyncService(판정·폴백·만료 분기)의 회귀 방어가 목적. +let testTarget = Target.target( + name: "AtchaV2Tests", + destinations: Atcha.destinations, + product: .unitTests, + bundleId: "\(Atcha.v2BundleID).tests", + deploymentTargets: Atcha.v2Deployment, + infoPlist: .default, + sources: ["Tests/**"], + dependencies: [.target(name: "AtchaV2")], + settings: .atchaV2() +) + let widgetTarget = Target.widgetExtension( name: "AtchaWidget", bundleId: "\(Atcha.v2BundleID).widget", @@ -84,12 +98,13 @@ let project = Project( developmentRegion: Atcha.developmentRegion ), settings: .atchaV2(), - targets: [appTarget, widgetTarget], + targets: [appTarget, widgetTarget, testTarget], schemes: [ .scheme( name: "AtchaV2", shared: true, buildAction: .buildAction(targets: ["AtchaV2"]), + testAction: .targets(["AtchaV2Tests"]), runAction: .runAction(configuration: "Debug", executable: "AtchaV2"), archiveAction: .archiveAction(configuration: "Debug"), profileAction: .profileAction(configuration: "Debug", executable: "AtchaV2"), diff --git a/Projects/App/Sources/AlarmSyncService.swift b/Projects/App/Sources/AlarmSyncService.swift index 7baff5c..4a422e1 100644 --- a/Projects/App/Sources/AlarmSyncService.swift +++ b/Projects/App/Sources/AlarmSyncService.swift @@ -32,10 +32,16 @@ import os /// 병합 저장하고, 스냅샷은 살아 있는데 활성 LA가 없는 죽은 세션은 로컬 재시작을 /// 위임한다(dismiss·확인 기록 존중은 어댑터 몫). 도보 초는 스냅샷에서 읽어 LA 알람 /// 시각 계산이 등록/refresh와 같은 기준을 탄다(이중 시각 금지). +/// Phase 16 갱신 신뢰성: ⑦ 홈 pull-to-refresh가 4번째 트리거(`AlarmSyncRequesting`)로 +/// 합류한다 — inFlight 합류가 있어 당김·포그라운드 복귀가 겹쳐도 refresh는 1회. +/// ⑧ sync 성공마다 확인 시각(checkedAt)을 방출·스냅샷(syncedAt)에 영속화해 신선도 +/// 스탬프("HH:mm 확인 기준")의 원천이 된다 — 시딩 방출은 직전 세션의 마지막 확인 +/// 시각을 나른다(실패 무음의 정직한 표면화, 원칙 3). ⑨ `UIApplication`·`Date()` 직접 +/// 참조는 주입(isAppActive·now)으로 교체 — App 테스트 타겟의 회귀 방어 대상이 됐다. // Sendable 프로토콜(AlarmSyncEvents 등) 채택이 기본 MainActor 격리를 nonisolated로 // 추론시키므로 명시한다 — 상태(subscribers 등)는 전부 메인 액터에서만 만진다. @MainActor -final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { +final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents, AlarmSyncRequesting { private let refreshAlarmUseCase: any RefreshAlarmUseCase private let evaluateChangeUseCase: any EvaluateAlarmChangeUseCase /// LA 표출 경로 — non-throwing 계약(어댑터가 실패 흡수)이라 이 훅의 어떤 실패도 무해하다. @@ -50,17 +56,25 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { private let snapshotStore: any AlarmSessionSnapshotStore /// 죽은 세션 LA 재시작 경로(Phase 14) — dismiss·확인 기록 판정은 어댑터가 한다. private let sessionRestorer: any LastTrainSessionRestoring + /// 표출 채널 분기용 앱 활성 판정(Phase 16) — UIApplication 직접 참조를 걷어내 + /// 테스트가 상태를 주입한다. 분기 의미(포그라운드 = 인앱 채널 단독)는 불변. + private let isAppActive: @MainActor () -> Bool + /// 만료·판정·스탬프의 시각 주입(Phase 16) — 실 Date() 직접 호출 제거(기존 관례). + private let now: @Sendable () -> Date private static let logger = Logger(subsystem: "com.atcha.iOS.v2", category: "AlarmSync") /// "⚠ 당겨짐" 배지 유지 시간 — 정책: 표출 시점 + 10분. private static let changeBadgeDuration: TimeInterval = 600 - private var subscribers: [UUID: AsyncStream.Continuation] = [:] + private var subscribers: [UUID: AsyncStream.Continuation] = [:] /// 변경 판정 구독자 — updates()와 달리 **replay 없음**(과거 변경이 재구독 시 재발화 금지). private var changeSubscribers: [UUID: AsyncStream.Continuation] = [:] /// 구독 전에 끝난 동기화를 놓치지 않기 위한 replay-1. 홈은 앱 시작 동기화와 /// 거의 동시에 구독하므로 순서에 기대지 않는다. 변경 판정의 "이전 값"이기도 하다. private var lastInfo: AlarmInfo? + /// lastInfo가 마지막으로 서버로 확인된 시각(Phase 16) — 신선도 스탬프의 원천. + /// sync 성공 시 now(), 시딩 복원 시 스냅샷의 syncedAt. 수신·방출 시각이 아니다. + private var lastCheckedAt: Date? /// Phase 13 만료 2차 방어 — 로컬 만료를 확정한 세션. 이후 refresh가 같은 routeId의 /// 과거 세션을 반환해도 무시한다(미래 출발이 오면 서버 우선으로 해제). private var locallyExpiredSession: AlarmInfo? @@ -85,7 +99,11 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { localNotification: any LocalNotificationPort, alarmScheduler: any AlarmScheduler, snapshotStore: any AlarmSessionSnapshotStore, - sessionRestorer: any LastTrainSessionRestoring + sessionRestorer: any LastTrainSessionRestoring, + isAppActive: @escaping @MainActor () -> Bool = { + UIApplication.shared.applicationState == .active + }, + now: @escaping @Sendable () -> Date = { Date() } ) { self.refreshAlarmUseCase = refreshAlarmUseCase self.evaluateChangeUseCase = evaluateChangeUseCase @@ -94,6 +112,8 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { self.alarmScheduler = alarmScheduler self.snapshotStore = snapshotStore self.sessionRestorer = sessionRestorer + self.isAppActive = isAppActive + self.now = now } /// 인증 부트스트랩 완료 후 1회 호출: 즉시 동기화(앱 시작 경로) + 포그라운드 @@ -116,6 +136,15 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { await sync() != nil ? .newData : .failed } + // MARK: - AlarmSyncRequesting (Phase 16 — 홈 pull-to-refresh) + + /// 수동 갱신 트리거(4번째) — 기존 sync()에 그대로 합류한다. 실패는 던지지 않고 + /// 스트림에도 흐르지 않는다(무음 정책) — 스탬프가 낡은 시각을 유지하는 것이 표면이다. + /// 테스트 진입점이기도 하다(NotificationCenter 없이 전 분기 도달). + nonisolated func syncNow() async { + _ = await sync() + } + /// 3경로 공용 동기화. 실패는 스트림에 흘리지 않는다 — 구독자는 상태를 유지하고, /// 다음 트리거(포그라운드·푸시)가 자연 재시도가 된다. @discardableResult @@ -128,7 +157,7 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { // 만료 선행 판정보다 먼저여야 재실행 직후의 과거 세션도 리컨실에 걸린다. await seedFromSnapshotIfNeeded() // Phase 13 선행 판정 — 확정은 refresh 결과를 본 뒤(미래 출발이면 서버 우선 취소). - let expiryCandidate = expireLocallyIfNeeded(now: Date()) + let expiryCandidate = expireLocallyIfNeeded(now: now()) let task = Task { [refreshAlarmUseCase] () -> AlarmInfo? in do { return try await refreshAlarmUseCase.execute() @@ -149,7 +178,7 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { return nil } - if let departure = info.departureTime, departure > Date() { + if let departure = info.departureTime, departure > now() { // 서버 우선 — 미래 출발 시각이 오면 만료 후보·확정 기록 모두 해제하고 정상 경로. locallyExpiredSession = nil } else if let expiryCandidate { @@ -166,14 +195,17 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { Self.logger.info("알람 동기화 성공: route=\(info.lastRouteId, privacy: .public)") let previous = lastInfo lastInfo = info + // Phase 16 — 서버가 방금 이 값을 확인해줬다. 이 시각이 스탬프의 유일한 원천. + let checkedAt = now() + lastCheckedAt = checkedAt // Phase 14 — sync 성공은 스냅샷 저장 시점. 도보·표시명은 같은 세션이면 보존한다. - let snapshot = await persistSyncedSnapshot(for: info) + let snapshot = await persistSyncedSnapshot(for: info, checkedAt: checkedAt) for continuation in subscribers.values { - continuation.yield(info) + continuation.yield(AlarmSyncUpdate(info: info, checkedAt: checkedAt)) } // Phase 14 죽은 세션 재시작 — 스냅샷은 살아 있는데 활성 LA가 없고 dismiss·확인 // 기록도 없으면 로컬 재시작(판정은 어댑터). 8시간 한도·시작 실패 세션 커버. - await sessionRestorer.restartIfNeeded(snapshot: snapshot, now: Date()) + await sessionRestorer.restartIfNeeded(snapshot: snapshot, now: now()) // Phase 11 피기백 — 이 시점에 알람 재스케줄은 이미 완료돼 있다 // (RefreshAlarmUseCase.execute 반환 = 재스케줄 포함). 표출은 그 뒤에만 덧붙는다. await propagateChange(previous: previous, latest: info) @@ -196,11 +228,15 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { locallyExpiredSession = snapshot.info } else if lastInfo == nil { lastInfo = snapshot.info + // Phase 16 — 시딩 복원값의 확인 시각은 "지금"이 아니라 스냅샷에 영속화된 + // 마지막 확인 시각이다. 직후 refresh가 실패해도(오프라인) 스탬프는 이 + // 낡은 시각을 정직하게 유지한다. + lastCheckedAt = snapshot.syncedAt Self.logger.info( "스냅샷 시딩: route=\(snapshot.info.lastRouteId, privacy: .public)" ) for continuation in subscribers.values { - continuation.yield(snapshot.info) + continuation.yield(AlarmSyncUpdate(info: snapshot.info, checkedAt: snapshot.syncedAt)) } } } @@ -208,11 +244,14 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { /// sync 성공 시 스냅샷 병합 저장 — 같은 세션(routeId 일치)이면 등록 시점 사실 /// (도보·표시명·수단·확인 기록)을 보존하고 info만 갱신, 다른 세션이면 아는 것만 담는다 /// (표시명 공백은 LA 재시작 시 "막차" 폴백, 카드는 상세 재조회가 채운다). - private func persistSyncedSnapshot(for info: AlarmInfo) async -> AlarmSessionSnapshot { + /// syncedAt도 함께 기록한다(Phase 16) — 재실행 시딩이 이 시각으로 스탬프를 복원한다. + private func persistSyncedSnapshot( + for info: AlarmInfo, checkedAt: Date + ) async -> AlarmSessionSnapshot { let existing = await snapshotStore.load() let snapshot: AlarmSessionSnapshot if let existing, existing.info.lastRouteId == info.lastRouteId { - snapshot = existing.updating(info: info, expired: false) + snapshot = existing.updating(info: info, expired: false, syncedAt: checkedAt) } else { snapshot = AlarmSessionSnapshot( info: info, @@ -220,7 +259,8 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { routeDisplayName: "", transportMode: nil, acknowledged: false, - expired: false + expired: false, + syncedAt: checkedAt ) } await snapshotStore.save(snapshot) @@ -262,10 +302,11 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { routeDisplayName: "", transportMode: nil, acknowledged: false, - expired: true + expired: true, + syncedAt: lastCheckedAt )) } - await presentSessionEnded(previous: session, now: Date()) + await presentSessionEnded(previous: session, now: now()) yieldChange(.sessionEnded) } @@ -273,7 +314,7 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { /// 판정 → 채널 분기. LA 호출은 전부 실패 무해(포트가 non-throwing) — 알람에 영향 없음. private func propagateChange(previous: AlarmInfo?, latest: AlarmInfo) async { - let now = Date() + let now = self.now() // 첫 수신(이전 값 없음)은 비교 대상이 없다 — unchanged 취급. let verdict = previous.map { evaluateChangeUseCase.execute(previous: $0, latest: latest, now: now) @@ -338,7 +379,7 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { changeBadgeExpiry: badgeExpiry, phase: .active ) - if UIApplication.shared.applicationState == .active { + if isAppActive() { // 포그라운드 — LA alert 소리·로컬 노티 없이 조용한 상태 갱신만(Phase 15 // 이중 알림 제거). 사용자 주의는 인앱 채널(changes 스트림 → 배너 강조 + // 토스트)이 단독으로 맡는다 — 일반 advanced·missed 분기와 동일 구조. @@ -367,7 +408,7 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { changeBadgeExpiry: badgeExpiry, phase: .active ) - if UIApplication.shared.applicationState == .active { + if isAppActive() { // 포그라운드 — LA alert 생략(조용한 업데이트 + 배지). 사용자 주의는 인앱 채널 // (changes 스트림 → 홈 배너 강조 + 토스트)이 맡는다. 이중 알림 방지. await liveActivity.update(state: state, alert: nil) @@ -414,7 +455,7 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { title: LastTrainChangeMessages.missedTitle, body: LastTrainChangeMessages.missedBody(latestDeparture: departure) ) - if UIApplication.shared.applicationState == .active { + if isAppActive() { // 포그라운드 — 상태 전환만 조용히. 사용자 주의는 인앱 채널이 맡는다(이중 알림 방지). await liveActivity.update(state: state, alert: nil) } else if await liveActivity.isAlertReachable { @@ -479,12 +520,12 @@ final class AlarmSyncService: AlarmSyncEvents, AlarmChangeEvents { // MARK: - AlarmSyncEvents - nonisolated func updates() -> AsyncStream { + nonisolated func updates() -> AsyncStream { AsyncStream { continuation in let id = UUID() Task { @MainActor in if let last = self.lastInfo { - continuation.yield(last) + continuation.yield(AlarmSyncUpdate(info: last, checkedAt: self.lastCheckedAt)) } self.subscribers[id] = continuation } diff --git a/Projects/App/Sources/AppCoordinator.swift b/Projects/App/Sources/AppCoordinator.swift index 431255d..e6ab172 100644 --- a/Projects/App/Sources/AppCoordinator.swift +++ b/Projects/App/Sources/AppCoordinator.swift @@ -42,7 +42,10 @@ final class AppCoordinator: Coordinator, CoordinatorFinishDelegate { self.container.alarmSyncService.activate() } catch { guard !Task.isCancelled else { return } - self.splashViewController?.showRetry() + // 원인별 문구 분기(Phase 16) — 오프라인만 구분, 그 외는 일시 장애 안내. + self.splashViewController?.showRetry( + message: BootstrapFailureMessage.text(for: error) + ) } } } diff --git a/Projects/App/Sources/AppDIContainer.swift b/Projects/App/Sources/AppDIContainer.swift index 87438cd..3250fe7 100644 --- a/Projects/App/Sources/AppDIContainer.swift +++ b/Projects/App/Sources/AppDIContainer.swift @@ -56,8 +56,14 @@ final class AppDIContainer { session: URLSession(configuration: sessionConfiguration) ) #else + // Phase 16 — 기본 60초 타임아웃은 심야의 약한 연결에서 1분 침묵이다. 빨리 + // 실패시키고(요청 10초) 멱등 GET 1회 재시도·신선도 스탬프가 정직성을 맡는다. + let sessionConfiguration = URLSessionConfiguration.default + sessionConfiguration.timeoutIntervalForRequest = 10 + sessionConfiguration.timeoutIntervalForResource = 30 let baseClient = URLSessionNetworkClient( - baseURL: AppEnvironment.current.apiBaseURL + baseURL: AppEnvironment.current.apiBaseURL, + session: URLSession(configuration: sessionConfiguration) ) #endif let sessionManager = AuthSessionManager( @@ -173,6 +179,8 @@ final class AppDIContainer { ), observeAlarmUseCase: DefaultObserveAlarmUseCase(events: alarmSyncService), observeAlarmChangeUseCase: DefaultObserveAlarmChangeUseCase(events: alarmSyncService), + // 홈 pull-to-refresh(Phase 16) — 4번째 트리거도 같은 동기화 한 곳으로 합류한다. + requestAlarmSyncUseCase: DefaultRequestAlarmSyncUseCase(requesting: alarmSyncService), // 재실행 카드 복원(Phase 14) — 기존 미사용 자산(detail 엔드포인트) 재활용. getLastRouteDetailUseCase: DefaultGetLastRouteDetailUseCase( repository: lastRouteRepository diff --git a/Projects/App/Sources/BootstrapFailureMessage.swift b/Projects/App/Sources/BootstrapFailureMessage.swift new file mode 100644 index 0000000..ac3b0e6 --- /dev/null +++ b/Projects/App/Sources/BootstrapFailureMessage.swift @@ -0,0 +1,14 @@ +import CoreNetwork +import Foundation + +/// 스플래시 부트스트랩 실패 문구 매핑(Phase 16) — 원인 불문 고정 문구를 오프라인/기타로 +/// 나눈다. 순수 함수라 AtchaV2Tests가 직접 검증한다. 현 DEV는 bootstrap이 +/// issuerNotConfigured를 삼켜 재시도 화면에 도달하지 않는다 — 실표출은 S1(익명 인증) 이후. +enum BootstrapFailureMessage { + static let offline = "네트워크 연결을 확인해주세요" + static let transient = "일시적인 문제가 생겼어요. 잠시 후 다시 시도해주세요" + + static func text(for error: any Error) -> String { + (error as? NetworkError)?.isOffline == true ? offline : transient + } +} diff --git a/Projects/App/Sources/SplashViewController.swift b/Projects/App/Sources/SplashViewController.swift index 0a1c0f4..e9f3788 100644 --- a/Projects/App/Sources/SplashViewController.swift +++ b/Projects/App/Sources/SplashViewController.swift @@ -22,7 +22,9 @@ final class SplashViewController: UIViewController { activityIndicator.startAnimating() } - func showRetry() { + /// 실패 원인별 문구(Phase 16) — 선택은 호출자(AppCoordinator + BootstrapFailureMessage)가 한다. + func showRetry(message: String) { + messageLabel.text = message activityIndicator.stopAnimating() retryStack.isHidden = false } @@ -36,7 +38,6 @@ final class SplashViewController: UIViewController { activityIndicator.hidesWhenStopped = true - messageLabel.text = "네트워크 연결을 확인해주세요" messageLabel.font = DSTypography.body1.font messageLabel.textColor = DSColor.Text.primary messageLabel.textAlignment = .center diff --git a/Projects/App/Tests/AlarmSyncServiceTests.swift b/Projects/App/Tests/AlarmSyncServiceTests.swift new file mode 100644 index 0000000..ff1fec1 --- /dev/null +++ b/Projects/App/Tests/AlarmSyncServiceTests.swift @@ -0,0 +1,391 @@ +@testable import AtchaV2 +import Domain +import Foundation +import Testing + +// AlarmSyncService(판정·폴백·만료 오케스트레이션)의 회귀 방어(Phase 16). +// 진입은 syncNow()(수동 갱신과 같은 경로 — NotificationCenter 없이 전 분기 도달), +// 시각·앱 활성 상태는 주입으로 고정한다(실 Date()·UIApplication 금지 규약). + +private struct StubError: Error {} + +private nonisolated let fixedNow = Date(timeIntervalSince1970: 1_755_800_000) + +private nonisolated func info(route: String, departure: Date?) -> AlarmInfo { + AlarmInfo(lastRouteId: route, departureTime: departure, updatedAt: nil, isReal: true) +} + +/// 잠금 박스 — 테스트 도중 스텁 동작(활성 상태·판정)을 바꾼다. +private nonisolated final class ValueBox: @unchecked Sendable { + private let lock = NSLock() + private var value: Value + init(_ value: Value) { self.value = value } + func get() -> Value { + lock.lock() + defer { lock.unlock() } + return value + } + func set(_ newValue: Value) { + lock.lock() + defer { lock.unlock() } + value = newValue + } +} + +private final class RefreshStub: RefreshAlarmUseCase, @unchecked Sendable { + private let lock = NSLock() + private var queue: [Result] + init(_ results: [Result]) { queue = results } + func enqueue(_ result: Result) { + lock.lock() + queue.append(result) + lock.unlock() + } + // NSLock은 async 컨텍스트에서 직접 못 쓴다 — 동기 헬퍼로 분리. + private func dequeue() -> Result? { + lock.lock() + defer { lock.unlock() } + return queue.isEmpty ? nil : queue.removeFirst() + } + func execute() async throws -> AlarmInfo { + guard let next = dequeue() else { throw StubError() } + return try next.get() + } +} + +/// 판정 고정 스텁 — 판정 로직 자체는 Domain 테스트 몫, 여기서는 분기만 본다. +private final class EvaluateStub: EvaluateAlarmChangeUseCase, @unchecked Sendable { + private let lock = NSLock() + private var verdict: AlarmChangeVerdict = .unchanged + func fix(_ newVerdict: AlarmChangeVerdict) { + lock.lock() + verdict = newVerdict + lock.unlock() + } + func execute(previous: AlarmInfo, latest: AlarmInfo, now: Date) -> AlarmChangeVerdict { + lock.lock() + defer { lock.unlock() } + return verdict + } +} + +private actor ActivitySpy: LastTrainChangeAlerting { + private var reachable = true + private(set) var updates: [(state: LastTrainActivityState, alertTitle: String?)] = [] + private(set) var finals: [LastTrainActivityState] = [] + func setReachable(_ value: Bool) { reachable = value } + var isDismissedByUser: Bool { !reachable } + var isAlertReachable: Bool { reachable } + func update(state: LastTrainActivityState, alert: (title: String, body: String)?) async { + updates.append((state, alert?.title)) + } + func end(final state: LastTrainActivityState) async { + finals.append(state) + } + var alertCount: Int { updates.count { $0.alertTitle != nil } } +} + +private actor NotiSpy: LocalNotificationPort { + private(set) var posted: [String] = [] + @discardableResult + func requestAuthorizationIfNeeded() async -> LocalNotificationAuthorizationOutcome { + .alreadySettled + } + func post(title: String, body: String) async { + posted.append(title) + } +} + +private actor SchedulerSpy: AlarmScheduler { + private(set) var cancelCount = 0 + func requestAuthorization() async -> Bool { true } + func replaceAlarm(id: String, fireDate: Date, title: String) async throws {} + func cancelAlarm() async { cancelCount += 1 } + func scheduledFireDate() async -> Date? { nil } +} + +private actor StoreStub: AlarmSessionSnapshotStore { + private(set) var snapshot: AlarmSessionSnapshot? + init(_ snapshot: AlarmSessionSnapshot?) { self.snapshot = snapshot } + func load() async -> AlarmSessionSnapshot? { snapshot } + func save(_ snapshot: AlarmSessionSnapshot) async { self.snapshot = snapshot } + func clear() async { snapshot = nil } +} + +private actor RestorerSpy: LastTrainSessionRestoring { + private(set) var restartCount = 0 + func reattachOrphans(snapshot: AlarmSessionSnapshot?, now: Date) async {} + func restartIfNeeded(snapshot: AlarmSessionSnapshot, now: Date) async { + restartCount += 1 + } +} + +@MainActor +private struct Harness { + let sut: AlarmSyncService + let refresh: RefreshStub + let evaluate: EvaluateStub + let activity: ActivitySpy + let noti: NotiSpy + let scheduler: SchedulerSpy + let store: StoreStub + let active: ValueBox + + /// 이전 값(diff 기준)을 심는 선행 동기화 — unchanged 판정으로 조용히 지나간다. + func primePreviousSession(departure: Date) async { + refresh.enqueue(.success(info(route: "r1", departure: departure))) + await sut.syncNow() + } +} + +@MainActor +private func makeHarness( + seeded: AlarmSessionSnapshot? = nil, + isAppActive: Bool = false +) -> Harness { + let refresh = RefreshStub([]) + let evaluate = EvaluateStub() + let activity = ActivitySpy() + let noti = NotiSpy() + let scheduler = SchedulerSpy() + let store = StoreStub(seeded) + let restorer = RestorerSpy() + let active = ValueBox(isAppActive) + let sut = AlarmSyncService( + refreshAlarmUseCase: refresh, + evaluateChangeUseCase: evaluate, + liveActivity: activity, + localNotification: noti, + alarmScheduler: scheduler, + snapshotStore: store, + sessionRestorer: restorer, + isAppActive: { active.get() }, + now: { fixedNow } + ) + return Harness( + sut: sut, refresh: refresh, evaluate: evaluate, activity: activity, + noti: noti, scheduler: scheduler, store: store, active: active + ) +} + +@MainActor +struct AlarmSyncServiceTests { + // MARK: - 신선도 스탬프 (Phase 16) + + @Test + func syncSuccess_publishesCheckedAtAndPersistsSyncedAt() async { + let harness = makeHarness() + let departure = fixedNow.addingTimeInterval(3600) + harness.refresh.enqueue(.success(info(route: "r1", departure: departure))) + + await harness.sut.syncNow() + + // replay-1이 확인 시각을 함께 나른다 — 스탬프의 원천은 sync 성공 시각(주입 now)뿐. + var iterator = harness.sut.updates().makeAsyncIterator() + let replayed = await iterator.next() + #expect(replayed == AlarmSyncUpdate( + info: info(route: "r1", departure: departure), checkedAt: fixedNow + )) + // 재실행 브리지에도 같은 시각이 영속화된다. + #expect(await harness.store.snapshot?.syncedAt == fixedNow) + } + + @Test + func syncFailure_afterSeeding_replaysSnapshotConfirmedTime() async { + // 재실행 + 오프라인: 시딩 복원값의 확인 시각은 "지금"이 아니라 스냅샷의 + // 마지막 확인 시각이어야 한다 — 낡음을 숨기지 않는다. + let seededCheckedAt = fixedNow.addingTimeInterval(-2400) + let departure = fixedNow.addingTimeInterval(1800) + let harness = makeHarness(seeded: AlarmSessionSnapshot( + info: info(route: "r1", departure: departure), + firstWalkSeconds: nil, + routeDisplayName: "6411번 버스", + transportMode: .bus, + acknowledged: false, + expired: false, + syncedAt: seededCheckedAt + )) + + await harness.sut.syncNow() // refresh 큐 비어 있음 → 실패(무음) + + var iterator = harness.sut.updates().makeAsyncIterator() + let replayed = await iterator.next() + #expect(replayed?.info.lastRouteId == "r1") + #expect(replayed?.checkedAt == seededCheckedAt) + } + + // MARK: - advanced(actionable) 채널 분기 (Phase 11·12·15 회귀) + + @Test + func advanced_background_reachable_sendsLiveActivityAlert() async { + let harness = makeHarness(isAppActive: false) + await harness.primePreviousSession(departure: fixedNow.addingTimeInterval(3600)) + + harness.evaluate.fix(.advanced(by: 600, actionable: true)) + harness.refresh.enqueue(.success(info(route: "r1", departure: fixedNow.addingTimeInterval(3000)))) + await harness.sut.syncNow() + + #expect(await harness.activity.alertCount == 1) + #expect(await harness.noti.posted.isEmpty) + } + + @Test + func advanced_background_unreachable_fallsBackToLocalNotification() async { + // Phase 15 폴백 회귀 — LA alert 도달 불가면 같은 문구의 로컬 노티로 갈아탄다. + let harness = makeHarness(isAppActive: false) + await harness.primePreviousSession(departure: fixedNow.addingTimeInterval(3600)) + + await harness.activity.setReachable(false) + harness.evaluate.fix(.advanced(by: 600, actionable: true)) + harness.refresh.enqueue(.success(info(route: "r1", departure: fixedNow.addingTimeInterval(3000)))) + await harness.sut.syncNow() + + #expect(await harness.noti.posted.count == 1) + #expect(await harness.activity.alertCount == 0) + } + + @Test + func advanced_foreground_quietUpdateOnly() async { + // 포그라운드 — alert·노티 없이 조용한 갱신(배지)만. 주의는 인앱 채널 단독. + let harness = makeHarness(isAppActive: true) + await harness.primePreviousSession(departure: fixedNow.addingTimeInterval(3600)) + let updatesBefore = await harness.activity.updates.count + + harness.evaluate.fix(.advanced(by: 600, actionable: true)) + harness.refresh.enqueue(.success(info(route: "r1", departure: fixedNow.addingTimeInterval(3000)))) + await harness.sut.syncNow() + + #expect(await harness.activity.alertCount == 0) + #expect(await harness.noti.posted.isEmpty) + #expect(await harness.activity.updates.count == updatesBefore + 1) + } + + // MARK: - 최후통첩 (새 알람 시각이 이미 과거·출발은 미래) + + @Test + func ultimatum_foreground_staysQuiet_backgroundEscalates() async { + // Phase 15 이중 알림 제거 회귀: 포그라운드 최후통첩은 조용한 상태 갱신뿐이다. + let harness = makeHarness(isAppActive: true) + await harness.primePreviousSession(departure: fixedNow.addingTimeInterval(3600)) + + harness.evaluate.fix(.advanced(by: 3500, actionable: true)) + // 출발 100초 뒤 → 알람 시각(출발−180초)은 이미 과거 = 마지노선 침범. + let ultimatumInfo = info(route: "r1", departure: fixedNow.addingTimeInterval(100)) + harness.refresh.enqueue(.success(ultimatumInfo)) + await harness.sut.syncNow() + + #expect(await harness.activity.alertCount == 0) + #expect(await harness.noti.posted.isEmpty) + let lastQuiet = await harness.activity.updates.last + #expect(lastQuiet?.state.urgency == .imminent) + + // 백그라운드 + 도달 불가 — 즉시 최후통첩이 로컬 노티로 나간다. + harness.active.set(false) + await harness.activity.setReachable(false) + harness.refresh.enqueue(.success(ultimatumInfo)) + await harness.sut.syncNow() + + #expect(await harness.noti.posted.count == 1) + } + + // MARK: - missed (advanced, actionable: false) + + @Test + func missed_background_unreachable_fallsBackToLocalNotification() async { + let harness = makeHarness(isAppActive: false) + await harness.primePreviousSession(departure: fixedNow.addingTimeInterval(3600)) + + await harness.activity.setReachable(false) + harness.evaluate.fix(.advanced(by: 3700, actionable: false)) + harness.refresh.enqueue(.success(info(route: "r1", departure: fixedNow.addingTimeInterval(-100)))) + await harness.sut.syncNow() + + #expect(await harness.noti.posted.count == 1) + // 실패 상태 전환은 LA 종료가 아니라 missed 상태 업데이트다 — end 호출 없음. + #expect(await harness.activity.finals.isEmpty) + } + + // MARK: - sessionEnded + + @Test + func sessionEnded_cancelsAlarmClearsSnapshotAndEndsActivity() async { + let harness = makeHarness(isAppActive: false) + await harness.primePreviousSession(departure: fixedNow.addingTimeInterval(3600)) + #expect(await harness.store.snapshot != nil) + + harness.evaluate.fix(.sessionEnded) + harness.refresh.enqueue(.success(info(route: "r1", departure: nil))) + await harness.sut.syncNow() + + #expect(await harness.scheduler.cancelCount == 1) + #expect(await harness.store.snapshot == nil) + #expect(await harness.activity.finals.last?.phase == .serviceEnded) + #expect(await harness.noti.posted.isEmpty) // 종료는 행동을 요구하지 않는다 — 폴백 없음. + } + + // MARK: - 클라 자체 만료 (Phase 13 회귀) + + @Test + func localExpiry_refreshFailure_finalizesTombstoneAndCancelsAlarm() async { + // 시딩된 과거 세션(출발+유예 경과) + refresh 실패 → 로컬 sessionEnded 확정. + let pastDeparture = fixedNow.addingTimeInterval(-120) + let harness = makeHarness(seeded: AlarmSessionSnapshot( + info: info(route: "r1", departure: pastDeparture), + firstWalkSeconds: nil, + routeDisplayName: "", + transportMode: nil, + acknowledged: false, + expired: false, + syncedAt: fixedNow.addingTimeInterval(-3600) + )) + var changeIterator = harness.sut.changes().makeAsyncIterator() + for _ in 0..<20 { await Task.yield() } // 구독 등록 드레인(변경 스트림은 replay 없음) + + await harness.sut.syncNow() // refresh 큐 비어 있음 → 실패여도 만료는 확정된다. + + #expect(await harness.scheduler.cancelCount == 1) + #expect(await harness.store.snapshot?.expired == true) + #expect(await harness.activity.finals.last?.phase == .serviceEnded) + let verdict = await changeIterator.next() + #expect(verdict == .sessionEnded) + } + + @Test + func localExpiry_serverReturnsFutureDeparture_serverWins() async { + // 만료 후보 상태에서 refresh가 미래 출발을 주면 만료를 취소한다(서버 우선). + let harness = makeHarness(seeded: AlarmSessionSnapshot( + info: info(route: "r1", departure: fixedNow.addingTimeInterval(-120)), + firstWalkSeconds: nil, + routeDisplayName: "", + transportMode: nil, + acknowledged: false, + expired: false + )) + let future = fixedNow.addingTimeInterval(1800) + harness.refresh.enqueue(.success(info(route: "r1", departure: future))) + + await harness.sut.syncNow() + + #expect(await harness.scheduler.cancelCount == 0) + #expect(await harness.store.snapshot?.expired == false) + #expect(await harness.store.snapshot?.info.departureTime == future) + } + + // MARK: - 수동 갱신 합류 (Phase 16) + + @Test + func syncNow_joinsInFlightSync() async { + // 당김·포그라운드 복귀가 겹쳐도 refresh는 1회 — inFlight 합류 회귀. + let harness = makeHarness() + harness.refresh.enqueue(.success(info(route: "r1", departure: fixedNow.addingTimeInterval(3600)))) + // 큐에 1건뿐 — 두 번째 실호출이 발생하면 실패(StubError)로 lastInfo가 남지 않는다. + + async let first: Void = harness.sut.syncNow() + async let second: Void = harness.sut.syncNow() + _ = await (first, second) + + var iterator = harness.sut.updates().makeAsyncIterator() + let replayed = await iterator.next() + #expect(replayed?.info.lastRouteId == "r1") + } +} diff --git a/Projects/App/Tests/BootstrapFailureMessageTests.swift b/Projects/App/Tests/BootstrapFailureMessageTests.swift new file mode 100644 index 0000000..80ad195 --- /dev/null +++ b/Projects/App/Tests/BootstrapFailureMessageTests.swift @@ -0,0 +1,26 @@ +@testable import AtchaV2 +import CoreNetwork +import Foundation +import Testing + +private struct SomeError: Error {} + +struct BootstrapFailureMessageTests { + @Test + func offlineNetworkError_mapsToConnectivityMessage() { + let error = NetworkError.offline(underlying: URLError(.notConnectedToInternet)) + #expect(BootstrapFailureMessage.text(for: error) == BootstrapFailureMessage.offline) + } + + @Test + func otherFailures_mapToTransientMessage() { + // 타임아웃·서버 오류·비네트워크 에러 전부 "일시적인 문제" — 오프라인만 구분한다. + #expect(BootstrapFailureMessage.text( + for: NetworkError.transport(underlying: URLError(.timedOut)) + ) == BootstrapFailureMessage.transient) + #expect(BootstrapFailureMessage.text( + for: NetworkError.unacceptableStatus(code: 500, data: Data()) + ) == BootstrapFailureMessage.transient) + #expect(BootstrapFailureMessage.text(for: SomeError()) == BootstrapFailureMessage.transient) + } +} diff --git a/Projects/Core/Network/Sources/NetworkError.swift b/Projects/Core/Network/Sources/NetworkError.swift index e55e7a9..15895ce 100644 --- a/Projects/Core/Network/Sources/NetworkError.swift +++ b/Projects/Core/Network/Sources/NetworkError.swift @@ -2,8 +2,28 @@ import Foundation public enum NetworkError: Error, Sendable { case invalidURL + /// 연결 자체가 없음(Phase 16) — URLError .notConnectedToInternet / .dataNotAllowed. + /// 즉시 재시도해도 재실패라 재시도 대상이 아니고, 스플래시 실패 문구 분기의 근거다. + /// .networkConnectionLost는 일시 장애(킵얼라이브 소켓 끊김 등)로 보고 transport에 + /// 남긴다 — 멱등 GET 1회 재시도로 살리는 쪽이 맞다. + case offline(underlying: any Error) case transport(underlying: any Error) case invalidResponse case unacceptableStatus(code: Int, data: Data) case decoding(underlying: any Error) + + /// 전송 실패 분류 단일 지점 — 클라이언트가 URLSession 에러를 이 함수로만 감싼다. + public static func classifyingTransport(_ error: any Error) -> NetworkError { + switch (error as? URLError)?.code { + case .notConnectedToInternet, .dataNotAllowed: + .offline(underlying: error) + default: + .transport(underlying: error) + } + } + + public var isOffline: Bool { + if case .offline = self { return true } + return false + } } diff --git a/Projects/Core/Network/Sources/URLSessionNetworkClient.swift b/Projects/Core/Network/Sources/URLSessionNetworkClient.swift index e6846d8..f00858f 100644 --- a/Projects/Core/Network/Sources/URLSessionNetworkClient.swift +++ b/Projects/Core/Network/Sources/URLSessionNetworkClient.swift @@ -19,12 +19,27 @@ public struct URLSessionNetworkClient: NetworkClient { public func data(for endpoint: any Endpoint) async throws -> Data { let request = try urlRequest(for: endpoint) + do { + return try await send(request) + } catch let error as NetworkError { + // 멱등 GET 1회 재시도(Phase 16) — transport 계열(타임아웃·연결 끊김)만. + // offline은 즉시 재실패라 무의미, 취소는 사용자 의사, HTTP 상태·디코딩은 + // 전송 실패가 아니다. POST/DELETE는 이중 발사(알람 등록·해제) 위험으로 금지. + guard endpoint.method == .get, case .transport(let underlying) = error, + (underlying as? URLError)?.code != .cancelled, + !(underlying is CancellationError) + else { throw error } + return try await send(request) + } + } + + private func send(_ request: URLRequest) async throws -> Data { let data: Data let response: URLResponse do { (data, response) = try await session.data(for: request) } catch { - throw NetworkError.transport(underlying: error) + throw NetworkError.classifyingTransport(error) } guard let http = response as? HTTPURLResponse else { throw NetworkError.invalidResponse diff --git a/Projects/Core/Network/Tests/URLSessionNetworkClientRetryTests.swift b/Projects/Core/Network/Tests/URLSessionNetworkClientRetryTests.swift new file mode 100644 index 0000000..48cd0c1 --- /dev/null +++ b/Projects/Core/Network/Tests/URLSessionNetworkClientRetryTests.swift @@ -0,0 +1,149 @@ +@testable import CoreNetwork +import Foundation +import Testing + +private struct GetEndpoint: Endpoint { + let path = "/ping" + let method: HTTPMethod = .get +} + +private struct PostEndpoint: Endpoint { + let path = "/register" + let method: HTTPMethod = .post +} + +/// URLProtocol 스텁 — 응답 큐를 순서대로 소비한다. static 상태를 쓰므로 +/// 이 스텁을 쓰는 테스트 스위트는 `.serialized`여야 한다. +private final class StubURLProtocol: URLProtocol { + nonisolated(unsafe) private static var queue: [Result<(status: Int, data: Data), URLError>] = [] + nonisolated(unsafe) private(set) static var requestCount = 0 + private static let lock = NSLock() + + static func reset(queue newQueue: [Result<(status: Int, data: Data), URLError>]) { + lock.lock() + defer { lock.unlock() } + queue = newQueue + requestCount = 0 + } + + override class func canInit(with request: URLRequest) -> Bool { true } + override class func canonicalRequest(for request: URLRequest) -> URLRequest { request } + override func stopLoading() {} + + override func startLoading() { + Self.lock.lock() + Self.requestCount += 1 + let next = Self.queue.isEmpty ? nil : Self.queue.removeFirst() + Self.lock.unlock() + + switch next { + case let .success((status, data)): + let response = HTTPURLResponse( + url: request.url!, statusCode: status, httpVersion: nil, headerFields: nil + )! + client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed) + client?.urlProtocol(self, didLoad: data) + client?.urlProtocolDidFinishLoading(self) + case let .failure(error): + client?.urlProtocol(self, didFailWithError: error) + case nil: + client?.urlProtocol(self, didFailWithError: URLError(.unknown)) + } + } +} + +private func makeClient() -> URLSessionNetworkClient { + let configuration = URLSessionConfiguration.ephemeral + configuration.protocolClasses = [StubURLProtocol.self] + return URLSessionNetworkClient( + baseURL: URL(string: "https://api.example.com")!, + session: URLSession(configuration: configuration) + ) +} + +@Suite(.serialized) +struct URLSessionNetworkClientRetryTests { + @Test + func get_transportFailureThenSuccess_retriesOnce() async throws { + StubURLProtocol.reset(queue: [ + .failure(URLError(.timedOut)), + .success((status: 200, data: Data("ok".utf8))), + ]) + let data = try await makeClient().data(for: GetEndpoint()) + #expect(data == Data("ok".utf8)) + #expect(StubURLProtocol.requestCount == 2) + } + + @Test + func get_transportFailureTwice_throwsAfterSingleRetry() async { + StubURLProtocol.reset(queue: [ + .failure(URLError(.networkConnectionLost)), + .failure(URLError(.networkConnectionLost)), + ]) + await #expect(throws: NetworkError.self) { + try await makeClient().data(for: GetEndpoint()) + } + // 1회 재시도까지만 — 무한 재시도 금지. + #expect(StubURLProtocol.requestCount == 2) + } + + @Test + func get_offline_throwsOfflineWithoutRetry() async { + StubURLProtocol.reset(queue: [ + .failure(URLError(.notConnectedToInternet)), + .success((status: 200, data: Data())), + ]) + do { + _ = try await makeClient().data(for: GetEndpoint()) + Issue.record("offline인데 성공했다") + } catch let error as NetworkError { + #expect(error.isOffline) + } catch { + Issue.record("NetworkError가 아닌 에러: \(error)") + } + // 연결 자체가 없으면 즉시 재실패라 재시도하지 않는다. + #expect(StubURLProtocol.requestCount == 1) + } + + @Test + func post_transportFailure_doesNotRetry() async { + StubURLProtocol.reset(queue: [ + .failure(URLError(.timedOut)), + .success((status: 200, data: Data())), + ]) + await #expect(throws: NetworkError.self) { + try await makeClient().data(for: PostEndpoint()) + } + // 비멱등(알람 등록 등)은 이중 발사 위험 — 재시도 금지. + #expect(StubURLProtocol.requestCount == 1) + } + + @Test + func get_httpErrorStatus_doesNotRetry() async { + StubURLProtocol.reset(queue: [ + .success((status: 500, data: Data())), + .success((status: 200, data: Data())), + ]) + await #expect(throws: NetworkError.self) { + try await makeClient().data(for: GetEndpoint()) + } + // 재시도 대상은 transport 계열뿐 — HTTP 상태 실패는 그대로 던진다. + #expect(StubURLProtocol.requestCount == 1) + } +} + +struct NetworkErrorClassificationTests { + @Test + func classifyingTransport_offlineCodes() { + #expect(NetworkError.classifyingTransport(URLError(.notConnectedToInternet)).isOffline) + #expect(NetworkError.classifyingTransport(URLError(.dataNotAllowed)).isOffline) + } + + @Test + func classifyingTransport_transientCodesStayTransport() { + // 연결 끊김·타임아웃은 일시 장애 — 재시도로 살린다(offline 아님). + #expect(!NetworkError.classifyingTransport(URLError(.networkConnectionLost)).isOffline) + #expect(!NetworkError.classifyingTransport(URLError(.timedOut)).isOffline) + #expect(!NetworkError.classifyingTransport(URLError(.cancelled)).isOffline) + } +} diff --git a/Projects/DesignSystem/Sources/Components/DSBanner.swift b/Projects/DesignSystem/Sources/Components/DSBanner.swift index 0e32833..c3c985c 100644 --- a/Projects/DesignSystem/Sources/Components/DSBanner.swift +++ b/Projects/DesignSystem/Sources/Components/DSBanner.swift @@ -12,6 +12,9 @@ public final class DSBanner: UIView { } private let label = UILabel() + /// 신선도 스탬프("HH:mm 확인 기준") 등 본문에 딸린 보조 라인 — nil이면 기존 렌더와 동일. + private let detailLabel = UILabel() + private let textStack = UIStackView() public init(text: String = "", style: Style = .normal) { super.init(frame: .zero) @@ -20,20 +23,30 @@ public final class DSBanner: UIView { label.font = DSTypography.label1.font label.textAlignment = .center - label.translatesAutoresizingMaskIntoConstraints = false - addSubview(label) + detailLabel.font = DSTypography.caption2.font + detailLabel.textAlignment = .center + detailLabel.isHidden = true + + textStack.axis = .vertical + textStack.alignment = .center + textStack.spacing = DSSpacing.xxs + [label, detailLabel].forEach(textStack.addArrangedSubview) + textStack.translatesAutoresizingMaskIntoConstraints = false + addSubview(textStack) NSLayoutConstraint.activate([ - label.leadingAnchor.constraint(equalTo: leadingAnchor, constant: DSSpacing.md), - label.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -DSSpacing.md), - label.topAnchor.constraint(equalTo: topAnchor, constant: DSSpacing.sm12), - label.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -DSSpacing.sm12), + textStack.leadingAnchor.constraint(equalTo: leadingAnchor, constant: DSSpacing.md), + textStack.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -DSSpacing.md), + textStack.topAnchor.constraint(equalTo: topAnchor, constant: DSSpacing.sm12), + textStack.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -DSSpacing.sm12), ]) configure(text: text, style: style) } - public func configure(text: String, style: Style = .normal) { + public func configure(text: String, style: Style = .normal, detailText: String? = nil) { label.text = text + detailLabel.text = detailText + detailLabel.isHidden = detailText == nil switch style { case .normal: backgroundColor = DSColor.Accent.container @@ -45,6 +58,9 @@ public final class DSBanner: UIView { backgroundColor = DSColor.State.urgent label.textColor = DSColor.Text.primary } + // 보조 라인은 본문과 같은 토큰 색의 감쇠 톤 — 스타일별 배경(컨테이너/솔리드) + // 어디서든 본문보다 한 단계 낮은 위계를 유지한다(DSRouteCard legs alpha 관례). + detailLabel.textColor = label.textColor.withAlphaComponent(0.72) } /// 갱신 강조 — 값이 바뀐 순간 1회 펄스로 시선을 끈다("막차가 당겨졌어요" 등). diff --git a/Projects/DesignSystem/Sources/Components/DSRouteCard.swift b/Projects/DesignSystem/Sources/Components/DSRouteCard.swift index 6379390..4560706 100644 --- a/Projects/DesignSystem/Sources/Components/DSRouteCard.swift +++ b/Projects/DesignSystem/Sources/Components/DSRouteCard.swift @@ -14,6 +14,8 @@ public final class DSRouteCard: UIView { public let legs: [DSTransportBadge.Kind] public let summaryText: String? public let destinationText: String? + /// 카드 하단 푸터(신선도 스탬프 "HH:mm 확인 기준" 등) — nil이면 기존 렌더와 동일. + public let footnoteText: String? public let tone: Tone public init( @@ -22,6 +24,7 @@ public final class DSRouteCard: UIView { legs: [DSTransportBadge.Kind] = [], summaryText: String? = nil, destinationText: String? = nil, + footnoteText: String? = nil, tone: Tone = .normal ) { self.badgeText = badgeText @@ -29,6 +32,7 @@ public final class DSRouteCard: UIView { self.legs = legs self.summaryText = summaryText self.destinationText = destinationText + self.footnoteText = footnoteText self.tone = tone } } @@ -40,6 +44,7 @@ public final class DSRouteCard: UIView { private let legsStack = UIStackView() private let summaryLabel = UILabel() private let destinationLabel = UILabel() + private let footnoteLabel = UILabel() private let contentStack = UIStackView() public init() { @@ -68,10 +73,13 @@ public final class DSRouteCard: UIView { destinationLabel.font = DSTypography.caption1.font destinationLabel.textColor = DSColor.Text.secondary + footnoteLabel.font = DSTypography.caption2.font + footnoteLabel.textColor = DSColor.Text.tertiary + contentStack.axis = .vertical contentStack.alignment = .leading contentStack.spacing = DSSpacing.sm - [badgeLabel, departureTimeLabel, legsStack, summaryLabel, destinationLabel] + [badgeLabel, departureTimeLabel, legsStack, summaryLabel, destinationLabel, footnoteLabel] .forEach(contentStack.addArrangedSubview) contentStack.translatesAutoresizingMaskIntoConstraints = false @@ -116,6 +124,9 @@ public final class DSRouteCard: UIView { destinationLabel.text = content.destinationText destinationLabel.isHidden = content.destinationText == nil + + footnoteLabel.text = content.footnoteText + footnoteLabel.isHidden = content.footnoteText == nil } /// 톤별 색 적용 — 재사용(configure 재호출) 시 양방향 모두 명시적으로 되돌린다. diff --git a/Projects/Domain/Sources/Entities/AlarmSessionSnapshot.swift b/Projects/Domain/Sources/Entities/AlarmSessionSnapshot.swift index 9790b5d..91a845a 100644 --- a/Projects/Domain/Sources/Entities/AlarmSessionSnapshot.swift +++ b/Projects/Domain/Sources/Entities/AlarmSessionSnapshot.swift @@ -18,6 +18,10 @@ public struct AlarmSessionSnapshot: Sendable, Equatable, Codable { public let acknowledged: Bool /// 로컬 만료 기록 (Phase 13 연동) — true면 죽은 세션 톰스톤. public let expired: Bool + /// 이 세션 값이 마지막으로 서버로 확인된 시각(Phase 16) — 등록 성공·sync 성공 시 + /// 갱신된다. 재실행 시딩이 이 값을 날라 신선도 스탬프("HH:mm 확인 기준")가 재실행· + /// 오프라인에서도 마지막 확인 시각을 정직하게 유지한다. 구 스냅샷은 nil로 디코딩된다. + public let syncedAt: Date? public init( info: AlarmInfo, @@ -25,7 +29,8 @@ public struct AlarmSessionSnapshot: Sendable, Equatable, Codable { routeDisplayName: String, transportMode: TransportMode?, acknowledged: Bool, - expired: Bool + expired: Bool, + syncedAt: Date? = nil ) { self.info = info self.firstWalkSeconds = firstWalkSeconds @@ -33,13 +38,16 @@ public struct AlarmSessionSnapshot: Sendable, Equatable, Codable { self.transportMode = transportMode self.acknowledged = acknowledged self.expired = expired + self.syncedAt = syncedAt } /// 세션 사실(도보·표시명·수단)은 유지하고 기록 필드만 바꾼 사본. + /// syncedAt은 명시할 때만 갱신된다 — 만료 톰스톤 전환 등은 마지막 확인 시각을 보존한다. public func updating( info: AlarmInfo? = nil, acknowledged: Bool? = nil, - expired: Bool? = nil + expired: Bool? = nil, + syncedAt: Date? = nil ) -> AlarmSessionSnapshot { AlarmSessionSnapshot( info: info ?? self.info, @@ -47,7 +55,8 @@ public struct AlarmSessionSnapshot: Sendable, Equatable, Codable { routeDisplayName: routeDisplayName, transportMode: transportMode, acknowledged: acknowledged ?? self.acknowledged, - expired: expired ?? self.expired + expired: expired ?? self.expired, + syncedAt: syncedAt ?? self.syncedAt ) } } diff --git a/Projects/Domain/Sources/Interfaces/AlarmSyncEvents.swift b/Projects/Domain/Sources/Interfaces/AlarmSyncEvents.swift index 3d6b02f..367c20a 100644 --- a/Projects/Domain/Sources/Interfaces/AlarmSyncEvents.swift +++ b/Projects/Domain/Sources/Interfaces/AlarmSyncEvents.swift @@ -1,10 +1,26 @@ import Foundation +/// 동기화 성공 방출값(Phase 16) — info에 "언제 서버로 확인했는가"를 동봉한다. +/// checkedAt이 신선도 스탬프("HH:mm 확인 기준")의 유일한 원천이다 — 구독자(홈)가 +/// 수신 시각으로 찍으면 스냅샷 시딩 복원값이 "지금 확인됨"으로 둔갑하므로 금지. +public struct AlarmSyncUpdate: Sendable, Equatable { + public let info: AlarmInfo + /// 서버 확인 시각. 스냅샷 시딩 복원이면 직전 세션의 마지막 확인 시각(스냅샷의 + /// syncedAt), 그것도 없으면 nil — nil이면 스탬프를 표시하지 않는다(정직한 기본값). + public let checkedAt: Date? + + public init(info: AlarmInfo, checkedAt: Date?) { + self.info = info + self.checkedAt = checkedAt + } +} + /// 알람 동기화 결과 포트 — 발행 주체는 App의 AlarmSyncService(앱 시작·포그라운드 -/// 복귀·사일런트 푸시 3경로를 RefreshAlarmUseCase 한 곳으로 모으는 유일한 호출자). -/// 실패는 흘리지 않는다 — 구독자는 성공 결과만 받고, 실패 시 기존 상태를 유지한다. +/// 복귀·사일런트 푸시·수동 갱신 4경로를 RefreshAlarmUseCase 한 곳으로 모으는 유일한 호출자). +/// 실패는 흘리지 않는다 — 구독자는 성공 결과만 받고, 실패 시 기존 상태를 유지한다 +/// (실패의 표면은 신선도 스탬프가 낡은 시각을 유지하는 것뿐 — 원칙 3). public protocol AlarmSyncEvents: Sendable { /// 구독자마다 독립 스트림. 구독 시 마지막 동기화 결과가 있으면 즉시 방출한다 /// (구독 전에 끝난 앱 시작 동기화를 놓치지 않도록). - func updates() -> AsyncStream + func updates() -> AsyncStream } diff --git a/Projects/Domain/Sources/Interfaces/AlarmSyncRequesting.swift b/Projects/Domain/Sources/Interfaces/AlarmSyncRequesting.swift new file mode 100644 index 0000000..88db2cf --- /dev/null +++ b/Projects/Domain/Sources/Interfaces/AlarmSyncRequesting.swift @@ -0,0 +1,10 @@ +import Foundation + +/// 수동 동기화 요청 포트(Phase 16) — 구현은 App의 AlarmSyncService(4번째 트리거). +/// 홈 pull-to-refresh가 유일한 호출자다 — 새 표출 채널을 만들지 않고, 결과는 +/// AlarmSyncEvents.updates() 스트림으로만 흐른다(실패 무음 정책 공유). +public protocol AlarmSyncRequesting: Sendable { + /// 동기화 1회를 요청하고 완료까지 기다린다. 진행 중 동기화가 있으면 합류한다 + /// (당김·포그라운드 복귀가 겹쳐도 refresh는 1회). 실패를 던지지 않는다. + func syncNow() async +} diff --git a/Projects/Domain/Sources/UseCases/ObserveAlarmUseCase.swift b/Projects/Domain/Sources/UseCases/ObserveAlarmUseCase.swift index 6778c4b..33c0ac3 100644 --- a/Projects/Domain/Sources/UseCases/ObserveAlarmUseCase.swift +++ b/Projects/Domain/Sources/UseCases/ObserveAlarmUseCase.swift @@ -1,7 +1,7 @@ import Foundation public protocol ObserveAlarmUseCase: Sendable { - func execute() -> AsyncStream + func execute() -> AsyncStream } public struct DefaultObserveAlarmUseCase: ObserveAlarmUseCase { @@ -11,7 +11,7 @@ public struct DefaultObserveAlarmUseCase: ObserveAlarmUseCase { self.events = events } - public func execute() -> AsyncStream { + public func execute() -> AsyncStream { events.updates() } } diff --git a/Projects/Domain/Sources/UseCases/RegisterAlarmUseCase.swift b/Projects/Domain/Sources/UseCases/RegisterAlarmUseCase.swift index a70808a..c9b09e4 100644 --- a/Projects/Domain/Sources/UseCases/RegisterAlarmUseCase.swift +++ b/Projects/Domain/Sources/UseCases/RegisterAlarmUseCase.swift @@ -70,13 +70,15 @@ public struct DefaultRegisterAlarmUseCase: RegisterAlarmUseCase { ) // 등록 성공 = 스냅샷 저장 시점(Phase 14) — 재실행 시 diff 기준·LA 재부착·카드 // 복원의 재료. 도보 초·표시명·수단은 등록 시점 경로에서만 얻을 수 있다. + // syncedAt = 등록 시각(Phase 16) — 서버가 방금 이 값을 받아들였으므로 확인이다. await snapshotStore?.save(AlarmSessionSnapshot( info: session, firstWalkSeconds: route.firstWalkSectionSeconds, routeDisplayName: route.sessionDisplayName, transportMode: route.boardingLeg?.mode, acknowledged: false, - expired: false + expired: false, + syncedAt: now() )) // 수명 정책: 알람 등록(서버+로컬)이 전부 성공한 뒤에만 LA를 시작한다. // start는 throws가 아니므로 LA 실패가 알람 등록을 실패시킬 수 없다. diff --git a/Projects/Domain/Sources/UseCases/RequestAlarmSyncUseCase.swift b/Projects/Domain/Sources/UseCases/RequestAlarmSyncUseCase.swift new file mode 100644 index 0000000..ef0cdd9 --- /dev/null +++ b/Projects/Domain/Sources/UseCases/RequestAlarmSyncUseCase.swift @@ -0,0 +1,20 @@ +import Foundation + +/// 홈 pull-to-refresh의 수동 갱신 진입점(Phase 16) — Observe 계열과 같은 패턴으로 +/// App의 AlarmSyncService(AlarmSyncRequesting)를 감싼다. 완료 = 동기화 종료(성공/실패 +/// 불문)이고, 갱신된 값은 ObserveAlarmUseCase 스트림이 따로 나른다. +public protocol RequestAlarmSyncUseCase: Sendable { + func execute() async +} + +public struct DefaultRequestAlarmSyncUseCase: RequestAlarmSyncUseCase { + private let requesting: any AlarmSyncRequesting + + public init(requesting: any AlarmSyncRequesting) { + self.requesting = requesting + } + + public func execute() async { + await requesting.syncNow() + } +} diff --git a/Projects/Domain/Tests/AlarmSessionSnapshotTests.swift b/Projects/Domain/Tests/AlarmSessionSnapshotTests.swift index fc85562..a81b70c 100644 --- a/Projects/Domain/Tests/AlarmSessionSnapshotTests.swift +++ b/Projects/Domain/Tests/AlarmSessionSnapshotTests.swift @@ -14,7 +14,8 @@ struct AlarmSessionSnapshotTests { routeDisplayName: "6411번 버스", transportMode: .bus, acknowledged: false, - expired: false + expired: false, + syncedAt: Date(timeIntervalSince1970: 1_755_995_000) ) @Test @@ -62,4 +63,39 @@ struct AlarmSessionSnapshotTests { #expect(tombstone.expired) #expect(tombstone.info == snapshot.info) } + + // MARK: - syncedAt (Phase 16 신선도 스탬프) + + @Test + func updating_preservesSyncedAtUnlessGiven() { + // 명시하지 않으면 마지막 확인 시각을 보존한다 — 톰스톤 전환이 스탬프를 지우면 안 된다. + let tombstone = snapshot.updating(expired: true) + #expect(tombstone.syncedAt == snapshot.syncedAt) + + let refreshed = snapshot.updating(syncedAt: Date(timeIntervalSince1970: 1_756_000_100)) + #expect(refreshed.syncedAt == Date(timeIntervalSince1970: 1_756_000_100)) + #expect(refreshed.info == snapshot.info) + } + + @Test + func decoding_snapshotWithoutSyncedAtKey_defaultsToNil() throws { + // Phase 16 이전에 저장된 스냅샷(구 포맷) — syncedAt 키 부재는 nil로 디코딩돼야 + // 재실행 브리지가 깨지지 않는다(하위호환). + let legacy = AlarmSessionSnapshot( + info: snapshot.info, + firstWalkSeconds: 120, + routeDisplayName: "6411번 버스", + transportMode: .bus, + acknowledged: false, + expired: false + ) + var object = try #require( + try JSONSerialization.jsonObject(with: JSONEncoder().encode(legacy)) as? [String: Any] + ) + object.removeValue(forKey: "syncedAt") + let data = try JSONSerialization.data(withJSONObject: object) + let decoded = try JSONDecoder().decode(AlarmSessionSnapshot.self, from: data) + #expect(decoded.syncedAt == nil) + #expect(decoded.info == snapshot.info) + } } diff --git a/Projects/Domain/Tests/DefaultObserveAlarmUseCaseTests.swift b/Projects/Domain/Tests/DefaultObserveAlarmUseCaseTests.swift index a31c532..274f479 100644 --- a/Projects/Domain/Tests/DefaultObserveAlarmUseCaseTests.swift +++ b/Projects/Domain/Tests/DefaultObserveAlarmUseCaseTests.swift @@ -3,33 +3,37 @@ import Foundation import Testing private struct StubAlarmSyncEvents: AlarmSyncEvents { - let handler: @Sendable () -> AsyncStream - func updates() -> AsyncStream { handler() } + let handler: @Sendable () -> AsyncStream + func updates() -> AsyncStream { handler() } } struct DefaultObserveAlarmUseCaseTests { @Test func execute_forwardsPortStream() async { - let info = AlarmInfo( - lastRouteId: "r1", - departureTime: Date(timeIntervalSince1970: 1_755_800_000), - updatedAt: nil, - isReal: true + let update = AlarmSyncUpdate( + info: AlarmInfo( + lastRouteId: "r1", + departureTime: Date(timeIntervalSince1970: 1_755_800_000), + updatedAt: nil, + isReal: true + ), + // 확인 시각이 함께 흘러야 한다 — 신선도 스탬프의 원천(Phase 16). + checkedAt: Date(timeIntervalSince1970: 1_755_790_000) ) let sut = DefaultObserveAlarmUseCase( events: StubAlarmSyncEvents { AsyncStream { continuation in - continuation.yield(info) + continuation.yield(update) continuation.finish() } } ) - var received: [AlarmInfo] = [] - for await update in sut.execute() { - received.append(update) + var received: [AlarmSyncUpdate] = [] + for await value in sut.execute() { + received.append(value) } - #expect(received == [info]) + #expect(received == [update]) } } diff --git a/Projects/Domain/Tests/DefaultRegisterAlarmUseCaseTests.swift b/Projects/Domain/Tests/DefaultRegisterAlarmUseCaseTests.swift index 61bb6b2..1ca0fd9 100644 --- a/Projects/Domain/Tests/DefaultRegisterAlarmUseCaseTests.swift +++ b/Projects/Domain/Tests/DefaultRegisterAlarmUseCaseTests.swift @@ -283,6 +283,8 @@ struct DefaultRegisterAlarmUseCaseTests { #expect(saved.first?.transportMode == .bus) #expect(saved.first?.acknowledged == false) #expect(saved.first?.expired == false) + // 등록 성공 = 서버 확인 — 신선도 스탬프의 원천이 등록 시각으로 기록된다(Phase 16). + #expect(saved.first?.syncedAt == fixedNow()) } @Test diff --git a/Projects/Domain/Tests/DefaultRequestAlarmSyncUseCaseTests.swift b/Projects/Domain/Tests/DefaultRequestAlarmSyncUseCaseTests.swift new file mode 100644 index 0000000..7d8c4e5 --- /dev/null +++ b/Projects/Domain/Tests/DefaultRequestAlarmSyncUseCaseTests.swift @@ -0,0 +1,22 @@ +@testable import Domain +import Foundation +import Testing + +private actor SpyAlarmSyncRequesting: AlarmSyncRequesting { + private(set) var syncNowCount = 0 + func syncNow() async { syncNowCount += 1 } +} + +struct DefaultRequestAlarmSyncUseCaseTests { + @Test + func execute_forwardsToPortOncePerCall() async { + let spy = SpyAlarmSyncRequesting() + let sut = DefaultRequestAlarmSyncUseCase(requesting: spy) + + await sut.execute() + await sut.execute() + + // 합류·중복 억제는 포트 구현(AlarmSyncService inFlight)의 몫 — UseCase는 위임만. + #expect(await spy.syncNowCount == 2) + } +} diff --git a/Projects/Feature/Home/Example/ExampleApp.swift b/Projects/Feature/Home/Example/ExampleApp.swift index 2667d95..e47752f 100644 --- a/Projects/Feature/Home/Example/ExampleApp.swift +++ b/Projects/Feature/Home/Example/ExampleApp.swift @@ -41,6 +41,7 @@ final class SceneDelegate: UIResponder, UIWindowSceneDelegate { cancelAlarmUseCase: PreviewCancelAlarmUseCase(), observeAlarmUseCase: PreviewObserveAlarmUseCase(), observeAlarmChangeUseCase: PreviewObserveAlarmChangeUseCase(), + requestAlarmSyncUseCase: PreviewRequestAlarmSyncUseCase(), getLastRouteDetailUseCase: PreviewGetLastRouteDetailUseCase(), searchCoordinatorBuildable: PreviewSearchCoordinatorBuildable() ) @@ -87,11 +88,18 @@ struct PreviewCancelAlarmUseCase: CancelAlarmUseCase { /// 등록된 알람이 없는 서버 상태를 흉내 낸다 — 동기화 이벤트가 오지 않으므로 화면을 건드리지 않는다. struct PreviewObserveAlarmUseCase: ObserveAlarmUseCase { - func execute() -> AsyncStream { + func execute() -> AsyncStream { AsyncStream { _ in } } } +/// 수동 갱신(pull-to-refresh) 스텁 — 잠깐 도는 스피너만 흉내 낸다(결과 스트림 없음). +struct PreviewRequestAlarmSyncUseCase: RequestAlarmSyncUseCase { + func execute() async { + try? await Task.sleep(for: .milliseconds(600)) + } +} + /// 막차 변경 판정이 없는 상태를 흉내 낸다 — 토스트·배너 강조는 발생하지 않는다. struct PreviewObserveAlarmChangeUseCase: ObserveAlarmChangeUseCase { func execute() -> AsyncStream { diff --git a/Projects/Feature/Home/Sources/HomeDIContainer.swift b/Projects/Feature/Home/Sources/HomeDIContainer.swift index 5cfdc10..faf9c6a 100644 --- a/Projects/Feature/Home/Sources/HomeDIContainer.swift +++ b/Projects/Feature/Home/Sources/HomeDIContainer.swift @@ -14,6 +14,7 @@ public final class HomeDIContainer: HomeCoordinatorBuildable { private let cancelAlarmUseCase: any CancelAlarmUseCase private let observeAlarmUseCase: any ObserveAlarmUseCase private let observeAlarmChangeUseCase: any ObserveAlarmChangeUseCase + private let requestAlarmSyncUseCase: any RequestAlarmSyncUseCase private let getLastRouteDetailUseCase: any GetLastRouteDetailUseCase private let searchCoordinatorBuildable: any SearchCoordinatorBuildable @@ -24,6 +25,7 @@ public final class HomeDIContainer: HomeCoordinatorBuildable { cancelAlarmUseCase: any CancelAlarmUseCase, observeAlarmUseCase: any ObserveAlarmUseCase, observeAlarmChangeUseCase: any ObserveAlarmChangeUseCase, + requestAlarmSyncUseCase: any RequestAlarmSyncUseCase, getLastRouteDetailUseCase: any GetLastRouteDetailUseCase, searchCoordinatorBuildable: any SearchCoordinatorBuildable ) { @@ -33,6 +35,7 @@ public final class HomeDIContainer: HomeCoordinatorBuildable { self.cancelAlarmUseCase = cancelAlarmUseCase self.observeAlarmUseCase = observeAlarmUseCase self.observeAlarmChangeUseCase = observeAlarmChangeUseCase + self.requestAlarmSyncUseCase = requestAlarmSyncUseCase self.getLastRouteDetailUseCase = getLastRouteDetailUseCase self.searchCoordinatorBuildable = searchCoordinatorBuildable } @@ -51,6 +54,7 @@ public final class HomeDIContainer: HomeCoordinatorBuildable { cancelAlarmUseCase: cancelAlarmUseCase, observeAlarmUseCase: observeAlarmUseCase, observeAlarmChangeUseCase: observeAlarmChangeUseCase, + requestAlarmSyncUseCase: requestAlarmSyncUseCase, getLastRouteDetailUseCase: getLastRouteDetailUseCase ) viewModel.onSearchRequested = onSearchRequested diff --git a/Projects/Feature/Home/Sources/HomeViewController.swift b/Projects/Feature/Home/Sources/HomeViewController.swift index 9318a6e..b569e92 100644 --- a/Projects/Feature/Home/Sources/HomeViewController.swift +++ b/Projects/Feature/Home/Sources/HomeViewController.swift @@ -32,6 +32,14 @@ final class HomeViewController: UIViewController { return stack }() + // pull-to-refresh(Phase 16) — 콘텐츠가 화면보다 짧아도 당길 수 있게 상시 바운스. + private let scrollView: UIScrollView = { + let scrollView = UIScrollView() + scrollView.alwaysBounceVertical = true + return scrollView + }() + private let refreshControl = UIRefreshControl() + init(viewModel: HomeViewModel) { self.viewModel = viewModel super.init(nibName: nil, bundle: nil) @@ -73,10 +81,24 @@ final class HomeViewController: UIViewController { private func configureUI() { view.backgroundColor = DSColor.Background.base - view.addSubview(contentStack) + refreshControl.addAction( + UIAction { [weak self] _ in self?.viewModel.refreshPulled() }, + for: .valueChanged + ) + scrollView.refreshControl = refreshControl + view.addSubview(scrollView) + scrollView.snp.makeConstraints { make in + make.top.equalTo(view.safeAreaLayoutGuide) + make.leading.trailing.bottom.equalToSuperview() + } + + scrollView.addSubview(contentStack) contentStack.snp.makeConstraints { make in - make.top.equalTo(view.safeAreaLayoutGuide).offset(DSSpacing.sm12) - make.leading.trailing.equalToSuperview().inset(DSSpacing.md) + make.top.equalTo(scrollView.contentLayoutGuide).offset(DSSpacing.sm12) + make.bottom.equalTo(scrollView.contentLayoutGuide) + make.leading.trailing.equalTo(scrollView.contentLayoutGuide).inset(DSSpacing.md) + // 세로 스크롤 전용 — 콘텐츠 폭을 프레임 폭에 고정한다(수평 스크롤 방지). + make.width.equalTo(scrollView.frameLayoutGuide).offset(-DSSpacing.md * 2) } [titleLabel, banner, departureRow, arrivalRow, routeCard, registerButton, cancelButton] @@ -169,6 +191,11 @@ final class HomeViewController: UIViewController { viewModel.onToast = { [weak self] event in self?.showToast(for: event) } + // 성공/실패 불문 동기화 종료 시 스피너를 내린다(Phase 16) — 실패 표출은 + // 스탬프가 낡은 시각을 유지하는 것뿐(무음 정책). + viewModel.onManualSyncFinished = { [weak self] in + self?.refreshControl.endRefreshing() + } render(viewModel.state) } @@ -184,7 +211,8 @@ final class HomeViewController: UIViewController { } if let card = state.routeCard { - routeCard.configure(with: card.dsContent) + // 신선도 스탬프(Phase 16)는 세션 상태라 State가 따로 나른다 — 표출 시점 합성. + routeCard.configure(with: card.dsContent(footnote: state.freshnessText)) routeCard.isHidden = false } else { routeCard.isHidden = true @@ -195,7 +223,11 @@ final class HomeViewController: UIViewController { cancelButton.isEnabled = !state.isAlarmBusy if let bannerData = state.banner { - banner.configure(text: bannerData.text, style: Self.bannerStyle(for: bannerData.urgency)) + banner.configure( + text: bannerData.text, + style: Self.bannerStyle(for: bannerData.urgency), + detailText: state.freshnessText + ) banner.isHidden = false } else { banner.isHidden = true diff --git a/Projects/Feature/Home/Sources/HomeViewData.swift b/Projects/Feature/Home/Sources/HomeViewData.swift index c6f30af..9ad020a 100644 --- a/Projects/Feature/Home/Sources/HomeViewData.swift +++ b/Projects/Feature/Home/Sources/HomeViewData.swift @@ -10,6 +10,15 @@ private let timeFormatter: DateFormatter = { return formatter }() +/// 신선도 스탬프 문구(Phase 16) — 배너 보조 라인·카드 푸터 공용. 등록 세션이 있고 +/// 확인 시각이 있을 때만 문구가 있다. 시각 포맷은 카드와 같은 캐시 포매터를 쓴다. +extension HomeViewModel { + static func freshnessText(checkedAt: Date?, isRegistered: Bool) -> String? { + guard isRegistered, let checkedAt else { return nil } + return "\(timeFormatter.string(from: checkedAt)) 확인 기준" + } +} + /// 홈에 표출되는 선택 경로 카드. Entity를 뷰에 직접 노출하지 않는다. struct RouteCardViewData: Equatable { /// 카드 톤 — past는 유예 경과 후의 "지난 막차" 상태(비활성 시각, Phase 13). @@ -65,13 +74,16 @@ struct RouteCardViewData: Equatable { ) } - var dsContent: DSRouteCard.Content { + /// footnote(신선도 스탬프)는 카드 사실이 아니라 세션 상태라 State가 따로 나른다 — + /// VC가 표출 시점에 합성한다(Phase 16). + func dsContent(footnote: String?) -> DSRouteCard.Content { .init( badgeText: badgeText, departureTimeText: departureTimeText, legs: legs, summaryText: summaryText, destinationText: destinationText, + footnoteText: footnote, tone: tone == .past ? .muted : .normal ) } diff --git a/Projects/Feature/Home/Sources/HomeViewModel.swift b/Projects/Feature/Home/Sources/HomeViewModel.swift index 5635341..52f9872 100644 --- a/Projects/Feature/Home/Sources/HomeViewModel.swift +++ b/Projects/Feature/Home/Sources/HomeViewModel.swift @@ -32,6 +32,10 @@ final class HomeViewModel { var banner: BannerViewData? var isAlarmBusy = false var alarmButton: AlarmButtonMode = .hidden + /// 신선도 스탬프 "HH:mm 확인 기준"(Phase 16) — 배너 보조 라인·카드 푸터 공용 + /// 단일 소스. 등록 세션과 확인 시각이 있을 때만 값이 있고, sync 무음 실패 시 + /// 낡은 시각을 그대로 유지하는 것이 실패의 정직한 표면이다(원칙 3). + var freshnessText: String? } /// 재방출되면 안 되는 원샷 안내 — 상태와 분리한다. @@ -56,6 +60,9 @@ final class HomeViewModel { /// Set by the ViewController; always invoked on the main actor. var onStateChange: ((State) -> Void)? var onToast: ((ToastEvent) -> Void)? + /// pull-to-refresh 종료 훅(Phase 16) — 성공/실패 불문 동기화가 끝나면 불린다 + /// (VC가 refreshControl.endRefreshing). 실패는 무음 — 결과 표출은 스트림·스탬프 몫. + var onManualSyncFinished: (() -> Void)? /// Set by the Coordinator: 검색 플로우를 열고, 선택 경로를 reply 클로저로 돌려받는다. var onSearchRequested: ((_ onRouteSelected: @escaping (LastRoute) -> Void) -> Void)? @@ -69,6 +76,7 @@ final class HomeViewModel { private let cancelAlarmUseCase: any CancelAlarmUseCase private let observeAlarmUseCase: any ObserveAlarmUseCase private let observeAlarmChangeUseCase: any ObserveAlarmChangeUseCase + private let requestAlarmSyncUseCase: any RequestAlarmSyncUseCase private let getLastRouteDetailUseCase: any GetLastRouteDetailUseCase private let now: @Sendable () -> Date private let bannerTickInterval: Duration @@ -76,12 +84,16 @@ final class HomeViewModel { private var selectedRoute: LastRoute? /// 서버에 알람이 등록된 경로 id — 해제 버튼·동기화 복원의 기준. private var registeredRouteId: String? + /// 세션 값이 마지막으로 서버로 확인된 시각(Phase 16) — 스트림의 checkedAt·등록 + /// 성공 시각만이 원천이다(수신 시각으로 찍지 않는다 — 시딩 복원값의 둔갑 방지). + private var lastCheckedAt: Date? private var locationTask: Task? private var alarmTask: Task? private var observeTask: Task? private var changeTask: Task? private var bannerTask: Task? private var restoreCardTask: Task? + private var refreshTask: Task? init( getCurrentLocationUseCase: any GetCurrentLocationUseCase, @@ -90,6 +102,7 @@ final class HomeViewModel { cancelAlarmUseCase: any CancelAlarmUseCase, observeAlarmUseCase: any ObserveAlarmUseCase, observeAlarmChangeUseCase: any ObserveAlarmChangeUseCase, + requestAlarmSyncUseCase: any RequestAlarmSyncUseCase, getLastRouteDetailUseCase: any GetLastRouteDetailUseCase, now: @escaping @Sendable () -> Date = { Date() }, bannerTickInterval: Duration = .seconds(60) @@ -100,6 +113,7 @@ final class HomeViewModel { self.cancelAlarmUseCase = cancelAlarmUseCase self.observeAlarmUseCase = observeAlarmUseCase self.observeAlarmChangeUseCase = observeAlarmChangeUseCase + self.requestAlarmSyncUseCase = requestAlarmSyncUseCase self.getLastRouteDetailUseCase = getLastRouteDetailUseCase self.now = now self.bannerTickInterval = bannerTickInterval @@ -112,6 +126,7 @@ final class HomeViewModel { changeTask?.cancel() bannerTask?.cancel() restoreCardTask?.cancel() + refreshTask?.cancel() } // MARK: - 입력 @@ -142,6 +157,19 @@ final class HomeViewModel { } } + /// pull-to-refresh(Phase 16) — 수동 동기화 1회. 진행 중 재진입은 no-op(이중 당김 + /// 무해). 실패는 무음 — 스피너 종료 + 스탬프가 낡은 시각을 유지하는 것이 표면이다. + func refreshPulled() { + guard refreshTask == nil else { return } + refreshTask = Task { [weak self] in + guard let useCase = self?.requestAlarmSyncUseCase else { return } + await useCase.execute() + guard let self, !Task.isCancelled else { return } + self.refreshTask = nil + self.onManualSyncFinished?() + } + } + /// 출발지/도착지 어느 필드를 탭해도 동일하게 검색 플로우로 진입한다. func searchFieldTapped() { onSearchRequested? { [weak self] route in @@ -172,18 +200,21 @@ final class HomeViewModel { guard let useCase = self?.registerAlarmUseCase else { return } do { let followUp = try await useCase.execute(route: route) - guard !Task.isCancelled else { return } - self?.registeredRouteId = route.id - self?.state.isAlarmBusy = false - self?.refreshAlarmButton() - self?.startBannerTimer( + guard !Task.isCancelled, let self else { return } + self.registeredRouteId = route.id + // 등록 성공 = 서버가 방금 이 값을 확인해줬다 — 스탬프 시작점(Phase 16). + self.lastCheckedAt = self.now() + self.state.isAlarmBusy = false + self.refreshAlarmButton() + self.refreshFreshness() + self.startBannerTimer( departure: route.departureTime, firstWalkSeconds: route.firstWalkSectionSeconds ) // 등록은 성공했고 폴백 노티만 잃었다 — 1회 안내(Phase 15). deniedNow는 // 이번 호출로 최초 요청이 이뤄졌고 거부된 경우뿐이라 재등록 시 반복되지 않는다. if followUp == .deniedNow { - self?.onToast?(.notificationPermissionDenied) + self.onToast?(.notificationPermissionDenied) } } catch AlarmError.permissionDenied { guard !Task.isCancelled else { return } @@ -212,6 +243,7 @@ final class HomeViewModel { guard !Task.isCancelled, let self else { return } self.bannerTask?.cancel() self.registeredRouteId = nil + self.lastCheckedAt = nil var newState = self.state newState.banner = nil newState.isAlarmBusy = false @@ -219,6 +251,7 @@ final class HomeViewModel { selectedRouteId: self.selectedRoute?.id, registeredRouteId: nil ) + newState.freshnessText = nil self.state = newState } catch { guard !Task.isCancelled else { return } @@ -239,16 +272,21 @@ final class HomeViewModel { observeTask?.cancel() observeTask = Task { [weak self] in guard let stream = self?.observeAlarmUseCase.execute() else { return } - for await info in stream { + for await update in stream { guard !Task.isCancelled else { return } - self?.alarmSynced(info) + self?.alarmSynced(update) } } } - private func alarmSynced(_ info: AlarmInfo) { + private func alarmSynced(_ update: AlarmSyncUpdate) { + let info = update.info registeredRouteId = info.lastRouteId + // 확인 시각은 스트림이 준 값만 쓴다(Phase 16) — 시딩 복원이면 직전 세션의 마지막 + // 확인 시각이고, 그것도 없으면 nil(스탬프 없음). 수신 시각으로 찍지 않는다. + lastCheckedAt = update.checkedAt refreshAlarmButton() + refreshFreshness() // 유예(출발+60초)가 지난 시각으로는 배너를 (재)시작하지 않는다 — 지난 막차의 // 복원은 오정보이고, 못 탐(actionable=false) 판정이 고정한 실패 배너를 후속 // 동기화가 덮어쓰는 일도 이 가드가 막는다. 유예 안이면 시작한다 — 발화~유예 @@ -333,12 +371,14 @@ final class HomeViewModel { // 여기서 지워진다. LA final state 종료·알람 취소는 App/Domain 경로의 몫. bannerTask?.cancel() registeredRouteId = nil + lastCheckedAt = nil var newState = state newState.banner = nil newState.alarmButton = Self.alarmButtonMode( selectedRouteId: selectedRoute?.id, registeredRouteId: nil ) + newState.freshnessText = nil state = newState onToast?(.lastTrainServiceEnded) case .delayed, .unchanged: @@ -378,6 +418,14 @@ final class HomeViewModel { ) } + /// 스탬프 재계산(Phase 16) — 등록 세션 존재 ∧ 확인 시각 존재일 때만 값이 있다. + private func refreshFreshness() { + state.freshnessText = Self.freshnessText( + checkedAt: lastCheckedAt, + isRegistered: registeredRouteId != nil + ) + } + private func startBannerTimer(departure: Date, firstWalkSeconds: Int?) { bannerTask?.cancel() // 매 틱 departure 기준으로 재계산 — 누적 드리프트가 없다. @@ -405,10 +453,13 @@ final class HomeViewModel { private func sessionExpired(departure: Date) { registeredRouteId = nil selectedRoute = nil + lastCheckedAt = nil var newState = state newState.banner = nil newState.routeCard = newState.routeCard?.asPastTrain(departure: departure) newState.alarmButton = .hidden + // "지난 막차" 카드에는 스탬프가 없다 — 세션이 끝난 값의 신선도는 무의미하다. + newState.freshnessText = nil state = newState } diff --git a/Projects/Feature/Home/Tests/HomeViewModelTests.swift b/Projects/Feature/Home/Tests/HomeViewModelTests.swift index e00594a..24cb6c5 100644 --- a/Projects/Feature/Home/Tests/HomeViewModelTests.swift +++ b/Projects/Feature/Home/Tests/HomeViewModelTests.swift @@ -33,8 +33,13 @@ private struct StubCancelAlarmUseCase: CancelAlarmUseCase { } private struct StubObserveAlarmUseCase: ObserveAlarmUseCase { - let handler: @Sendable () -> AsyncStream - func execute() -> AsyncStream { handler() } + let handler: @Sendable () -> AsyncStream + func execute() -> AsyncStream { handler() } +} + +private struct StubRequestAlarmSyncUseCase: RequestAlarmSyncUseCase { + let handler: @Sendable () async -> Void + func execute() async { await handler() } } private struct StubObserveAlarmChangeUseCase: ObserveAlarmChangeUseCase { @@ -148,12 +153,13 @@ private func makeSUT( register: @escaping @Sendable (LastRoute) async throws -> Void = { _ in }, registerOutcome: LocalNotificationAuthorizationOutcome = .alreadySettled, cancel: @escaping @Sendable (String) async throws -> Void = { _ in }, - alarmUpdates: @escaping @Sendable () -> AsyncStream = { + alarmUpdates: @escaping @Sendable () -> AsyncStream = { AsyncStream { $0.finish() } }, alarmChanges: @escaping @Sendable () -> AsyncStream = { AsyncStream { $0.finish() } }, + requestSync: @escaping @Sendable () async -> Void = {}, routeDetail: @escaping @Sendable (String) async throws -> LastRoute = { _ in throw StubError() }, @@ -169,12 +175,20 @@ private func makeSUT( cancelAlarmUseCase: StubCancelAlarmUseCase(handler: cancel), observeAlarmUseCase: StubObserveAlarmUseCase(handler: alarmUpdates), observeAlarmChangeUseCase: StubObserveAlarmChangeUseCase(handler: alarmChanges), + requestAlarmSyncUseCase: StubRequestAlarmSyncUseCase(handler: requestSync), getLastRouteDetailUseCase: StubGetLastRouteDetailUseCase(handler: routeDetail), now: now, bannerTickInterval: bannerTickInterval ) } +/// 스트림 yield용 축약 — 확인 시각이 무관한 기존 시나리오는 checkedAt 없이 흘린다. +private nonisolated func syncUpdate( + _ info: AlarmInfo, checkedAt: Date? = nil +) -> AlarmSyncUpdate { + AlarmSyncUpdate(info: info, checkedAt: checkedAt) +} + // MARK: - 테스트 @MainActor @@ -546,15 +560,15 @@ struct HomeViewModelTests { // 앱 재실행 복원 시나리오: 카드 없이 서버 알람만 있는 상태 — 앱 시작 동기화가 // 스트림으로 도착한다. let departure = fixedNow.addingTimeInterval(30 * 60) - let (stream, continuation) = AsyncStream.makeStream() + let (stream, continuation) = AsyncStream.makeStream() let sut = makeSUT(alarmUpdates: { stream }) let recorder = StateRecorder() recorder.attach(to: sut) sut.viewDidLoad() - continuation.yield( + continuation.yield(syncUpdate( AlarmInfo(lastRouteId: "r1", departureTime: departure, updatedAt: nil, isReal: true) - ) + )) await recorder.waitUntilLast { $0.banner != nil } // 30분 출발 → 알람까지 27분(1620초) — caution 구간. @@ -566,7 +580,7 @@ struct HomeViewModelTests { @Test func alarmSync_updatesBannerToNewDeparture() async { let route = makeRoute(id: "r1", departure: fixedNow.addingTimeInterval(42 * 60)) - let (stream, continuation) = AsyncStream.makeStream() + let (stream, continuation) = AsyncStream.makeStream() let sut = makeSUT(alarmUpdates: { stream }) let recorder = StateRecorder() recorder.attach(to: sut) @@ -576,14 +590,14 @@ struct HomeViewModelTests { await recorder.waitUntilLast { $0.banner?.text == "출발까지 39분" } // 서버가 15분 당긴 시각을 돌려준다 (포그라운드 복귀·푸시 동기화 공용 경로). - continuation.yield( + continuation.yield(syncUpdate( AlarmInfo( lastRouteId: "r1", departureTime: fixedNow.addingTimeInterval(27 * 60), updatedAt: nil, isReal: true ) - ) + )) await recorder.waitUntilLast { $0.banner?.text == "출발까지 24분" } #expect(sut.state.alarmButton == .cancel) @@ -709,20 +723,20 @@ struct HomeViewModelTests { func alarmSync_pastGraceDeparture_doesNotStartCountdown() async { // 유예(출발+60초)가 지난 시각의 동기화 복원 — 지난 막차 배너를 되살리지 않는다. // 못 탐 판정이 고정한 실패 배너를 후속 동기화가 덮어쓰는 것도 같은 가드가 막는다. - let (stream, continuation) = AsyncStream.makeStream() + let (stream, continuation) = AsyncStream.makeStream() let sut = makeSUT(alarmUpdates: { stream }) let recorder = StateRecorder() recorder.attach(to: sut) sut.viewDidLoad() - continuation.yield( + continuation.yield(syncUpdate( AlarmInfo( lastRouteId: "r1", departureTime: fixedNow.addingTimeInterval(-60), updatedAt: nil, isReal: true ) - ) + )) await recorder.waitUntilLast { $0.alarmButton == .cancel } #expect(sut.state.banner == nil) @@ -731,20 +745,20 @@ struct HomeViewModelTests { @Test func alarmSync_withinGrace_restoresDepartNowBanner() async { // 발화~유예 창의 동기화 복원 — 2단계 "지금 출발하세요"도 복원 대상이다 (Phase 13). - let (stream, continuation) = AsyncStream.makeStream() + let (stream, continuation) = AsyncStream.makeStream() let sut = makeSUT(alarmUpdates: { stream }) let recorder = StateRecorder() recorder.attach(to: sut) sut.viewDidLoad() - continuation.yield( + continuation.yield(syncUpdate( AlarmInfo( lastRouteId: "r1", departureTime: fixedNow.addingTimeInterval(-30), updatedAt: nil, isReal: true ) - ) + )) await recorder.waitUntilLast { $0.banner != nil } #expect(sut.state.banner == .init(text: "지금 출발하세요", urgency: .imminent)) @@ -844,7 +858,7 @@ struct HomeViewModelTests { // 도보 반영 배너까지 복원한다 — "무슨 경로인지 모르는 해제 버튼" 해소. let departure = fixedNow.addingTimeInterval(42 * 60) let route = makeWalkRoute(id: "r1", departure: departure, walkSeconds: 120) - let (stream, continuation) = AsyncStream.makeStream() + let (stream, continuation) = AsyncStream.makeStream() let sut = makeSUT( alarmUpdates: { stream }, routeDetail: { routeId in @@ -856,9 +870,9 @@ struct HomeViewModelTests { recorder.attach(to: sut) sut.viewDidLoad() - continuation.yield( + continuation.yield(syncUpdate( AlarmInfo(lastRouteId: "r1", departureTime: departure, updatedAt: nil, isReal: true) - ) + )) await recorder.waitUntilLast { $0.routeCard != nil } #expect(sut.state.routeCard == RouteCardViewData(entity: route)) @@ -871,15 +885,15 @@ struct HomeViewModelTests { func alarmSync_detailFails_keepsCancelButtonWithoutCard() async { // 복원 실패는 현행 폴백 — 카드 없이 해제 버튼·배너만. (기본 routeDetail 스텁이 throw) let departure = fixedNow.addingTimeInterval(30 * 60) - let (stream, continuation) = AsyncStream.makeStream() + let (stream, continuation) = AsyncStream.makeStream() let sut = makeSUT(alarmUpdates: { stream }) let recorder = StateRecorder() recorder.attach(to: sut) sut.viewDidLoad() - continuation.yield( + continuation.yield(syncUpdate( AlarmInfo(lastRouteId: "r1", departureTime: departure, updatedAt: nil, isReal: true) - ) + )) await recorder.waitUntilLast { $0.banner != nil } for _ in 0..<20 { await Task.yield() } @@ -892,7 +906,7 @@ struct HomeViewModelTests { // 등록 직후의 동기화 — 카드가 이미 있으면 상세 재조회를 하지 않는다. let route = makeRoute(id: "r1", departure: fixedNow.addingTimeInterval(42 * 60)) let fetched = FetchFlag() - let (stream, continuation) = AsyncStream.makeStream() + let (stream, continuation) = AsyncStream.makeStream() let sut = makeSUT( alarmUpdates: { stream }, routeDetail: { _ in @@ -907,19 +921,199 @@ struct HomeViewModelTests { sut.registerAlarmTapped() await recorder.waitUntilLast { $0.banner != nil } - continuation.yield( + continuation.yield(syncUpdate( AlarmInfo( lastRouteId: "r1", departureTime: fixedNow.addingTimeInterval(42 * 60), updatedAt: nil, isReal: true ) - ) + )) for _ in 0..<20 { await Task.yield() } #expect(!fetched.value) #expect(sut.state.routeCard == RouteCardViewData(entity: route)) } + + // MARK: - 수동 갱신 (Phase 16 pull-to-refresh) + + @Test + func refreshPulled_invokesSyncAndSignalsFinish() async { + let calls = ValueBox(0) + let sut = makeSUT(requestSync: { calls.update { $0 + 1 } }) + let finished = ValueBox(0) + sut.onManualSyncFinished = { finished.update { $0 + 1 } } + + sut.refreshPulled() + while finished.get() < 1 { await Task.yield() } + + #expect(calls.get() == 1) + #expect(finished.get() == 1) + } + + @Test + func refreshPulled_whileInFlight_isNoOp() async { + // 스텁 동기화가 게이트에 막혀 있는 동안의 재당김은 no-op이어야 한다(이중 당김 무해). + let gate = ValueBox(false) + let calls = ValueBox(0) + let sut = makeSUT(requestSync: { + calls.update { $0 + 1 } + while !gate.get() { await Task.yield() } + }) + let finished = ValueBox(0) + sut.onManualSyncFinished = { finished.update { $0 + 1 } } + + sut.refreshPulled() + sut.refreshPulled() + gate.update { _ in true } + while finished.get() < 1 { await Task.yield() } + for _ in 0..<20 { await Task.yield() } + + #expect(calls.get() == 1) + #expect(finished.get() == 1) + + // 완료 후의 당김은 새 동기화다. + sut.refreshPulled() + while finished.get() < 2 { await Task.yield() } + #expect(calls.get() == 2) + } + + // MARK: - 신선도 스탬프 (Phase 16) + + @Test + func freshnessText_requiresRegisteredSessionAndCheckedAt() { + let checkedAt = fixedNow + let expected = "\(makeStampFormatter().string(from: checkedAt)) 확인 기준" + #expect(HomeViewModel.freshnessText(checkedAt: checkedAt, isRegistered: true) == expected) + // 확인 시각이 없으면(구 스냅샷 시딩 등) 스탬프를 지어내지 않는다. + #expect(HomeViewModel.freshnessText(checkedAt: nil, isRegistered: true) == nil) + // 등록 세션이 없으면 후보 카드에 스탬프를 달지 않는다. + #expect(HomeViewModel.freshnessText(checkedAt: checkedAt, isRegistered: false) == nil) + } + + @Test + func registerAlarm_success_stampsFreshnessWithNow() async { + let route = makeRoute(id: "r1", departure: fixedNow.addingTimeInterval(42 * 60)) + let sut = makeSUT() + let recorder = StateRecorder() + recorder.attach(to: sut) + + sut.routeSelected(route) + #expect(sut.state.freshnessText == nil) + sut.registerAlarmTapped() + await recorder.waitUntilLast { $0.banner != nil } + + // 등록 성공 = 서버 확인 — now(고정 시계) 기준으로 스탬프가 시작된다. + #expect(sut.state.freshnessText + == "\(makeStampFormatter().string(from: fixedNow)) 확인 기준") + } + + @Test + func alarmSync_checkedAt_updatesStamp_andSeededNilKeepsNoStamp() async { + // 시딩 복원(checkedAt = 직전 확인 시각)은 그 낡은 시각을 그대로 표시하고, + // 이후 성공 동기화(checkedAt = 새 시각)가 스탬프를 전진시킨다. + let departure = fixedNow.addingTimeInterval(30 * 60) + let seededCheckedAt = fixedNow.addingTimeInterval(-40 * 60) + let (stream, continuation) = AsyncStream.makeStream() + let sut = makeSUT(alarmUpdates: { stream }) + let recorder = StateRecorder() + recorder.attach(to: sut) + sut.viewDidLoad() + + continuation.yield(syncUpdate( + AlarmInfo(lastRouteId: "r1", departureTime: departure, updatedAt: nil, isReal: true), + checkedAt: seededCheckedAt + )) + await recorder.waitUntilLast { $0.freshnessText != nil } + #expect(sut.state.freshnessText + == "\(makeStampFormatter().string(from: seededCheckedAt)) 확인 기준") + + continuation.yield(syncUpdate( + AlarmInfo(lastRouteId: "r1", departureTime: departure, updatedAt: nil, isReal: true), + checkedAt: fixedNow + )) + await recorder.waitUntilLast { + $0.freshnessText == "\(makeStampFormatter().string(from: fixedNow)) 확인 기준" + } + } + + @Test + func manualSync_noStreamEvent_keepsStaleStamp() async { + // 무음 실패의 표면: 당김이 아무 이벤트도 못 얻으면 스탬프는 낡은 시각을 유지한다. + let route = makeRoute(id: "r1", departure: fixedNow.addingTimeInterval(42 * 60)) + let sut = makeSUT() + let recorder = StateRecorder() + recorder.attach(to: sut) + sut.routeSelected(route) + sut.registerAlarmTapped() + await recorder.waitUntilLast { $0.freshnessText != nil } + let stampBefore = sut.state.freshnessText + + let finished = ValueBox(0) + sut.onManualSyncFinished = { finished.update { $0 + 1 } } + sut.refreshPulled() + while finished.get() < 1 { await Task.yield() } + + #expect(sut.state.freshnessText == stampBefore) + #expect(recorder.toasts.isEmpty) // 실패 토스트 금지 — 무음 정책. + } + + @Test + func cancelAlarm_clearsFreshnessStamp() async { + let route = makeRoute(id: "r1", departure: fixedNow.addingTimeInterval(42 * 60)) + let sut = makeSUT() + let recorder = StateRecorder() + recorder.attach(to: sut) + sut.routeSelected(route) + sut.registerAlarmTapped() + await recorder.waitUntilLast { $0.freshnessText != nil } + + sut.cancelAlarmTapped() + await recorder.waitUntilLast { $0.banner == nil && !$0.isAlarmBusy } + + #expect(sut.state.freshnessText == nil) + } + + @Test + func sessionEndedAndExpiry_clearFreshnessStamp() async { + // 종료·만료 정리와 함께 스탬프도 사라진다 — "지난 막차"에 신선도는 무의미하다. + let clock = NowBox(fixedNow) + let departure = fixedNow.addingTimeInterval(42 * 60) + let route = makeRoute(id: "r1", departure: departure) + let (stream, continuation) = AsyncStream.makeStream() + let sut = makeSUT( + alarmChanges: { stream }, + now: { clock.get() }, + bannerTickInterval: .milliseconds(1) + ) + let recorder = StateRecorder() + recorder.attach(to: sut) + sut.viewDidLoad() + sut.routeSelected(route) + sut.registerAlarmTapped() + // 스탬프는 배너보다 먼저 설정된다 — 배너까지 뜬 뒤에 종료를 흘려야 정리를 검증한다. + await recorder.waitUntilLast { $0.banner != nil && $0.freshnessText != nil } + + continuation.yield(.sessionEnded) + await recorder.waitUntilLast { $0.banner == nil } + #expect(sut.state.freshnessText == nil) + + // 재등록 후 유예 경과(3단계 전이)도 스탬프를 정리한다. + sut.registerAlarmTapped() + await recorder.waitUntilLast { $0.banner != nil && $0.freshnessText != nil } + clock.set(departure.addingTimeInterval(60)) + await recorder.waitUntilLast { $0.banner == nil && $0.freshnessText == nil } + #expect(sut.state.routeCard?.tone == .past) + } +} + +/// 스탬프 기대값용 포매터 — 프로덕션(HomeViewData)과 같은 구성(HH:mm, ko_KR). +@MainActor +private func makeStampFormatter() -> DateFormatter { + let formatter = DateFormatter() + formatter.dateFormat = "HH:mm" + formatter.locale = Locale(identifier: "ko_KR") + return formatter } /// 상세 재조회 호출 여부 기록용 — 스텁 클로저가 @Sendable이라 클래스 박스로 관찰한다. From 77ede3c4df4c535d48a5f6fd3a40dc9a711c2de9 Mon Sep 17 00:00:00 2001 From: AppGoni Date: Sun, 23 Aug 2026 23:22:12 +0900 Subject: [PATCH 06/14] =?UTF-8?q?docs:=20Phase=2016=20=EC=9E=90=EB=8F=99?= =?UTF-8?q?=20=EA=B2=80=EC=88=98=20=EA=B2=B0=EA=B3=BC=20=EA=B8=B0=EB=A1=9D?= =?UTF-8?q?=20+=20CLAUDE.md=20=EA=B0=B1=EC=8B=A0=20=EC=B1=84=EB=84=90=20?= =?UTF-8?q?=EC=84=9C=EC=88=A0=20=EA=B0=B1=EC=8B=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- CLAUDE.md | 2 +- docs/prompts/atcha-v2-refresh-reliability-prompt.md | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 9a9f206..3b8e65f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -81,7 +81,7 @@ AtchaV2(앱, 조합 루트: 어댑터·스플래시·AlarmSyncService) ─► Ho - **익명 인증 발급 엔드포인트 미확정** — `UnconfiguredAnonymousSessionIssuer` 스텁이 주입돼 있어 실서버에서는 토큰 없이 동작한다(알람 서버 기능 전부 불가). Debug(DEV)는 `DevDemoFallbacks`가 데모 데이터로 가린다 — 실서버 스펙 확정 시 이 폴백과 `AppDIContainer`의 `#if DEV` 주입을 제거할 것. - `AppEnvironment`의 base URL은 dev/live 실주소 반영 완료. **Stage는 dev 호스트를 공유 중** — 전용 호스트만 미정. -- `Projects/App/Resources/GoogleService-Info.plist`는 **레거시 번들 ID(`com.atcha.iOS`)용 파일**이라 존재 가드만 통과할 뿐 V2(`com.atcha.iOS.v2`)로의 사일런트 푸시가 성립하지 않는다 — V2용 재발급·교체 필요. FCM 토큰 서버 전달도 미구현(로깅만)이라 갱신 채널은 현재 폴링(앱 시작·포그라운드 복귀)뿐. +- `Projects/App/Resources/GoogleService-Info.plist`는 **레거시 번들 ID(`com.atcha.iOS`)용 파일**이라 존재 가드만 통과할 뿐 V2(`com.atcha.iOS.v2`)로의 사일런트 푸시가 성립하지 않는다 — V2용 재발급·교체 필요. FCM 토큰 서버 전달도 미구현(로깅만)이라 갱신 채널은 현재 폴링(앱 시작·포그라운드 복귀)과 홈 pull-to-refresh(수동)뿐. - AtchaV2는 iOS 26 전용. AlarmKit(CoreAlarm)·Live Activity(CoreLiveActivity + AtchaWidget 익스텐션)는 Phase 9~12에서 구축 완료. - Phase 12 이후의 갭 분석·후속 로드맵: `docs/planning/atcha-v2-post12-roadmap.md` / Phase 13·14(알람 이후 + 재실행 정합성) 구현 프롬프트: `docs/prompts/atcha-v2-session-lifecycle-prompt.md`. - Phase 검수는 사람 검수 대신 **자동 검수 규약**(`docs/prompts/atcha-v2-auto-verification.md`)을 따른다 — 에이전트가 computer use로 시뮬레이터 검수를 직접 수행·증적 보고하고, 실기기 잔여 항목만 사용자에게 이관. diff --git a/docs/prompts/atcha-v2-refresh-reliability-prompt.md b/docs/prompts/atcha-v2-refresh-reliability-prompt.md index 6227c15..3dcad5c 100644 --- a/docs/prompts/atcha-v2-refresh-reliability-prompt.md +++ b/docs/prompts/atcha-v2-refresh-reliability-prompt.md @@ -184,7 +184,9 @@ iOS 26 시뮬레이터(Debug/DEV)에서 에이전트가 직접 수행하고 단 ⑤ **회귀**: 앞당김 주입 + 포그라운드 → 기존 인앱 채널(토스트 + 배너 강조) 동작 유지 + 스탬프 갱신. 스피너 진행 중 재당김 → 재진입 no-op(로그 증적). 당김 제스처 자동화가 불가로 판명되면(AX 기반 조작 한계): 판정을 "자동화 불가"로 기록하고, VM 경로는 단위 테스트로 검증돼 있으므로 **DEV 플로팅 디버그 메뉴에 검수용 "수동 갱신" 항목(syncNow 직결, DEV 한정 — 변경 시뮬레이터와 동일 취급)을 추가**해 ②·③의 스탬프 판정을 대체 수행하고, 실제 당김 제스처만 실기기 잔여로 이관한다. -**실기기 잔여**: 실서버 오프라인·타임아웃 실측(스플래시 문구 분기 실표출 포함 — 현 DEV는 issuerNotConfigured 삼킴으로 재시도 화면 도달 불가, S1 이후 확인). 사일런트 푸시 실수신 경로(기존 항상-잔여 항목). (해당 시) pull-to-refresh 당김 제스처 실동작. +> **검수 결과 기록 (2026-08-23 수행)**: ①③④⑤ 통과(증적 스크린샷 확보 — 스탬프 표출·성공 sync 전진·재실행 시딩 복원·포그라운드 인앱 채널+스탬프 갱신). ②의 "무음 실패 시 스탬프 유지"는 재실행 직후 자동 sync 실패(주입 없음)와 대기 관찰로 입증(23:14 스탬프가 23:17까지, 23:18 스탬프가 재실행 후에도 유지). **당김 제스처는 "자동화 불가" 판정** — orca 합성 마우스 드래그가 UIRefreshControl을 확정적으로 울리는지 스피너 증적을 잡지 못했다. 당김 아래 전 체인(refreshPulled → UseCase → syncNow → sync 합류)은 3계층 단위 테스트로 검증돼 있고 스탬프 판정 ②·③이 주입 sync로 이미 확보돼, 대체 수단(DEV "수동 갱신" 항목)은 추가하지 않았다. 실제 당김 제스처 실동작만 실기기 잔여로 이관. + +**실기기 잔여**: pull-to-refresh 당김 제스처 실동작(위 기록 — 스피너 표출·당김 트리거 확인). 실서버 오프라인·타임아웃 실측(스플래시 문구 분기 실표출 포함 — 현 DEV는 issuerNotConfigured 삼킴으로 재시도 화면 도달 불가, S1 이후 확인). 사일런트 푸시 실수신 경로(기존 항상-잔여 항목). --- From d8ce38ba6fd995d4e323a4f1371d511bb868d6dc Mon Sep 17 00:00:00 2001 From: AppGoni Date: Sun, 23 Aug 2026 23:24:50 +0900 Subject: [PATCH 07/14] =?UTF-8?q?docs:=20AtchaV2=20Phase=2017=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20=ED=94=84=EB=A1=AC=ED=94=84=ED=8A=B8=20=E2=80=94=20?= =?UTF-8?q?=EA=B2=80=EC=83=89=C2=B7=ED=99=88=20=EB=A7=88=EC=B0=B0=20?= =?UTF-8?q?=ED=8C=A9=20(=EB=B9=88=20=EC=83=81=ED=83=9C=20+=20=ED=95=84?= =?UTF-8?q?=EB=93=9C=20=EC=A0=95=ED=95=A9=20+=20=EC=A7=84=EC=9E=85=C2=B7?= =?UTF-8?q?=EC=9D=B4=ED=83=88=20=EA=B2=BD=EB=A1=9C=20+=20=EC=98=A4?= =?UTF-8?q?=EB=8A=98/=EB=82=B4=EC=9D=BC=20=EB=9D=BC=EB=B2=A8,=20=EC=9E=90?= =?UTF-8?q?=EB=8F=99=20=EA=B2=80=EC=88=98=20=EA=B7=9C=EC=95=BD=20=EA=B8=B0?= =?UTF-8?q?=EC=A4=80)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- docs/prompts/atcha-v2-friction-pack-prompt.md | 189 ++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 docs/prompts/atcha-v2-friction-pack-prompt.md diff --git a/docs/prompts/atcha-v2-friction-pack-prompt.md b/docs/prompts/atcha-v2-friction-pack-prompt.md new file mode 100644 index 0000000..b0d5f1d --- /dev/null +++ b/docs/prompts/atcha-v2-friction-pack-prompt.md @@ -0,0 +1,189 @@ +# AtchaV2 검색·홈 마찰 팩 구현 프롬프트 — 빈 상태 + 필드 정합 + 진입·이탈 경로 + 오늘/내일 라벨 + +> **사용법**: 이 문서 전체를 Claude Code에 컨텍스트로 전달하고 `"Phase 17을 진행해"`라고 지시한다. +> 실행 에이전트는 [마스터 프롬프트](atcha-v2-master-prompt.md)의 **진행 프로토콜·공통 규칙·공통 acceptance를 그대로 상속**하며, 한 번에 한 Phase만 수행한다. +> 갭 분석·우선순위 정본은 [Post-12 로드맵](../planning/atcha-v2-post12-roadmap.md)의 "Phase 17 — 검색·홈 마찰 팩" 절. 충돌 시 **CLAUDE.md > 마스터 프롬프트 > [LA 프롬프트](atcha-v2-live-activity-prompt.md) > [세션 수명주기 프롬프트](atcha-v2-session-lifecycle-prompt.md) > [인지 채널 방어선 프롬프트](atcha-v2-channel-defense-prompt.md) > [갱신 신뢰성 프롬프트](atcha-v2-refresh-reliability-prompt.md) > 이 문서** 순. +> **검수는 사람 검수가 아니라 [자동 검수 규약](atcha-v2-auto-verification.md)을 따른다** — 실행 에이전트가 computer use로 직접 수행·증적 보고하고, 실기기 잔여 항목만 사용자에게 이관한다. +> 작성일: 2026-08-23. + +--- + +## Goal (최상위) + +**첫 90초의 이탈 요인을 제거한다 — 빈 화면이 말을 하게 하고, 탭한 필드로 들어가게 하고, 나가는 모든 경로가 흔적 없이 닫히게 하고, 심야의 시각이 어느 날인지 말하게 한다.** 권한을 전부 거부한 "조회 전용 사용자"의 최소 동작 보장이기도 하다. + +현재 검색 화면은 최근 검색 0건·검색 결과 0건에서 **완전한 백지**고(DSEmptyState는 있는데 이 두 상태엔 안 쓴다), 장소 검색엔 로딩 상태가 없어 타이핑 후 침묵한다. 홈 `arrivalField`는 어떤 상태와도 연결되지 않아 경로 카드 옆에 placeholder("도착지를 검색해 주세요")가 영구 공존하고, 출발지·도착지 어느 필드를 탭해도 같은 화면·같은 슬롯으로 들어간다. 검색 화면의 이탈 경로는 `closeFlow()` 하나만 코디네이터를 정리한다 — 스와이프 백은 (숨긴 내비바 때문에) 아예 비활성이고, 노티 탭 랜딩의 `popToRootViewController`는 `SearchCoordinator`를 누수시킨다(AppCoordinator에 "Phase 17이 일괄 해소" 주석으로 기록된 빚). `LocationError`는 2케이스뿐이라 전역 위치 OFF·restricted가 전부 "권한 거부 + 설정으로 이동"으로 뭉개지고(restricted엔 설정 이동이 무의미하다), 심야 앱인데 "도착 00:29"가 오늘인지 내일인지 아무도 말하지 않는다. `serviceEnded`/`noRoute`의 "다시 검색하기"는 최근 검색 화면 복귀만 하고(재검색 실동작 없음), 기획서가 요구한 최근 검색 스와이프 삭제는 누락돼 있다. 이 문서는 그 일곱 구멍을 막는다. Phase 번호는 갱신 신뢰성(16)에 이어 **17**. + +마찰 팩의 완성 상태 (이 문서가 만드는 구조): + +``` +홈 + 출발지/도착지 필드 ── 탭한 필드로 진입 ──────► 검색 (SearchEntryField — Interface 신설) + arrivalField ◄── 선택 경로의 도착지명 ──────── onRouteSelected가 (LastRoute, Place) 동반 + 위치 실패 3분기 ── denied(설정 이동) / 전역 OFF(설정 이동) / restricted(설정 이동 없음) + +검색 + 최근 검색 0건·결과 0건 ──► DSEmptyState (백지 해소) 키워드 검색 ──► .loadingPlaces 스피너 + serviceEnded·noRoute "다시 검색하기" ──► 도착지 슬롯 초기화 + 포커스 (실동작) + 최근 검색 행 ──► trailing 스와이프 삭제 (기존 X 버튼 유지) + +이탈 경로 — didShow 단일 정리 지점 (UINavigationControllerDelegate) + 백 버튼 pop ─┬─► navigationController(_:didShow:) → 검색 VC가 스택에 없으면 + 스와이프 백 ─┤ SearchCoordinator.finish() 1회 (스와이프 백은 이번에 활성화) + popToRoot ───┘ → returnToHome 누수 빚 청산 (AppCoordinator 주석 마감) + +시각 표기 — "내일"만 접두, 무라벨 = 오늘 + "내일 00:10 출발" / "도착 내일 00:29 · 환승 1회" (검색 결과 카드·대안 행·홈 카드 공통) +``` + +확정된 제품 결정사항 (변경하려면 사용자에게 먼저 물을 것 — [로드맵](../planning/atcha-v2-post12-roadmap.md) 2026-08-23 확정): + +| 항목 | 결정 | +|---|---| +| 검색 빈 상태 2종 | `.recent([])` → "최근 검색이 없어요" + "도착지를 검색해 막차 시간을 확인해 보세요" / `.places([])` → "검색 결과가 없어요" + "다른 키워드로 검색해 보세요". 둘 다 **액션 버튼 없음**(타이핑이 곧 회복 경로), 아이콘은 기존 `DSIcon.illustCharacterGray` 재사용. 빈 recent엔 "최근 검색" 헤더도 없다(기존 `rows.isEmpty` 가드 유지) | +| 장소 검색 로딩 | `State`에 `.loadingPlaces` 신설 — **디바운스 통과 후** 요청 직전에 진입(타이핑 중 매 글자 깜빡임 방지). 기존 `activityIndicator` 재사용, `loadingRoutes`와 달리 **키보드를 내리지 않는다**(타이핑 계속이 정상 흐름) | +| 도착지 반환 | `onRouteSelected` 콜백을 `(LastRoute, Place) -> Void`로 확장 — Place는 확정된 도착지(경로 검색의 불변식상 항상 존재). 홈 `State.arrivalText: String?`에 바인딩. **재실행 복원 경로는 placeholder 유지 수용** — 복원엔 도착지 명칭 원천이 없다(스냅샷 확장은 스코프 밖) | +| 필드 구분 진입 | Interface에 `public enum SearchEntryField: Sendable, Equatable { case departure, arrival }` 신설 + `makeSearchCoordinator(navigationController:initialField:onRouteSelected:)`. initialField는 **초기 활성 슬롯만** 결정 — 현재 위치 프리필 정책(성공 시 도착지로 포커스 이동, 사용자가 만진 슬롯 불가침)은 불변 | +| 코디네이터 정리 | `SearchCoordinator`가 `NSObject` + `UINavigationControllerDelegate` 채택, `didShow`에서 검색 VC가 스택에 없으면 정리 — **백 버튼·스와이프 백·popToRoot가 전부 이 한 지점으로 수렴**한다(`closeFlow`는 pop만 남긴다). 이전 delegate 보관·복원. 스와이프 백 제스처는 검색 화면에서 활성화(숨긴 내비바로 현재 죽어 있음 — `interactivePopGestureRecognizer` delegate 조정, 루트에선 시작 금지) | +| LocationError | `restricted`·`servicesDisabled` 케이스 신설(기존 2케이스 유지 — 추가만). 어댑터 매핑은 **순수 함수** `classify(denied:deniedGlobally:restricted:)`로 분리(AtchaV2Tests 대상): restricted → `.restricted` > deniedGlobally → `.servicesDisabled` > denied → `.permissionDenied` 우선순위. 홈 토스트 3분기: denied → 기존 문구+설정 이동 / 전역 OFF → "기기의 위치 서비스가 꺼져 있어요"+설정 이동 / restricted → "이 기기에선 위치를 사용할 수 없어요. 출발지를 검색해 주세요" **설정 이동 없음** | +| 오늘/내일 라벨 | **"내일"만 접두, 무라벨 = 오늘** (라벨 소음 최소화). 적용 표면: 검색 결과 카드·대안 행·홈 경로 카드의 출발/도착 시각. 판정은 순수 함수(캘린더 일자 비교, `Calendar` 주입으로 테스트 고정) — 오늘 nil / 내일 "내일" / 그 외 nil(막차 도메인상 비발생, 방어). "지난 막차" 카드(`asPastTrain`)는 **제외**(과거 시각 라벨은 스코프 밖). ViewData 생성에 `now` 주입 — SearchViewModel에 `now` 주입 신설(기존 VM 관례와 동일) | +| 다시 검색하기 실동작 | `serviceEnded`/`noRoute`의 액션 = **도착지 슬롯 초기화**(arrival 미확정 + arrivalText 비움 + activeField `.arrival`) + 최근 검색 복귀 — 키보드가 도착지로 포커스돼 즉시 재검색 가능. `.failed`(두 슬롯 확정)의 "다시 시도" = 경로 재검색은 현행 유지 | +| 최근 검색 스와이프 삭제 | `trailingSwipeActionsConfigurationForRowAt` — `.recent` 행에만 destructive "삭제" → 기존 `didDeleteRecent(at:)` 경유. **기존 X 버튼(accessory .delete)은 유지**(스와이프는 추가 수단, 기획서 요구 충족) | +| DEV 검수 훅 | `DevDemoFallbacks`에 검수 재료 3건 추가(DEV 한정 — 변경 시뮬레이터와 동일 취급): ① 예약 키워드 "결과없음" → 장소 0건 ② 예약 키워드 "경로없음" → 좌표 (0,0) 데모 장소 1건 + 경로 검색이 end (0,0)이면 빈 목록(→ 정규화 가정에 따라 serviceEnded) ③ 데모 대안 경로 1건(id `dev-demo-route-tomorrow`, **다음 자정+10분 출발**) — 더보기 확장·내일 라벨 검수 재료. 예약 훅은 base 호출 **전에** 판정(결정론 확보). featured(index 0)는 기존 데모 경로 그대로 — 변경 시뮬레이터 기준 시각(`noteKnownSession`) 정합 불변 | + +--- + +## 이 문서가 다시 정의하지 않는 것 (중복 금지) + +아래는 기존 Phase 산출물이다. **계약을 바꾸지 않고 명시된 지점만 확장한다.** 이 목록의 계약을 깨고 싶어지면 멈추고 사용자에게 물을 것. + +| 산출물 | 소속 | 이 문서에서의 취급 | +|---|---|---| +| `DSEmptyState`·`DSListCell`·`DSTextField`·`DSToast` API | Phase 4 | **DesignSystem 소스 변경 0이 기본** — 기존 API로 전부 성립한다(빈 상태는 configure 재사용, 스와이프는 tableView 레벨). 부족이 발견되면 멈추고 물을 것 | +| 검색 상태 머신 불변식 (`.loadingRoutes`/`.routes`는 두 슬롯 확정 시에만) | Phase 5 | 불변 — `.loadingPlaces`는 키워드 검색 전용 상태로 **추가**만 한다. 디바운스+이전 Task cancel 구조 불변 | +| 현재 위치 프리필 정책 (실패 무음, 사용자가 만진 슬롯 불가침, 늦은 도착 마감) | Phase 5·6 | 불변 — initialField는 초기 활성 슬롯만 정한다. 권한 안내 UX는 홈 담당 유지 | +| Phase 16 산출물 전체 (pull-to-refresh·스탬프·`AlarmSyncRequesting`·홈 스크롤 구조) | Phase 16 | 불변 — 홈 렌더에 arrivalField 바인딩 한 줄이 얹힐 뿐. 배너·카드·스탬프 표출 로직 무변경 | +| `AlarmSyncService` 판정·폴백·만료 분기 / LA·알람·세션 수명주기 | Phase 8~16 | **무변경.** 이 Phase는 알람 경로를 건드리지 않는다 | +| `DefaultSearchLastRoutesUseCase` 정규화(빈 목록 = serviceEnded 가정, 미확정 #3 TODO) | Phase 1 | 불변 — "다시 검색하기"는 표출 이후의 회복 동작만 바꾼다. responseCode 매핑 추가 금지 | +| DEV 데모 폴백·변경 시뮬레이터 성격 (실패 시에만 대체, 실서버 확정 시 일괄 제거) | Phase 7·11·14 | 성격 불변 — 검수 훅 3건을 **같은 파일·같은 제거 단위**로 추가한다. 예약 훅의 사전 판정은 "실패 시에만"의 명시적 예외로 주석에 기록 | +| 서버 계약 전체 | 마스터 공통 규칙 | **서버 변경 0.** Domain 변경은 `LocationError` 케이스 추가뿐 | + +## 전제 조건 + +1. **Phase 16 완료가 전제** (`feat/v2-phase16-refresh-reliability` 기준). 이 문서 내부의 병렬 없음 — Phase 17 단일. +2. 서버 트랙(로드맵 S1~S4)과 **완전 독립** — 미확정 입력을 새로 요구하지 않는다. 검수는 [자동 검수 규약](atcha-v2-auto-verification.md)에 따라 DEV 데모 폴백(+이번 검수 훅)을 재료로 에이전트가 직접 수행한다. +3. **스와이프 제스처(엣지 스와이프 백·셀 스와이프 삭제) 자동화는 실측 제약**(AX 액션 기반 조작만 신뢰)에 걸릴 수 있다 — 불가로 판명되면 자동 검수 절에 명시된 대체 경로(백 버튼 pop = 같은 didShow 정리 경로 / X 버튼 삭제 = 같은 `didDeleteRecent` 경로 + 단위 테스트)로 판정하고 실제 제스처만 실기기 잔여로 이관한다. + +--- + +## Phase 17 — 검색·홈 마찰 팩 + +### Goal +빈 화면이 다음 행동을 말하고(빈 상태 2종+로딩), 홈 필드가 상태와 정합하고(arrivalField·필드 구분 진입), 검색 화면의 모든 이탈 경로가 코디네이터를 정리하고(didShow 일원화+스와이프 백 활성화), 위치 실패가 사유별로 정직하게 안내되고(LocationError 세분화), 심야의 시각이 날짜를 말하고(내일 라벨), 막힌 검색이 한 탭으로 재개된다(다시 검색하기 실동작+스와이프 삭제). + +### Requirements + +- **Domain — `LocationError` 세분화 (추가만)**: + ```swift + public enum LocationError: Error, Equatable, Sendable { + case permissionDenied // 이 앱의 권한 거부 — "설정으로 이동"이 유효 + /// 스크린타임·MDM 제약 — 사용자가 설정으로 못 푼다. "설정으로 이동" 무의미. + case restricted + /// 기기 전역 위치 서비스 OFF — 앱 설정이 아니라 시스템 설정의 문제. + case servicesDisabled + case unavailable + } + ``` +- **App — `CoreLocationServiceAdapter` 매핑 분리**: 판정을 순수 함수로 추출하고 어댑터는 이를 경유한다: + ```swift + /// CLLocationUpdate의 3개 거부 플래그 → LocationError. nil이면 계속 대기(진행 중). + /// 우선순위: restricted > servicesDisabled > permissionDenied — 더 좁은 회복 경로가 이긴다. + static func classify(denied: Bool, deniedGlobally: Bool, restricted: Bool) -> LocationError? + ``` + `AtchaV2Tests`에 4분기(+전부 false → nil) 테스트. +- **SearchFeatureInterface — 진입 필드 + 도착지 반환 (파괴적 변경 2건, 이 두 건 외 시그니처 불변)**: + ```swift + /// 검색 진입 시 활성화할 슬롯 — 홈의 어느 필드를 탭했는지가 그대로 넘어온다(Phase 17). + public enum SearchEntryField: Sendable, Equatable { + case departure + case arrival + } + @MainActor + public protocol SearchCoordinatorBuildable { + func makeSearchCoordinator( + navigationController: UINavigationController, + initialField: SearchEntryField, + onRouteSelected: @escaping (LastRoute, Place) -> Void // Place = 확정된 도착지 + ) -> any Coordinator + } + ``` + 콜사이트는 `HomeDIContainer`·Home Example 스텁뿐 — 전부 따라간다. +- **SearchFeature — 빈 상태·로딩·진입 필드·다시 검색하기·스와이프 삭제·내일 라벨**: + - `SearchViewModel`: `init`에 `initialField: SearchEntryField = .departure`(→ `fields.activeField` 초깃값 매핑)와 `now: @escaping @Sendable () -> Date = { Date() }` 주입 추가. `State`에 `case loadingPlaces` 추가 — `keywordDidChange`의 검색 Task가 **디바운스 통과 후** `.loadingPlaces`로 전이하고 성공 시 `.places`(0건 포함), 실패 시 기존 `.failed`. `onRouteChosen: ((LastRoute, Place) -> Void)?`로 확장 — `didSelectRoute`가 확정 `arrival`을 동반한다(불변식상 항상 존재, `guard let` 방어). `didTapEmptyAction`의 `serviceEnded`/`noRoute` 분기: `arrival = nil` + `arrivalText` 비움 + `activeField = .arrival` + `showRecent()` — 키보드 포커스는 기존 `renderFields` diff가 처리한다. `.failed` 분기 현행 유지. + - `RouteViewData`/`RouteResultsViewData`: `now` 파라미터 추가, 출발·도착 시각에 내일 접두 — `"내일 00:10 출발"` / `"도착 내일 00:29 · 환승 1회"`. 내일 판정 순수 함수는 파일 스코프 헬퍼로 두고 **HomeFeature와 중복을 허용**한다(`TransportBadgeMapper` 선례 — 피처 간 공유 모듈 신설 금지): + ```swift + /// 내일이면 "내일 " 접두, 오늘·그 외는 빈 문자열 (무라벨 = 오늘. 이틀+ 미래·과거는 막차 도메인상 비발생 — 방어적 무라벨). + func dayPrefix(for date: Date, now: Date, calendar: Calendar = .current) -> String + ``` + - `SearchViewController`: `.recent([])`·`.places([])`에 결정사항 문구로 `DSEmptyState` 표출(액션 버튼 없음), `.loadingPlaces`에 `activityIndicator` 표출(키보드 유지·rows 비움). `.recent` 행에 trailing 스와이프 "삭제"(destructive) → `didDeleteRecent(at:)`. 스와이프 백 활성화: `viewDidAppear`에서 `interactivePopGestureRecognizer` delegate를 잡고 `gestureRecognizerShouldBegin`에서 `viewControllers.count > 1`일 때만 허용. + - `SearchCoordinator`: `NSObject` 상속 + `UINavigationControllerDelegate`. `start()`에서 이전 delegate 보관 후 자신을 설치하고 pushed VC를 weak 보관. `navigationController(_:didShow:)`에서 **검색 VC가 스택에 없으면** 이전 delegate 복원 + `finish()` — 1회 가드(finished 플래그). `closeFlow()`는 pop만 한다(finish는 didShow로 일원화 — 백 버튼·경로 선택·스와이프 백·popToRoot가 전부 같은 지점에서 정리). 테스트: didShow를 직접 호출해 pop 후 정리 1회·재호출 no-op·검색 VC 잔존 시 no-op을 검증. + - `SearchDIContainer`: `initialField` 전달 + 콜백 시그니처 추종. Example 앱 스텁도 따라간다. +- **HomeFeature — arrivalField 바인딩 + 필드 구분 진입 + 위치 3분기 + 내일 라벨**: + - `HomeViewModel`: `import SearchFeatureInterface`(의존 그래프상 기존 허용). `searchFieldTapped(_ field: SearchEntryField)`로 확장, `onSearchRequested: ((_ initialField: SearchEntryField, _ onRouteSelected: @escaping (LastRoute, Place) -> Void) -> Void)?`. `routeSelected(_ route: LastRoute, arrival: Place)` — `State.arrivalText: String?`에 `arrival.name` 세팅(다음 선택 시 교체, 세션 정리에도 유지 — 도착지는 세션이 끝나도 사실이다). 재실행 복원 경로는 세팅하지 않는다(결정사항 — placeholder 수용, 주석으로 기록). `DepartureState.needsSearch`의 `deniedPermission` 연관값 제거(미사용 — 사유는 ToastEvent가 나른다). `ToastEvent`에 `locationServicesDisabled`·`locationRestricted` 추가, `loadCurrentLocation`의 catch를 `LocationError` 케이스별 3분기로(restricted·servicesDisabled → `.needsSearch` + 각 토스트, `unavailable`·기타 → 기존 무토스트 `.needsSearch`). `didBecomeActive` 재확인 가드는 불변(사유 불문 `.needsSearch`면 재조회 — restricted에도 무해). + - `RouteCardViewData`: `init(entity:now:)`로 확장 — 출발·도착 시각 내일 접두(검색과 같은 규칙·중복 헬퍼). `asPastTrain`은 불변. 콜사이트(`routeSelected`·`restoreRouteCardIfNeeded`)는 VM의 `now()`를 넘긴다. + - `HomeViewController`: `render`가 `arrivalField.setText(state.arrivalText ?? "")` 반영. 필드 행 액션을 필드별로 분리(`searchFieldTapped(.departure)`/`.arrival`). 토스트 3분기 — restricted만 액션 없음. + - `HomeCoordinator`·`HomeDIContainer`: `initialField`·`(LastRoute, Place)` 배선 통과. Example 앱 스텁 추종. +- **App — 누수 빚 청산 + DEV 검수 훅**: + - `AppCoordinator.returnToHome`: 누수 주석을 해소 기록으로 교체 — popToRoot가 didShow 정리 경로를 타므로 추가 코드 없음(주석만 갱신). + - `DevDemoFallbacks`: 결정사항의 검수 훅 3건 — ① `searchPlaces`가 base 호출 전에 키워드 "결과없음"이면 `[]` ② "경로없음"이면 좌표 (0,0) 데모 장소 1건, `searchLastRoutes`가 base 호출 전에 end (0,0)이면 `[]`(빈 목록 정규화 = serviceEnded 표면) ③ 데모 경로 목록에 대안 1건 추가 — id `dev-demo-route-tomorrow`, 출발 = **다음 자정+10분**(`Calendar.startOfDay` 기준 계산, 검수 시각 무관 항상 "내일"), 기존 legs 재사용 가능. `noteKnownSession`은 계속 index 0(기존 데모 경로) 기준 — 변경 시뮬레이터·알람 검수 플로우 불변. +- **테스트 (Swift Testing — 스텁·주입, 실 Date()·실 UserDefaults 금지)**: + - `SearchFeatureTests`: ① initialField `.arrival` → 초기 `fields.activeField == .arrival` ② 디바운스 통과 후 `.loadingPlaces` → 성공 `.places` / 0건 `.places([])` / 실패 `.failed` ③ `didSelectRoute` → `(route, arrivalPlace)` 전달 ④ `didTapEmptyAction`(serviceEnded·noRoute) → arrivalText 비움 + activeField `.arrival` + `.recent` 복귀, 이후 장소 선택 시 도착지 슬롯에 반영 ⑤ `dayPrefix`·`RouteViewData` 내일 접두(고정 now·고정 캘린더) ⑥ `SearchCoordinator` didShow 정리(1회 가드·잔존 시 no-op·delegate 복원). + - `HomeFeatureTests`: ① `routeSelected(_:arrival:)` → `arrivalText` 세팅 + 기존 카드·배너 동작 회귀 ② `searchFieldTapped(.arrival)`/`(.departure)` → `onSearchRequested`에 그대로 전달 ③ `LocationError` 3분기 토스트(restricted·servicesDisabled·permissionDenied) + `.needsSearch` 전이 ④ `RouteCardViewData` 내일 접두(고정 now) + `asPastTrain` 무라벨 유지. + - `AtchaV2Tests`: `classify` 4분기 + 우선순위. + +### Constraints +- **Phase 18 선취 금지**: 최근 경로 원탭 칩, 홈에서의 즉시 재검색, `SearchLastRoutesUseCase`의 홈 주입은 이 문서 밖. 재실행 복원의 arrivalText를 스냅샷·최근 검색으로 채우려는 시도 금지(결정사항 — placeholder 수용). +- 미확정 #3(serviceEnded/noRoute의 responseCode 실측) 해소 시도 금지 — 정규화 로직·TODO 불변. +- DesignSystem 소스 변경 0이 기본(기존 컴포넌트 API로 성립). `Tuist/Package.swift`·`Package.resolved`·매니페스트(`Project.swift`/`Workspace.swift`) 무변경 — 신규 타겟 없음, `tuist generate` 불필요. +- 알람·LA·sync·스냅샷 경로 무변경 (`AlarmSyncService`·`RefreshAlarmUseCase`·`AlarmSessionSnapshot` 등). 홈 pull-to-refresh·스탬프 표출 회귀 금지. +- `UIApplication`·CoreLocation 심볼의 Domain·Feature 유입 금지(기존 규약 — `SearchEntryField`·`LocationError`는 순수 타입). Feature 간 공유 모듈 신설 금지 — 내일 라벨 헬퍼는 중복 허용(선례 명시). +- Interface 파괴적 변경은 명시된 2건(initialField·arrival 동반)뿐 — 그 외 공개 시그니처 불변. 레거시 무변경. + +### Acceptance +공통 acceptance(Debug+Stage 빌드) + `-scheme Domain test` + `-scheme SearchFeature test` + `-scheme HomeFeature test` + `-scheme AtchaV2 test` + `SearchFeatureExample`·`HomeFeatureExample` Debug 빌드(스텁 시그니처 추종 확인) + `git diff --stat`으로 DesignSystem·매니페스트·`Package.resolved` 무변경 확인. + +### 자동 검수 (블로킹 — [자동 검수 규약](atcha-v2-auto-verification.md)) +iOS 26 시뮬레이터(Debug/DEV)에서 에이전트가 직접 수행하고 단계별 스크린샷 증적으로 보고. 재료: DEV 데모 폴백 + 이번 검수 훅 3건. 시나리오 ①·②·⑤·⑥은 검색 진입·타이핑·AXPress만으로 성립한다. +① **빈 상태 — 최근 검색 0건**: 앱 데이터 초기화 상태(`simctl uninstall` 후 재설치)로 실행 → 검색 진입 → "최근 검색이 없어요" 빈 상태 스크린샷 (백지 아님의 직접 증명). +② **빈 상태 — 검색 결과 0건 + 로딩**: 도착지 슬롯에 예약 키워드 "결과없음" 입력 → "검색 결과가 없어요" 빈 상태 스크린샷. 로딩 스피너는 순간적이라 스크린샷 타이밍이 플레이키하다 — 포착되면 증적, 못 잡으면 "관찰 불가(순간 상태)"로 기록하고 단위 테스트(②)로 갈음한다. +③ **도착지 탭 진입 + arrivalField 바인딩**: 홈 도착지 필드 탭 → 검색 화면 **도착지 슬롯 활성**(키보드 포커스) 증적 / 홈 복귀 후 출발지 필드 탭 → 출발지 슬롯 활성 증적. 이어서 데모 경로 선택 → 홈 복귀 → **arrivalField에 도착지명 표출**(placeholder 아님) 스크린샷. +④ **스와이프 백 + 코디네이터 정리**: 검색 진입 → 좌측 엣지 스와이프 백 시도(computer use). 제스처 자동화 불가로 판명되면(규약 실측 제약): 판정을 "자동화 불가"로 기록하고 — 백 버튼 pop이 **같은 didShow 정리 경로**이므로 백 버튼 검수 + 단위 테스트 ⑥ 증적으로 갈음, 실제 스와이프 제스처만 실기기 잔여로 이관한다. 어느 경로든 **pop 후 재진입 → 검색 플로우 정상 동작**(검색·선택 재수행 가능) 스크린샷 필수. +⑤ **오늘/내일 라벨**: 데모 검색(아무 키워드) → 결과 화면 "더보기" AXPress → 대안 행에 "내일 HH:mm" 라벨 + featured(오늘)는 무라벨 **대비** 스크린샷 → 대안(내일 경로) 선택 → 홈 카드 "내일 HH:mm 출발" 스크린샷. 알람 등록은 하지 않는다(라벨 검수 전용 경로). +⑥ **다시 검색하기 실동작**: 도착지 슬롯에 "경로없음" 입력 → 데모 장소 선택 → "오늘 막차가 끊겼어요"(빈 목록 정규화) 화면 → "다시 검색하기" AXPress → 최근 검색 복귀 + **도착지 슬롯이 비워지고 활성**(재검색 즉시 가능) 스크린샷. +⑦ **최근 검색 스와이프 삭제**: 최근 검색 행 스와이프 시도 — 불가 시 기존 X 버튼 삭제로 갈음(같은 `didDeleteRecent` 경로) + 실제 스와이프는 실기기 잔여 이관. 삭제 후 목록 갱신(마지막 1건 삭제 시 ①의 빈 상태 표출) 스크린샷. +⑧ **위치 거부 분기 + 회귀**: 재설치 직후 위치 권한 팝업 "허용 안 함" AXPress → "위치 권한이 꺼져 있어요"+설정 이동 토스트 증적(denied 분기). 이후 권한 허용 재설치 상태에서 데모 경로 알람 등록 → **배너+스탬프+arrivalField 동시 표출** 정상(Phase 16 표면 회귀 없음) 스크린샷. +전역 위치 OFF는 설정 앱 AX 조작이 성립할 때만 시도(플레이키하면 "자동화 불가" 기록 후 실기기 잔여) — restricted는 시뮬레이터 재현 불가(스크린타임 제약)로 항상 실기기 잔여, 매핑은 `AtchaV2Tests`가 담보한다. + +**실기기 잔여**: 엣지 스와이프 백·셀 스와이프 삭제의 실제 제스처 감각(자동화 불가 판명 시). restricted(스크린타임 제약) 실측. 전역 위치 서비스 OFF 실측(설정 조작 자동화 불가 시). 사일런트 푸시 실수신(기존 항상-잔여 항목 — 이 Phase 무관 승계). + +--- + +## 진행 프로토콜 + +[마스터 프롬프트의 진행 프로토콜](atcha-v2-master-prompt.md#진행-프로토콜) 1~6을 그대로 상속한다. 추가 규칙: + +1. 이 문서는 **Phase 17 단일** — 내부 병렬 없음. Phase 16 완료 커밋 위에서 진행한다. +2. ["이 문서가 다시 정의하지 않는 것"](#이-문서가-다시-정의하지-않는-것-중복-금지) 표의 계약을 바꾸고 싶어지면 멈추고 사용자에게 물을 것. +3. **Phase 18 산출물을 선취하지 않는다** — [로드맵](../planning/atcha-v2-post12-roadmap.md)의 몫. +4. 검수는 [자동 검수 규약](atcha-v2-auto-verification.md)을 따른다 — "자동 검수 (블로킹)"는 에이전트가 computer use로 수행·증적 보고를 마쳐야 하고, "실기기 잔여"만 사용자에게 이관한다. **acceptance 전부 실행·보고 + 자동 검수 증적 보고 후 정지** — 다음 Phase로 진행하지 않는다. +5. 제스처 자동화 불가가 확정되면 결과를 **이 문서 자동 검수 절에 기록**하고 명시된 대체 경로로 검수를 완료한다. + +## 미확정 입력 (참조) + +이 문서는 새 미확정 입력을 만들지 않는다. 관련 기존 항목의 취급: + +| # | 항목 | 이 문서에서의 취급 | +|---|---|---| +| 3 | "막차 종료"/"경로 없음"의 서버 표현 (responseCode 실측값) | **미해소 유지** — "다시 검색하기"는 표출 이후의 회복 동작만 실동작으로 바꾼다. 빈 목록 = serviceEnded 가정·TODO 그대로. 검수 훅 ②는 이 가정 위에서 serviceEnded 표면을 재료로 쓴다 | +| 11 | 서버의 "등록된 알람 없음" 표현 | 이 문서 밖 — 알람 경로 무변경 | +| 원장 전체 | [Post-12 로드맵](../planning/atcha-v2-post12-roadmap.md)의 "미확정 입력 원장" 절 참조 | | From a1a15309d675147e773d7d5dbaad6424fdd02b8e Mon Sep 17 00:00:00 2001 From: AppGoni Date: Sun, 23 Aug 2026 23:41:32 +0900 Subject: [PATCH 08/14] =?UTF-8?q?feat:=20AtchaV2=20Phase=2017=20=E2=80=94?= =?UTF-8?q?=20=EA=B2=80=EC=83=89=C2=B7=ED=99=88=20=EB=A7=88=EC=B0=B0=20?= =?UTF-8?q?=ED=8C=A9=20(=EB=B9=88=20=EC=83=81=ED=83=9C=202=EC=A2=85+?= =?UTF-8?q?=EB=A1=9C=EB=94=A9=20+=20=EB=8F=84=EC=B0=A9=EC=A7=80=20?= =?UTF-8?q?=EB=B0=94=EC=9D=B8=EB=94=A9=C2=B7=ED=95=84=EB=93=9C=20=EC=A7=84?= =?UTF-8?q?=EC=9E=85=20+=20didShow=20=EC=BD=94=EB=94=94=EB=84=A4=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=EC=A0=95=EB=A6=AC=C2=B7=EC=8A=A4=EC=99=80=EC=9D=B4?= =?UTF-8?q?=ED=94=84=20=EB=B0=B1=20+=20LocationError=20=EC=84=B8=EB=B6=84?= =?UTF-8?q?=ED=99=94=20+=20=EC=98=A4=EB=8A=98/=EB=82=B4=EC=9D=BC=20?= =?UTF-8?q?=EB=9D=BC=EB=B2=A8=20+=20=EB=8B=A4=EC=8B=9C=20=EA=B2=80?= =?UTF-8?q?=EC=83=89=ED=95=98=EA=B8=B0=C2=B7=EC=8A=A4=EC=99=80=EC=9D=B4?= =?UTF-8?q?=ED=94=84=20=EC=82=AD=EC=A0=9C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 검색: 최근/결과 0건 DSEmptyState, .loadingPlaces(디바운스 후), 다시 검색하기 = 도착지 슬롯 초기화+포커스, 최근 검색 trailing 스와이프 삭제 - Interface: SearchEntryField + initialField, onRouteSelected가 (LastRoute, Place) 동반 - 홈: arrivalText 바인딩, 탭한 필드로 검색 진입, 위치 실패 3분기 토스트(restricted는 설정 이동 없음) - SearchCoordinator: NSObject+UINavigationControllerDelegate — 백 버튼·스와이프 백(활성화)·popToRoot didShow 단일 정리 - Domain: LocationError restricted/servicesDisabled 신설, App classify 순수 함수(AtchaV2Tests) - 오늘/내일: 내일만 접두(무라벨=오늘), Search/Home ViewData now 주입, 지난 막차 제외 - DEV 검수 훅: 예약 키워드(결과없음/경로없음) + 내일 출발 데모 대안 경로 Co-Authored-By: Claude Fable 5 --- .../Adapters/CoreLocationServiceAdapter.swift | 20 +- .../Sources/Adapters/DevDemoFallbacks.swift | 48 ++++- Projects/App/Sources/AppCoordinator.swift | 5 +- .../Tests/LocationErrorClassifyTests.swift | 38 ++++ .../Sources/Entities/LocationError.swift | 7 +- .../Feature/Home/Example/ExampleApp.swift | 18 +- .../Home/Sources/HomeCoordinator.swift | 11 +- .../Home/Sources/HomeDIContainer.swift | 9 +- .../Home/Sources/HomeViewController.swift | 31 ++- .../Feature/Home/Sources/HomeViewData.swift | 16 +- .../Feature/Home/Sources/HomeViewModel.swift | 51 +++-- .../Home/Tests/HomeViewModelTests.swift | 178 +++++++++++++++--- .../Feature/Search/Example/ExampleApp.swift | 9 +- .../SearchCoordinatorBuildable.swift | 10 +- .../Search/Sources/SearchCoordinator.swift | 46 ++++- .../Search/Sources/SearchDIContainer.swift | 10 +- .../Search/Sources/SearchViewController.swift | 49 ++++- .../Search/Sources/SearchViewData.swift | 24 ++- .../Search/Sources/SearchViewModel.swift | 44 ++++- .../Search/Tests/SearchCoordinatorTests.swift | 106 +++++++++++ .../Search/Tests/SearchViewModelTests.swift | 149 ++++++++++++++- 21 files changed, 773 insertions(+), 106 deletions(-) create mode 100644 Projects/App/Tests/LocationErrorClassifyTests.swift create mode 100644 Projects/Feature/Search/Tests/SearchCoordinatorTests.swift diff --git a/Projects/App/Sources/Adapters/CoreLocationServiceAdapter.swift b/Projects/App/Sources/Adapters/CoreLocationServiceAdapter.swift index 7d86d85..a761101 100644 --- a/Projects/App/Sources/Adapters/CoreLocationServiceAdapter.swift +++ b/Projects/App/Sources/Adapters/CoreLocationServiceAdapter.swift @@ -8,13 +8,25 @@ import Domain /// App 모듈 기본 격리가 MainActor라 이 클래스는 암시적 Sendable — 프로토콜의 /// nonisolated async 요구사항은 격리 witness로 충족된다. final class CoreLocationServiceAdapter: LocationService { + /// CLLocationUpdate의 거부 플래그 3종 → LocationError 매핑(Phase 17). nil = 진행 중. + /// 우선순위: restricted > 전역 OFF > 앱 권한 거부 — 더 좁은 회복 경로가 이긴다 + /// (restricted는 설정으로 못 풀고, 전역 OFF는 앱 권한 상태를 무의미하게 만든다). + static func classify(denied: Bool, deniedGlobally: Bool, restricted: Bool) -> LocationError? { + if restricted { return .restricted } + if deniedGlobally { return .servicesDisabled } + if denied { return .permissionDenied } + return nil + } + func currentLocation() async throws -> Coordinate { do { for try await update in CLLocationUpdate.liveUpdates() { - if update.authorizationDenied - || update.authorizationDeniedGlobally - || update.authorizationRestricted { - throw LocationError.permissionDenied + if let error = Self.classify( + denied: update.authorizationDenied, + deniedGlobally: update.authorizationDeniedGlobally, + restricted: update.authorizationRestricted + ) { + throw error } if let location = update.location { return Coordinate( diff --git a/Projects/App/Sources/Adapters/DevDemoFallbacks.swift b/Projects/App/Sources/Adapters/DevDemoFallbacks.swift index ea2f75f..cd5def6 100644 --- a/Projects/App/Sources/Adapters/DevDemoFallbacks.swift +++ b/Projects/App/Sources/Adapters/DevDemoFallbacks.swift @@ -13,7 +13,27 @@ import Foundation struct DevDemoFallbackPlaceRepository: PlaceRepository { let base: any PlaceRepository + /// Phase 17 검수 훅 — 이 좌표의 장소를 도착지로 고르면 경로 검색이 빈 목록을 반환한다 + /// (빈 목록 정규화 = serviceEnded 표면의 유일한 DEV 재현 수단). + static let emptyRouteCoordinate = Coordinate(latitude: 0, longitude: 0) + func searchPlaces(keyword: String, near coordinate: Coordinate?) async throws -> [Place] { + // Phase 17 검수 훅 — 예약 키워드는 base보다 먼저 판정한다("실패 시에만" 원칙의 + // 명시적 예외, 검수 결정론 확보). 빈 상태·serviceEnded 화면의 재현 재료. + if keyword == "결과없음" { + print("⚠️ [DEV 검수 훅] 예약 키워드 → 장소 0건 반환") + return [] + } + if keyword == "경로없음" { + print("⚠️ [DEV 검수 훅] 예약 키워드 → 빈 경로 유도 데모 장소 반환") + return [ + Place( + name: "경로없음 (데모)", + address: "도착지로 선택하면 빈 경로 응답을 시연해요", + coordinate: Self.emptyRouteCoordinate + ), + ] + } do { return try await base.searchPlaces(keyword: keyword, near: coordinate) } catch { print("⚠️ [DEV 우회] 장소 검색 실패 → 데모 장소 반환: \(error)") @@ -45,15 +65,22 @@ struct DevDemoFallbackLastRouteRepository: LastRouteRepository { let base: any LastRouteRepository func searchLastRoutes(start: Coordinate, end: Coordinate) async throws -> [LastRoute] { + // Phase 17 검수 훅 — 예약 도착지(경로없음 데모 장소)는 base보다 먼저 판정한다. + // 빈 목록은 정규화 가정(미확정 #3)에 따라 serviceEnded로 표면화된다. + if end == DevDemoFallbackPlaceRepository.emptyRouteCoordinate { + print("⚠️ [DEV 검수 훅] 예약 도착지 → 빈 경로 목록 반환 (serviceEnded 정규화 재료)") + return [] + } do { return try await base.searchLastRoutes(start: start, end: end) } catch { print("⚠️ [DEV 우회] 막차 검색 실패 → 데모 경로 반환: \(error)") let route = Self.demoRoute(start: start, end: end) // 변경 시뮬레이터의 기준 출발 시각 — 데모 흐름에선 검색 직후 이 경로가 등록된다. + // 대안(내일 출발)은 기준 시각에 관여하지 않는다 — index 0 정합 불변. await DevChangeSimulator.shared.noteKnownSession( routeId: route.id, departureTime: route.departureTime ) - return [route] + return [route, Self.tomorrowDemoRoute(start: start, end: end)] } } @@ -76,15 +103,30 @@ struct DevDemoFallbackLastRouteRepository: LastRouteRepository { } } + /// 오늘/내일 라벨(Phase 17) 검수 재료 — 더보기의 대안 경로로 항상 "내일" 출발이 + /// 표시되게 다음 자정+10분을 출발 시각으로 잡는다(검수 시각 무관 결정론). + /// 알람 등록 검수 플로우는 featured(index 0)를 쓰므로 이 경로와 무관하다. + private static func tomorrowDemoRoute(start: Coordinate, end: Coordinate) -> LastRoute { + let startOfToday = Calendar.current.startOfDay(for: Date()) + let nextMidnight = Calendar.current.date(byAdding: .day, value: 1, to: startOfToday) + ?? startOfToday.addingTimeInterval(24 * 60 * 60) + return demoRoute( + start: start, + end: end, + departure: nextMidnight.addingTimeInterval(10 * 60), + id: "dev-demo-route-tomorrow" + ) + } + /// 출발 시각은 8분 뒤 — 알람이 도보(첫 walk leg 120초)+버퍼(180초) 반영으로 +3분 /// 시점에 걸린다(Phase 14 검수 ③: 배너·LA·발화가 전부 "출발 − 도보 − 3분" 기준). /// 더 이르면 등록 탭 시점에 이미 과거가 되어 tooLate 가드·AlarmKit 거부에 걸린다. private static func demoRoute( - start: Coordinate, end: Coordinate, departure: Date? = nil + start: Coordinate, end: Coordinate, departure: Date? = nil, id: String = "dev-demo-route" ) -> LastRoute { let departure = departure ?? Date().addingTimeInterval(8 * 60) return LastRoute( - id: "dev-demo-route", + id: id, departureTime: departure, totalTime: 2940, totalWalkTime: 480, diff --git a/Projects/App/Sources/AppCoordinator.swift b/Projects/App/Sources/AppCoordinator.swift index e6ab172..7b6d331 100644 --- a/Projects/App/Sources/AppCoordinator.swift +++ b/Projects/App/Sources/AppCoordinator.swift @@ -67,9 +67,8 @@ final class AppCoordinator: Coordinator, CoordinatorFinishDelegate { /// 스플래시 단계의 탭이면 popToRoot가 스플래시에 머무를 뿐 — 부트스트랩 후 홈 자연 랜딩. func returnToHome() { navigationController.presentedViewController?.dismiss(animated: false) - // 프로그램적 pop은 SearchCoordinator.closeFlow()를 타지 않아 자식 코디네이터가 - // 잔존할 수 있다 — 스와이프 백 누수와 같은 계열이라 Phase 17 - // (UINavigationControllerDelegate 정리)이 일괄 해소한다. 여기서 선취하지 않는다. + // 프로그램적 pop도 SearchCoordinator의 didShow 정리 경로를 탄다(Phase 17) — + // 백 버튼·스와이프 백과 같은 단일 지점에서 자식 코디네이터가 finish된다. navigationController.popToRootViewController(animated: false) } diff --git a/Projects/App/Tests/LocationErrorClassifyTests.swift b/Projects/App/Tests/LocationErrorClassifyTests.swift new file mode 100644 index 0000000..3ce8691 --- /dev/null +++ b/Projects/App/Tests/LocationErrorClassifyTests.swift @@ -0,0 +1,38 @@ +@testable import AtchaV2 +import Domain +import Testing + +/// CLLocationUpdate 거부 플래그 → LocationError 매핑(Phase 17) — 사유별 안내 분기의 원천. +@MainActor +struct LocationErrorClassifyTests { + @Test + func eachFlag_mapsToItsOwnCase() { + #expect(CoreLocationServiceAdapter.classify( + denied: true, deniedGlobally: false, restricted: false + ) == .permissionDenied) + #expect(CoreLocationServiceAdapter.classify( + denied: false, deniedGlobally: true, restricted: false + ) == .servicesDisabled) + #expect(CoreLocationServiceAdapter.classify( + denied: false, deniedGlobally: false, restricted: true + ) == .restricted) + } + + @Test + func noFlags_meansStillInProgress() { + #expect(CoreLocationServiceAdapter.classify( + denied: false, deniedGlobally: false, restricted: false + ) == nil) + } + + @Test + func priority_narrowerRecoveryPathWins() { + // restricted > 전역 OFF > 앱 권한 거부 — 복합 플래그에선 더 좁은 회복 경로가 이긴다. + #expect(CoreLocationServiceAdapter.classify( + denied: true, deniedGlobally: true, restricted: true + ) == .restricted) + #expect(CoreLocationServiceAdapter.classify( + denied: true, deniedGlobally: true, restricted: false + ) == .servicesDisabled) + } +} diff --git a/Projects/Domain/Sources/Entities/LocationError.swift b/Projects/Domain/Sources/Entities/LocationError.swift index a3c3033..b1b9d2d 100644 --- a/Projects/Domain/Sources/Entities/LocationError.swift +++ b/Projects/Domain/Sources/Entities/LocationError.swift @@ -1,5 +1,10 @@ -/// 위치 조회 실패 사유 — 권한 거부를 구분해야 Feature가 "검색 유도 + 설정 이동" UX로 분기할 수 있다. +/// 위치 조회 실패 사유 — 사유별로 회복 경로가 다르므로 Feature가 안내를 분기한다(Phase 17). public enum LocationError: Error, Equatable, Sendable { + /// 이 앱의 권한 거부 — "설정으로 이동"이 유효한 회복 경로다. case permissionDenied + /// 스크린타임·MDM 제약 — 사용자가 설정으로 못 푼다. "설정으로 이동" 안내 금지. + case restricted + /// 기기 전역 위치 서비스 OFF — 앱 권한이 아니라 시스템 설정의 문제. + case servicesDisabled case unavailable } diff --git a/Projects/Feature/Home/Example/ExampleApp.swift b/Projects/Feature/Home/Example/ExampleApp.swift index e47752f..fa88555 100644 --- a/Projects/Feature/Home/Example/ExampleApp.swift +++ b/Projects/Feature/Home/Example/ExampleApp.swift @@ -121,7 +121,8 @@ struct PreviewGetLastRouteDetailUseCase: GetLastRouteDetailUseCase { struct PreviewSearchCoordinatorBuildable: SearchCoordinatorBuildable { func makeSearchCoordinator( navigationController: UINavigationController, - onRouteSelected: @escaping (LastRoute) -> Void + initialField: SearchEntryField, + onRouteSelected: @escaping (LastRoute, Place) -> Void ) -> any Coordinator { PreviewSearchCoordinator(onRouteSelected: onRouteSelected) } @@ -131,17 +132,26 @@ final class PreviewSearchCoordinator: Coordinator { var childCoordinators: [any Coordinator] = [] weak var finishDelegate: (any CoordinatorFinishDelegate)? - private let onRouteSelected: (LastRoute) -> Void + private let onRouteSelected: (LastRoute, Place) -> Void - init(onRouteSelected: @escaping (LastRoute) -> Void) { + init(onRouteSelected: @escaping (LastRoute, Place) -> Void) { self.onRouteSelected = onRouteSelected } func start() { - onRouteSelected(Self.makeCannedRoute()) + onRouteSelected(Self.makeCannedRoute(), Self.makeCannedArrival()) finish() } + // 도착지 필드 바인딩(Phase 17) 시연용 — canned 경로의 하차지와 같은 동네. + nonisolated static func makeCannedArrival() -> Place { + Place( + name: "구로디지털단지역", + address: "서울 구로구 도림천로 486", + coordinate: Coordinate(latitude: 37.4853, longitude: 126.9015) + ) + } + // nonisolated: 상세 재조회 스텁(nonisolated async)에서도 공유한다. nonisolated static func makeCannedRoute() -> LastRoute { let departure = Date().addingTimeInterval(42 * 60) diff --git a/Projects/Feature/Home/Sources/HomeCoordinator.swift b/Projects/Feature/Home/Sources/HomeCoordinator.swift index 0f90c97..9d358ab 100644 --- a/Projects/Feature/Home/Sources/HomeCoordinator.swift +++ b/Projects/Feature/Home/Sources/HomeCoordinator.swift @@ -1,5 +1,6 @@ import CoreCoordinator import Domain +import SearchFeatureInterface import UIKit final class HomeCoordinator: Coordinator, CoordinatorFinishDelegate { @@ -17,8 +18,8 @@ final class HomeCoordinator: Coordinator, CoordinatorFinishDelegate { func start() { let viewController = container.makeHomeViewController( - onSearchRequested: { [weak self] onRouteSelected in - self?.startSearchFlow(onRouteSelected: onRouteSelected) + onSearchRequested: { [weak self] initialField, onRouteSelected in + self?.startSearchFlow(initialField: initialField, onRouteSelected: onRouteSelected) } ) navigationController?.pushViewController(viewController, animated: false) @@ -26,10 +27,14 @@ final class HomeCoordinator: Coordinator, CoordinatorFinishDelegate { // MARK: - 검색 플로우 - private func startSearchFlow(onRouteSelected: @escaping (LastRoute) -> Void) { + private func startSearchFlow( + initialField: SearchEntryField, + onRouteSelected: @escaping (LastRoute, Place) -> Void + ) { guard let navigationController else { return } let child = container.makeSearchCoordinator( navigationController: navigationController, + initialField: initialField, onRouteSelected: onRouteSelected ) // start() 안에서 동기로 finish()될 수 있으므로(예: Example 스텁) 배선을 먼저 끝낸다. diff --git a/Projects/Feature/Home/Sources/HomeDIContainer.swift b/Projects/Feature/Home/Sources/HomeDIContainer.swift index faf9c6a..0a13b70 100644 --- a/Projects/Feature/Home/Sources/HomeDIContainer.swift +++ b/Projects/Feature/Home/Sources/HomeDIContainer.swift @@ -45,7 +45,10 @@ public final class HomeDIContainer: HomeCoordinatorBuildable { } func makeHomeViewController( - onSearchRequested: @escaping (_ onRouteSelected: @escaping (LastRoute) -> Void) -> Void + onSearchRequested: @escaping ( + _ initialField: SearchEntryField, + _ onRouteSelected: @escaping (LastRoute, Place) -> Void + ) -> Void ) -> UIViewController { let viewModel = HomeViewModel( getCurrentLocationUseCase: getCurrentLocationUseCase, @@ -63,10 +66,12 @@ public final class HomeDIContainer: HomeCoordinatorBuildable { func makeSearchCoordinator( navigationController: UINavigationController, - onRouteSelected: @escaping (LastRoute) -> Void + initialField: SearchEntryField, + onRouteSelected: @escaping (LastRoute, Place) -> Void ) -> any Coordinator { searchCoordinatorBuildable.makeSearchCoordinator( navigationController: navigationController, + initialField: initialField, onRouteSelected: onRouteSelected ) } diff --git a/Projects/Feature/Home/Sources/HomeViewController.swift b/Projects/Feature/Home/Sources/HomeViewController.swift index b569e92..4b14de7 100644 --- a/Projects/Feature/Home/Sources/HomeViewController.swift +++ b/Projects/Feature/Home/Sources/HomeViewController.swift @@ -1,5 +1,6 @@ import DesignSystem import Domain +import SearchFeatureInterface import SnapKit import UIKit @@ -18,8 +19,12 @@ final class HomeViewController: UIViewController { private let banner = DSBanner() private let departureField = DSTextField(placeholder: "출발지를 검색해 주세요", showsAccentDot: true) private let arrivalField = DSTextField(placeholder: "도착지를 검색해 주세요") - private lazy var departureRow = makeFieldRow(icon: DSIcon.myLocation24, field: departureField) - private lazy var arrivalRow = makeFieldRow(icon: DSIcon.place24, field: arrivalField) + private lazy var departureRow = makeFieldRow( + icon: DSIcon.myLocation24, field: departureField, entry: .departure + ) + private lazy var arrivalRow = makeFieldRow( + icon: DSIcon.place24, field: arrivalField, entry: .arrival + ) private let routeCard = DSRouteCard() private let registerButton = DSButton(title: "알람 등록하기") // DSButton은 title이 init 고정이라 토글은 버튼 2개의 표시 전환으로 구현한다. @@ -125,7 +130,10 @@ final class HomeViewController: UIViewController { /// 홈의 필드는 편집이 아니라 검색 진입 트리거다. DSTextField에는 편집 시작 훅이 /// 없으므로 필드 터치를 통째로 죽이고 UIControl 래퍼가 탭을 가져간다. - private func makeFieldRow(icon: UIImage, field: DSTextField) -> UIControl { + /// 탭한 필드가 검색 진입 슬롯이 된다(Phase 17) — entry가 그대로 넘어간다. + private func makeFieldRow( + icon: UIImage, field: DSTextField, entry: SearchEntryField + ) -> UIControl { let row = UIControl() let iconView = UIImageView(image: icon) iconView.tintColor = DSColor.Icon.default @@ -143,7 +151,7 @@ final class HomeViewController: UIViewController { make.top.trailing.bottom.equalToSuperview() } row.addAction( - UIAction { [weak self] _ in self?.viewModel.searchFieldTapped() }, + UIAction { [weak self] _ in self?.viewModel.searchFieldTapped(entry) }, for: .touchUpInside ) return row @@ -210,6 +218,9 @@ final class HomeViewController: UIViewController { departureField.setText("") } + // 도착지 필드 = 선택 경로의 도착지명(Phase 17). nil이면 placeholder가 유도한다. + arrivalField.setText(state.arrivalText ?? "") + if let card = state.routeCard { // 신선도 스탬프(Phase 16)는 세션 상태라 State가 따로 나른다 — 표출 시점 합성. routeCard.configure(with: card.dsContent(footnote: state.freshnessText)) @@ -254,6 +265,18 @@ final class HomeViewController: UIViewController { UIApplication.shared.open(url) } ) + case .locationServicesDisabled: + DSToast.show( + "기기의 위치 서비스가 꺼져 있어요", + in: view, + action: .init(title: "설정으로 이동") { + guard let url = URL(string: UIApplication.openSettingsURLString) else { return } + UIApplication.shared.open(url) + } + ) + case .locationRestricted: + // restricted는 설정으로 못 푸는 제약 — "설정으로 이동"을 안내하지 않는다(Phase 17). + DSToast.show("이 기기에선 위치를 사용할 수 없어요. 출발지를 검색해 주세요", in: view) case .alarmPermissionNeeded: DSToast.show( "알람 권한이 꺼져 있어요", diff --git a/Projects/Feature/Home/Sources/HomeViewData.swift b/Projects/Feature/Home/Sources/HomeViewData.swift index 9ad020a..8e37174 100644 --- a/Projects/Feature/Home/Sources/HomeViewData.swift +++ b/Projects/Feature/Home/Sources/HomeViewData.swift @@ -19,6 +19,14 @@ extension HomeViewModel { } } +/// 자정 넘김 표기(Phase 17) — 내일이면 "내일 " 접두, 오늘·그 외는 무라벨(무라벨 = 오늘). +/// 이틀+ 미래·과거는 막차 도메인상 비발생 — 방어적 무라벨. 피처 간 공유 모듈을 만들지 +/// 않으므로 SearchFeature와 중복이다(TransportBadgeMapper 선례). +func dayPrefix(for date: Date, now: Date, calendar: Calendar = .current) -> String { + guard let tomorrow = calendar.date(byAdding: .day, value: 1, to: now) else { return "" } + return calendar.isDate(date, inSameDayAs: tomorrow) ? "내일 " : "" +} + /// 홈에 표출되는 선택 경로 카드. Entity를 뷰에 직접 노출하지 않는다. struct RouteCardViewData: Equatable { /// 카드 톤 — past는 유예 경과 후의 "지난 막차" 상태(비활성 시각, Phase 13). @@ -34,14 +42,16 @@ struct RouteCardViewData: Equatable { let destinationText: String let tone: Tone - init(entity: LastRoute) { + init(entity: LastRoute, now: Date) { badgeText = "가장 늦은 차" - departureTimeText = "\(timeFormatter.string(from: entity.departureTime)) 출발" + let departurePrefix = dayPrefix(for: entity.departureTime, now: now) + departureTimeText = "\(departurePrefix)\(timeFormatter.string(from: entity.departureTime)) 출발" legs = TransportBadgeMapper.kinds(for: entity.legs) summaryText = Self.summary(from: entity.legs) let arrival = entity.departureTime.addingTimeInterval(TimeInterval(entity.totalTime)) - destinationText = "도착 \(timeFormatter.string(from: arrival)) · 환승 \(entity.transferCount)회" + let arrivalPrefix = dayPrefix(for: arrival, now: now) + destinationText = "도착 \(arrivalPrefix)\(timeFormatter.string(from: arrival)) · 환승 \(entity.transferCount)회" tone = .normal } diff --git a/Projects/Feature/Home/Sources/HomeViewModel.swift b/Projects/Feature/Home/Sources/HomeViewModel.swift index 52f9872..3f68fc9 100644 --- a/Projects/Feature/Home/Sources/HomeViewModel.swift +++ b/Projects/Feature/Home/Sources/HomeViewModel.swift @@ -1,5 +1,6 @@ import Domain import Foundation +import SearchFeatureInterface // Convention: every ViewModel in the codebase is @MainActor. @MainActor @@ -9,7 +10,8 @@ final class HomeViewModel { /// 역지오코딩된 현재 위치 라벨. case current(name: String) /// 위치를 쓸 수 없어 검색으로 출발지를 정해야 하는 상태. - case needsSearch(deniedPermission: Bool) + /// 실패 사유는 ToastEvent가 나른다(Phase 17) — 표시 상태는 사유와 무관하다. + case needsSearch } nonisolated struct BannerViewData: Equatable { @@ -28,6 +30,9 @@ final class HomeViewModel { struct State: Equatable { var departure: DepartureState = .loading + /// 도착지 필드 표시값(Phase 17) — 선택 경로의 도착지명. nil이면 placeholder. + /// 재실행 복원 경로는 도착지 명칭 원천이 없어 채우지 않는다(결정사항 — 수용). + var arrivalText: String? var routeCard: RouteCardViewData? var banner: BannerViewData? var isAlarmBusy = false @@ -41,6 +46,10 @@ final class HomeViewModel { /// 재방출되면 안 되는 원샷 안내 — 상태와 분리한다. enum ToastEvent: Equatable { case locationPermissionNeeded + /// 기기 전역 위치 서비스 OFF(Phase 17) — 앱 권한이 아니라 시스템 설정의 문제. + case locationServicesDisabled + /// 스크린타임·MDM 제약(Phase 17) — 설정으로 못 푼다. "설정으로 이동" 안내 금지. + case locationRestricted case alarmPermissionNeeded case alarmRegisterFailed case alarmCancelFailed @@ -63,8 +72,12 @@ final class HomeViewModel { /// pull-to-refresh 종료 훅(Phase 16) — 성공/실패 불문 동기화가 끝나면 불린다 /// (VC가 refreshControl.endRefreshing). 실패는 무음 — 결과 표출은 스트림·스탬프 몫. var onManualSyncFinished: (() -> Void)? - /// Set by the Coordinator: 검색 플로우를 열고, 선택 경로를 reply 클로저로 돌려받는다. - var onSearchRequested: ((_ onRouteSelected: @escaping (LastRoute) -> Void) -> Void)? + /// Set by the Coordinator: 검색 플로우를 열고, 선택 경로·도착지를 reply 클로저로 + /// 돌려받는다. initialField = 탭한 필드가 그대로 진입 슬롯이 된다(Phase 17). + var onSearchRequested: (( + _ initialField: SearchEntryField, + _ onRouteSelected: @escaping (LastRoute, Place) -> Void + ) -> Void)? private(set) var state = State() { didSet { if state != oldValue { onStateChange?(state) } } @@ -170,17 +183,19 @@ final class HomeViewModel { } } - /// 출발지/도착지 어느 필드를 탭해도 동일하게 검색 플로우로 진입한다. - func searchFieldTapped() { - onSearchRequested? { [weak self] route in - self?.routeSelected(route) + /// 탭한 필드가 그대로 검색 진입 슬롯이 된다(Phase 17) — 도착지 탭이면 도착지부터. + func searchFieldTapped(_ field: SearchEntryField) { + onSearchRequested?(field) { [weak self] route, arrival in + self?.routeSelected(route, arrival: arrival) } } - func routeSelected(_ route: LastRoute) { + func routeSelected(_ route: LastRoute, arrival: Place) { selectedRoute = route var newState = state - newState.routeCard = RouteCardViewData(entity: route) + newState.routeCard = RouteCardViewData(entity: route, now: now()) + // 도착지 필드를 선택 경로의 도착지명과 정합시킨다(Phase 17) — placeholder 공존 해소. + newState.arrivalText = arrival.name // 새 경로 선택 = 기존 배너는 더 이상 유효하지 않다 (재등록 전까지 숨김). newState.banner = nil newState.alarmButton = Self.alarmButtonMode( @@ -320,7 +335,8 @@ final class HomeViewModel { self.state.routeCard == nil else { return } self.selectedRoute = route var newState = self.state - newState.routeCard = RouteCardViewData(entity: route) + // 복원 경로는 도착지 명칭 원천이 없다 — arrivalText는 placeholder 유지(Phase 17 수용). + newState.routeCard = RouteCardViewData(entity: route, now: self.now()) newState.alarmButton = Self.alarmButtonMode( selectedRouteId: route.id, registeredRouteId: self.registeredRouteId @@ -399,14 +415,21 @@ final class HomeViewModel { let place = try await geocodeUseCase.execute(coordinate: coordinate) guard !Task.isCancelled else { return } self?.state.departure = .current(name: place.name) - } catch LocationError.permissionDenied { + } catch let error as LocationError { guard !Task.isCancelled else { return } - self?.state.departure = .needsSearch(deniedPermission: true) - self?.onToast?(.locationPermissionNeeded) + self?.state.departure = .needsSearch + // 사유별 안내 분기(Phase 17) — 회복 경로가 다르다. restricted는 설정으로 + // 못 푸는 제약이라 "설정으로 이동"을 안내하지 않는다(VC 매핑). + switch error { + case .permissionDenied: self?.onToast?(.locationPermissionNeeded) + case .servicesDisabled: self?.onToast?(.locationServicesDisabled) + case .restricted: self?.onToast?(.locationRestricted) + case .unavailable: break // 일시 실패 — 검색 유도만, 안내 없음. + } } catch { guard !Task.isCancelled else { return } // 역지오코딩 실패 포함 — 검색으로 출발지를 정하면 된다. - self?.state.departure = .needsSearch(deniedPermission: false) + self?.state.departure = .needsSearch } } } diff --git a/Projects/Feature/Home/Tests/HomeViewModelTests.swift b/Projects/Feature/Home/Tests/HomeViewModelTests.swift index 24cb6c5..2a4c908 100644 --- a/Projects/Feature/Home/Tests/HomeViewModelTests.swift +++ b/Projects/Feature/Home/Tests/HomeViewModelTests.swift @@ -1,6 +1,7 @@ import Domain import Foundation @testable import HomeFeature +import SearchFeatureInterface import Testing private struct StubError: Error {} @@ -114,6 +115,15 @@ private final class StateRecorder { private nonisolated let fixedNow = Date(timeIntervalSince1970: 1_755_800_000) +/// 검색 플로우가 동반하는 확정 도착지(Phase 17) — 도착지 필드 바인딩의 원천. +private nonisolated func makeArrival(_ name: String = "구로디지털단지역") -> Place { + Place( + name: name, + address: "서울 구로구 도림천로 486", + coordinate: Coordinate(latitude: 37.4853, longitude: 126.9015) + ) +} + private nonisolated func makeRoute(id: String, departure: Date) -> LastRoute { LastRoute( id: id, @@ -214,7 +224,7 @@ struct HomeViewModelTests { recorder.attach(to: sut) sut.viewDidLoad() - await recorder.waitUntilLast { $0.departure == .needsSearch(deniedPermission: true) } + await recorder.waitUntilLast { $0.departure == .needsSearch } #expect(recorder.toasts == [.locationPermissionNeeded]) } @@ -226,7 +236,7 @@ struct HomeViewModelTests { recorder.attach(to: sut) sut.viewDidLoad() - await recorder.waitUntilLast { $0.departure == .needsSearch(deniedPermission: false) } + await recorder.waitUntilLast { $0.departure == .needsSearch } #expect(recorder.toasts.isEmpty) } @@ -244,7 +254,7 @@ struct HomeViewModelTests { let recorder = StateRecorder() recorder.attach(to: sut) sut.viewDidLoad() - await recorder.waitUntilLast { $0.departure == .needsSearch(deniedPermission: true) } + await recorder.waitUntilLast { $0.departure == .needsSearch } let statesBefore = recorder.states.count granted.update { _ in true } @@ -267,7 +277,7 @@ struct HomeViewModelTests { let recorder = StateRecorder() recorder.attach(to: sut) sut.viewDidLoad() - await recorder.waitUntilLast { $0.departure == .needsSearch(deniedPermission: true) } + await recorder.waitUntilLast { $0.departure == .needsSearch } let statesBefore = recorder.states.count sut.didBecomeActive() @@ -305,9 +315,9 @@ struct HomeViewModelTests { let recorder = StateRecorder() recorder.attach(to: sut) - sut.routeSelected(route) + sut.routeSelected(route, arrival: makeArrival()) - #expect(sut.state.routeCard == RouteCardViewData(entity: route)) + #expect(sut.state.routeCard == RouteCardViewData(entity: route, now: fixedNow)) #expect(sut.state.banner == nil) } @@ -318,7 +328,7 @@ struct HomeViewModelTests { let recorder = StateRecorder() recorder.attach(to: sut) - sut.routeSelected(route) + sut.routeSelected(route, arrival: makeArrival()) sut.registerAlarmTapped() #expect(sut.state.isAlarmBusy) await recorder.waitUntilLast { $0.banner != nil } @@ -339,7 +349,7 @@ struct HomeViewModelTests { let recorder = StateRecorder() recorder.attach(to: sut) - sut.routeSelected(route) + sut.routeSelected(route, arrival: makeArrival()) sut.registerAlarmTapped() while recorder.toasts.isEmpty { await Task.yield() } // 배너는 틱 태스크가 비동기로 채운다 — 토스트와 별도로 기다린다. @@ -357,7 +367,7 @@ struct HomeViewModelTests { let recorder = StateRecorder() recorder.attach(to: sut) - sut.routeSelected(route) + sut.routeSelected(route, arrival: makeArrival()) sut.registerAlarmTapped() await recorder.waitUntilLast { $0.banner != nil } @@ -371,7 +381,7 @@ struct HomeViewModelTests { let recorder = StateRecorder() recorder.attach(to: sut) - sut.routeSelected(route) + sut.routeSelected(route, arrival: makeArrival()) sut.registerAlarmTapped() while recorder.toasts.isEmpty { await Task.yield() } @@ -387,11 +397,14 @@ struct HomeViewModelTests { let sut = makeSUT() let recorder = StateRecorder() recorder.attach(to: sut) - sut.routeSelected(route) + sut.routeSelected(route, arrival: makeArrival()) sut.registerAlarmTapped() await recorder.waitUntilLast { $0.banner != nil } - sut.routeSelected(makeRoute(id: "r2", departure: fixedNow.addingTimeInterval(30 * 60))) + sut.routeSelected( + makeRoute(id: "r2", departure: fixedNow.addingTimeInterval(30 * 60)), + arrival: makeArrival() + ) #expect(sut.state.banner == nil) #expect(sut.state.routeCard?.departureTimeText != nil) @@ -465,7 +478,7 @@ struct HomeViewModelTests { let sut = makeSUT(now: { clock.get() }, bannerTickInterval: .milliseconds(1)) let recorder = StateRecorder() recorder.attach(to: sut) - sut.routeSelected(route) + sut.routeSelected(route, arrival: makeArrival()) sut.registerAlarmTapped() await recorder.waitUntilLast { $0.banner != nil } @@ -491,7 +504,7 @@ struct HomeViewModelTests { let recorder = StateRecorder() recorder.attach(to: sut) - sut.routeSelected(route) + sut.routeSelected(route, arrival: makeArrival()) sut.registerAlarmTapped() await recorder.waitUntilLast { $0.banner?.text == "출발까지 39분" } @@ -508,7 +521,7 @@ struct HomeViewModelTests { let recorder = StateRecorder() recorder.attach(to: sut) - sut.routeSelected(route) + sut.routeSelected(route, arrival: makeArrival()) sut.registerAlarmTapped() while recorder.toasts.isEmpty { await Task.yield() } @@ -524,7 +537,7 @@ struct HomeViewModelTests { let sut = makeSUT() let recorder = StateRecorder() recorder.attach(to: sut) - sut.routeSelected(route) + sut.routeSelected(route, arrival: makeArrival()) sut.registerAlarmTapped() await recorder.waitUntilLast { $0.banner != nil } @@ -543,7 +556,7 @@ struct HomeViewModelTests { let sut = makeSUT(cancel: { _ in throw StubError() }) let recorder = StateRecorder() recorder.attach(to: sut) - sut.routeSelected(route) + sut.routeSelected(route, arrival: makeArrival()) sut.registerAlarmTapped() await recorder.waitUntilLast { $0.banner != nil } @@ -585,7 +598,7 @@ struct HomeViewModelTests { let recorder = StateRecorder() recorder.attach(to: sut) sut.viewDidLoad() - sut.routeSelected(route) + sut.routeSelected(route, arrival: makeArrival()) sut.registerAlarmTapped() await recorder.waitUntilLast { $0.banner?.text == "출발까지 39분" } @@ -670,7 +683,7 @@ struct HomeViewModelTests { let recorder = StateRecorder() recorder.attach(to: sut) sut.viewDidLoad() - sut.routeSelected(route) + sut.routeSelected(route, arrival: makeArrival()) sut.registerAlarmTapped() await recorder.waitUntilLast { $0.banner != nil } @@ -701,7 +714,7 @@ struct HomeViewModelTests { let recorder = StateRecorder() recorder.attach(to: sut) sut.viewDidLoad() - sut.routeSelected(route) + sut.routeSelected(route, arrival: makeArrival()) sut.registerAlarmTapped() await recorder.waitUntilLast { $0.banner?.text == "출발까지 39분" } @@ -807,7 +820,7 @@ struct HomeViewModelTests { let recorder = StateRecorder() recorder.attach(to: sut) - sut.routeSelected(route) + sut.routeSelected(route, arrival: makeArrival()) sut.registerAlarmTapped() await recorder.waitUntilLast { $0.banner != nil } @@ -823,7 +836,7 @@ struct HomeViewModelTests { let recorder = StateRecorder() recorder.attach(to: sut) - sut.routeSelected(route) + sut.routeSelected(route, arrival: makeArrival()) sut.registerAlarmTapped() while recorder.toasts.isEmpty { await Task.yield() } @@ -875,7 +888,7 @@ struct HomeViewModelTests { )) await recorder.waitUntilLast { $0.routeCard != nil } - #expect(sut.state.routeCard == RouteCardViewData(entity: route)) + #expect(sut.state.routeCard == RouteCardViewData(entity: route, now: fixedNow)) #expect(sut.state.alarmButton == .cancel) // 배너도 상세의 도보 초 반영 기준으로 재시작됐다 (42분 − 2분 도보 − 3분 버퍼 = 37분). await recorder.waitUntilLast { $0.banner?.text == "출발까지 37분" } @@ -917,7 +930,7 @@ struct HomeViewModelTests { let recorder = StateRecorder() recorder.attach(to: sut) sut.viewDidLoad() - sut.routeSelected(route) + sut.routeSelected(route, arrival: makeArrival()) sut.registerAlarmTapped() await recorder.waitUntilLast { $0.banner != nil } @@ -932,7 +945,7 @@ struct HomeViewModelTests { for _ in 0..<20 { await Task.yield() } #expect(!fetched.value) - #expect(sut.state.routeCard == RouteCardViewData(entity: route)) + #expect(sut.state.routeCard == RouteCardViewData(entity: route, now: fixedNow)) } // MARK: - 수동 갱신 (Phase 16 pull-to-refresh) @@ -998,7 +1011,7 @@ struct HomeViewModelTests { let recorder = StateRecorder() recorder.attach(to: sut) - sut.routeSelected(route) + sut.routeSelected(route, arrival: makeArrival()) #expect(sut.state.freshnessText == nil) sut.registerAlarmTapped() await recorder.waitUntilLast { $0.banner != nil } @@ -1044,7 +1057,7 @@ struct HomeViewModelTests { let sut = makeSUT() let recorder = StateRecorder() recorder.attach(to: sut) - sut.routeSelected(route) + sut.routeSelected(route, arrival: makeArrival()) sut.registerAlarmTapped() await recorder.waitUntilLast { $0.freshnessText != nil } let stampBefore = sut.state.freshnessText @@ -1064,7 +1077,7 @@ struct HomeViewModelTests { let sut = makeSUT() let recorder = StateRecorder() recorder.attach(to: sut) - sut.routeSelected(route) + sut.routeSelected(route, arrival: makeArrival()) sut.registerAlarmTapped() await recorder.waitUntilLast { $0.freshnessText != nil } @@ -1074,6 +1087,113 @@ struct HomeViewModelTests { #expect(sut.state.freshnessText == nil) } + // MARK: - 검색·홈 마찰 팩 (Phase 17) + + @Test + func routeSelected_bindsArrivalFieldText() async { + let route = makeRoute(id: "r1", departure: fixedNow.addingTimeInterval(42 * 60)) + let sut = makeSUT() + + #expect(sut.state.arrivalText == nil) + sut.routeSelected(route, arrival: makeArrival("신림동")) + + #expect(sut.state.arrivalText == "신림동") + // 새 경로 선택은 도착지명을 교체한다. + sut.routeSelected( + makeRoute(id: "r2", departure: fixedNow.addingTimeInterval(30 * 60)), + arrival: makeArrival("당산역") + ) + #expect(sut.state.arrivalText == "당산역") + } + + @Test + func searchFieldTapped_forwardsTappedFieldAsEntry() async { + let sut = makeSUT() + let received = ValueBox<[SearchEntryField]>([]) + sut.onSearchRequested = { field, _ in received.update { $0 + [field] } } + + sut.searchFieldTapped(.arrival) + sut.searchFieldTapped(.departure) + + #expect(received.get() == [.arrival, .departure]) + } + + @Test + func searchReply_bindsRouteCardAndArrival() async { + let route = makeRoute(id: "r1", departure: fixedNow.addingTimeInterval(42 * 60)) + let arrival = makeArrival("신림동") + let sut = makeSUT() + sut.onSearchRequested = { _, reply in reply(route, arrival) } + + sut.searchFieldTapped(.arrival) + + #expect(sut.state.routeCard == RouteCardViewData(entity: route, now: fixedNow)) + #expect(sut.state.arrivalText == "신림동") + } + + @Test + func viewDidLoad_servicesDisabled_needsSearchAndEmitsSystemToast() async { + let sut = makeSUT(location: { throw LocationError.servicesDisabled }) + let recorder = StateRecorder() + recorder.attach(to: sut) + + sut.viewDidLoad() + await recorder.waitUntilLast { $0.departure == .needsSearch } + while recorder.toasts.isEmpty { await Task.yield() } + + #expect(recorder.toasts == [.locationServicesDisabled]) + } + + @Test + func viewDidLoad_restricted_needsSearchAndEmitsRestrictedToast() async { + // restricted는 설정으로 못 푸는 제약 — 별도 안내(설정 이동 없음, VC 매핑)로 분기한다. + let sut = makeSUT(location: { throw LocationError.restricted }) + let recorder = StateRecorder() + recorder.attach(to: sut) + + sut.viewDidLoad() + await recorder.waitUntilLast { $0.departure == .needsSearch } + while recorder.toasts.isEmpty { await Task.yield() } + + #expect(recorder.toasts == [.locationRestricted]) + } + + @Test + func viewDidLoad_locationUnavailable_needsSearchWithoutToast() async { + let sut = makeSUT(location: { throw LocationError.unavailable }) + let recorder = StateRecorder() + recorder.attach(to: sut) + + sut.viewDidLoad() + await recorder.waitUntilLast { $0.departure == .needsSearch } + for _ in 0..<20 { await Task.yield() } + + #expect(recorder.toasts.isEmpty) + } + + @Test + func routeCardViewData_labelsTomorrowDepartureAndArrival() { + // 자정 넘김 표기 — 내일 출발 경로는 출발·도착 모두 "내일" 접두가 붙는다. + let tomorrowDeparture = Calendar.current.date(byAdding: .day, value: 1, to: fixedNow)! + let card = RouteCardViewData( + entity: makeRoute(id: "r1", departure: tomorrowDeparture), now: fixedNow + ) + #expect(card.departureTimeText.hasPrefix("내일 ")) + #expect(card.destinationText.hasPrefix("도착 내일 ")) + + // 오늘 경로는 무라벨 — 무라벨 = 오늘. + let today = RouteCardViewData( + entity: makeRoute(id: "r2", departure: fixedNow.addingTimeInterval(3600)), now: fixedNow + ) + #expect(!today.departureTimeText.hasPrefix("내일 ")) + #expect(!today.destinationText.contains("내일")) + + // "지난 막차" 카드는 라벨 스코프 밖 — 기존 문구 유지. + let past = card.asPastTrain(departure: tomorrowDeparture) + #expect(past.departureTimeText.hasSuffix("출발이었어요")) + #expect(!past.departureTimeText.hasPrefix("내일 ")) + } + @Test func sessionEndedAndExpiry_clearFreshnessStamp() async { // 종료·만료 정리와 함께 스탬프도 사라진다 — "지난 막차"에 신선도는 무의미하다. @@ -1089,7 +1209,7 @@ struct HomeViewModelTests { let recorder = StateRecorder() recorder.attach(to: sut) sut.viewDidLoad() - sut.routeSelected(route) + sut.routeSelected(route, arrival: makeArrival()) sut.registerAlarmTapped() // 스탬프는 배너보다 먼저 설정된다 — 배너까지 뜬 뒤에 종료를 흘려야 정리를 검증한다. await recorder.waitUntilLast { $0.banner != nil && $0.freshnessText != nil } diff --git a/Projects/Feature/Search/Example/ExampleApp.swift b/Projects/Feature/Search/Example/ExampleApp.swift index 6f2f6c8..29e78c0 100644 --- a/Projects/Feature/Search/Example/ExampleApp.swift +++ b/Projects/Feature/Search/Example/ExampleApp.swift @@ -52,19 +52,22 @@ final class SceneDelegate: UIResponder, UIWindowSceneDelegate { ) let coordinator = container.makeSearchCoordinator( navigationController: navigationController, - onRouteSelected: { [weak self] route in self?.showSelectedRoute(route) } + initialField: .departure, + onRouteSelected: { [weak self] route, arrival in + self?.showSelectedRoute(route, arrival: arrival) + } ) coordinator.finishDelegate = self searchCoordinator = coordinator coordinator.start() } - private func showSelectedRoute(_ route: LastRoute) { + private func showSelectedRoute(_ route: LastRoute, arrival: Place) { let formatter = DateFormatter() formatter.dateFormat = "HH:mm" let alert = UIAlertController( title: "경로 선택됨", - message: "\(formatter.string(from: route.departureTime)) 출발 · 환승 \(route.transferCount)회 (id: \(route.id))", + message: "\(formatter.string(from: route.departureTime)) 출발 → \(arrival.name) · 환승 \(route.transferCount)회 (id: \(route.id))", preferredStyle: .alert ) alert.addAction(UIAlertAction(title: "확인", style: .default)) diff --git a/Projects/Feature/Search/Interface/SearchCoordinatorBuildable.swift b/Projects/Feature/Search/Interface/SearchCoordinatorBuildable.swift index 6382ad1..afcc2b2 100644 --- a/Projects/Feature/Search/Interface/SearchCoordinatorBuildable.swift +++ b/Projects/Feature/Search/Interface/SearchCoordinatorBuildable.swift @@ -2,13 +2,21 @@ import CoreCoordinator import Domain import UIKit +/// 검색 진입 시 활성화할 슬롯 — 홈의 어느 필드를 탭했는지가 그대로 넘어온다(Phase 17). +public enum SearchEntryField: Sendable, Equatable { + case departure + case arrival +} + /// Entry point other modules use to start the Search flow. /// The concrete builder is the feature's DIContainer; wiring happens at the /// App composition root. @MainActor public protocol SearchCoordinatorBuildable { + /// onRouteSelected의 Place는 확정된 도착지 — 홈 도착지 필드가 이 이름과 정합한다(Phase 17). func makeSearchCoordinator( navigationController: UINavigationController, - onRouteSelected: @escaping (LastRoute) -> Void + initialField: SearchEntryField, + onRouteSelected: @escaping (LastRoute, Place) -> Void ) -> any Coordinator } diff --git a/Projects/Feature/Search/Sources/SearchCoordinator.swift b/Projects/Feature/Search/Sources/SearchCoordinator.swift index d15948c..8cb030d 100644 --- a/Projects/Feature/Search/Sources/SearchCoordinator.swift +++ b/Projects/Feature/Search/Sources/SearchCoordinator.swift @@ -1,41 +1,75 @@ import CoreCoordinator import Domain +import SearchFeatureInterface import UIKit -final class SearchCoordinator: Coordinator { +// NSObject 상속은 UINavigationControllerDelegate(NSObjectProtocol) 요구 — 이탈 경로 +// (백 버튼·스와이프 백·popToRoot)를 didShow 한 지점에서 정리하기 위해서다(Phase 17). +final class SearchCoordinator: NSObject, Coordinator { var childCoordinators: [any Coordinator] = [] weak var finishDelegate: (any CoordinatorFinishDelegate)? // The App (window root) owns the navigation controller. private weak var navigationController: UINavigationController? private let container: SearchDIContainer - private let onRouteSelected: (LastRoute) -> Void + private let initialField: SearchEntryField + private let onRouteSelected: (LastRoute, Place) -> Void + // didShow 정리 판정용 — pop이 끝나 이 VC가 스택에 없으면 플로우 종료다. + private weak var searchViewController: UIViewController? + private weak var previousNavigationDelegate: (any UINavigationControllerDelegate)? + // 모든 이탈 경로가 didShow로 수렴한다 — finish는 1회만. + private var isFinished = false init( navigationController: UINavigationController, container: SearchDIContainer, - onRouteSelected: @escaping (LastRoute) -> Void + initialField: SearchEntryField, + onRouteSelected: @escaping (LastRoute, Place) -> Void ) { self.navigationController = navigationController self.container = container + self.initialField = initialField self.onRouteSelected = onRouteSelected } func start() { + guard let navigationController else { return } let viewController = container.makeSearchViewController( - onRouteChosen: { [weak self] route in - self?.onRouteSelected(route) + initialField: initialField, + onRouteChosen: { [weak self] route, arrival in + self?.onRouteSelected(route, arrival) self?.closeFlow() }, onBack: { [weak self] in self?.closeFlow() } ) - navigationController?.pushViewController(viewController, animated: true) + searchViewController = viewController + previousNavigationDelegate = navigationController.delegate + navigationController.delegate = self + navigationController.pushViewController(viewController, animated: true) } + /// pop만 한다 — 코디네이터 정리는 didShow가 수행한다(이탈 경로 공통의 단일 지점). private func closeFlow() { navigationController?.popViewController(animated: true) + } +} + +extension SearchCoordinator: UINavigationControllerDelegate { + func navigationController( + _ navigationController: UINavigationController, + didShow viewController: UIViewController, + animated: Bool + ) { + guard !isFinished else { return } + // 검색 VC가 아직 스택에 있으면(최초 push·스와이프 취소) 플로우 진행 중이다. + if let searchViewController, + navigationController.viewControllers.contains(searchViewController) { + return + } + isFinished = true + navigationController.delegate = previousNavigationDelegate finish() } } diff --git a/Projects/Feature/Search/Sources/SearchDIContainer.swift b/Projects/Feature/Search/Sources/SearchDIContainer.swift index 61f41d8..35cea9c 100644 --- a/Projects/Feature/Search/Sources/SearchDIContainer.swift +++ b/Projects/Feature/Search/Sources/SearchDIContainer.swift @@ -26,24 +26,28 @@ public final class SearchDIContainer: SearchCoordinatorBuildable { public func makeSearchCoordinator( navigationController: UINavigationController, - onRouteSelected: @escaping (LastRoute) -> Void + initialField: SearchEntryField, + onRouteSelected: @escaping (LastRoute, Place) -> Void ) -> any Coordinator { SearchCoordinator( navigationController: navigationController, container: self, + initialField: initialField, onRouteSelected: onRouteSelected ) } func makeSearchViewController( - onRouteChosen: @escaping (LastRoute) -> Void, + initialField: SearchEntryField, + onRouteChosen: @escaping (LastRoute, Place) -> Void, onBack: @escaping () -> Void ) -> UIViewController { let viewModel = SearchViewModel( searchPlacesUseCase: searchPlacesUseCase, searchLastRoutesUseCase: searchLastRoutesUseCase, recentSearchesUseCase: recentSearchesUseCase, - getCurrentLocationUseCase: getCurrentLocationUseCase + getCurrentLocationUseCase: getCurrentLocationUseCase, + initialField: initialField ) viewModel.onRouteChosen = onRouteChosen viewModel.onBackRequested = onBack diff --git a/Projects/Feature/Search/Sources/SearchViewController.swift b/Projects/Feature/Search/Sources/SearchViewController.swift index 1331650..2b8dd8c 100644 --- a/Projects/Feature/Search/Sources/SearchViewController.swift +++ b/Projects/Feature/Search/Sources/SearchViewController.swift @@ -49,6 +49,13 @@ final class SearchViewController: UIViewController { navigationController?.setNavigationBarHidden(true, animated: animated) } + // 숨긴 내비바는 스와이프 백 제스처를 죽인다 — delegate를 잡아 되살린다(Phase 17). + // 코디네이터 정리는 pop 경로 공통의 didShow(SearchCoordinator)가 수행한다. + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + navigationController?.interactivePopGestureRecognizer?.delegate = self + } + override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) navigationController?.setNavigationBarHidden(false, animated: animated) @@ -155,8 +162,27 @@ final class SearchViewController: UIViewController { case let .recent(places): showsRecentHeader = true rows = places.map { .place($0, showsDelete: true) } + // 빈 상태 2종(Phase 17) — 백지 대신 다음 행동을 말한다. 액션 버튼 없음 + // (타이핑이 곧 회복 경로). 빈 목록엔 "최근 검색" 헤더도 없다(rows.isEmpty 가드). + if places.isEmpty { + showEmptyState( + title: "최근 검색이 없어요", + message: "도착지를 검색해 막차 시간을 확인해 보세요" + ) + } case let .places(places): rows = places.map { .place($0, showsDelete: false) } + if places.isEmpty { + showEmptyState( + title: "검색 결과가 없어요", + message: "다른 키워드로 검색해 보세요" + ) + } + case .loadingPlaces: + // 키워드 검색 로딩(Phase 17) — loadingRoutes와 달리 키보드를 유지한다 + // (타이핑 계속이 정상 흐름). + rows = [] + activityIndicator.startAnimating() case .loadingRoutes: rows = [] view.endEditing(true) @@ -211,7 +237,7 @@ final class SearchViewController: UIViewController { return rows } - private func showEmptyState(title: String, message: String, actionTitle: String) { + private func showEmptyState(title: String, message: String, actionTitle: String? = nil) { emptyState.configure( with: .init( icon: DSIcon.illustCharacterGray, @@ -313,6 +339,20 @@ extension SearchViewController: UITableViewDelegate { } } + // 최근 검색 스와이프 삭제(Phase 17, 기획서 요구) — 기존 X 버튼과 같은 경로를 탄다. + func tableView( + _ tableView: UITableView, + trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath + ) -> UISwipeActionsConfiguration? { + guard case .place(_, showsDelete: true) = rows[indexPath.row] else { return nil } + let delete = UIContextualAction(style: .destructive, title: "삭제") { + [weak self] _, _, completion in + self?.viewModel.didDeleteRecent(at: indexPath.row) + completion(true) + } + return UISwipeActionsConfiguration(actions: [delete]) + } + func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { guard showsRecentHeader, !rows.isEmpty else { return nil } return DSSectionHeader(title: "최근 검색") @@ -324,6 +364,13 @@ extension SearchViewController: UITableViewDelegate { } } +extension SearchViewController: UIGestureRecognizerDelegate { + // 루트에서는 시작 금지 — 검색 화면이 스택 위에 있을 때만 스와이프 백을 허용한다. + func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { + (navigationController?.viewControllers.count ?? 0) > 1 + } +} + // DSRouteCard는 UIView라 리스트에 태우려면 셀 래퍼가 필요하다 — // 셀이면 didSelectRowAt이 탭 처리까지 해결한다. private final class SearchRouteCardCell: UITableViewCell { diff --git a/Projects/Feature/Search/Sources/SearchViewData.swift b/Projects/Feature/Search/Sources/SearchViewData.swift index d087ad2..6366c46 100644 --- a/Projects/Feature/Search/Sources/SearchViewData.swift +++ b/Projects/Feature/Search/Sources/SearchViewData.swift @@ -11,6 +11,14 @@ private let timeFormatter: DateFormatter = { return formatter }() +/// 자정 넘김 표기(Phase 17) — 내일이면 "내일 " 접두, 오늘·그 외는 무라벨(무라벨 = 오늘). +/// 이틀+ 미래·과거는 막차 도메인상 비발생 — 방어적 무라벨. 피처 간 공유 모듈을 만들지 +/// 않으므로 HomeFeature와 중복이다(TransportBadgeMapper 선례). +func dayPrefix(for date: Date, now: Date, calendar: Calendar = .current) -> String { + guard let tomorrow = calendar.date(byAdding: .day, value: 1, to: now) else { return "" } + return calendar.isDate(date, inSameDayAs: tomorrow) ? "내일 " : "" +} + struct PlaceViewData: Equatable { let name: String let address: String @@ -28,14 +36,16 @@ struct RouteViewData: Equatable { let summaryText: String? let destinationText: String - init(entity: LastRoute, isFeatured: Bool) { + init(entity: LastRoute, isFeatured: Bool, now: Date) { badgeText = isFeatured ? "가장 늦은 차" : nil - departureTimeText = "\(timeFormatter.string(from: entity.departureTime)) 출발" + let departurePrefix = dayPrefix(for: entity.departureTime, now: now) + departureTimeText = "\(departurePrefix)\(timeFormatter.string(from: entity.departureTime)) 출발" legs = TransportBadgeMapper.kinds(for: entity.legs) summaryText = Self.summary(from: entity.legs) let arrival = entity.departureTime.addingTimeInterval(TimeInterval(entity.totalTime)) - destinationText = "도착 \(timeFormatter.string(from: arrival)) · 환승 \(entity.transferCount)회" + let arrivalPrefix = dayPrefix(for: arrival, now: now) + destinationText = "도착 \(arrivalPrefix)\(timeFormatter.string(from: arrival)) · 환승 \(entity.transferCount)회" } // "탑승지 → 환승지 → 하차지" — 도보 구간은 경유지로 세지 않는다. @@ -55,9 +65,11 @@ struct RouteResultsViewData: Equatable { let isExpanded: Bool /// `entities`는 비어 있지 않아야 한다 (`.available`이 상류에서 보장). - init(entities: [LastRoute], isExpanded: Bool) { - featured = RouteViewData(entity: entities[0], isFeatured: true) - alternatives = entities.dropFirst().map { RouteViewData(entity: $0, isFeatured: false) } + init(entities: [LastRoute], isExpanded: Bool, now: Date) { + featured = RouteViewData(entity: entities[0], isFeatured: true, now: now) + alternatives = entities.dropFirst().map { + RouteViewData(entity: $0, isFeatured: false, now: now) + } self.isExpanded = isExpanded } } diff --git a/Projects/Feature/Search/Sources/SearchViewModel.swift b/Projects/Feature/Search/Sources/SearchViewModel.swift index 7e8a8f9..60b7da3 100644 --- a/Projects/Feature/Search/Sources/SearchViewModel.swift +++ b/Projects/Feature/Search/Sources/SearchViewModel.swift @@ -1,5 +1,6 @@ import Domain import Foundation +import SearchFeatureInterface // Convention: every ViewModel in the codebase is @MainActor. @MainActor @@ -15,6 +16,8 @@ final class SearchViewModel { case idle case recent([PlaceViewData]) case places([PlaceViewData]) + /// 키워드 검색 진행 중(Phase 17) — 디바운스 통과 후에만 진입한다(타이핑 깜빡임 방지). + case loadingPlaces case loadingRoutes case routes(RouteResultsViewData) case serviceEnded @@ -32,8 +35,8 @@ final class SearchViewModel { /// Set by the ViewController; always invoked on the main actor. var onStateChange: ((State) -> Void)? var onFieldsChange: ((FieldsViewData) -> Void)? - /// Set by the Coordinator. - var onRouteChosen: ((LastRoute) -> Void)? + /// Set by the Coordinator. Place = 확정 도착지 — 홈 도착지 필드의 원천이다(Phase 17). + var onRouteChosen: ((LastRoute, Place) -> Void)? var onBackRequested: (() -> Void)? private(set) var state: State = .idle { @@ -64,6 +67,8 @@ final class SearchViewModel { private let recentSearchesUseCase: any RecentSearchesUseCase // nil이면(예: Example 스텁 구성) 프리필·near 바이어스 없이 동작한다. private let getCurrentLocationUseCase: (any GetCurrentLocationUseCase)? + // 오늘/내일 라벨 판정의 기준 시각(Phase 17) — 실 Date() 직접 호출 대신 주입(기존 VM 관례). + private let now: @Sendable () -> Date private let debounceInterval: Duration private var searchTask: Task? @@ -78,13 +83,18 @@ final class SearchViewModel { searchLastRoutesUseCase: any SearchLastRoutesUseCase, recentSearchesUseCase: any RecentSearchesUseCase, getCurrentLocationUseCase: (any GetCurrentLocationUseCase)? = nil, + initialField: SearchEntryField = .departure, + now: @escaping @Sendable () -> Date = { Date() }, debounceInterval: Duration = .milliseconds(300) ) { self.searchPlacesUseCase = searchPlacesUseCase self.searchLastRoutesUseCase = searchLastRoutesUseCase self.recentSearchesUseCase = recentSearchesUseCase self.getCurrentLocationUseCase = getCurrentLocationUseCase + self.now = now self.debounceInterval = debounceInterval + // 탭한 필드로 진입한다(Phase 17) — 초기 활성 슬롯만 정하고 프리필 정책은 불변. + fields.activeField = (initialField == .arrival) ? .arrival : .departure } deinit { @@ -142,6 +152,8 @@ final class SearchViewModel { let useCase = self?.searchPlacesUseCase else { return } try? await Task.sleep(for: interval) guard !Task.isCancelled else { return } + // 디바운스 통과 = 이 키워드로 실제 요청한다 — 로딩은 여기서부터(Phase 17). + self?.state = .loadingPlaces do { // 현재 위치가 확보된 경우에만 근처 우선 정렬 바이어스를 건다. let places = try await useCase.execute(keyword: trimmed, near: self?.currentCoordinate) @@ -183,19 +195,32 @@ final class SearchViewModel { func didTapMore() { guard case .routes = state, !availableRoutes.isEmpty else { return } isExpanded.toggle() - state = .routes(RouteResultsViewData(entities: availableRoutes, isExpanded: isExpanded)) + state = .routes( + RouteResultsViewData(entities: availableRoutes, isExpanded: isExpanded, now: now()) + ) } func didSelectRoute(at index: Int) { guard case .routes = state, availableRoutes.indices.contains(index) else { return } - onRouteChosen?(availableRoutes[index]) + // 불변식: routes 상태는 두 슬롯 확정 시에만 존재한다 — arrival은 항상 있다(방어 가드). + guard let arrival else { return } + onRouteChosen?(availableRoutes[index], arrival) } func didTapEmptyAction() { switch state { case .failed where departure != nil && arrival != nil: searchRoutes() - case .failed, .serviceEnded, .noRoute: + case .serviceEnded, .noRoute: + // "다시 검색하기" 실동작(Phase 17) — 도착지 슬롯을 비우고 포커스를 넘겨 + // 즉시 재검색이 가능하게 한다. 출발지는 유지(대개 현재 위치). + arrival = nil + var newFields = fields + newFields.arrivalText = "" + newFields.activeField = .arrival + fields = newFields + showRecent() + case .failed: showRecent() default: break @@ -267,9 +292,12 @@ final class SearchViewModel { guard !Task.isCancelled else { return } switch result { case let .available(routes) where !routes.isEmpty: - self?.availableRoutes = routes - self?.isExpanded = false - self?.state = .routes(RouteResultsViewData(entities: routes, isExpanded: false)) + guard let self else { return } + self.availableRoutes = routes + self.isExpanded = false + self.state = .routes( + RouteResultsViewData(entities: routes, isExpanded: false, now: self.now()) + ) case .available: // 정규화가 놓친 빈 목록 방어. self?.state = .noRoute diff --git a/Projects/Feature/Search/Tests/SearchCoordinatorTests.swift b/Projects/Feature/Search/Tests/SearchCoordinatorTests.swift new file mode 100644 index 0000000..e618c70 --- /dev/null +++ b/Projects/Feature/Search/Tests/SearchCoordinatorTests.swift @@ -0,0 +1,106 @@ +import CoreCoordinator +import Domain +@testable import SearchFeature +import SearchFeatureInterface +import Testing +import UIKit + +// 코디네이터 조립용 최소 스텁 — Tests/Example 중복은 의도된 트레이드오프(기존 규약). +private struct StubSearchPlacesUseCase: SearchPlacesUseCase { + func execute(keyword: String, near coordinate: Coordinate?) async throws -> [Place] { [] } +} + +private struct StubSearchLastRoutesUseCase: SearchLastRoutesUseCase { + func execute(start: Coordinate, end: Coordinate) async throws -> LastRouteSearchResult { + .noRoute + } +} + +private struct StubRecentSearchesUseCase: RecentSearchesUseCase { + func fetch() async throws -> [Place] { [] } + func save(_ place: Place) async throws {} + func remove(_ place: Place) async throws {} +} + +@MainActor +private final class FinishRecorder: CoordinatorFinishDelegate { + private(set) var finishedCount = 0 + func coordinatorDidFinish(_ coordinator: any Coordinator) { finishedCount += 1 } +} + +/// 이전 delegate 복원 검증용 더미. +private final class PriorNavigationDelegate: NSObject, UINavigationControllerDelegate {} + +@MainActor +private func makeCoordinator(navigationController: UINavigationController) -> SearchCoordinator { + SearchCoordinator( + navigationController: navigationController, + container: SearchDIContainer( + searchPlacesUseCase: StubSearchPlacesUseCase(), + searchLastRoutesUseCase: StubSearchLastRoutesUseCase(), + recentSearchesUseCase: StubRecentSearchesUseCase() + ), + initialField: .departure, + onRouteSelected: { _, _ in } + ) +} + +/// 이탈 경로(백 버튼·스와이프 백·popToRoot) 공통의 didShow 정리(Phase 17) — +/// 실제 전환 없이 didShow를 직접 호출해 판정 로직을 검증한다. +@MainActor +struct SearchCoordinatorTests { + @Test + func start_installsSelfAsNavigationDelegate() { + let navigationController = UINavigationController(rootViewController: UIViewController()) + let prior = PriorNavigationDelegate() + navigationController.delegate = prior + let sut = makeCoordinator(navigationController: navigationController) + + sut.start() + + #expect(navigationController.delegate === sut) + #expect(navigationController.viewControllers.count == 2) + } + + @Test + func didShow_whileSearchStillOnStack_doesNotFinish() { + let navigationController = UINavigationController(rootViewController: UIViewController()) + let sut = makeCoordinator(navigationController: navigationController) + let recorder = FinishRecorder() + sut.finishDelegate = recorder + sut.start() + + // 최초 push의 didShow — 검색 VC가 스택에 있으므로 플로우 진행 중이다. + sut.navigationController( + navigationController, + didShow: navigationController.viewControllers[1], + animated: false + ) + + #expect(recorder.finishedCount == 0) + #expect(navigationController.delegate === sut) + } + + @Test + func didShow_afterPop_finishesOnceAndRestoresDelegate() { + let navigationController = UINavigationController(rootViewController: UIViewController()) + let prior = PriorNavigationDelegate() + navigationController.delegate = prior + let sut = makeCoordinator(navigationController: navigationController) + let recorder = FinishRecorder() + sut.finishDelegate = recorder + sut.start() + + // pop 결과 시뮬레이션 — 백 버튼·스와이프 백·popToRoot 전부 같은 스택 상태로 끝난다. + let root = navigationController.viewControllers[0] + navigationController.viewControllers = [root] + sut.navigationController(navigationController, didShow: root, animated: false) + + #expect(recorder.finishedCount == 1) + #expect(navigationController.delegate === prior) + + // 중복 didShow는 no-op — finish는 1회 가드. + sut.navigationController(navigationController, didShow: root, animated: false) + #expect(recorder.finishedCount == 1) + } +} diff --git a/Projects/Feature/Search/Tests/SearchViewModelTests.swift b/Projects/Feature/Search/Tests/SearchViewModelTests.swift index abf112d..240b0a3 100644 --- a/Projects/Feature/Search/Tests/SearchViewModelTests.swift +++ b/Projects/Feature/Search/Tests/SearchViewModelTests.swift @@ -1,6 +1,7 @@ import Domain import Foundation @testable import SearchFeature +import SearchFeatureInterface import Testing private struct StubSearchPlacesUseCase: SearchPlacesUseCase { @@ -91,6 +92,8 @@ private final class StateRecorder { } } +private nonisolated let fixedNow = Date(timeIntervalSince1970: 1_755_800_000) + private nonisolated func makePlace(_ name: String) -> Place { Place( name: name, @@ -132,13 +135,16 @@ private func makeSUT( placesHandler: @escaping @Sendable (String) async throws -> [Place] = { _ in [] }, routesHandler: @escaping @Sendable () async throws -> LastRouteSearchResult = { .available([]) }, store: RecentStore = RecentStore(), - location: (@Sendable () async throws -> Coordinate)? = nil + location: (@Sendable () async throws -> Coordinate)? = nil, + initialField: SearchEntryField = .departure ) -> SearchViewModel { SearchViewModel( searchPlacesUseCase: StubSearchPlacesUseCase(handler: placesHandler), searchLastRoutesUseCase: StubSearchLastRoutesUseCase(handler: routesHandler), recentSearchesUseCase: StubRecentSearchesUseCase(store: store), getCurrentLocationUseCase: location.map(StubGetCurrentLocationUseCase.init(handler:)), + initialField: initialField, + now: { fixedNow }, debounceInterval: .zero ) } @@ -212,7 +218,7 @@ struct SearchViewModelTests { await recorder.waitUntilLast { if case .routes = $0 { true } else { false } } #expect(recorder.states.contains(.loadingRoutes)) - let expected = RouteResultsViewData(entities: routes, isExpanded: false) + let expected = RouteResultsViewData(entities: routes, isExpanded: false, now: fixedNow) #expect(recorder.states.last == .routes(expected)) #expect(expected.featured.badgeText == "가장 늦은 차") #expect(expected.alternatives.count == 1) @@ -288,10 +294,10 @@ struct SearchViewModelTests { await recorder.waitUntilLast { if case .routes = $0 { true } else { false } } sut.didTapMore() - #expect(recorder.states.last == .routes(RouteResultsViewData(entities: routes, isExpanded: true))) + #expect(recorder.states.last == .routes(RouteResultsViewData(entities: routes, isExpanded: true, now: fixedNow))) sut.didTapMore() - #expect(recorder.states.last == .routes(RouteResultsViewData(entities: routes, isExpanded: false))) + #expect(recorder.states.last == .routes(RouteResultsViewData(entities: routes, isExpanded: false, now: fixedNow))) } @Test @@ -419,18 +425,24 @@ struct SearchViewModelTests { sut.didSelectListItem(at: 0) await recorder.waitUntilLast { if case .routes = $0 { true } else { false } } - #expect(recorder.states.last == .routes(RouteResultsViewData(entities: routes, isExpanded: false))) + #expect(recorder.states.last == .routes(RouteResultsViewData(entities: routes, isExpanded: false, now: fixedNow))) } @Test - func selectRoute_forwardsEntityToOnRouteChosen() async { + func selectRoute_forwardsEntityAndConfirmedArrival() async { + // 도착지 동반(Phase 17) — 홈 도착지 필드의 원천이므로 확정된 그 장소여야 한다. + let arrival = makePlace("회사") let routes = [makeRoute(id: "r1"), makeRoute(id: "r2")] let sut = makeSUT( - placesHandler: { _ in [makePlace("강남역")] }, + placesHandler: { _ in [arrival] }, routesHandler: { .available(routes) } ) var chosen: LastRoute? - sut.onRouteChosen = { chosen = $0 } + var chosenArrival: Place? + sut.onRouteChosen = { route, place in + chosen = route + chosenArrival = place + } let recorder = StateRecorder() recorder.attach(to: sut) await driveBothSlotsConfirmed(sut: sut, recorder: recorder) @@ -439,5 +451,126 @@ struct SearchViewModelTests { sut.didSelectRoute(at: 0) #expect(chosen == routes[0]) + #expect(chosenArrival == arrival) + } + + // MARK: - Phase 17: 진입 필드·로딩·빈 결과·다시 검색하기·내일 라벨 + + @Test + func initialFieldArrival_startsWithArrivalSlotActive() { + let sut = makeSUT(initialField: .arrival) + #expect(sut.fields.activeField == .arrival) + + let departureEntry = makeSUT(initialField: .departure) + #expect(departureEntry.fields.activeField == .departure) + } + + @Test + func keywordSearch_passesThroughLoadingPlaces() async { + let place = makePlace("강남역") + let sut = makeSUT(placesHandler: { _ in [place] }) + let recorder = StateRecorder() + recorder.attach(to: sut) + + sut.keywordDidChange("강남", in: .departure) + await recorder.waitUntilLast { if case .places = $0 { true } else { false } } + + // 디바운스 통과 후 요청 직전의 로딩 상태를 반드시 거친다. + #expect(recorder.states.contains(.loadingPlaces)) + } + + @Test + func keywordSearch_zeroResults_showsEmptyPlaces() async { + let sut = makeSUT(placesHandler: { _ in [] }) + let recorder = StateRecorder() + recorder.attach(to: sut) + + sut.keywordDidChange("결과없는키워드", in: .arrival) + await recorder.waitUntilLast { $0 == .places([]) } + + // 0건도 .places로 흐른다 — VC가 빈 상태("검색 결과가 없어요")를 그린다. + #expect(recorder.states.last == .places([])) + } + + @Test + func emptyResultAction_resetsArrivalSlotAndReturnsToRecent() async { + // "다시 검색하기" 실동작: 도착지 슬롯 초기화 + 포커스 + 최근 검색 복귀. + let sut = makeSUT( + placesHandler: { _ in [makePlace("강남역")] }, + routesHandler: { .serviceEnded } + ) + let recorder = StateRecorder() + recorder.attach(to: sut) + await driveBothSlotsConfirmed(sut: sut, recorder: recorder) + await recorder.waitUntilLast { $0 == .serviceEnded } + #expect(!sut.fields.arrivalText.isEmpty) + + sut.didTapEmptyAction() + await recorder.waitUntilLast { if case .recent = $0 { true } else { false } } + + #expect(sut.fields.arrivalText.isEmpty) + #expect(sut.fields.activeField == .arrival) + // 출발지는 유지 — 즉시 새 도착지 검색이 가능하다. + #expect(sut.fields.departureText == "강남역") + } + + @Test + func noRouteAction_alsoResetsArrivalSlot() async { + let sut = makeSUT( + placesHandler: { _ in [makePlace("강남역")] }, + routesHandler: { .noRoute } + ) + let recorder = StateRecorder() + recorder.attach(to: sut) + await driveBothSlotsConfirmed(sut: sut, recorder: recorder) + await recorder.waitUntilLast { $0 == .noRoute } + + sut.didTapEmptyAction() + await recorder.waitUntilLast { if case .recent = $0 { true } else { false } } + + #expect(sut.fields.arrivalText.isEmpty) + #expect(sut.fields.activeField == .arrival) + } + + @Test + func dayPrefix_labelsOnlyTomorrow() { + var calendar = Calendar(identifier: .gregorian) + calendar.timeZone = TimeZone(identifier: "Asia/Seoul")! + let now = calendar.date( + from: DateComponents(year: 2026, month: 8, day: 23, hour: 23, minute: 40) + )! + let lateTonight = calendar.date( + from: DateComponents(year: 2026, month: 8, day: 23, hour: 23, minute: 55) + )! + let afterMidnight = calendar.date( + from: DateComponents(year: 2026, month: 8, day: 24, hour: 0, minute: 29) + )! + let dayAfterTomorrow = calendar.date( + from: DateComponents(year: 2026, month: 8, day: 25, hour: 0, minute: 10) + )! + + #expect(dayPrefix(for: lateTonight, now: now, calendar: calendar) == "") + #expect(dayPrefix(for: afterMidnight, now: now, calendar: calendar) == "내일 ") + // 이틀+ 미래는 막차 도메인상 비발생 — 방어적 무라벨. + #expect(dayPrefix(for: dayAfterTomorrow, now: now, calendar: calendar) == "") + } + + @Test + func routeViewData_labelsTomorrowDepartureAndArrival() { + let tomorrowDeparture = Calendar.current.date(byAdding: .day, value: 1, to: fixedNow)! + let tomorrow = RouteViewData( + entity: makeRoute(id: "r1", departureOffset: tomorrowDeparture.timeIntervalSince(fixedNow)), + isFeatured: true, + now: fixedNow + ) + #expect(tomorrow.departureTimeText.hasPrefix("내일 ")) + #expect(tomorrow.destinationText.hasPrefix("도착 내일 ")) + + // 오늘 출발·오늘 도착은 무라벨 — 무라벨 = 오늘. + let today = RouteViewData( + entity: makeRoute(id: "r2", departureOffset: 60), isFeatured: true, now: fixedNow + ) + #expect(!today.departureTimeText.hasPrefix("내일 ")) + #expect(!today.destinationText.contains("내일")) } } From 6e7d3dc044d04284da4cc0659fc54b4464319d42 Mon Sep 17 00:00:00 2001 From: AppGoni Date: Mon, 24 Aug 2026 01:02:39 +0900 Subject: [PATCH 09/14] =?UTF-8?q?fix:=20=EA=B2=80=EC=83=89=20=EB=B9=88=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=C2=B7=EC=8A=A4=ED=94=BC=EB=84=88=EB=A5=BC=20?= =?UTF-8?q?=ED=82=A4=EB=B3=B4=EB=93=9C=20=EC=9C=84=20=EA=B0=80=EC=8B=9C=20?= =?UTF-8?q?=EC=98=81=EC=97=AD=20=EC=A4=91=EC=95=99=EC=97=90=20=EB=B0=B0?= =?UTF-8?q?=EC=B9=98=20(Phase=2017=20=EC=9E=90=EB=8F=99=20=EA=B2=80?= =?UTF-8?q?=EC=88=98=EC=97=90=EC=84=9C=20=EB=B0=9C=EA=B2=AC=20=E2=80=94=20?= =?UTF-8?q?=ED=83=80=EC=9D=B4=ED=95=91=20=EC=A4=91=20=EB=B9=88=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=20=EB=AC=B8=EA=B5=AC=EA=B0=80=20=ED=82=A4=EB=B3=B4?= =?UTF-8?q?=EB=93=9C=EC=97=90=20=EA=B0=80=EB=A6=BC)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- .../Search/Sources/SearchViewController.swift | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Projects/Feature/Search/Sources/SearchViewController.swift b/Projects/Feature/Search/Sources/SearchViewController.swift index 2b8dd8c..9e218ad 100644 --- a/Projects/Feature/Search/Sources/SearchViewController.swift +++ b/Projects/Feature/Search/Sources/SearchViewController.swift @@ -102,12 +102,24 @@ final class SearchViewController: UIViewController { make.top.equalTo(separator.snp.bottom) make.leading.trailing.bottom.equalToSuperview() } + // 빈 상태·스피너는 키보드 위 가시 영역의 중앙에 둔다(Phase 17) — 타이핑 중 뜨는 + // 빈 상태(최근 0건·결과 0건)의 문구가 키보드에 가리지 않아야 한다. + // keyboardLayoutGuide는 키보드가 없으면 화면 하단을 따르므로 분기가 필요 없다. + let aboveKeyboardArea = UILayoutGuide() + view.addLayoutGuide(aboveKeyboardArea) + NSLayoutConstraint.activate([ + aboveKeyboardArea.topAnchor.constraint(equalTo: separator.bottomAnchor), + aboveKeyboardArea.leadingAnchor.constraint(equalTo: view.leadingAnchor), + aboveKeyboardArea.trailingAnchor.constraint(equalTo: view.trailingAnchor), + aboveKeyboardArea.bottomAnchor.constraint(equalTo: view.keyboardLayoutGuide.topAnchor), + ]) emptyState.snp.makeConstraints { make in - make.center.equalTo(tableView) + make.centerY.equalTo(aboveKeyboardArea.snp.centerY) make.leading.trailing.equalToSuperview().inset(DSSpacing.lg) } activityIndicator.snp.makeConstraints { make in - make.center.equalTo(tableView) + make.centerX.equalToSuperview() + make.centerY.equalTo(aboveKeyboardArea.snp.centerY) } navigationBar.onBack = { [weak self] in self?.viewModel.didTapBack() } From 2e1c680533700c07925cf1f0babadac73af138fe Mon Sep 17 00:00:00 2001 From: AppGoni Date: Mon, 24 Aug 2026 01:08:13 +0900 Subject: [PATCH 10/14] =?UTF-8?q?docs:=20Phase=2017=20=EC=9E=90=EB=8F=99?= =?UTF-8?q?=20=EA=B2=80=EC=88=98=20=EA=B2=B0=EA=B3=BC=20=EA=B8=B0=EB=A1=9D?= =?UTF-8?q?=20+=20=EA=B7=9C=EC=95=BD=EC=97=90=20=EC=9E=A0=EA=B8=88=20?= =?UTF-8?q?=ED=99=94=EB=A9=B4=20=EB=8C=80=EC=B2=B4=20=EA=B2=BD=EB=A1=9C(XC?= =?UTF-8?q?UITest=20=ED=95=98=EB=8B=88=EC=8A=A4)=20=EC=8B=A4=EC=B8=A1=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- docs/prompts/atcha-v2-auto-verification.md | 3 +++ docs/prompts/atcha-v2-friction-pack-prompt.md | 2 ++ 2 files changed, 5 insertions(+) diff --git a/docs/prompts/atcha-v2-auto-verification.md b/docs/prompts/atcha-v2-auto-verification.md index 61769c9..731ace6 100644 --- a/docs/prompts/atcha-v2-auto-verification.md +++ b/docs/prompts/atcha-v2-auto-verification.md @@ -23,6 +23,9 @@ 추가 실측 규약: +- **Mac 화면 잠금 중 대체 경로 (2026-08-24 실측)**: 잠금 중에는 System Events·orca 모두 창 AX 트리가 비어 조작 불가지만, **XCUITest 하니스는 성립한다** — 스크래치 Tuist 프로젝트(더미 host 앱 + `.uiTests` 타겟)에서 `XCUIApplication(bundleIdentifier: "com.atcha.iOS.v2")`로 앱을 구동하면 XCTRunner가 시뮬레이터 디바이스 내부에서 이벤트를 주입하므로 잠금·AX와 무관하다. 증적은 `XCUIScreen.main.screenshot()`을 호스트 경로에 직접 기록(시뮬레이터 프로세스 = 호스트 FS 공유). 시스템 권한 알럿은 `XCUIApplication(bundleIdentifier: "com.apple.springboard")`의 버튼으로 처리하고, **알람 등록 검수는 알림 권한 알럿 응답까지 등록 UseCase가 대기하므로 배너 표출까지 알럿을 반복 소거**해야 한다. 엣지 스와이프 백(좌표 드래그)·셀 스와이프(`swipeLeft`)도 이 경로로 신뢰 가능 — AX 좌표 클릭 불신뢰 제약의 대체다. 한글 `typeText` 입력도 성립. +- Simulator.app의 AX 트리가 응답하지 않으면(창 열거 0·entire contents 타임아웃) `killall "System Events"` 후 재시도, 그래도 안 되면 Mac 잠금 상태부터 확인할 것(잠금이 원인인 경우가 많다). + - **강제 종료 재현은 `xcrun simctl terminate`** — 앱 스위처 스와이프 자동화 불필요. - **LA dismiss 검수는 DEV dismiss 토글 사용** — 잠금화면 스와이프 삭제 자동화가 불안정해서 그 용도로 만들어진 수단(플로팅 디버그 메뉴의 dismiss 기록 토글, `devToggleDismissedByUser`)을 쓴다. - **막차 변경 주입은 DEV 플로팅 "변경" 버튼** (SceneDelegate) — 앞당김/늦춤/운행 종료. actionable 경로가 필요하면 늦춤 먼저 → 앞당김 순서로 주입한다(실측 관례). diff --git a/docs/prompts/atcha-v2-friction-pack-prompt.md b/docs/prompts/atcha-v2-friction-pack-prompt.md index b0d5f1d..38adc05 100644 --- a/docs/prompts/atcha-v2-friction-pack-prompt.md +++ b/docs/prompts/atcha-v2-friction-pack-prompt.md @@ -166,6 +166,8 @@ iOS 26 시뮬레이터(Debug/DEV)에서 에이전트가 직접 수행하고 단 **실기기 잔여**: 엣지 스와이프 백·셀 스와이프 삭제의 실제 제스처 감각(자동화 불가 판명 시). restricted(스크린타임 제약) 실측. 전역 위치 서비스 OFF 실측(설정 조작 자동화 불가 시). 사일런트 푸시 실수신(기존 항상-잔여 항목 — 이 Phase 무관 승계). +> **검수 결과 기록 (2026-08-24 실측)**: Mac 화면 잠금으로 AX 조작이 전면 불가한 상황에서 [규약의 잠금 시 대체 경로](atcha-v2-auto-verification.md)(XCUITest 하니스)로 ①~⑧ 전 시나리오 자동 검수 완료 — **스와이프 백(엣지 드래그)·셀 스와이프 삭제 제스처 자동화가 XCUITest로 성립**해 ④·⑦의 불가 시 분기가 필요 없었다. 검수 중 발견·수정 1건: 타이핑 중 빈 상태 문구가 키보드에 가림 → 빈 상태·스피너를 `keyboardLayoutGuide` 위 가시 영역 중앙으로 이동. 실기기 잔여로 남은 것은 restricted(스크린타임)·전역 위치 OFF 실측(설정 앱 조작 미시도 — `classify` 매핑은 AtchaV2Tests 담보)과 제스처 실감각뿐. + --- ## 진행 프로토콜 From 620ba049c3a6f7e53690a546b3103e24de4d80d8 Mon Sep 17 00:00:00 2001 From: AppGoni Date: Mon, 24 Aug 2026 01:32:02 +0900 Subject: [PATCH 11/14] =?UTF-8?q?docs:=20AtchaV2=20Phase=2018=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20=ED=94=84=EB=A1=AC=ED=94=84=ED=8A=B8=20=E2=80=94=20?= =?UTF-8?q?=EC=B5=9C=EA=B7=BC=20=EA=B2=BD=EB=A1=9C=20=EC=9B=90=ED=83=AD=20?= =?UTF-8?q?=EC=B9=A9=20(3=ED=83=AD=E2=86=921=ED=83=AD,=20=EC=B5=9C?= =?UTF-8?q?=EA=B7=BC=20=EA=B2=80=EC=83=89=20=ED=91=9C=EB=A9=B4=20=ED=99=95?= =?UTF-8?q?=EC=9E=A5,=20=EC=9E=90=EB=8F=99=20=EA=B2=80=EC=88=98=20?= =?UTF-8?q?=EA=B7=9C=EC=95=BD=20=EA=B8=B0=EC=A4=80)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- docs/prompts/atcha-v2-one-tap-chip-prompt.md | 149 +++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 docs/prompts/atcha-v2-one-tap-chip-prompt.md diff --git a/docs/prompts/atcha-v2-one-tap-chip-prompt.md b/docs/prompts/atcha-v2-one-tap-chip-prompt.md new file mode 100644 index 0000000..4448c40 --- /dev/null +++ b/docs/prompts/atcha-v2-one-tap-chip-prompt.md @@ -0,0 +1,149 @@ +# AtchaV2 최근 경로 원탭 칩 구현 프롬프트 — 홈 원탭 재검색 (3탭 → 1탭) + +> **사용법**: 이 문서 전체를 Claude Code에 컨텍스트로 전달하고 `"Phase 18을 진행해"`라고 지시한다. +> 실행 에이전트는 [마스터 프롬프트](atcha-v2-master-prompt.md)의 **진행 프로토콜·공통 규칙·공통 acceptance를 그대로 상속**하며, 한 번에 한 Phase만 수행한다. +> 갭 분석·우선순위 정본은 [Post-12 로드맵](../planning/atcha-v2-post12-roadmap.md)의 "Phase 18 — 최근 경로 원탭 칩" 절. 충돌 시 **CLAUDE.md > 마스터 프롬프트 > [LA 프롬프트](atcha-v2-live-activity-prompt.md) > [세션 수명주기 프롬프트](atcha-v2-session-lifecycle-prompt.md) > [인지 채널 방어선 프롬프트](atcha-v2-channel-defense-prompt.md) > [갱신 신뢰성 프롬프트](atcha-v2-refresh-reliability-prompt.md) > [마찰 팩 프롬프트](atcha-v2-friction-pack-prompt.md) > 이 문서** 순. +> **검수는 사람 검수가 아니라 [자동 검수 규약](atcha-v2-auto-verification.md)을 따른다** — 실행 에이전트가 computer use로 직접 수행·증적 보고하고, 실기기 잔여 항목만 사용자에게 이관한다. +> 작성일: 2026-08-24. + +--- + +## Goal (최상위) + +**"간편 그 자체"를 반복 사용자에게 체감시킨다 — 어제 검색한 그 경로를 오늘은 한 탭으로.** 3탭(홈 필드 탭 → 최근 검색 행 탭 → 결과 경로 탭)이 1탭(홈 칩 탭)이 된다. + +현재 홈은 매 방문이 백지에서 시작한다 — 최근 검색이 로컬에 저장돼 있는데도(Phase 2) 그 데이터가 닿는 표면은 검색 화면의 목록뿐이라, 매일 같은 경로를 확인하는 핵심 사용자(심야 귀가 반복)도 매번 검색 화면을 왕복해야 한다. 이 문서는 홈 검색 필드 아래에 **마지막 도착지 칩 1개**("→ 신림동")를 놓고, 탭 시 **현재 위치 기준 즉시 재검색 → 결과 카드를 홈에 바로 표출**한다(검색 화면 생략). 이것은 **"최근 검색만, 즐겨찾기 없음" 확정 결정과 충돌하지 않는 표면 확장**이다 — 별도 저장·관리 UI가 없고, 데이터 원천은 기존 `RecentSearchRepository` 하나뿐이다. **알람 자동 등록은 하지 않는다** — 칩의 종착은 카드 표출까지고, 등록은 명시적 버튼 탭만. Phase 번호는 마찰 팩(17)에 이어 **18**. + +원탭 칩의 완성 상태 (이 문서가 만드는 구조): + +``` +홈 + 출발지/도착지 필드 + [→ 신림동] ◄── 최근 검색 최신 1건 (RecentSearchesUseCase.fetch()[0]) + │ 경로 선택 시 도착지를 save로 승격(중복 최신 갱신 재사용) + └─ 탭 ──► 현재 위치 조회 ──► SearchLastRoutesUseCase(start: 현재 위치, end: 칩 도착지) + │ │ + │ 실패 ├─ available → featured(0번) 카드 즉시 표출 + ▼ │ (routeSelected 수렴 — 검색 복귀와 같은 상태 의미) + 기존 위치 토스트 ├─ serviceEnded/noRoute/실패 → 토스트 (카드 무변경) + 3분기 재사용 └─ 알람 등록 없음 — "알람 등록하기" 버튼이 다음 탭 +``` + +확정된 제품 결정사항 (변경하려면 사용자에게 먼저 물을 것 — [로드맵](../planning/atcha-v2-post12-roadmap.md) 2026-08-23 확정 + 이 문서 2026-08-24 구체화): + +| 항목 | 결정 | +|---|---| +| 칩 데이터 원천 | **`RecentSearchesUseCase.fetch()`의 최신 1건**(기존 레포 정책: 최신순·중복 최신 갱신·10개 제한 — 소비만 하고 정책 무변경). 칩 전용 저장 키·스냅샷 확장·별도 영속화 **금지** — "최근 검색의 표면 확장" 정의를 코드로 지킨다 | +| 도착지 승격 | `routeSelected(_:arrival:)`가 도착지를 `save`로 **승격**(기존 "중복 시 최신 갱신" 재사용 — 새 저장 의미 없음). 출발지를 나중에 확정한 경우에도 칩 = "마지막으로 경로를 확정한 도착지"가 되도록 하는 최소 수단이다. 칩 탭 성공도 같은 경로로 수렴하므로 멱등 재저장이다 | +| 칩 라벨·개수 | `"→ {도착지명}"` **1개만**. N개 목록·삭제 액세서리·관리 UI 금지(그건 즐겨찾기다 — 반대 확정). 최근 검색 0건이면 칩 자체가 없다 | +| 칩 위치 | 도착지 필드 행 아래, 경로 카드 위 — leading 정렬(스택 전폭 늘림 금지) | +| 칩 갱신 시점 | ① `viewDidLoad` ② `viewWillAppear`(검색 화면을 다녀온 뒤의 삭제 반영 — 승격 save 진행 중이면 no-op, 승격 파이프라인이 끝나며 최신을 반영한다) ③ `routeSelected` 직접 세팅(fetch 대기 없이 즉시 정합) | +| 탭 플로우 | 현재 위치 조회(`GetCurrentLocationUseCase` — 역지오코딩 불필요, 좌표만) → `SearchLastRoutesUseCase.execute(start: 현재 위치, end: 칩 도착지)` → `.available`의 **featured(0번, 가장 늦은 차)**를 `routeSelected(_:arrival:)`로 수렴 — 카드·arrivalText·배너 무효화·버튼 계산이 검색 복귀와 완전히 같은 의미다. 대안 경로 표출은 풀 검색 화면의 몫(칩은 featured 원탭 전용) | +| 실패 표면 | **전부 토스트, 카드·필드 무변경**(홈에 카드 외 빈 상태 표면을 새로 만들지 않는다). `LocationError` 3분기는 기존 토스트 재사용(denied/전역 OFF/restricted — Phase 17 문구·액션 그대로), `unavailable`·기타 위치 실패 → "현재 위치를 확인하지 못했어요. 잠시 후 다시 시도해 주세요", `serviceEnded` → "오늘 막차가 끊겼어요", `noRoute` → "대중교통 경로를 찾지 못했어요"(검색 DSEmptyState 제목과 동일 표기 — 화면 간 어휘 통일), 경로 검색 throw → "막차를 찾지 못했어요. 다시 시도해 주세요". 신규 4건 전부 액션 버튼 없음 | +| 재진입 가드 | `State.isChipBusy` — 진행 중 칩 비활성(더블 탭 1회 실행). 알람 busy와는 독립(검색 복귀 경로와 같은 노출 수준 유지 — 추가 가드 금지) | +| 알람 자동 등록 금지 | 칩 탭 경로에서 `RegisterAlarmUseCase` 호출 **0회** — 테스트가 직접 검증한다. 카드 표출 후 "알람 등록하기" 버튼이 명시적 다음 탭이다 | +| DSChip 신설 | `DSButton`은 title이 init 고정이라(홈의 버튼 2개 우회가 그 한계의 기록) 동적 도착지명에 부적합 — **`DSChip`(UIButton 서브클래스, `setText(_:)` 갱신 가능)** 신설. height 32 + `DSTypography.label2` + cornerRadius `DSRadius.lg`(= 높이 절반, pill) + secondary 계열 색 매핑(bg `Fill.elevated`/text `Text.primary`, disabled `Fill.surface`/`Text.disabled`) — DSButton의 configuration·eager 컬러 적용 패턴 준수. 갤러리(ComponentDemos) 데모 1행 추가 | +| DEV 검수 훅 | **신규 0건** — 기존 재료로 전 시나리오가 성립한다: 데모 장소 선택 → 최근 저장(칩 생성), "경로없음" 데모 장소(Phase 17 훅) → 칩 serviceEnded 재현, `simctl location set` → 현재 위치 주입. `DevDemoFallbacks` 무변경 | + +--- + +## 이 문서가 다시 정의하지 않는 것 (중복 금지) + +아래는 기존 Phase 산출물이다. **계약을 바꾸지 않고 명시된 지점만 확장한다.** 이 목록의 계약을 깨고 싶어지면 멈추고 사용자에게 물을 것. + +| 산출물 | 소속 | 이 문서에서의 취급 | +|---|---|---| +| 검색 화면 전부 (상태 머신·빈 상태·didShow 정리·스와이프·내일 라벨) | Phase 5·17 | **SearchFeature 소스 변경 0.** 칩은 검색 화면을 생략하는 별도 진입로다 | +| `RecentSearchRepositoryImpl` 정책 (최신순·중복 최신 갱신·10개 제한) | Phase 2 | 불변 — 칩은 소비자일 뿐. 승격 저장도 기존 save 의미(중복 갱신)를 그대로 쓴다 | +| `routeSelected(_:arrival:)`의 상태 의미 (카드·arrivalText·배너 무효화·버튼 계산) | Phase 6~17 | 불변 — 칩 성공 경로가 **이 한 지점으로 수렴**한다(칩 전용 상태 전이 신설 금지). 승격 저장 한 줄이 얹힐 뿐 | +| `DefaultSearchLastRoutesUseCase` 정규화 (빈 목록 = serviceEnded 가정, 미확정 #3 TODO) | Phase 1 | 불변 — 칩은 정규화 결과의 소비자다. responseCode 매핑 추가 금지 | +| 위치 실패 3분기 (`LocationError` 세분화 + ToastEvent 3종 + 문구·액션) | Phase 17 | 불변 — 칩 탭의 위치 실패가 **같은 이벤트를 재사용**한다(문구 분기 중복 신설 금지) | +| `AlarmSyncService` 판정·폴백·만료 / LA·알람·세션 수명주기 / 스탬프·pull-to-refresh | Phase 8~16 | **무변경.** 이 Phase는 알람 경로를 건드리지 않는다 — 자동 등록 금지가 그 경계다 | +| Interface 공개 계약 (`HomeCoordinatorBuildable`·`SearchCoordinatorBuildable`·`SearchEntryField`) | Phase 5~17 | **변경 0** — 칩은 홈 내부 표면이라 Interface에 닿지 않는다 | +| DEV 데모 폴백·변경 시뮬레이터·검수 훅 3건 | Phase 7~17 | **무변경** — 결정사항대로 신규 훅 없이 기존 재료를 조합한다 | +| 서버 계약 전체 | 마스터 공통 규칙 | **서버 변경 0. Domain 변경 0** — 필요한 UseCase(`SearchLastRoutesUseCase`·`RecentSearchesUseCase`)는 Phase 1·2 산출물 그대로다 | + +## 전제 조건 + +1. **Phase 17 완료가 전제** (`feat/v2-phase17-friction-pack` 기준). 이 문서 내부의 병렬 없음 — Phase 18 단일. 작업 브랜치는 Phase 17 완료 커밋 위 `feat/v2-phase18-one-tap-chip`(스택 PR 관례 — 커밋 전 브랜치 확인). +2. 서버 트랙(로드맵 S1~S4)과 **완전 독립** — 미확정 입력을 새로 요구하지 않는다. 검수는 [자동 검수 규약](atcha-v2-auto-verification.md)에 따라 DEV 데모 폴백을 재료로 에이전트가 직접 수행한다. +3. 현재 위치 검수 재료는 **`xcrun simctl location booted set ,`**(헤드리스 좌표 주입)으로 확보한다. Mac 화면 잠금 시에는 규약의 대체 경로(XCUITest 하니스)를 그대로 상속한다 — 칩 탭·타이핑·권한 알럿 전부 그 경로로 성립한다(2026-08-24 실측 승계). + +--- + +## Phase 18 — 최근 경로 원탭 칩 + +### Goal +반복 사용자의 재검색이 홈에서 끝난다 — 마지막 도착지가 칩으로 홈에 상주하고(최근 검색의 표면 확장), 탭 한 번에 현재 위치 기준 막차가 카드로 표출되며(검색 화면 생략), 알람 등록은 여전히 명시적 버튼 탭만이 수행한다(자동 등록 금지). + +### Requirements + +- **DesignSystem — `DSChip` 신설**: + ```swift + /// 컴팩트 pill 칩 — 동적 텍스트(setText) 지원이 DSButton(title init 고정)과의 차이다. + public final class DSChip: UIButton { + public init() + public func setText(_ text: String) + } + ``` + 결정사항의 시각 스펙(height 32·label2·`DSRadius.lg` pill·secondary 계열 색·disabled 상태)과 DSButton의 configuration 패턴(eager 컬러 적용 + `configurationUpdateHandler` — 호스트 없는 테스트에서도 초기 구성이 완전해야 한다)을 따른다. `DSChipTests`(기존 DS 테스트 관례 — 초기 구성·setText 반영·disabled 색) + `ComponentDemos` 갤러리 데모 1행. +- **HomeFeature — 칩 상태·탭 플로우·승격 저장**: + - `HomeViewModel`: `init`에 `searchLastRoutesUseCase: any SearchLastRoutesUseCase`·`recentSearchesUseCase: any RecentSearchesUseCase` 주입 추가. `State`에 `recentRouteChipText: String?`(nil = 칩 숨김)·`isChipBusy: Bool = false` 추가, 원본 `chipPlace: Place?`는 private 보관(표시는 문자열, 검색은 Place — Entity 뷰 노출 금지 관례). Task 3개 신설·보관·deinit cancel: `chipTask`(fetch), `chipSaveTask`(승격 저장 — fetch류가 저장을 cancel하면 안 되므로 분리, 검색 VM `saveTask` 선례), `chipSearchTask`(원탭 재검색). + - `refreshChip()` (private): `chipSaveTask` 진행 중이면 no-op → `recentSearchesUseCase.fetch()` 최신 1건으로 `chipPlace`·`recentRouteChipText`(`"→ {name}"`) 갱신, 0건이면 nil. `viewDidLoad()`와 신설 `viewWillAppear()`가 호출한다. + - `routeSelected(_:arrival:)` 확장: `chipPlace = arrival` + 칩 텍스트 직접 세팅(즉시 정합) + `chipSaveTask`로 `save(arrival)` 승격(완료 시 task nil 리셋 — `refreshChip`의 no-op 가드 해제 지점). 기존 카드·arrivalText·배너·버튼 전이는 무변경. + - `chipTapped()`: `chipPlace` 존재 ∧ `!isChipBusy` 가드 → `isChipBusy = true` → `chipSearchTask`에서 현재 위치 조회 → 재검색 → 결과 분기(결정사항 표). 성공(`.available` 비어 있지 않음)은 `routeSelected(routes[0], arrival: chipPlace)` 수렴, 빈 `available`은 `noRoute` 취급(검색 VM의 방어 선례). 종료 시 `isChipBusy = false`(성공·실패 공통). `[weak self]` + `Task.isCancelled` 가드 관례 준수. + - `ToastEvent`에 4건 추가: `chipLocationUnavailable`·`chipSearchFailed`·`chipServiceEnded`·`chipNoRoute`. 위치 실패의 denied/전역 OFF/restricted는 **기존 3종 이벤트를 그대로 재발화**한다(분기 로직은 `loadCurrentLocation`의 catch와 같은 매핑 — 문구·액션 중복 신설 금지). + - `HomeViewController`: `viewWillAppear`에서 `viewModel.viewWillAppear()` 호출 추가. 도착지 필드 행 아래에 칩 행(래퍼 UIView + `DSChip` leading 고정 — 스택 전폭 늘림 방지) 삽입, `render`가 `recentRouteChipText` nil ↔ 행 숨김·`setText` 반영·`isChipBusy` ↔ `isEnabled` 반영. 칩 액션 → `chipTapped()`. 신규 토스트 4건 매핑(전부 액션 없음, 문구는 결정사항 표). + - `HomeDIContainer`: init에 UseCase 2건 추가(파괴적 변경 — 콜사이트는 `AppDIContainer`·Home Example뿐, 전부 따라간다) + `makeHomeViewController` 주입. +- **App — 조합 루트 공유 배선 (이 Phase의 App 변경은 이것뿐)**: + - `AppDIContainer.makeHomeDIContainer`: `DefaultSearchLastRoutesUseCase`·`DefaultRecentSearchesUseCase`를 지역 상수로 1회 생성해 **Search·Home 컨테이너에 같은 인스턴스를 공유**한다(같은 저장소를 봐야 검색의 저장·삭제가 칩에 그대로 비친다 — 기존 `recentSearchRepository` 1회 생성과 같은 이유). +- **Example — Home 스텁 추종**: `PreviewRecentSearchesUseCase`(canned 1건 — `makeCannedArrival()` 재사용, 칩 즉시 표출)·`PreviewSearchLastRoutesUseCase`(canned 경로 1건 반환 — 칩 탭 시연 성립) 신설·주입. +- **테스트 (Swift Testing — 스텁·주입, 실 Date()·실 UserDefaults 금지)**: + - `HomeFeatureTests`: ① 최근 1건 이상 → `viewDidLoad` 후 칩 `"→ {name}"` / 0건 → nil ② `routeSelected` → 칩 즉시 갱신 + 승격 save 호출 기록 검증 ③ `chipTapped` 성공 → 카드(featured)·arrivalText·`alarmButton == .register`·배너 nil + busy 해제 + **`RegisterAlarmUseCase` 호출 0회(자동 등록 금지 직접 검증)** ④ 위치 실패 4분기(denied·전역 OFF·restricted → 기존 토스트 3종 / unavailable → `chipLocationUnavailable`) + 카드 무변경 ⑤ `serviceEnded` → `chipServiceEnded` / `noRoute`·빈 `available` → `chipNoRoute` / throw → `chipSearchFailed`, 전부 카드 무변경 + busy 해제 ⑥ 더블 탭 → 재검색 1회(busy 가드) ⑦ `viewWillAppear` 재조회 — 삭제 반영(칩 nil 전환)·승격 save 진행 중 no-op ⑧ 기존 배너·스탬프·복원 테스트 무회귀. + - `DesignSystemTests`: `DSChipTests` (위 DS 절). + +### Constraints +- **즐겨찾기 선취 금지**: 칩 데이터의 유일한 원천은 `RecentSearchRepository` — 칩 전용 저장 키·별도 영속화·관리 UI(삭제·고정·다중) 금지. `AlarmSessionSnapshot` 확장 금지(재실행 복원 arrivalText placeholder 수용은 Phase 17 결정 그대로 — 칩은 그것과 별개 표면으로 공존한다). +- **알람 자동 등록 금지**: 칩 탭 경로에서 `RegisterAlarmUseCase`·`AlarmScheduler`에 닿는 코드 금지. 밤 시간대 자동 재검색·제안 카드([제품 결정 트랙](../planning/atcha-v2-post12-roadmap.md) v1.1 후보)·"집" 배지 선취 금지 — 칩은 탭이라는 명시적 의사가 있을 때만 검색한다. +- **SearchFeature·Domain·AtchaData·CoreStorage 소스 변경 0.** Interface 공개 계약 변경 0. `DevDemoFallbacks` 변경 0. 매니페스트(`Project.swift`/`Workspace.swift`)·`Tuist/Package.swift`·`Package.resolved` 무변경 — 신규 타겟 없음, `tuist generate` 불필요. +- 알람·LA·sync·스냅샷 경로 무변경. 홈 pull-to-refresh·스탬프·배너·복원 회귀 금지 — 칩 성공 경로는 `routeSelected` 수렴이라 이 표면들과 같은 규칙을 자동 상속한다. +- DesignSystem 변경은 `DSChip`(+테스트·갤러리 데모)에 한정 — 기존 컴포넌트 API 파괴적 변경 금지. +- 미확정 #3(serviceEnded/noRoute의 responseCode 실측) 해소 시도 금지 — 정규화 로직·TODO 불변. + +### Acceptance +공통 acceptance(Debug+Stage 빌드) + `-scheme DesignSystem test` + `-scheme HomeFeature test` + `-scheme AtchaV2 test`(조합 루트 변경 회귀) + `HomeFeatureExample` Debug 빌드(스텁 시그니처 추종 확인) + `git diff --stat`으로 SearchFeature·Domain·AtchaData·매니페스트·`Package.resolved` 무변경 확인. + +### 자동 검수 (블로킹 — [자동 검수 규약](atcha-v2-auto-verification.md)) +iOS 26 시뮬레이터(Debug/DEV)에서 에이전트가 직접 수행하고 단계별 스크린샷 증적으로 보고. 재료: DEV 데모 폴백(기존 그대로) + `simctl location set` 좌표 주입 + Phase 17 검수 훅("경로없음" 데모 장소). Mac 잠금 시 XCUITest 하니스 대체 경로 상속. +① **칩 없음 — 초기 상태**: 앱 데이터 초기화(`simctl uninstall` 후 재설치)·위치 허용으로 실행 → 홈에 칩 미표출 스크린샷 (최근 검색 0건 = 칩 없음의 직접 증명). +② **칩 생성**: 검색 진입 → 데모 장소를 도착지로 선택 → 데모 경로 선택 → 홈 복귀 → **칩 "→ {장소명}" + arrivalField 동시 표출** 스크린샷. +③ **칩 영속**: `simctl terminate` → 재실행 → 홈에 칩 유지 스크린샷 (재실행 복원 경로의 arrivalText는 placeholder 유지 — 칩과의 공존이 정상 상태다). +④ **원탭 재검색 (핵심)**: 칩 탭 → **검색 화면 진입 없이** 홈에 경로 카드 즉시 표출 — 탭 직전·직후 스크린샷 쌍으로 화면 전환 없음을 증명. 카드와 함께 "알람 등록하기" 버튼이 노출되되 **배너 없음 = 알람 미등록**(자동 등록 금지의 화면 증거) 확인. +⑤ **칩 serviceEnded**: 검색에서 "경로없음" 데모 장소를 도착지로 선택(최근 1위 갱신) → serviceEnded 화면에서 백 → 홈 칩 "→ 경로없음 (데모)" → 탭 → **"오늘 막차가 끊겼어요" 토스트 + 카드 무변경** 스크린샷. +⑥ **위치 거부 분기**: 재설치 후 위치 권한 "허용 안 함" → 검색 플로우(출발지·도착지 모두 수동)로 최근을 만든 뒤 → 칩 탭 → "위치 권한이 꺼져 있어요"+설정 이동 토스트 스크린샷 (denied 분기 — 카드 미표출). 전역 위치 OFF·restricted는 Phase 17과 동일 취급(설정 조작 성립 시에만 시도, restricted는 항상 실기기 잔여 — 매핑은 기존 테스트 담보). +⑦ **최근 삭제 정합**: 검색 진입 → 최근 검색 전부 삭제 → 백 → **홈 칩 소멸** 스크린샷 (viewWillAppear 재조회의 직접 증명). +⑧ **명시적 등록 + 회귀**: 칩 탭으로 표출된 카드에서 "알람 등록하기" AXPress(권한 알럿 처리 포함) → **배너+스탬프+카드 동시 표출** 정상(Phase 16·17 표면 회귀 없음) 스크린샷. +경로 검색 throw 폴백(`chipSearchFailed`)은 DEV 데모 폴백이 실패를 삼켜 시뮬레이터 재현이 불가하다 — 단위 테스트 ⑤로 갈음하고 그렇게 기록한다. + +**실기기 잔여**: 실기기 GPS 기반 칩 재검색 실측(시뮬 좌표 주입은 참고값). restricted(스크린타임 제약) 실측(Phase 17 승계). 사일런트 푸시 실수신(기존 항상-잔여 항목 — 이 Phase 무관 승계). + +--- + +## 진행 프로토콜 + +[마스터 프롬프트의 진행 프로토콜](atcha-v2-master-prompt.md#진행-프로토콜) 1~6을 그대로 상속한다. 추가 규칙: + +1. 이 문서는 **Phase 18 단일** — 내부 병렬 없음. Phase 17 완료 커밋 위 `feat/v2-phase18-one-tap-chip` 브랜치에서 진행한다(커밋 전 브랜치 확인). +2. ["이 문서가 다시 정의하지 않는 것"](#이-문서가-다시-정의하지-않는-것-중복-금지) 표의 계약을 바꾸고 싶어지면 멈추고 사용자에게 물을 것. +3. **[제품 결정 트랙](../planning/atcha-v2-post12-roadmap.md)의 산출물을 선취하지 않는다** — 밤 시간 자동 재검색·"집" 배지·홈 위치 기반 자동 막차는 별도 논의 후의 몫이다. +4. 검수는 [자동 검수 규약](atcha-v2-auto-verification.md)을 따른다 — "자동 검수 (블로킹)"는 에이전트가 computer use로 수행·증적 보고를 마쳐야 하고, "실기기 잔여"만 사용자에게 이관한다. **acceptance 전부 실행·보고 + 자동 검수 증적 보고 후 정지** — 다음 Phase로 진행하지 않는다. +5. 자동화 불가가 확정된 항목은 결과를 **이 문서 자동 검수 절에 기록**하고 명시된 대체 경로로 검수를 완료한다. + +## 미확정 입력 (참조) + +이 문서는 새 미확정 입력을 만들지 않는다. 관련 기존 항목의 취급: + +| # | 항목 | 이 문서에서의 취급 | +|---|---|---| +| 3 | "막차 종료"/"경로 없음"의 서버 표현 (responseCode 실측값) | **미해소 유지** — 칩은 정규화 결과(`serviceEnded`/`noRoute`)를 토스트로 표면화할 뿐이다. 검수 ⑤는 이 가정(빈 목록 = serviceEnded) 위에서 기존 훅을 재료로 쓴다 | +| 원장 전체 | [Post-12 로드맵](../planning/atcha-v2-post12-roadmap.md)의 "미확정 입력 원장" 절 참조 | | From 5f53636e1ef0dc027ff3811fddbff9a878e6d08a Mon Sep 17 00:00:00 2001 From: AppGoni Date: Mon, 24 Aug 2026 01:45:49 +0900 Subject: [PATCH 12/14] =?UTF-8?q?feat:=20AtchaV2=20Phase=2018=20=E2=80=94?= =?UTF-8?q?=20=EC=B5=9C=EA=B7=BC=20=EA=B2=BD=EB=A1=9C=20=EC=9B=90=ED=83=AD?= =?UTF-8?q?=20=EC=B9=A9=20(DSChip=20+=20=ED=99=88=20=EC=B9=A9=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=C2=B7=EC=9B=90=ED=83=AD=20=EC=9E=AC=EA=B2=80=EC=83=89?= =?UTF-8?q?=20+=20=EB=8F=84=EC=B0=A9=EC=A7=80=20=EC=8A=B9=EA=B2=A9=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5,=20=EC=95=8C=EB=9E=8C=20=EC=9E=90=EB=8F=99?= =?UTF-8?q?=20=EB=93=B1=EB=A1=9D=20=EC=97=86=EC=9D=8C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- Projects/App/Sources/AppDIContainer.swift | 13 +- .../DesignSystem/Example/ComponentDemos.swift | 15 + .../Sources/Components/DSChip.swift | 52 ++++ Projects/DesignSystem/Tests/DSChipTests.swift | 46 +++ .../Feature/Home/Example/ExampleApp.swift | 20 ++ .../Home/Sources/HomeDIContainer.swift | 10 +- .../Home/Sources/HomeViewController.swift | 41 ++- .../Feature/Home/Sources/HomeViewModel.swift | 125 ++++++++ .../Home/Tests/HomeViewModelTests.swift | 267 ++++++++++++++++++ docs/prompts/atcha-v2-one-tap-chip-prompt.md | 2 +- 10 files changed, 586 insertions(+), 5 deletions(-) create mode 100644 Projects/DesignSystem/Sources/Components/DSChip.swift create mode 100644 Projects/DesignSystem/Tests/DSChipTests.swift diff --git a/Projects/App/Sources/AppDIContainer.swift b/Projects/App/Sources/AppDIContainer.swift index 3250fe7..7574ef8 100644 --- a/Projects/App/Sources/AppDIContainer.swift +++ b/Projects/App/Sources/AppDIContainer.swift @@ -151,11 +151,17 @@ final class AppDIContainer { let locationService = CoreLocationServiceAdapter() let getCurrentLocation: any GetCurrentLocationUseCase = DefaultGetCurrentLocationUseCase(locationService: locationService) + // 원탭 칩(Phase 18) — 검색과 홈이 같은 인스턴스를 봐야 검색의 저장·삭제가 + // 칩에 그대로 비친다 (recentSearchRepository 1회 생성과 같은 이유). + let searchLastRoutes: any SearchLastRoutesUseCase = + DefaultSearchLastRoutesUseCase(repository: lastRouteRepository) + let recentSearches: any RecentSearchesUseCase = + DefaultRecentSearchesUseCase(repository: recentSearchRepository) let searchContainer = SearchDIContainer( searchPlacesUseCase: DefaultSearchPlacesUseCase(repository: placeRepository), - searchLastRoutesUseCase: DefaultSearchLastRoutesUseCase(repository: lastRouteRepository), - recentSearchesUseCase: DefaultRecentSearchesUseCase(repository: recentSearchRepository), + searchLastRoutesUseCase: searchLastRoutes, + recentSearchesUseCase: recentSearches, getCurrentLocationUseCase: getCurrentLocation ) @@ -185,6 +191,9 @@ final class AppDIContainer { getLastRouteDetailUseCase: DefaultGetLastRouteDetailUseCase( repository: lastRouteRepository ), + // 원탭 칩(Phase 18) — 검색 화면과 같은 인스턴스 공유(위 주석 참조). + searchLastRoutesUseCase: searchLastRoutes, + recentSearchesUseCase: recentSearches, searchCoordinatorBuildable: searchContainer ) } diff --git a/Projects/DesignSystem/Example/ComponentDemos.swift b/Projects/DesignSystem/Example/ComponentDemos.swift index 622769a..ffc912a 100644 --- a/Projects/DesignSystem/Example/ComponentDemos.swift +++ b/Projects/DesignSystem/Example/ComponentDemos.swift @@ -22,6 +22,21 @@ final class ButtonsDemoViewController: GalleryScreenViewController { let disabled = DSButton(title: "비활성", style: .primary) disabled.isEnabled = false contentStack.addArrangedSubview(disabled) + + addSectionTitle("DSChip") + let chip = DSChip() + chip.setText("→ 신림동") + let disabledChip = DSChip() + disabledChip.setText("→ 구로디지털단지역") + disabledChip.isEnabled = false + [chip, disabledChip].forEach { contentStack.addArrangedSubview(leadingRow($0)) } + } + + /// 칩은 자기 크기 컴포넌트 — 스택 전폭으로 늘리지 않고 leading에 붙인다(홈과 같은 배치). + private func leadingRow(_ view: UIView) -> UIStackView { + let row = UIStackView(arrangedSubviews: [view, UIView()]) + row.axis = .horizontal + return row } } diff --git a/Projects/DesignSystem/Sources/Components/DSChip.swift b/Projects/DesignSystem/Sources/Components/DSChip.swift new file mode 100644 index 0000000..caf63c3 --- /dev/null +++ b/Projects/DesignSystem/Sources/Components/DSChip.swift @@ -0,0 +1,52 @@ +import UIKit + +/// 컴팩트 pill 칩 — 최근 경로 원탭(Phase 18)처럼 내용이 데이터를 따라 바뀌는 표면용. +/// DSButton은 title이 init 고정이라(홈의 등록/해제 버튼 2개 우회가 그 기록) 동적 +/// 텍스트 자리에 부적합하다 — setText 갱신 가능이 이 컴포넌트의 존재 이유다. +public final class DSChip: UIButton { + private static let height: CGFloat = 32 + + public init() { + super.init(frame: .zero) + + var configuration = UIButton.Configuration.filled() + // 높이 절반 = pill. DSRadius.lg(16)가 그 값과 일치한다. + configuration.background.cornerRadius = DSRadius.lg + configuration.cornerStyle = .fixed + configuration.contentInsets = .init( + top: 0, leading: DSSpacing.md, bottom: 0, trailing: DSSpacing.md + ) + // Colors are applied eagerly so the initial configuration is complete + // without waiting for an update pass (which never runs in hostless + // tests); the update handler keeps them in sync with state changes. + Self.applyColors(&configuration, isEnabled: true) + self.configuration = configuration + + configurationUpdateHandler = { button in + guard var configuration = button.configuration else { return } + Self.applyColors(&configuration, isEnabled: button.isEnabled) + button.configuration = configuration + } + } + + public func setText(_ text: String) { + configuration?.attributedTitle = AttributedString( + text, attributes: AttributeContainer([.font: DSTypography.label2.font]) + ) + } + + static func applyColors(_ configuration: inout UIButton.Configuration, isEnabled: Bool) { + // secondary 계열 매핑(DSButton.secondary와 동일 척도) — 강조가 아니라 보조 진입점이다. + configuration.baseBackgroundColor = isEnabled ? DSColor.Fill.elevated : DSColor.Fill.surface + configuration.baseForegroundColor = isEnabled ? DSColor.Text.primary : DSColor.Text.disabled + } + + public override var intrinsicContentSize: CGSize { + CGSize(width: super.intrinsicContentSize.width, height: Self.height) + } + + @available(*, unavailable) + public required init?(coder: NSCoder) { + fatalError("init(coder:) is not supported") + } +} diff --git a/Projects/DesignSystem/Tests/DSChipTests.swift b/Projects/DesignSystem/Tests/DSChipTests.swift new file mode 100644 index 0000000..c98861f --- /dev/null +++ b/Projects/DesignSystem/Tests/DSChipTests.swift @@ -0,0 +1,46 @@ +@testable import DesignSystem +import Testing +import UIKit + +@MainActor +struct DSChipTests { + @Test + func setTextUpdatesTitle() { + let chip = DSChip() + chip.setText("→ 신림동") + #expect(chip.configuration?.title == "→ 신림동") + chip.setText("→ 강남역") + #expect(chip.configuration?.title == "→ 강남역") + } + + @Test + func enabledUsesSecondaryColors() { + let chip = DSChip() + let configuration = chip.configuration + #expect(configuration?.baseBackgroundColor.map { + colorsMatch($0, DSColor.Fill.elevated) + } == true) + #expect(configuration?.baseForegroundColor.map { + colorsMatch($0, DSColor.Text.primary) + } == true) + } + + @Test + func disabledAppearanceMutesColors() { + var configuration = UIButton.Configuration.filled() + DSChip.applyColors(&configuration, isEnabled: false) + #expect(configuration.baseBackgroundColor.map { + colorsMatch($0, DSColor.Fill.surface) + } == true) + #expect(configuration.baseForegroundColor.map { + colorsMatch($0, DSColor.Text.disabled) + } == true) + } + + @Test + func pillShapeIsFixedHeight() { + let chip = DSChip() + #expect(chip.intrinsicContentSize.height == 32) + #expect(chip.configuration?.background.cornerRadius == DSRadius.lg) + } +} diff --git a/Projects/Feature/Home/Example/ExampleApp.swift b/Projects/Feature/Home/Example/ExampleApp.swift index fa88555..937acf7 100644 --- a/Projects/Feature/Home/Example/ExampleApp.swift +++ b/Projects/Feature/Home/Example/ExampleApp.swift @@ -43,6 +43,8 @@ final class SceneDelegate: UIResponder, UIWindowSceneDelegate { observeAlarmChangeUseCase: PreviewObserveAlarmChangeUseCase(), requestAlarmSyncUseCase: PreviewRequestAlarmSyncUseCase(), getLastRouteDetailUseCase: PreviewGetLastRouteDetailUseCase(), + searchLastRoutesUseCase: PreviewSearchLastRoutesUseCase(), + recentSearchesUseCase: PreviewRecentSearchesUseCase(), searchCoordinatorBuildable: PreviewSearchCoordinatorBuildable() ) let coordinator = container.makeHomeCoordinator(navigationController: navigationController) @@ -116,6 +118,24 @@ struct PreviewGetLastRouteDetailUseCase: GetLastRouteDetailUseCase { } } +/// 원탭 칩 재검색 스텁(Phase 18) — canned 경로 1건을 돌려줘 칩 탭 → 카드 시연이 성립한다. +struct PreviewSearchLastRoutesUseCase: SearchLastRoutesUseCase { + func execute(start: Coordinate, end: Coordinate) async throws -> LastRouteSearchResult { + try? await Task.sleep(for: .milliseconds(400)) + return .available([PreviewSearchCoordinator.makeCannedRoute()]) + } +} + +/// 최근 검색 스텁(Phase 18) — canned 1건으로 칩이 즉시 표출된다. save/remove는 no-op. +struct PreviewRecentSearchesUseCase: RecentSearchesUseCase { + func fetch() async throws -> [Place] { + [PreviewSearchCoordinator.makeCannedArrival()] + } + + func save(_ place: Place) async throws {} + func remove(_ place: Place) async throws {} +} + /// 검색 플로우 스텁: 화면 전환 없이 canned 경로를 즉시 반환한다. /// 실제 검색 UX 시연은 SearchFeatureExample이 담당한다. struct PreviewSearchCoordinatorBuildable: SearchCoordinatorBuildable { diff --git a/Projects/Feature/Home/Sources/HomeDIContainer.swift b/Projects/Feature/Home/Sources/HomeDIContainer.swift index 0a13b70..a465a63 100644 --- a/Projects/Feature/Home/Sources/HomeDIContainer.swift +++ b/Projects/Feature/Home/Sources/HomeDIContainer.swift @@ -16,6 +16,8 @@ public final class HomeDIContainer: HomeCoordinatorBuildable { private let observeAlarmChangeUseCase: any ObserveAlarmChangeUseCase private let requestAlarmSyncUseCase: any RequestAlarmSyncUseCase private let getLastRouteDetailUseCase: any GetLastRouteDetailUseCase + private let searchLastRoutesUseCase: any SearchLastRoutesUseCase + private let recentSearchesUseCase: any RecentSearchesUseCase private let searchCoordinatorBuildable: any SearchCoordinatorBuildable public init( @@ -27,6 +29,8 @@ public final class HomeDIContainer: HomeCoordinatorBuildable { observeAlarmChangeUseCase: any ObserveAlarmChangeUseCase, requestAlarmSyncUseCase: any RequestAlarmSyncUseCase, getLastRouteDetailUseCase: any GetLastRouteDetailUseCase, + searchLastRoutesUseCase: any SearchLastRoutesUseCase, + recentSearchesUseCase: any RecentSearchesUseCase, searchCoordinatorBuildable: any SearchCoordinatorBuildable ) { self.getCurrentLocationUseCase = getCurrentLocationUseCase @@ -37,6 +41,8 @@ public final class HomeDIContainer: HomeCoordinatorBuildable { self.observeAlarmChangeUseCase = observeAlarmChangeUseCase self.requestAlarmSyncUseCase = requestAlarmSyncUseCase self.getLastRouteDetailUseCase = getLastRouteDetailUseCase + self.searchLastRoutesUseCase = searchLastRoutesUseCase + self.recentSearchesUseCase = recentSearchesUseCase self.searchCoordinatorBuildable = searchCoordinatorBuildable } @@ -58,7 +64,9 @@ public final class HomeDIContainer: HomeCoordinatorBuildable { observeAlarmUseCase: observeAlarmUseCase, observeAlarmChangeUseCase: observeAlarmChangeUseCase, requestAlarmSyncUseCase: requestAlarmSyncUseCase, - getLastRouteDetailUseCase: getLastRouteDetailUseCase + getLastRouteDetailUseCase: getLastRouteDetailUseCase, + searchLastRoutesUseCase: searchLastRoutesUseCase, + recentSearchesUseCase: recentSearchesUseCase ) viewModel.onSearchRequested = onSearchRequested return HomeViewController(viewModel: viewModel) diff --git a/Projects/Feature/Home/Sources/HomeViewController.swift b/Projects/Feature/Home/Sources/HomeViewController.swift index 4b14de7..4266d3c 100644 --- a/Projects/Feature/Home/Sources/HomeViewController.swift +++ b/Projects/Feature/Home/Sources/HomeViewController.swift @@ -25,6 +25,18 @@ final class HomeViewController: UIViewController { private lazy var arrivalRow = makeFieldRow( icon: DSIcon.place24, field: arrivalField, entry: .arrival ) + // 최근 경로 원탭 칩(Phase 18) — 자기 크기 컴포넌트라 스택 전폭으로 늘리지 않고 + // 래퍼의 leading에 붙인다. 표시·활성은 render가 State로 반영한다. + private let recentRouteChip = DSChip() + private lazy var chipRow: UIView = { + let row = UIView() + row.addSubview(recentRouteChip) + recentRouteChip.snp.makeConstraints { make in + make.leading.top.bottom.equalToSuperview() + make.trailing.lessThanOrEqualToSuperview() + } + return row + }() private let routeCard = DSRouteCard() private let registerButton = DSButton(title: "알람 등록하기") // DSButton은 title이 init 고정이라 토글은 버튼 2개의 표시 전환으로 구현한다. @@ -79,6 +91,8 @@ final class HomeViewController: UIViewController { super.viewWillAppear(animated) // 홈은 자체 타이틀을 그린다 — 시스템 내비바 숨김(Search와 동일 규약). navigationController?.setNavigationBarHidden(true, animated: animated) + // 검색 화면을 다녀오며 바뀐 최근 검색(삭제 포함)을 칩에 반영한다(Phase 18). + viewModel.viewWillAppear() } // MARK: - UI @@ -106,18 +120,25 @@ final class HomeViewController: UIViewController { make.width.equalTo(scrollView.frameLayoutGuide).offset(-DSSpacing.md * 2) } - [titleLabel, banner, departureRow, arrivalRow, routeCard, registerButton, cancelButton] + [titleLabel, banner, departureRow, arrivalRow, chipRow, routeCard, registerButton, cancelButton] .forEach(contentStack.addArrangedSubview) contentStack.addArrangedSubview(makeCaptionStack()) contentStack.setCustomSpacing(DSSpacing.lg20, after: titleLabel) contentStack.setCustomSpacing(DSSpacing.sm, after: departureRow) + // 칩이 숨겨져도 필드→카드 간격이 기존(lg)과 같도록 앞뒤 모두 lg를 쓴다. contentStack.setCustomSpacing(DSSpacing.lg, after: arrivalRow) + contentStack.setCustomSpacing(DSSpacing.lg, after: chipRow) banner.isHidden = true + chipRow.isHidden = true routeCard.isHidden = true registerButton.isHidden = true cancelButton.isHidden = true + recentRouteChip.addAction( + UIAction { [weak self] _ in self?.viewModel.chipTapped() }, + for: .touchUpInside + ) registerButton.addAction( UIAction { [weak self] _ in self?.viewModel.registerAlarmTapped() }, for: .touchUpInside @@ -221,6 +242,15 @@ final class HomeViewController: UIViewController { // 도착지 필드 = 선택 경로의 도착지명(Phase 17). nil이면 placeholder가 유도한다. arrivalField.setText(state.arrivalText ?? "") + // 최근 경로 원탭 칩(Phase 18) — nil이면 숨김, 재검색 진행 중엔 비활성(더블 탭 방지). + if let chipText = state.recentRouteChipText { + recentRouteChip.setText(chipText) + chipRow.isHidden = false + } else { + chipRow.isHidden = true + } + recentRouteChip.isEnabled = !state.isChipBusy + if let card = state.routeCard { // 신선도 스탬프(Phase 16)는 세션 상태라 State가 따로 나른다 — 표출 시점 합성. routeCard.configure(with: card.dsContent(footnote: state.freshnessText)) @@ -277,6 +307,15 @@ final class HomeViewController: UIViewController { case .locationRestricted: // restricted는 설정으로 못 푸는 제약 — "설정으로 이동"을 안내하지 않는다(Phase 17). DSToast.show("이 기기에선 위치를 사용할 수 없어요. 출발지를 검색해 주세요", in: view) + case .chipLocationUnavailable: + DSToast.show("현재 위치를 확인하지 못했어요. 잠시 후 다시 시도해 주세요", in: view) + case .chipSearchFailed: + DSToast.show("막차를 찾지 못했어요. 다시 시도해 주세요", in: view) + case .chipServiceEnded: + // 검색 화면 빈 상태 제목과 같은 어휘(Phase 18) — 화면 간 표기 통일. + DSToast.show("오늘 막차가 끊겼어요", in: view) + case .chipNoRoute: + DSToast.show("대중교통 경로를 찾지 못했어요", in: view) case .alarmPermissionNeeded: DSToast.show( "알람 권한이 꺼져 있어요", diff --git a/Projects/Feature/Home/Sources/HomeViewModel.swift b/Projects/Feature/Home/Sources/HomeViewModel.swift index 3f68fc9..756c18b 100644 --- a/Projects/Feature/Home/Sources/HomeViewModel.swift +++ b/Projects/Feature/Home/Sources/HomeViewModel.swift @@ -33,6 +33,11 @@ final class HomeViewModel { /// 도착지 필드 표시값(Phase 17) — 선택 경로의 도착지명. nil이면 placeholder. /// 재실행 복원 경로는 도착지 명칭 원천이 없어 채우지 않는다(결정사항 — 수용). var arrivalText: String? + /// 최근 경로 원탭 칩(Phase 18) — 최근 검색 최신 1건의 "→ {도착지명}". nil이면 숨김. + /// 원천은 RecentSearchRepository 하나뿐(최근 검색의 표면 확장 — 즐겨찾기 아님). + var recentRouteChipText: String? + /// 칩 재검색 진행 중(Phase 18) — 칩 비활성(더블 탭 방지). 알람 busy와 독립이다. + var isChipBusy = false var routeCard: RouteCardViewData? var banner: BannerViewData? var isAlarmBusy = false @@ -50,6 +55,14 @@ final class HomeViewModel { case locationServicesDisabled /// 스크린타임·MDM 제약(Phase 17) — 설정으로 못 푼다. "설정으로 이동" 안내 금지. case locationRestricted + /// 칩 원탭 재검색(Phase 18)의 위치 일시 실패 — 명시적 탭에 무음은 없다. + case chipLocationUnavailable + /// 칩 재검색 자체 실패(Phase 18) — 재시도 유도. 카드·필드는 무변경이 원칙. + case chipSearchFailed + /// 칩 재검색 결과 오늘 막차 종료(Phase 18) — 검색 빈 상태 제목과 같은 어휘. + case chipServiceEnded + /// 칩 재검색 결과 경로 없음(Phase 18). + case chipNoRoute case alarmPermissionNeeded case alarmRegisterFailed case alarmCancelFailed @@ -91,10 +104,14 @@ final class HomeViewModel { private let observeAlarmChangeUseCase: any ObserveAlarmChangeUseCase private let requestAlarmSyncUseCase: any RequestAlarmSyncUseCase private let getLastRouteDetailUseCase: any GetLastRouteDetailUseCase + private let searchLastRoutesUseCase: any SearchLastRoutesUseCase + private let recentSearchesUseCase: any RecentSearchesUseCase private let now: @Sendable () -> Date private let bannerTickInterval: Duration private var selectedRoute: LastRoute? + /// 칩의 원본 도착지(Phase 18) — 표시는 문자열(State), 재검색은 이 Place가 한다. + private var chipPlace: Place? /// 서버에 알람이 등록된 경로 id — 해제 버튼·동기화 복원의 기준. private var registeredRouteId: String? /// 세션 값이 마지막으로 서버로 확인된 시각(Phase 16) — 스트림의 checkedAt·등록 @@ -107,6 +124,10 @@ final class HomeViewModel { private var bannerTask: Task? private var restoreCardTask: Task? private var refreshTask: Task? + private var chipTask: Task? + // 승격 저장은 재조회와 분리 보관 — 재조회가 저장을 cancel하면 안 된다(검색 VM saveTask 선례). + private var chipSaveTask: Task? + private var chipSearchTask: Task? init( getCurrentLocationUseCase: any GetCurrentLocationUseCase, @@ -117,6 +138,8 @@ final class HomeViewModel { observeAlarmChangeUseCase: any ObserveAlarmChangeUseCase, requestAlarmSyncUseCase: any RequestAlarmSyncUseCase, getLastRouteDetailUseCase: any GetLastRouteDetailUseCase, + searchLastRoutesUseCase: any SearchLastRoutesUseCase, + recentSearchesUseCase: any RecentSearchesUseCase, now: @escaping @Sendable () -> Date = { Date() }, bannerTickInterval: Duration = .seconds(60) ) { @@ -128,6 +151,8 @@ final class HomeViewModel { self.observeAlarmChangeUseCase = observeAlarmChangeUseCase self.requestAlarmSyncUseCase = requestAlarmSyncUseCase self.getLastRouteDetailUseCase = getLastRouteDetailUseCase + self.searchLastRoutesUseCase = searchLastRoutesUseCase + self.recentSearchesUseCase = recentSearchesUseCase self.now = now self.bannerTickInterval = bannerTickInterval } @@ -140,6 +165,9 @@ final class HomeViewModel { bannerTask?.cancel() restoreCardTask?.cancel() refreshTask?.cancel() + chipTask?.cancel() + chipSaveTask?.cancel() + chipSearchTask?.cancel() } // MARK: - 입력 @@ -148,6 +176,12 @@ final class HomeViewModel { loadCurrentLocation() observeAlarmUpdates() observeAlarmChanges() + refreshChip() + } + + /// 홈 재노출(Phase 18) — 검색 화면을 다녀오며 바뀐 최근 검색(삭제 포함)을 칩에 반영한다. + func viewWillAppear() { + refreshChip() } /// 설정을 다녀온 뒤(didBecomeActive) 위치 권한 회복을 재확인한다(Phase 15). @@ -192,10 +226,13 @@ final class HomeViewModel { func routeSelected(_ route: LastRoute, arrival: Place) { selectedRoute = route + chipPlace = arrival var newState = state newState.routeCard = RouteCardViewData(entity: route, now: now()) // 도착지 필드를 선택 경로의 도착지명과 정합시킨다(Phase 17) — placeholder 공존 해소. newState.arrivalText = arrival.name + // 칩도 즉시 정합(Phase 18) — fetch를 기다리지 않는다. 방금 확정한 도착지가 최신이다. + newState.recentRouteChipText = "→ \(arrival.name)" // 새 경로 선택 = 기존 배너는 더 이상 유효하지 않다 (재등록 전까지 숨김). newState.banner = nil newState.alarmButton = Self.alarmButtonMode( @@ -204,6 +241,64 @@ final class HomeViewModel { ) state = newState bannerTask?.cancel() + promoteChipDestination(arrival) + } + + /// 최근 경로 원탭(Phase 18) — 현재 위치 기준 즉시 재검색, 검색 화면 생략. + /// 성공은 routeSelected로 수렴한다(카드·도착지·배너 무효화·버튼이 검색 복귀와 같은 의미). + /// 알람 자동 등록은 없다 — 등록은 명시적 버튼 탭만(확정 결정). + func chipTapped() { + guard let destination = chipPlace, !state.isChipBusy else { return } + state.isChipBusy = true + chipSearchTask?.cancel() + chipSearchTask = Task { [weak self] in + defer { self?.state.isChipBusy = false } + + let start: Coordinate + do { + guard let locationUseCase = self?.getCurrentLocationUseCase else { return } + start = try await locationUseCase.execute() + } catch let error as LocationError { + guard !Task.isCancelled else { return } + // 사유별 안내는 기존 3분기 이벤트 재사용(Phase 17 문구·액션 그대로). + // 명시적 탭이라 unavailable도 무음일 수 없다 — loadCurrentLocation과의 차이. + switch error { + case .permissionDenied: self?.onToast?(.locationPermissionNeeded) + case .servicesDisabled: self?.onToast?(.locationServicesDisabled) + case .restricted: self?.onToast?(.locationRestricted) + case .unavailable: self?.onToast?(.chipLocationUnavailable) + } + return + } catch { + guard !Task.isCancelled else { return } + self?.onToast?(.chipLocationUnavailable) + return + } + + guard !Task.isCancelled, + let routesUseCase = self?.searchLastRoutesUseCase else { return } + do { + let result = try await routesUseCase.execute( + start: start, end: destination.coordinate + ) + guard !Task.isCancelled, let self else { return } + switch result { + case let .available(routes) where !routes.isEmpty: + // featured(0번 = 가장 늦은 차)만 원탭의 몫 — 대안 표출은 풀 검색 화면 담당. + self.routeSelected(routes[0], arrival: destination) + case .available: + // 정규화가 놓친 빈 목록 방어 (검색 VM 선례). + self.onToast?(.chipNoRoute) + case .serviceEnded: + self.onToast?(.chipServiceEnded) + case .noRoute: + self.onToast?(.chipNoRoute) + } + } catch { + guard !Task.isCancelled else { return } + self?.onToast?(.chipSearchFailed) + } + } } func registerAlarmTapped() { @@ -403,6 +498,36 @@ final class HomeViewModel { } } + /// 칩 재조회(Phase 18) — 최근 검색 최신 1건이 칩의 유일한 원천이다(즐겨찾기 아님). + /// 승격 저장이 진행 중이면 no-op — 저장 전의 낡은 목록으로 되돌리는 경합을 막는다 + /// (저장 완료가 가드를 풀고, 다음 재노출 재조회가 확정 목록을 반영한다). + private func refreshChip() { + guard chipSaveTask == nil else { return } + chipTask?.cancel() + chipTask = Task { [weak self] in + guard let useCase = self?.recentSearchesUseCase else { return } + // 로드 실패는 칩 없음으로 무해화한다 (검색 화면의 최근 목록과 같은 취급). + let latest = ((try? await useCase.fetch()) ?? []).first + guard !Task.isCancelled, let self else { return } + self.chipPlace = latest + self.state.recentRouteChipText = latest.map { "→ \($0.name)" } + } + } + + /// 도착지 승격(Phase 18) — 기존 save의 "중복 시 최신 갱신"을 재사용해 확정 도착지를 + /// 최근 검색 최신으로 올린다(새 저장 의미 없음 — 출발지를 나중에 확정한 경우에도 + /// 칩 = 마지막으로 경로를 확정한 도착지가 되게 하는 최소 수단이다). 칩 탭 경로의 + /// 재저장은 이미 최신 1위라 멱등이다. + private func promoteChipDestination(_ place: Place) { + chipSaveTask?.cancel() + chipSaveTask = Task { [weak self] in + guard let useCase = self?.recentSearchesUseCase else { return } + try? await useCase.save(place) + guard !Task.isCancelled else { return } + self?.chipSaveTask = nil + } + } + private func loadCurrentLocation() { locationTask?.cancel() state.departure = .loading diff --git a/Projects/Feature/Home/Tests/HomeViewModelTests.swift b/Projects/Feature/Home/Tests/HomeViewModelTests.swift index 2a4c908..c3f8533 100644 --- a/Projects/Feature/Home/Tests/HomeViewModelTests.swift +++ b/Projects/Feature/Home/Tests/HomeViewModelTests.swift @@ -53,6 +53,21 @@ private struct StubGetLastRouteDetailUseCase: GetLastRouteDetailUseCase { func execute(routeId: String) async throws -> LastRoute { try await handler(routeId) } } +private struct StubSearchLastRoutesUseCase: SearchLastRoutesUseCase { + let handler: @Sendable (Coordinate, Coordinate) async throws -> LastRouteSearchResult + func execute(start: Coordinate, end: Coordinate) async throws -> LastRouteSearchResult { + try await handler(start, end) + } +} + +private struct StubRecentSearchesUseCase: RecentSearchesUseCase { + let fetchHandler: @Sendable () async throws -> [Place] + let saveHandler: @Sendable (Place) async throws -> Void + func fetch() async throws -> [Place] { try await fetchHandler() } + func save(_ place: Place) async throws { try await saveHandler(place) } + func remove(_ place: Place) async throws {} +} + /// 테스트 도중 스텁 동작을 바꾸거나 호출 횟수를 세기 위한 가변 박스 (NowBox와 동일 패턴). private nonisolated final class ValueBox: @unchecked Sendable { private let lock = NSLock() @@ -173,6 +188,11 @@ private func makeSUT( routeDetail: @escaping @Sendable (String) async throws -> LastRoute = { _ in throw StubError() }, + searchRoutes: @escaping @Sendable (Coordinate, Coordinate) async throws -> LastRouteSearchResult = { _, _ in + throw StubError() + }, + recentFetch: @escaping @Sendable () async throws -> [Place] = { [] }, + recentSave: @escaping @Sendable (Place) async throws -> Void = { _ in }, now: @escaping @Sendable () -> Date = { fixedNow }, bannerTickInterval: Duration = .seconds(60) ) -> HomeViewModel { @@ -187,6 +207,10 @@ private func makeSUT( observeAlarmChangeUseCase: StubObserveAlarmChangeUseCase(handler: alarmChanges), requestAlarmSyncUseCase: StubRequestAlarmSyncUseCase(handler: requestSync), getLastRouteDetailUseCase: StubGetLastRouteDetailUseCase(handler: routeDetail), + searchLastRoutesUseCase: StubSearchLastRoutesUseCase(handler: searchRoutes), + recentSearchesUseCase: StubRecentSearchesUseCase( + fetchHandler: recentFetch, saveHandler: recentSave + ), now: now, bannerTickInterval: bannerTickInterval ) @@ -1225,6 +1249,249 @@ struct HomeViewModelTests { await recorder.waitUntilLast { $0.banner == nil && $0.freshnessText == nil } #expect(sut.state.routeCard?.tone == .past) } + + // MARK: - 최근 경로 원탭 칩 (Phase 18) + + @Test + func viewDidLoad_recentSearchExists_showsChipForLatest() async { + // 칩은 최근 검색 최신 1건 — 목록의 첫 항목만 표면화한다. + let sut = makeSUT(recentFetch: { [makeArrival("신림동"), makeArrival("강남역")] }) + let recorder = StateRecorder() + recorder.attach(to: sut) + + sut.viewDidLoad() + await recorder.waitUntilLast { $0.recentRouteChipText == "→ 신림동" } + + #expect(sut.state.recentRouteChipText == "→ 신림동") + } + + @Test + func viewDidLoad_noRecentSearch_hidesChip() async { + let sut = makeSUT() + let recorder = StateRecorder() + recorder.attach(to: sut) + + sut.viewDidLoad() + await recorder.waitUntilLast { $0.departure == .current(name: "강남역") } + for _ in 0..<20 { await Task.yield() } + + #expect(sut.state.recentRouteChipText == nil) + } + + @Test + func routeSelected_updatesChipImmediatelyAndPromotesArrival() async { + // 칩은 fetch를 기다리지 않고 즉시 정합하고, 도착지는 save로 승격된다(중복 최신 갱신 재사용). + let saved = ValueBox([String]()) + let sut = makeSUT(recentSave: { place in saved.update { $0 + [place.name] } }) + let recorder = StateRecorder() + recorder.attach(to: sut) + + sut.routeSelected( + makeRoute(id: "r1", departure: fixedNow.addingTimeInterval(3600)), + arrival: makeArrival("당산역") + ) + + #expect(sut.state.recentRouteChipText == "→ 당산역") + while saved.get().isEmpty { await Task.yield() } + #expect(saved.get() == ["당산역"]) + } + + @Test + func chipTapped_success_showsFeaturedCardWithoutRegisteringAlarm() async { + // 원탭 성공 = routeSelected 수렴 — 카드는 featured(0번), 알람 등록은 0회여야 한다. + let registerCalls = ValueBox(0) + let searched = ValueBox([Coordinate]()) + let destination = makeArrival("신림동") + let featured = makeRoute(id: "featured", departure: fixedNow.addingTimeInterval(3600)) + let alternative = makeRoute(id: "alt", departure: fixedNow.addingTimeInterval(1800)) + let sut = makeSUT( + register: { _ in registerCalls.update { $0 + 1 } }, + searchRoutes: { start, end in + searched.update { $0 + [start, end] } + return .available([featured, alternative]) + }, + recentFetch: { [destination] } + ) + let recorder = StateRecorder() + recorder.attach(to: sut) + sut.viewDidLoad() + await recorder.waitUntilLast { $0.recentRouteChipText == "→ 신림동" } + + sut.chipTapped() + await recorder.waitUntilLast { $0.routeCard != nil && !$0.isChipBusy } + + // 재검색 좌표: start = 현재 위치(스텁), end = 칩 도착지. + #expect(searched.get() == [ + Coordinate(latitude: 37.4979, longitude: 127.0276), destination.coordinate, + ]) + #expect(sut.state.routeCard == RouteCardViewData(entity: featured, now: fixedNow)) + #expect(sut.state.arrivalText == "신림동") + #expect(sut.state.alarmButton == .register) + #expect(sut.state.banner == nil) + // 알람 자동 등록 금지(확정 결정)의 직접 검증 — 등록은 명시적 버튼 탭만. + #expect(registerCalls.get() == 0) + #expect(recorder.toasts.isEmpty) + } + + @Test + func chipTapped_locationDenied_reusesPermissionToastAndShowsNoCard() async { + // 위치 실패 안내는 기존 3분기 이벤트를 재사용한다 — 칩 전용 문구를 만들지 않는다. + let denied = ValueBox(false) + let sut = makeSUT( + location: { + guard !denied.get() else { throw LocationError.permissionDenied } + return Coordinate(latitude: 37.4979, longitude: 127.0276) + }, + recentFetch: { [makeArrival("신림동")] } + ) + let recorder = StateRecorder() + recorder.attach(to: sut) + sut.viewDidLoad() + await recorder.waitUntilLast { + $0.recentRouteChipText == "→ 신림동" && $0.departure == .current(name: "강남역") + } + + denied.update { _ in true } + sut.chipTapped() + while recorder.toasts.isEmpty { await Task.yield() } + + #expect(recorder.toasts == [.locationPermissionNeeded]) + #expect(sut.state.routeCard == nil) + #expect(!sut.state.isChipBusy) + } + + @Test + func chipTapped_locationUnavailable_emitsChipToast() async { + // 명시적 탭에 무음은 없다 — loadCurrentLocation(무토스트)과 다른 분기. + let unavailable = ValueBox(false) + let sut = makeSUT( + location: { + guard !unavailable.get() else { throw LocationError.unavailable } + return Coordinate(latitude: 37.4979, longitude: 127.0276) + }, + recentFetch: { [makeArrival("신림동")] } + ) + let recorder = StateRecorder() + recorder.attach(to: sut) + sut.viewDidLoad() + await recorder.waitUntilLast { $0.recentRouteChipText == "→ 신림동" } + + unavailable.update { _ in true } + sut.chipTapped() + while recorder.toasts.isEmpty { await Task.yield() } + + #expect(recorder.toasts == [.chipLocationUnavailable]) + #expect(sut.state.routeCard == nil) + } + + @Test + func chipTapped_normalizedAndFailedResults_emitMatchingToasts() async { + // serviceEnded/noRoute/빈 available/실패 전부 토스트만 — 카드·필드는 무변경. + enum Scenario: Sendable { case serviceEnded, noRoute, emptyAvailable, failure } + let scenario = ValueBox(Scenario.serviceEnded) + let sut = makeSUT( + searchRoutes: { _, _ in + switch scenario.get() { + case .serviceEnded: return .serviceEnded + case .noRoute: return .noRoute + case .emptyAvailable: return .available([]) + case .failure: throw StubError() + } + }, + recentFetch: { [makeArrival("신림동")] } + ) + let recorder = StateRecorder() + recorder.attach(to: sut) + sut.viewDidLoad() + await recorder.waitUntilLast { $0.recentRouteChipText == "→ 신림동" } + + for (scenarioCase, expected) in [ + (Scenario.serviceEnded, HomeViewModel.ToastEvent.chipServiceEnded), + (.noRoute, .chipNoRoute), + (.emptyAvailable, .chipNoRoute), + (.failure, .chipSearchFailed), + ] { + scenario.update { _ in scenarioCase } + let toastsBefore = recorder.toasts.count + sut.chipTapped() + while recorder.toasts.count == toastsBefore { await Task.yield() } + #expect(recorder.toasts.last == expected) + await recorder.waitUntilLast { !$0.isChipBusy } + } + #expect(sut.state.routeCard == nil) + #expect(sut.state.arrivalText == nil) + } + + @Test + func chipTapped_whileBusy_ignoresSecondTap() async { + // 더블 탭 = 재검색 1회 — busy 가드가 재진입을 막는다. + let calls = ValueBox(0) + let release = ValueBox(false) + let sut = makeSUT( + searchRoutes: { _, _ in + calls.update { $0 + 1 } + while !release.get() { await Task.yield() } + return .serviceEnded + }, + recentFetch: { [makeArrival("신림동")] } + ) + let recorder = StateRecorder() + recorder.attach(to: sut) + sut.viewDidLoad() + await recorder.waitUntilLast { $0.recentRouteChipText == "→ 신림동" } + + sut.chipTapped() + #expect(sut.state.isChipBusy) + sut.chipTapped() + release.update { _ in true } + while recorder.toasts.isEmpty { await Task.yield() } + + #expect(calls.get() == 1) + #expect(recorder.toasts == [.chipServiceEnded]) + } + + @Test + func viewWillAppear_refetchesChip_reflectingDeletion() async { + // 검색 화면에서 최근을 지우고 돌아오면 칩도 사라져야 한다 — 재노출 재조회. + let recents = ValueBox([makeArrival("신림동")]) + let sut = makeSUT(recentFetch: { recents.get() }) + let recorder = StateRecorder() + recorder.attach(to: sut) + sut.viewDidLoad() + await recorder.waitUntilLast { $0.recentRouteChipText == "→ 신림동" } + + recents.update { _ in [] } + sut.viewWillAppear() + await recorder.waitUntilLast { $0.recentRouteChipText == nil } + + #expect(sut.state.recentRouteChipText == nil) + } + + @Test + func viewWillAppear_whilePromotionInFlight_keepsJustSelectedChip() async { + // 승격 저장이 끝나기 전의 재조회는 no-op — 낡은 목록이 방금의 도착지를 덮지 않는다. + let release = ValueBox(false) + let sut = makeSUT( + recentFetch: { [] }, // 저장 전의 낡은(빈) 목록. + recentSave: { _ in while !release.get() { await Task.yield() } } + ) + let recorder = StateRecorder() + recorder.attach(to: sut) + + sut.routeSelected( + makeRoute(id: "r1", departure: fixedNow.addingTimeInterval(3600)), + arrival: makeArrival("당산역") + ) + #expect(sut.state.recentRouteChipText == "→ 당산역") + + sut.viewWillAppear() + for _ in 0..<20 { await Task.yield() } + #expect(sut.state.recentRouteChipText == "→ 당산역") + + release.update { _ in true } + for _ in 0..<20 { await Task.yield() } + #expect(sut.state.recentRouteChipText == "→ 당산역") + } } /// 스탬프 기대값용 포매터 — 프로덕션(HomeViewData)과 같은 구성(HH:mm, ko_KR). diff --git a/docs/prompts/atcha-v2-one-tap-chip-prompt.md b/docs/prompts/atcha-v2-one-tap-chip-prompt.md index 4448c40..9f661f0 100644 --- a/docs/prompts/atcha-v2-one-tap-chip-prompt.md +++ b/docs/prompts/atcha-v2-one-tap-chip-prompt.md @@ -105,7 +105,7 @@ ### Constraints - **즐겨찾기 선취 금지**: 칩 데이터의 유일한 원천은 `RecentSearchRepository` — 칩 전용 저장 키·별도 영속화·관리 UI(삭제·고정·다중) 금지. `AlarmSessionSnapshot` 확장 금지(재실행 복원 arrivalText placeholder 수용은 Phase 17 결정 그대로 — 칩은 그것과 별개 표면으로 공존한다). - **알람 자동 등록 금지**: 칩 탭 경로에서 `RegisterAlarmUseCase`·`AlarmScheduler`에 닿는 코드 금지. 밤 시간대 자동 재검색·제안 카드([제품 결정 트랙](../planning/atcha-v2-post12-roadmap.md) v1.1 후보)·"집" 배지 선취 금지 — 칩은 탭이라는 명시적 의사가 있을 때만 검색한다. -- **SearchFeature·Domain·AtchaData·CoreStorage 소스 변경 0.** Interface 공개 계약 변경 0. `DevDemoFallbacks` 변경 0. 매니페스트(`Project.swift`/`Workspace.swift`)·`Tuist/Package.swift`·`Package.resolved` 무변경 — 신규 타겟 없음, `tuist generate` 불필요. +- **SearchFeature·Domain·AtchaData·CoreStorage 소스 변경 0.** Interface 공개 계약 변경 0. `DevDemoFallbacks` 변경 0. 매니페스트(`Project.swift`/`Workspace.swift`)·`Tuist/Package.swift`·`Package.resolved` 무변경 — 신규 타겟 없음. 단 신규 소스 파일(`DSChip.swift` 등)은 생성 시점 글롭에 잡히도록 `tuist generate --no-open` 1회 재생성이 필요하다(2026-08-24 실측 — 매니페스트 무변경과 별개다). - 알람·LA·sync·스냅샷 경로 무변경. 홈 pull-to-refresh·스탬프·배너·복원 회귀 금지 — 칩 성공 경로는 `routeSelected` 수렴이라 이 표면들과 같은 규칙을 자동 상속한다. - DesignSystem 변경은 `DSChip`(+테스트·갤러리 데모)에 한정 — 기존 컴포넌트 API 파괴적 변경 금지. - 미확정 #3(serviceEnded/noRoute의 responseCode 실측) 해소 시도 금지 — 정규화 로직·TODO 불변. From 2770032a43e2b1ad4f0e718bd59c877ecc9f2eca Mon Sep 17 00:00:00 2001 From: AppGoni Date: Mon, 24 Aug 2026 02:17:29 +0900 Subject: [PATCH 13/14] =?UTF-8?q?docs:=20Phase=2018=20=EC=9E=90=EB=8F=99?= =?UTF-8?q?=20=EA=B2=80=EC=88=98=20=EA=B2=B0=EA=B3=BC=20=EA=B8=B0=EB=A1=9D?= =?UTF-8?q?(=E2=91=A0~=E2=91=A7=20=ED=86=B5=EA=B3=BC)=20+=20=EA=B7=9C?= =?UTF-8?q?=EC=95=BD=EC=97=90=20=EC=9C=84=EC=B9=98=20=EA=B6=8C=ED=95=9C=20?= =?UTF-8?q?=EC=95=8C=EB=9F=BF=20Allow=20Once=20=ED=95=A8=EC=A0=95=C2=B7?= =?UTF-8?q?=EC=9C=84=EC=B9=98=20=EC=A3=BC=EC=9E=85=20=EC=8B=A4=EC=B8=A1=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- docs/prompts/atcha-v2-auto-verification.md | 2 ++ docs/prompts/atcha-v2-one-tap-chip-prompt.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/docs/prompts/atcha-v2-auto-verification.md b/docs/prompts/atcha-v2-auto-verification.md index 731ace6..95a335b 100644 --- a/docs/prompts/atcha-v2-auto-verification.md +++ b/docs/prompts/atcha-v2-auto-verification.md @@ -25,6 +25,8 @@ - **Mac 화면 잠금 중 대체 경로 (2026-08-24 실측)**: 잠금 중에는 System Events·orca 모두 창 AX 트리가 비어 조작 불가지만, **XCUITest 하니스는 성립한다** — 스크래치 Tuist 프로젝트(더미 host 앱 + `.uiTests` 타겟)에서 `XCUIApplication(bundleIdentifier: "com.atcha.iOS.v2")`로 앱을 구동하면 XCTRunner가 시뮬레이터 디바이스 내부에서 이벤트를 주입하므로 잠금·AX와 무관하다. 증적은 `XCUIScreen.main.screenshot()`을 호스트 경로에 직접 기록(시뮬레이터 프로세스 = 호스트 FS 공유). 시스템 권한 알럿은 `XCUIApplication(bundleIdentifier: "com.apple.springboard")`의 버튼으로 처리하고, **알람 등록 검수는 알림 권한 알럿 응답까지 등록 UseCase가 대기하므로 배너 표출까지 알럿을 반복 소거**해야 한다. 엣지 스와이프 백(좌표 드래그)·셀 스와이프(`swipeLeft`)도 이 경로로 신뢰 가능 — AX 좌표 클릭 불신뢰 제약의 대체다. 한글 `typeText` 입력도 성립. - Simulator.app의 AX 트리가 응답하지 않으면(창 열거 0·entire contents 타임아웃) `killall "System Events"` 후 재시도, 그래도 안 되면 Mac 잠금 상태부터 확인할 것(잠금이 원인인 경우가 많다). +- **위치 권한 알럿 자동화 함정 (2026-08-24 실측)**: 허용 버튼을 `label IN {"앱을 사용하는 동안 허용", "한 번 허용", ...}` 류의 다중 라벨 firstMatch로 누르면 **"한 번 허용(Allow Once)"이 눌린다** — 그 세션은 정상 동작하지만 재실행부터 권한이 소멸하고, 이후의 위치 재조회(`CLLocationUpdate.liveUpdates`)는 **권한 알럿 재표출 없이 nil 업데이트 1건 후 즉시 종료**된다(→ 앱은 unavailable 처리, 증상이 "위치가 조용히 안 잡힘"으로 보여 원인 추적이 어렵다). 허용 검수는 라벨을 **"앱을 사용하는 동안 허용"/"Allow While Using App"으로 한정**할 것. +- **위치 주입 (2026-08-24 실측)**: While-Using 정식 허용 + 검수 전 `xcrun simctl location set ,`(정적 1회)이면 앱 시작 조회뿐 아니라 **재조회 스트림(검색 프리필·홈 재조회 등)에도 픽스가 도달**한다. 반면 Allow Once로 오염된 상태에서는 `location start`(waypoint 연속 시뮬레이션)·`set` 반복 펌프·XCUITest의 `XCUIDevice.shared.location` 어느 것으로도 구제되지 않는다 — 위치가 안 잡히면 주입 수단을 바꾸기 전에 **권한 상태부터 의심**할 것(`simctl privacy grant location `로 확정 부여 가능). - **강제 종료 재현은 `xcrun simctl terminate`** — 앱 스위처 스와이프 자동화 불필요. - **LA dismiss 검수는 DEV dismiss 토글 사용** — 잠금화면 스와이프 삭제 자동화가 불안정해서 그 용도로 만들어진 수단(플로팅 디버그 메뉴의 dismiss 기록 토글, `devToggleDismissedByUser`)을 쓴다. diff --git a/docs/prompts/atcha-v2-one-tap-chip-prompt.md b/docs/prompts/atcha-v2-one-tap-chip-prompt.md index 9f661f0..61d27e4 100644 --- a/docs/prompts/atcha-v2-one-tap-chip-prompt.md +++ b/docs/prompts/atcha-v2-one-tap-chip-prompt.md @@ -127,6 +127,8 @@ iOS 26 시뮬레이터(Debug/DEV)에서 에이전트가 직접 수행하고 단 **실기기 잔여**: 실기기 GPS 기반 칩 재검색 실측(시뮬 좌표 주입은 참고값). restricted(스크린타임 제약) 실측(Phase 17 승계). 사일런트 푸시 실수신(기존 항상-잔여 항목 — 이 Phase 무관 승계). +> **검수 결과 기록 (2026-08-24 실측)**: [규약의 XCUITest 하니스 경로](atcha-v2-auto-verification.md)(Phase 17 하니스 승계)로 ①~⑧ 전 시나리오 자동 검수 **통과**(Run 1: 위치 허용 7건 + Run 2: 위치 거부 1건, 증적 p18-01~p18-10). Run 2는 도착지→출발지 순 확정으로 저장 순서상 최근 1위가 출발지가 되는 상황을 만들어 **승격 저장(칩 = 확정 도착지)을 화면으로 직접 검증**했다. 검수 중 앱 결함 0건 — 초기 2회 실패는 전부 하니스·환경 원인: ① 권한 알럿 자동화의 `label IN` firstMatch가 **"한 번 허용(Allow Once)"을 눌러** 재실행부터 권한이 소멸(→ 위치 재조회가 nil 업데이트 후 즉시 종료 = unavailable), ② `simctl location start`(waypoint)·`simctl location set` 펌프·`XCUIDevice.location` 주입 모두 Allow Once 상태의 재조회 스트림을 구제하지 못함. **While-Using 정식 허용 + 사전 `simctl location set` 정적 좌표**면 재조회 스트림(검색 프리필·칩 탭)까지 픽스가 정상 도달한다 — 규약에 실측 추가. 실기기 잔여는 위 목록 그대로. + --- ## 진행 프로토콜 From d6281ebc18c7088c1d8d6aa9f975702556575291 Mon Sep 17 00:00:00 2001 From: AppGoni Date: Mon, 24 Aug 2026 09:22:11 +0900 Subject: [PATCH 14/14] =?UTF-8?q?feat:=20=EB=A0=88=EA=B1=B0=EC=8B=9C=20?= =?UTF-8?q?=EC=8A=A4=ED=94=8C=EB=9E=98=EC=8B=9C=20=EB=B9=84=EC=A3=BC?= =?UTF-8?q?=EC=96=BC=20V2=20=EC=9D=B4=EC=8B=9D=20(=EB=B0=B0=EA=B2=BD+?= =?UTF-8?q?=EC=BA=90=EB=A6=AD=ED=84=B0+=EB=A1=9C=EA=B3=A0=20PNG=203?= =?UTF-8?q?=EC=A2=85,=20=EB=9F=B0=EC=B9=98=EC=8A=A4=ED=81=AC=EB=A6=B0=20st?= =?UTF-8?q?oryboard=20=ED=94=BD=EC=85=80=20=EB=8F=99=EC=9D=BC=20=EA=B5=AC?= =?UTF-8?q?=EC=84=B1,=20=EC=8A=A4=ED=94=BC=EB=84=88=C2=B7=EC=9E=AC?= =?UTF-8?q?=EC=8B=9C=EB=8F=84=20UI=20=EC=9C=A0=EC=A7=80)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 레거시 Icon.xcassets에서 Splash_BG/img_Atcha/img_Atcha_character를 Projects/App/Resources/Assets.xcassets(splashBackground/splashLogo/splashCharacter)로 복사 — iCloud 중복 파일(" 2.*") 제외, 기능 로직(버전체크·라우팅)은 이식하지 않음 - SplashViewController: "앗차" 텍스트 라벨 → 전체 배경 이미지 + 캐릭터/로고 세로 스택(간격 12, 정중앙). AppCoordinator가 쓰는 showLoading/showRetry/onRetryTapped API와 스피너(로고 아래)·재시도 UI는 유지 - LaunchScreen.storyboard 신규 + UILaunchScreen → UILaunchStoryboardName 교체로 런치→스플래시 전환이 레거시처럼 끊김 없이 보임 (스토리보드 없음 규약의 유일 예외 — 런치스크린은 iOS가 storyboard/UILaunchScreen만 허용) - 검증: Debug·Stage 시뮬레이터 빌드 성공, iPhone 17 시뮬 실측으로 런치스크린·스플래시·홈 진입 프레임 캡처 확인 (로고 위치 튐 없음) Co-Authored-By: Claude Fable 5 --- Projects/App/Project.swift | 2 +- .../splashBackground.imageset/Contents.json | 23 +++++++ .../splashBackground.imageset/Splash_BG.png | Bin 0 -> 124509 bytes .../Splash_BG@2x.png | Bin 0 -> 266771 bytes .../Splash_BG@3x.png | Bin 0 -> 432460 bytes .../splashCharacter.imageset/Contents.json | 23 +++++++ .../img_Atcha_character.png | Bin 0 -> 1567 bytes .../img_Atcha_character@2x.png | Bin 0 -> 2911 bytes .../img_Atcha_character@3x.png | Bin 0 -> 4327 bytes .../splashLogo.imageset/Contents.json | 23 +++++++ .../splashLogo.imageset/img_Atcha.png | Bin 0 -> 1382 bytes .../splashLogo.imageset/img_Atcha@2x.png | Bin 0 -> 2700 bytes .../splashLogo.imageset/img_Atcha@3x.png | Bin 0 -> 4077 bytes .../App/Resources/LaunchScreen.storyboard | 58 ++++++++++++++++++ .../App/Sources/SplashViewController.swift | 43 +++++++++---- 15 files changed, 160 insertions(+), 12 deletions(-) create mode 100644 Projects/App/Resources/Assets.xcassets/splashBackground.imageset/Contents.json create mode 100644 Projects/App/Resources/Assets.xcassets/splashBackground.imageset/Splash_BG.png create mode 100644 Projects/App/Resources/Assets.xcassets/splashBackground.imageset/Splash_BG@2x.png create mode 100644 Projects/App/Resources/Assets.xcassets/splashBackground.imageset/Splash_BG@3x.png create mode 100644 Projects/App/Resources/Assets.xcassets/splashCharacter.imageset/Contents.json create mode 100644 Projects/App/Resources/Assets.xcassets/splashCharacter.imageset/img_Atcha_character.png create mode 100644 Projects/App/Resources/Assets.xcassets/splashCharacter.imageset/img_Atcha_character@2x.png create mode 100644 Projects/App/Resources/Assets.xcassets/splashCharacter.imageset/img_Atcha_character@3x.png create mode 100644 Projects/App/Resources/Assets.xcassets/splashLogo.imageset/Contents.json create mode 100644 Projects/App/Resources/Assets.xcassets/splashLogo.imageset/img_Atcha.png create mode 100644 Projects/App/Resources/Assets.xcassets/splashLogo.imageset/img_Atcha@2x.png create mode 100644 Projects/App/Resources/Assets.xcassets/splashLogo.imageset/img_Atcha@3x.png create mode 100644 Projects/App/Resources/LaunchScreen.storyboard diff --git a/Projects/App/Project.swift b/Projects/App/Project.swift index 68fe0fc..4074bba 100644 --- a/Projects/App/Project.swift +++ b/Projects/App/Project.swift @@ -9,7 +9,7 @@ let appTarget = Target.target( deploymentTargets: Atcha.v2Deployment, infoPlist: .extendingDefault(with: [ "CFBundleDisplayName": "앗차", - "UILaunchScreen": [:], + "UILaunchStoryboardName": "LaunchScreen", "NSAlarmKitUsageDescription": "막차 시간에 맞춰 알람을 울리기 위해 권한이 필요합니다.", "NSLocationWhenInUseUsageDescription": "현재 위치를 출발지로 사용하기 위해 위치 정보 접근 권한이 필요합니다.", // 사일런트 푸시(content-available=1) 수신용 — 사용자 알림 권한과 무관. diff --git a/Projects/App/Resources/Assets.xcassets/splashBackground.imageset/Contents.json b/Projects/App/Resources/Assets.xcassets/splashBackground.imageset/Contents.json new file mode 100644 index 0000000..ce423f3 --- /dev/null +++ b/Projects/App/Resources/Assets.xcassets/splashBackground.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "Splash_BG.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Splash_BG@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Splash_BG@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Projects/App/Resources/Assets.xcassets/splashBackground.imageset/Splash_BG.png b/Projects/App/Resources/Assets.xcassets/splashBackground.imageset/Splash_BG.png new file mode 100644 index 0000000000000000000000000000000000000000..1745c8ffc9d3565525a5dcdef0a145eb7a23a772 GIT binary patch literal 124509 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 qW`V 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�kMfoGclF3;Jo+fW-fA6ziJ}(5%a_A<&Men= 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

`MYptu6@U2^IR43VH?%2H&Tu-%tmkH{zLIEJ&D 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

~-|Nk_OSDT>`3QEH6YU2(NRyi=9nIMc$W~?N#Oc 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

>~)y?>2%4}}jv>{k>>c~fY*aRd! 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

  • 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¬6^C&1)5^a$-V^-9F<%x z;_#=uaxS~y-tzT`xzmH0hYnXDTTe$;HAGajg2oj0v(0}81i1E4pL%_LZil7vz5s(J zEjlF9TPa~H6{^8LG=KM$(U&QeN)N+1YiP056iA6DMb$+HqMlZ5yxTVm-t+~|xwu$m zx>aM}^;5#dG^ABM7*2xcpZ9|J`|F1&$6yVz=NhX>venc+z*z!Z6Ch>gn}{%WAPk9- zGOy*Nvl)QEv^Q#jc%FKCij>Lq^#FdZ>?#P7n#=zSGNd(RHp#RoU+3J>fj;sY%{`e) z21PT-M1>`p!8&MpFr;($i4jyXc=TQ9fP8SN^@jI7XxMol9SHX&Aq9$(3Mk@%BN@%N za)#PTYA*}}Ax1h~|EoTel7n*_)%0F_g;sg1vA~Qc$hyZ|#7#Q9c;N0paacWuM;i39 z;eYwKG!b|NV8oJ@+Lo4ELIZe4#x7V-Wide31#v>?WlV$q4(y>|LVg=|HRr+l5dIa;VY1 z5Ysl@kByn+Ycn7*qZMW@NlK;#aCU%5hV~0h9oxGpSKs(1Q9FDcU#Fy-Zf>60Yk?uN ziaVlP->F^3aKfu=4Gp8~gOwR21Xs@EzfgGI=FaiY=G|<5S;0+*pf8gb!|v)r9^afZ zjVm5eifizc2|IcqG~YX|DYET&4Oo&RX;>D!zjgvn$geJjq)SaSJ=g$SN{gWVqs*xMs|{ z>X0tNCZ_Dg7WLy3*>n4Me=68Nt@CA`k_jf*)@#dI#5!_?q2SXuffF|cOsz#p_rie+ zAs}uJJVqKY8%dl<%>YczT7ftEonRIE@A5hp-K}$EdX?>$bt&(ldrnS}az>H!>5Uhw z=)U=OOT-J8pYR*!s(7i1_d9iqejBZ2%-N`lqxu^992gSAmUVWr^36lI{SG+9Ic|Pc z2sHFl@v86Rnpo5ZGVfd1uz};#@$qCBk9L(8k6oc#sBt4(%t7`SacV>v6v)Qs-+U$> zR?HQUN`VcYB(m69$y@}>eo4rzCux56{ z(LnSX|1H5NGa8evs}~t6v#9(MMCm_;eC=jH1=t4o;H+IDCSXo`of)YVdy4yq=1E|r zcg=+KBct53+0@ki=!Si@hFr1uM^-3zUP(%ubi*$V`dRyo$Mm8dz-ZZPbI_}E%O7lw z;R|Wq;VTzhy-dOOl>=uM`i6u!NZ$ZHi|FhEl^+xoU?BiYCsGgq&`$f(jx;0nZAHpG zePW|l*i&UixjpaW>{OX}i2v7wk4MGapb*2`Chu*|Gf)TD<6ZryUk{%G67R{@wqQbU z>w#%;8jEuTe)b^n#}x>NBEQYC{skYu3V)_;$Jjhp?4gDT3N&tUVSWq##Hltk=uu-avR)Pd?z0WVg9WbO*0t+hN8b}@;+x(4e-Ov z12UuktTvfg4s?g=pY<6_6TkJ~(_+*5;r>Vq+s#p}r#5}4vhn<7r)YcATZMw0q1m2R zA0+224_2UbdWy{sg(f}QcJ?v;lPAJzEbwC^@6?2aHEOK}F0vsERwK3HeGimN2})n0 z(>v?>1IoBpV@;b|USV0O@E;rSmD zmHv{Ojg+@eat2_g?Q^wUYqWE<$;}$XZgOBWSmkjqTvU>{o1sNIJ;XE;7}^E-aPS;79LMR-z`TG3O-MkX4+)T3tGqsU0`Y(X!)n&O|2j{vsl?64E% z90}!wT40Zc*aO42qCaSpeN}8U&c%(t$_NbY&wBz>x)tYTm&axD zN{2ipRL_%aJZWKoY&k&Qb#YquM?OB!Z8H6pzCY_Vef0@h!|n;bw2j>9sv*R5=ZWg3 zR`>0-?>ruUUeYY3#6PGkFvnrq=G(!hB{WmLobY@%s&?_m@02w35!j57ECM+BM(+2b zq#gZ#%1c}rB3Uyz`OC6tchGhc6}E6)_Vs|R-k@`;5{;m0Aa=}j(r(PwJ~FujL~iSN z<;WCD-EH}r&}&%ufJz3|YxEFlZ2McvG)}joIXcEYM^H%o$l9H1$KgmI0LE9mXQ`7m z)w_tF?#*`6UbDWm&*7E+bAH0-cti&+k6jH+u1Ix@Yumcj;KH+{4H`EioB#k8e1_zI z@T8lT89^0jEg*R)B5TkjrUys{waHc1QYX9uZlw?DzyukB1@DBD5tW@{gVZU74gs=? z{p=fC*$y^m|L!{#$P3-7WXX477gT<~3HM9U*$TMV?rCST;edGaHM{gv;Id70-R_Xig>s}3{+M|+Vy2N`4tJ7S!FkqhuRz;luAZH zwcKokqry&U^=`>kDra!)Yc)YfiicB-ux_T;BMt}o_NuiHkQpTmojUdHrhfH<)pdB-MvvFlU`%zj4sW@us~P$Q{EgL= z^STOk%PdIzoB9`W^VW1|z45j9x<9s<#@_#s@Sm0#xK>6!u-!m**bY!>i9_#ju}AHA zxYK$08#)~o;E+p_>NzrrJLOrM=}=J?55~=9W8RlOweBcuq-48?-;tWyCLgTIp!a;7R$`843vDN$#SNe~n3Tnp%s)4QWoB|&xNAtou8I|fWZQa7n5;RAe>Ike`dnW9 zVq|snjoXF6xZx)Jmy!Ntvdp=0aGQZtyf+!)1dA_*vK}JIA;>wo*;ZTGMxu&M{^3eIGg#i2LO{E%wHI)Appfpf}ch5?@KG zE&%TsYJPTC1=3b;z!Hd=fMZ4D5Q+;NOiYf1{n>14Ax$YuDq7lkPRzk#=lPV;>BF~{ zCp1q=YA=Z5Q%on9PMAA|kdGNBJy}oVRM|^BS5}N}SG>_jssq~*Olpv}Z zp&B105q0QMM3X3@+84@f;cxY6Arky9zx&=PYyN8PYl@#_icV#Hv8ny3LjpU0-xqVy zLf6~Yuf;Y#jY-vX!!AvNaqpI-Zo;FqdA7g^98(Yyxd>ki4 zgm3hz%8q#r_SaY2A&Gs5hR`E@e+O(4e`slh+XnhgeypjU7!SShMiiuqp7ZI`Nagxa zLWy)A@r5G*sU(1b2w+kOut))_F^Q`-k2m=NgaRQSAbnmS2@fD*_)}5x4C$H7U0)Ls zM||+Hhr7B{X`MfK>T@*Yo`d=geUG2I28Yz}Frjz#t(p82QrE5=-RG8Gs1VDk&au|& zRFnAK-m?AnbQs`q7#J3R$UIfaAV>b#@ajEnR+~!^OW#4;HS6=uzgEjUwVQ>?RuDY> zy5z@Sh#z{B0==$9P2}5ox|8qQA_SnEc(n!puZfwcPhv>m5Nm+^Q{*0?G5a>6A>y7> zMrN(xYzU2{Vcm=?%?9P>m%^rwC(#NP@>BYtdw-t$v}?<4o!AUbH?`BH(LdmoeD&bS z>Y%~;uau#>ZVxeytioDHkuL%2cd+f0*1YiX8Cb94mSeBLE%s{~|abctdpTB7z=?*Il`` zjtSDoIERxbK39^37@9!mr;q{nA3V?xaG&*1Z@O&)0;>*}AABx)c75G0AO(hK}wrV>Jrp24T(i$6>!5QhndE?z7 z0+W?j1fnDBI0LZtJf8IDH*Ofsa#3oJ4>Kj14Z03Q<2OA~?(}}}3Ci%idv{(9zU2i&_sn2Ne3ZuzTf9d(^!1L)k zuJDQ8zz(-2f6sdJfzn*aKq*mk?e}KJ+z0+Z240uR+eqx}7!Rf(#2>>T`yP4KlxEQw zFh8KmewJu9$^&Z!kTQUeXS+)b%g>!otsT(&wq|@3755S*c1~eRfR}Wueqcgha3(Rf|7OURipTA9mZ1Siudx)b%HLW2wGi@`@7(1PA)Je zZ(maA^xj#{=0FPU%FDNVB5(438 z8H=mH?T<|k3>!`Cy?#x48K;R*qYxu6NvCSwA{;p9XUm;0`iGYSgCmuly3AEZq&r!| ztm0AM_GoQBekl*_FF&wLyWnb{j!6_+xmf8$KN+T7rK5vVPBxwm<$yfpeTdF~d`Y?w zJmsfg-9CV+38D&RZRzr__!Hyrr8GCI7g7=kl4wuGwlUe|6J)WJ6uc)Tnx$)_w~8M; z6U!*%yI%A%rtMu`@gKwYP~6YpkCB0LU0J{jf7OXUR5;sP0M8?tL)t!#y>}_e6i5Q- z0qwIaGEDCS+p^?k^IS2%*!;`Cnc8a&-x;3gnO&%JREF~8TzmfHVU@#ZQWYoP`n1it zI>87(+8T52QA5pJN18_?N_Iz-1{m^PhgMe`6}=i{y=4LUp#uZ=N9d2r`fM4sxB}2i zax_x^LoAE*&9dSmGdm6akeU}mWE`V2zD@(CWQAJq+9Q~apF!Ws35AeGRs&mF{C^sR zq>P9t)`jpt!P@Vr2&)g5-yr7$C;zyT5E&U5erm57X<1er@g+M<24(zb8Fzd=h|jzi z9gbeCzrQmbIU!>?v~#&%q7+*G+{UcWcGpUa`_|lv*6u}&>og*tZZFXT?HHrkNcM_h zjdO>2QvSfiRs49K0B$V6*c(+9KTBKos`2+=z9Et!==@Ute z*m>)50`SEyGY;Sa^*vg@~Wt)?1nPzc~Evd?} z%fkos=1v_{+flRKOGYD|u~o7C#6vMY`sh6KeAK8@bk+739r~HIR)*JY6OMwjndfV= zR~kmN{WF(8%)KiY4z*zlA@vmc&fz_{{+o(C5AZDklIXT?5-9=^*LH|i$Lqs1Az-RE zFSeGZVI@=kb3&G1U%QDn)dHi|L31@p|*|8 zM2H)CU?}QNlSIjd$hYg@+hhh$$m6}!W>?$@E6bMlJo4HVmf^;OZ8B@6R)SpJhj$-w zQ){wv!|JY;WG{`|GS6uMh@qz(<@KgqBMm)&3 zlIwXL96V*~MZUhOodY^eaC{7^yXy3}axu=M&kc3qr0R<_@iFJP7lyd}8PfrKVnVXdsa;8a=T=qirQYaX;x`XeQ|okKiq%6mKm>pB_w%ip=Rmfw|T=gpl(FMC{9-B8F5 zo5JtP-sGET93jKaindojheEfHGxqzA`*dc+>}txzR+5Q7NhBYyLfjcy^6b=XmnR|? zfzg0OuG(yw{R5(3(=HE1&8@B}ZROx|QT#D9Q|fO{jWUeg*Bs#v-b<(2J~K`0*$>;e zZe#~ixQ{m}-PlxJz4iCt3eKKRFETIsM`s_>J&)g7Db*XrR`tWc-HIlUt5eNgwezbl z#+x;CDf4qnIrZrTs+4Gnf@~-T7l)-XkB?xX8$4zJ;h_6Y-T(SRp(v;#P_rfZ$vz-n z5)0W@NAQR);^q4cG7FXg7~1C2$#^>^BQ2kCW}z~pwS{_$#_D`BnxX_T8aC!3d=BWt zNwY+ggEiF3*8ff>TA?jm_JPFFCH?7Fiuwf@^m9!SX*$LmLx%P|Qjqqs`UjAyd$)U@TeJDU-;5^&o~${|yiqQys9WU~ zn0a(0WKo#()&6X)fQ3S#XK%iQq-F)2D3bb9KnEv{h}}yeblv@jvO#3vFZb1VDpK*{ zvmj2}6B|}RYOYr{rd<!$ghhQk)JO; z@$n034r`?K=4x5tni$#Zso=mibA=>s>|laG)Qg7m0XqK5LX02ykIT#2{H`HVLaSJ~ zgoJe_pB)(5@;QRQtrbGWsyHKeku!R zoVZ5BBdD%kp^f~sBGa~}AKUNTRMw(R;T6CQDf1Z&)E@JCcDh1AYp{%xPo{L$&46fD z;sQ{b!^OS}6Ri~ZRF~F!g9rxqx%`b929Ci%bhU|ogG=MP(NumH_XxEw(EF}`LaGeX zo)kyP9J;inLfr&9)s!&Nm+z|?x4Jh4n6xUMh`*D|W$U>yQ=m+m9fF(3o~83=CcIGx z?07bCzYxU3#m#mo@36vEsO3=b0`spt_`dr4x2AJL)nC?9*t|sw+Av7A=~T%{x2-gF zEM-tBqJbDIa4VA`e@bbY%oUU2LW$(-vJU$F3bLQ`M@D=u*$th<*}n>R6B69CKUg}Z z_YC4FQ}^u?4Q3i|^ri&=Wl~J&A4P zxF35{-?{ZAFK3|Fh%_x1^AiV&N|;Y3qJQEV|6{Ka=}DagUU);oVsVbCfGnuv5|xa8 zaa=I@iKpL11~SU_0wK9X?XtV>TGVKJ)o{9wzD)d&zg34kj^lRNXNC)6O(--Ae)GBi z64LdNc8`8@%`+2ub|02bh!-jv&qIC^GNlBcTmU5N{m}Ix$#Q*{V*3YlQlVFb{#uD)Z zM10y0YNE~Vxr%e4trSRmBaRv7gmab)y7nB24(31Gx0j>gqo30KzBvgzGLulPD~_W` zs=*DYDt*!#x^twcOhn7$$A8OPed-*o@@Ldk=BRo1U>ge)9ld*EAWs{eIUFdIQ5m!} z>%i-~e2GWq=sn)PzL)U!UftqKpTFf2WA_Nd0x@mC(P@@NrMXY-S}A|qQ?g}z+dkWOliIC%7 z<(G!x-MIHo{;aIy)CDH)SF6YgkHWcJPmk})t*TQ>x0O$xTz`sjZqbz(((20y@a&Au zWDt@pj(C1^mz7KN&*k&-GCQmjA$k*K&z2L|M(@i43ge8+d2_;_ufCz4viG+Ue_E(I z{}SvUHV7B$N>=I!O2uCfmvNdh{@Z%NK8mSSwII(Sg?$X(2W`6`Gb@w2zFS$9d5cSB zB5MZl4>$k24E&dG0Z(Cq291l=BG`#&wWm3`*RF0nE2MK{2zuy}n#W_tPws!3g*+ke@YBO#eUgV7>wI$*qTQxXtmvz>-&^=@{CDmP7NRqYwZCwn@52ii@tPs zd=PUUFH7@Xnqf(=Fr?uv z5mY|e3E$2_U<>mucjhL-h$a2_2gLGDe45{q!T+M$nL!(JZNPdFGa$v~j)pocAN5r! z*m9ziRZuzjAw7%!QfKV4n}5^5kLK5cg0%PUvJ}05|5QDWJU3UhzogSPe8*?BJn+)B zdtvoUMQJ{^oa8~+pC%t?R&NUzFUi}UQ_KT@%pP%CPHvT>R^@WMfIhu1ED1v)*3%@o zO2m!=Y*xAG&6hozO#!+Er<9-sf`~x?Bz~U0E## zM{Y-vpL`Wn7Jl|LM&zo7XH4j!wF^C`T%FY0)E`FMCJw3T?PJUwRxQ=#+5Hl>+PX!~ zBbwW*I~Pvp2oG9Thw+&)!=#)DP@ro3e+2k-<$>>rTR`|uyhbC_a*tQ&wQ#C2*T+I*WvTTDxf*N~LL>ZLmf0@*C$RQxNQW39WBbTA=b5O?Jsw z+695FnlR{ZmO(~Pg<>lcZ_X$Dt0}fV#+x(I)(q?V-h<&4_qZJ%ec~OvW#04@pMU5C zS@AibJ)m-}Dhv1`NKqYy7919z)@G=r9HM$rp1IWU?J`X;63@7``RI7HFW zolE=RC!Flbz@>=onBIJ*(nAoMz(TEswy1&;zfo&z$=k9nB>U(oZM}andmoi?#^o?iUAUG=z0l2w>-zd;d}K z{sh5 zEpc}@TZP;?o_-O}su1+aFlg0zC@=r%bmSPyg<^JG)UtLw2oMURpX!DMe+6@*A$tQ} z`K}QO3zr=O)>5M}&fQn00RR$6nTg*?6I2#w@FwgZ0VjTTMCbi7c>(cv9AdEJ`1`F- z#X)f&Zmz@9WjiJt9iD2IaVJ18oZP1ncvC3m$1)mk#eI{^$|v^MjS2S4y0ccXT=b^X z_;K&a5i)t0I3!sj);ls`ffY0SFa$`&UB57@&DEK>1>qTD$Pbmo78|ZGc!Tu$wc)le z6dr(V3(reb5cKdLo;K+9L!+8#>R3o9L5e)5Q??ArQAfW}Pl z2P%I7H5}A2ADw-fvc8{7HXSyts1SWAWMo>45d*3D1^hRtG{tNjE@6lv(7LMwg!F~>9J5EDm#Q7$&fQGlsuSwiyN?_15^vb&yFro70V;5LO&yZYF|S)nMff1LJ1+kA$RV zEM5G%I1wn8lUN4DTW8k(U%R$$>0N+={E4Jr$76BAd^gW({UNL5o%9FvO8;q++9H_a<4g9F`?B!xp3T;pt&G(fzPv@G#N%F%>NUkD z+sSai7D%9gII$p>1YU^YlZbzT)<#5`8Nomu1xK7G#@-iDd`tln;kf@s#Ct2P<<-yS ziPVmRpK3R%$-^%mqv4wDY%dtD?n_UE4pX2z@e`@y{IhY{H(R!~I*)PEJE8E<_$lfu z9bYhO@!I=M*%PQVZrS8Y@H?(v_srK)%Zxu|AtFVoQ^4S00 zi)5Hf{YZC$radvNJ?8Y`TBLh-dtLXTx>7-4&9hC%jd$PZ`WAMcwiYgFONY})^qxh} z{~bpSk}3-d%9BLQ0#Op;@oSZi^G_=bmLr0?R(Qvkjv2zv#WgvmUB!9*xLU?j?Ck8+ zN9nB@tAlr3QrNP0eiwavD}^fxI#Cc(gK@5^7`uCC79ByA2K9y1~3Q+yg>s+nfJ)e+5{ilPO z)=$c)&Dp&lw$zRK&(ZUYRj=8WW)&d|$6uC{6^;Fg;#I$9|LsfUApR*P@VQ|^=;XN1 zk$s6i`YAH>~@tqshkZDvt>OzWvIDj3b#?e7HEGxku!=$OC3q7pF7*mu?j_ybwh{JJq z5}GFGgFu5j{Uq2Og(wmVQEj_2@Eteb4>)BAI*E7xGpccQwc~Xpsf7W8AzjJ_4$)lP zdU_6fn>&RtG9gH`a?9m5ZCQb(gO`&1J9+6-TEo-dj#L7E{%PuHeNdYM_7kBZn1(!&GQ|tQ%=WHsae z7OL5Mi9+CywHTH%sLKTQ@G-KG_()E40%Z2A)x36hiNV=1Rs^!cTb$1+G}C%adJab0mMaWp)k$+n?NBDxcxcHk-0~Kj8 zcet4Si^wNl

    sR^EIq2_a;?amYNBelX7I4KblpZy#_Z*%)l|Ex%pTUaJ4NY-ul4TI5j6=hx?*@t+oQb{*r&jif5!Z~P(T!X^^|RPfc*%Eh<}eai01a=NJF zb;RW3RFZ&ZL#>w}k##Qzg|F9LH@cD%cz@>9t0E*Qo|qJV^!HqDC!c9!xg-oWE30*BrvSAvT@StI zNbS4_K)yBsI3?|Yo()?ZeG!1ClrJZ!SuX~_lK?D5^xA6DdCw#=RGh~rPZ@=Bztfx) zF{i>GVQhU&`PY}ZD}T~&1Wz{ZcB^6&wx)Dg?S0M-ALw&UALTHzlR>513)8!HkRR~k zRzONXKR)-q)L@YwqsT$@$~Q_O>?d+LeT|2N&c>)EAXqKQc0Iv8oFv$RIyy*=sZ~amhTe2vto=qt=6V|5RdTLW{`WFT4!h(|F?0!sH;8JQM<3qS>Cu zPX`aI`_5V##1)Zt5B`0&a7m=B&xDkPI_{C?L%8GP^`m);=+@h=Q+}`C#?MKr7;8jM z4~%q{UZnzda%07n=5rKd{HorcK6@c`zs`HHe!di4Pk1faM|~4E6u{|3m$LU1hy0n- zmOGhU#a!hQSIf04`x{=VDcCn5Fe6LZj+mXG_x^Qw9at&_*B-m-3`s|5>&eh0K!*~5 zjox?vRu|v_TbT~9jvuUwU8B0u`Eob5zh1N-4E6Mz*-?3msV;i&d+)%ZN6w!3sCF!kI?Qp|abS?Le>R;Pg?Ip=dP7racbY1Kr(7lq4k~AaRP}nGn?mBLY|)N(5|Y zIj4Zxs`_9yI`W#Kd8BWH!VQK#x_}F~KjDA8YHDes`V`vQu!Ay=3xjUY+bNg>{rVMl z%_i>26cmko=Wp@B3SW<8s~q@s zI){-Eu^ZH9nK3A6_6)q!K=fH?2llrCZnH^tmB^2uu?|SvoE~w zB)ok=zr#}>2bI32kbE;p$b8K#Ha(J8mHpya!@;d~VMcwdN@7cbe)an<@3Or_79m2$ zkB=`9GHZ@B>PSyP{mkwTCMs40EYkca+D-TUMZF})FY~an+R<3Kt(Hyi+SAonm3pBu zTXnVy`+T~iSJJ$C)6&WoyiySW9_+GlBC#?cb9qM@sE_a;c5uP;G}pmb9QX@%>lqFJ z|KUr4V?C9jQ`jTCBZV5}Q_XbV53XGk!#97qrw97;Gqh6hwAJkD6tCId~ol7wmlfi-^iQVCgE|Sx&M37=I;%sPk zHdp|~Z5>aq=7Ka%gL~>~Y=#lQA1Uw)0WyeiL#QPG)8D)wkE<74-Q84+HLqmqrSwnR{Z^=SfwbWQaG98!=F)|6srZlJ4_;V z68f)?iczd&N$`ZI?a|xwNYt8+2Vid(!P|dHH6q+S84?z|?3pQ#oQA5u*xZx6cazM_ z`R}V;OQSJXJrDC|2&D9l!{n%|KGEVRbjJ^dsK3Ph2=ECam8JhV4g!t`w;urbIe^pV z0Ty0hpVIrGkLBF#*uV|r9y5NiiAT)5(~oqz6hAjl&hbYnQDEN@tgcBkQ3hyRsRx=5 ze@#be*hGey3Mhbk!>dJJ@@YTiCYU@1`qrL3uB!;b#y_zxJT7Kd!`>G8T0?djP2p8XBt6YBgu2O1ae&5Sas3S_j-Y09>K zfwj>~GiCb14Ed#accTHF4oTnWV=a}fh4t$@nuM(i7@VI|UAdUgtq_h$Z6xX@JN5ha znw=s+gc0cCIFAINT;hApze_NHq%A4F0GwNBIPaT1PGGK=@ollk*pb&ZAxHZ(EIs4| zH@lKOEns_LQIm;~`ao-SglI{Dk@jG+ z(M5il$?=M^=>hf-Rz2a=o5o%o$GE>+`SM1LK0>;0>Abb}$4d7#F!3Y>7}7JpU!@Q6 z?k7T)AA4a4YK z^4M>z zj#0y5!r|T(n337rp1(e`;3nv+6uh$AiiWf(F3Oa%b~a#jDGUCuK+#$OkJ5Vf?n?s8 z3#ci;Jcli?xn&9KRCmbh5Ad=L=vi-SPVKr&kiRQ5tX^Uj+g=Mrd5Y3j4ep=gFMCt# z@*R2O-jNuao$=oG4WEb%P3X8ZG=9Uv7VgSIyZ1)PV%(_liJ|nB;Yf<(SLR`1PU+EO zRf{1F*EJXvJdO7+czY1SIMA$?hZfIZqcyv&^Ol8mnOQ#_v>Lx3F;f)K>4WS-zSld$bI@XWZR2XsO@0?zuZiSpl(>qrEnNO0cu&#rq=6tQMfol8_+PHd=X zYsm+89F=E(uA~9XtzIa!AHN*8Eqwm8J`dkg7QIqjVP$ocftFI|u$Mxa`u7mRtwZVX zg@JagPu^lLXF~0t(+)d8jz0=z?u|vM;M5(IhB^aRbl!ICrIlM}inDpdbbEXEY`D4f z`Mq`feU!g2JB@E#(WuMw`-X5~cosBF>ikNas{`-+8DYX9W{i|agWBSbr?Q+AK4%gy zoO1bf?@Dg#_Mkkkf30)dFNtpxv=vI7`7k%?b;#_vqmsnxIw{l3 zMuw%AYxlPKhkhL%BFqU1w`K@3bu#Yrud&uJQCcU_@`(UdL6jb}>k3gDTd&w76D60( z?fUihhUAvbEnjUUwHs}@2UIBxD(^>w}@$#q3;f(mYFiN7qNpEWHj!_&9aHsG#@np1I_~!lA07{TK+~X-50g z=wbJ^<)m~6Dx@7GRc~sp!vAVdu5{f84~vV+Rwd9ut0sx@!-LU>bvRP#0P+)nhKGRL zL7;ZdGkQo25&mjT&@(x(Vb|~$eaWSjtjxp>TEGtg3PTWzGpe?M+=wmh8YyEqG?KGlq3xdA+a3|ge}>a_r0zZ z@aAw-04gggt2||Bt|}hBGrslynqDneH{0 z3$-`)$|~;|#chq^ZWLbvY5Jrj)1;rh)XpAqSZ(Ie5M63WcS+R{56begjF;%}YTG{_ zyF-xq=2c-6kL5W^+j3uQ5*^-G#+ZFw30RqZS6;c7aJQ*=udDJzy0EjcV)8pW@}cD6 z^m$%!>+W}Cc6)A+(xs0*I(f*0wN-+O+RBKUhhn(cok~N;M z?79g1ud=`iJQSZ5?+x36Xz*WGvksmd@07yCln@#%S*&~~-n1ugk7Q#-iNR~AfNC?T z8tfyTnFvJDh^9HAZtn+Ret+cwQ0pged5XQt>7ob zg8Tb|HfE)IuN4`ESgod9oRoVLr{4ebHEaFjseJ1_tMRQllY511pi=st-!xhKhTQd; zYmMA!`0k7Chgf?>`LI}hujlbA^50iUS+?#jms$^*(Z zKN+2s3=AdUs_jIqJhZeH`T#g2K|YMo55c^GREywXi9k7+zuS_6G)Q$0Vc}8g?&7C& ze|7&_^0BU{hl)!5(e4*+8GZ7&7F)%>HBKCDP3>;_#S*l}H}rDgmp2WMx3RlB-v=kO z7(K0Hs=X*-ZW24=gDX*hhgxnti^zq;9~#I;&6LHKM=hQQhBipDjKUuXo2i214B>*M z{v?MY^bY@#;u;ripxUjDV#is8F5L|R z-L=~v{ba0oFyD*OWIdEI=sX}ggOz2BK{=*2PLu8qJug_ADlL9y*;M50$Kw+4E(I=)&=(k!YlV=9j{>`>Qw5$COc+v4@r7Y-_3*w|y0gyce?mok?i;bV| zy<(o7{H3}tmOew@IqOCJ`Q|m^bZ=UbQCv?kc{a6}o`+4g8q`{s;A>=nev6{{hGLXM zhdDu}(L!a~Yf#kd zV)O&fnWVp6V9eV8Wl6KO5`R!r-~nH#y!0f*Ls^H%idCxa?eATFg#@bFEU#WzRLDwh z!-Y+eSDP4W^F0a&=9(AQ)ZA4gT1J{VsHE8xXH2 zH#uZ)666dG{1)xx!vx^}H8u>T0vwf$vJu zUfp}%*cqlCRU}n43F^=dktPcNr8XUIggP{7GG;9SAWqRB*u-NKAm{E7s(-5*A3myh z`Dl=AG0!0Iox`QN0=K}d46{jxjg~LBbC7*j_Hn~xW3(#Nv3;x9M|yUqi$z|+O|M;5 zkP$N_vKQ|LVC)JnmkFXs(iQsemVr4K9qFFItDkoN0RD+0MOQE%1BB-R zrJx$x6Pp1Pr-jA%H|XR3=-WoDYZr}iyl`I~=~3H9Yum zr|Nq3!Q=Zfu#}HBAun7UirqpbORWc@-p4x0+KRn8T81yO_7((O%Nl8t|LfIsBF-*&3m38Zx1!&U@KGKJ zdM+b;r6ks0#ax~y}Mn4?TWLv&k1mNF~peXDg>&Tk)Mg#?w@z@xRFg2%;4ew%$CPiTF zxtk)Ijr{H$F^2a7y);+B=+7BN0>+=Y27F8us75{joMbv7=Slwr7Xrp4r7lLZ*sv9P z={hrbUQb(9-)z?0_X`%|>OsW-pFZonQ)Rz=gh~)et=W5(aE%WUP9x;5is$OFexdoP z%h!6L5H5H^>{;kh@2jI8GgIrfg*i1}V?i2Uxrx`1?~t)#d0Qupag>vL?dn=-xSl+R>V`Kp3@% zXrtcB)n9m2KZohz`zG?iRk0JL(8~aosxl+Em`K$Xi}tx*ez(=vT$mi272Jgl!Do4ttIK65yZ&x*Qk>0k9`bK_1iMNp5uRVr7cf zm-pq8iL(*5t!dS+^n$Y1@yD4uFhAg&4}tYx^wx?d*z`##iRvC~>V6ejrZqix9WB@=4b5g3O%hu0OT>GFX13 zx=P*}To?>A;55;g6W_}m0`cQ+2nCW~fJ5}nE&?8ENVT zu`7wQs|{&Res>rN&{YIn&+@cx4naECm~n~-kk3hgMkN4#$%hbd86hMB4|o!RFaTEH zM_#7f95^M#8H3f^Tx7+t-*@7mv{-8-TPC(5m?xXtcb6A@D0Rh-$FdwKU!rFDVMX+Fb@ax-tY@tIesTFNwaBbjC`&iES3lCvx{<(HC~vOdUp(coWr@0Vi< zc46c>nf-d!K@K;oe#AJ9kEpMXYw~;F z7Z6Y>2?a)p2#BO~hqR=k64D3)qf3b~5T#2&8b(MdFuGF^L^?-FGh+0pQTsi^_viQh zXKeU#oO7Q0+@&`i!BEk-#%vf}0e#+_BSm`KMQ5+Y@4=2gk@ zckChl2Sf#A2VV{IFSweCeYOsDmi$JjS?kBSgU#M0Mj{)>Wr2Dg7Uj4hh#fMy3M6rh zZF0Vf8_+QSi1)y~6Zv>>=zD^#mHlON$oEk)JJu@a(*xaGIf~|CDTu%Tj&b`|!tB_* z@LPtoJ<=ldvJ_$9iqF9wbk^imTsK`idy)On??3GFY=ze`SrTJy$%*Uw#P_1(p9R~J z)sa&B^HtSaZ^_R3&5|E*r<(dkp?(C}hz^RC$l1|bx|cf%`qjvkmk1>6>>bLJYnmYb zKKPn*6wE9PaFS#Fld#0}0Impb(MXnm{WTVso-sHa9cOI#t&c8c;Soqbb^D(O+iO(C zzI&K&tZ>3ACC7uR#3P*@mgtgz4eTKXWK%rH&pbUlfEa*ZuF1=6`R4d8x_e8eH!~jq z)1|)0$)ILlTPLbIWPM4~FeX$bZo{uw0@LI9TUCh#HEl}6aQq8=(%t9ePa)=fE)tk`JrC_9PvXd}kf?7eLrrO#%8iI>qxL*r!mfG2J<4ZASEXuoy0}Yt zCUaXx752qrf=@YJey}Kw#4o%ORhltV2VLkjWao23=Q*Ct{T_Op(CB5C#JsLXV=Q$1q9nsp!5aj`6m`8xxHQgT3=p zgUmNdV;Yd`U5krJ&@s2)zC%ZKxe*pKAO18qYWKmgL#FL#@5MdRFkQmU zbu0PAwVe&;z4qo-qw65N%!bdyg=h(UEfYz(8k~$qF@3A*JE@)t-QweDrc&!1BKx7c zH~7+i!j^B9PcCP=>wRhd`Qn4U3cM^RZDRzNXGL_c^Fb+#v#y)sq~!oG`ci%#z&gc+ zBbmdgT^!3;%RdfU;AaSYkpT#N%zCk>OhCaw;>82AM8!ebhAKLmmBfZj17liC)PQ&a zXC}mV|L{;k*P*4_nHGuRmhu@qrrjuWV1==p38wXUZ%dKI4|yJ+v7K>2eT87Zo#f=k zZ0CF)9Gy3#NTzO>oOy3ABntCRhk(-jz$O`VhA0v2+$5AYCSOEwxxrLo3z5`|bvmnp zH2en|--64)AbfxqsX1WPP=LwWIhrC=x|rUT)^C1BV}fp4-`69Qv}%qtUavytPVt#E z%Q)$t+&(XrpY*+$W`px$?}Z3Zw14>oqvl{p>5m?Z3mkhxB`HQX97X8e7(q<45=rwidbH;j3S!tHtvuLk+%+Vjq%tGxG4YT()fB zr%SE<1vJQDl&h&enDmtO$vyxq3`pqx?(@XjUhHn|nG&pdq_Ob+_h*qviZ-{~Zb`A8+@|Bct|9NQ` z#F`G)hyq~vc7>o*}}>vI4s;t6_~8{U9WCvJXHf8OP<1)}J2lEMZ$K%HAOp>w)#5 zaAYU<(`NahCc!frLjIvsjKKjIqxL;(*CfC zQAbu=%|d3q+uvF)@nU`7e0M#n2E6{N-NZ9(WrUUR+Mv-k?Cxr1H+4VyA?CGI9V$6pq ziH_Sokj?>qCl0ye^-Ei~?*!kIiJX1u>jn;UIaeedOLSeEOL61hICLFcZ3+wFgW%q# zd!b=@I1@nyFa&9dmC!aoIk5jx$nW`;77Efo3Wt7q8)mn;dm35YpVcS6EG^>derC!@ znl?>Do?05FOj6~c?q1`QiZ`-itHS%n+bEcWDFlM~zSF{+vIR4pau5?)pSPpE^^on< zXs9Ev3O#o+p)H0GhAmladCAzf?E1mJ`Na8RRs&QnU$^EAJX`PaIrVZICg2+z@Y|on z;M%HEwd(l*d$zMx0A%+la61?)z^r=P3t~NCz*Dg9!=lfzK(y2HOEEU&dT!!&VW0Xv zL=(-T`n>HXFH2(d+NOs;pH#ht@LBX;TBR_e>c-!*LHEJ;4jbF*?#5cII_$t;4K{Vc zOxk1MRGH62mfZKb$~(5nO|}eiCg+X)ul`bhHQmhgWANR_L6EbTEK}3gj^oeNp>#$o zr>QfZVti_N^t|0_SKK27$SHc%B&!N)nd+6aq=Z@_cZ-0w7<|lcQ z`Q9-<4ecLdfc|)U!f$0K>ux2@^e}WIWHalr<~f691WM8@NcMVlAR5eY-Jy4W4jJw5 z;?#B?%h2SyJP7)IOr!N$wnK$adye{STw=o9Kd?OYF0xZLji5RYI4X8Dz*>@?xiUFy{HMC((RDtgW z9EcV^iAMf&s7Elnx8JZJKLO8Zq~bFxiUSXS^&X2~NT(jN#kx4| zCsRM1;*>l6das1xR>(f}GlpkW)uwVWy`QE=kY9+N%Ri|s_VYlihD0Jct~V-dd`}b_xx#;K4tN z$h~VUo*P3@--D6QE@BsiQr`if2-R({i<52fWgEuvB3KY=Bk*z_U{xza`200k ze!Dq5t8ZX;X0Sh6Z0N1!RYAK5_V2}3;fhtj3SkF8%NbBc`?#Nb|8HuqoOTipD{xgE z%`&uy1vE%=M&rtTStg}xLR-cz3c7T~*98SGCK5|>6~+O$k-o62 zci8HhbS&k03>E{!Cf|mb$p@G@c#y4W^rd>`aFm_=N_hnU(%6;mz8{_|jtCLa2wF>b zg9v+%o$FkC&$CUNV%{V-xEV^O>!tWNd8I{JLU-m~)JP;BFq!*3@os`70lg0ue^wSb?+? zHismdVfeihO%A_8;vkLqIAP$?_-V1u+YvIf`i-W+P#%%wRv^fGny0M47W%fy+{Ia^WS6(H{ zCUCjnzG7&AiLvH=pBygN2gFE2=(qb=Gwj72_5wDO6Ti!rvMVDp=U*?WEY|^mu<)bI zv1^Y9bcU&Cia9?OI-=Xz6_MxZqo*DR65o2EVyW+43qIY|&2*ECtx{*FMQj6#URBM;B7a~vtf1ovF zK!h;)aJuXj`Bfq>Udgu0DN?=ngwJ@eSHSm|rvfDaUDuJ<01~Itv^3wob1CpisYQ;!7 zM?mGppm2M^3IidcoZDSF*8h2Vx4l2GlF6CuIB3$mRa^3?R-p;jk4yMqOq)n?@**mw z!}~pNpJJ_4)1;bfXcm{{kp9D+--(Q!%p>B()KXbfE|=oEAo+aK@xDA;l$)NLtH^$A z*2IxMIaP<3{g^83y^a~$!r5?S%(${o96aq%N`CEiRVSTu8A|w_jB@&PD-K^P1e0hm z4gw?x?S~)(QkDbO8$MeD zu#wTzo8SD%R`z3k?Z=UtGJYG$SitAIazTJ>fDSO60{GOBNz=H9QE)ja^d{}9*Z$_+ygBG7zVAozj`btSoCW*jL z6VElLWNAd+M3J|JO2J7X=5)OitWzM3{qIq-_0mJHW_91QrMNB0ljWxwX=IZZe6^Zz z3SlSa@|Sp#TERyvhOePIG-^v`%hWfkezDhTt-pFUd~C{asPb%|N`w>1;(7&K+%f?m zHQ}a30NGmgMN_Z*xX&oikc`!5eZ$;B>IqH zc&9p4o9E0oYaD?_G1NY55L?V}P#w8vuFgu}5i)4&sD6r!zPT=M_O)2Bq^|;>DzC2a zDlze`abVE;3uXuRC4J||K=;p8+tSs20NPgc`;cau@5(}*OMILBFUg~^J=FSv7zPvK zg%y|iRdHHRLN-eT=rWt8$PT7tLYT}-7zU{=fOVfJP1}CSll>DXxJ`eYWJKLeyY|H280=hE2YA$8`sUAu zb0owjjpqF}L{z=)@tMlYE2F?r<;y;f`U6e_3QkuIDJ3<4Gj5jspGOY-Xt8>pdjG8n zB7+xYmzvUx^}UqK#yj`PeiEc%AX+Y+i~>a}uV)%4df|HF8MrZ5MjM(UTm9G1;3qqrZ}OG?RZFKDJjSzO_icLOfN~KSUZs-*j0$ zP>&v_t$Ze{_xhcc`fETmfSNnbL3cI8d58SdD90phBao!VJ&u@Ts5qA8MmQ};s($(c ziYu3)lIvR-eji*_;&}4l$Nn7kcf7A{BO=_Ox3-$2X*+0n*J(yZP#sO7p_yAm6Z}JC z#Z3kZ20o&#=H zb(I;|f^wHpcoVQMa4*n3uq=lSf6ABS@O|_X89SvzC<-!3ErOSW=l%P%&*_Hkjc^nq zGd9?~{f(v`L-Mb4o($52(1yT8(H1N(c*2Tp!({}IaccBSzPdqD4G&*i#MF5O12ff} zoq$tRQZvokM{akwrfS8HNI@2pC5>%;rrb{OZ6Vb@t;`?l`7veB+4SU1rkOwOnEQ$n z)Qu{gdZ{k9>WyX)`CgrK}vj?r+iv+v+J>=2g_y10s? zv7d2sOE~!f9s)KUgZ&+Meeqr}oV^xlJjs3Z_Eu2lXRx4z+VH72ob~=tB=?#((@f9d zE>?Jkql$(6gLnyBfx=2>I`>8W%b~kfZDX`C#mw0jA|z;d>${`a_FiyVL{*%Ca(sTL zkS;cl!f5T6|DA^t29}w4z~uI{GcsrB?`-C1iK(hII2QSqT-ul+_t}G*!IBI8{;-|w z!{KbNu>M%-B{ZKIMI=3--vzzXa*l7P@OlPBUobT*8!s++=h((h+X`iZ9#oBQ2mY+<= zm-dobLMO8G{3E-ayP-w}TQ)JB1>jp^A!wgoqFCFb9|_qcQySV=(h5Iv3PiROp@VlS+k=G$x>=kpcq6IueEysWTIPj5^R5x3p+`4KU6zOx571JFta zq}jmGRZ;~&7>`Q4itHb7;?_EQ4gd*#UMz{ijPVh&4I~!qqpLDL*;D`UMV}u^da%e= zv`$W()RxQpis-ppInPgp3qkD3>xsV7VP5_SoY5Z3R0R9Wy()uWu<_p+3Tb>At*Yi! zz(veC?&M7_T=?W`d*WF|+pxZngT_{e%@9?A^QNMmNK@L*K}9tl(?*2I@FDlRWo0YL zO_B*-&wi-=Ety`%B0tDw!kehTy1P*o=ua6&;65x99AoB+J7C~8{_}Pi9D8t}o#p)I zi1VIV04{5QBM*+nkU?1T)c zTchmwPhnPFJ_->ya9%&t%FHxTWR1s;P;=7Pi;_$;JCpOJtcvW^ae;SC3f}kjoBZOZ z8CKTwT1>n$Ul?YL%gcIzt^`H|_a~9ifhde>67U#8F#4~7h)V7P@(I_8pzxBh;vwSH zb$fE(UAex1Mz7zo&7(Bx7V7Eq7ww9bwhM{lDvCpdWbCxhi^@&?~(YIMXMW~nx4CSQB{=lR!|AjdgpdQPGKEspOzS;``Y_od+dnvcPc>H@A%roV(uKPuDsMRk!0Sq)6vlA{pz30#%z@k6FjP?HZyr0z)V5ud2JvsM0D#)egO5jVHE~=_i~7To->d%4Uh$pWq_H*?CHhp zDO&UWDrQeo-;mlBWcj-RfzrrzuiXV7Z=X*@8Lphp+R5aWVh5mO&d38u53^$CZ#?nI zx-#18v?bZ87#aOuj6KIVp^-!+$qm7x1D`1g5dj2Qw~mWId2nP@{oI)EqpX@ODlw25 zHkVhF&6gb|YT-^MGp6>6&I|c!|88jE*@^_KM6#t0q!g|=>u&JYUwI54JA|X4lv>I705>+xTw_obvcS%Z(y7v2z ze;JdT$$~LP4Q2v&3H9h=opl^2ob4q zk80PojI_9Hkp6eLSiApJk24MggaQqNVO;>g3UvH0lQ-B{TPr8fUf2vTqW6D@w$xHZCX@z$O!4na+b8jPrkHA6Ld|KgYf} zZ)tAJqAf3-QldPIt88!94??fc2gwl8my42Mefs8-QkvHoRypF@IKBeJ>`%S_R$2^X z@(wkuD8?w7)>sdgNbnOcfe!@8r=sKf_^J!q!$oVP^U2O_ruUUjGAk~87(CUad${(6 zz;q(~lA3Q^KHBm~=xv46k0M)TqeKp$Y9}L%v0p$UrPc3Lgm~DhIjg3zS>ianXqYb` z5&&wq!?0Wlu69|kV?~C>jneRt0Hy9EtR)-3<;Z<>W4&jf#SUF*D?`s9Ri!brnlY0Y z-OzcwbyR+h%r=C?77WgWNvy@TvqY9^b@q?Xz4v zOjwHCX>w)Ib+R(K`%|3ndPw&bPYNC9J%fZj-)dJ9RYK@Q1Hr6EiE}mr-%1LbI;9m- zk!&Fo;Wtr8Y0?_*8Ul!%a_UjGe>yl@G+w&ZwEO1j!^PK!Um#@lKo<9^ZuqaB0aO5N zajYb0Ayb?KR*1pIQl~h0YNH%}7iQye5rlJ0q7z(bIT)Tr@T5$Xf(OlQmEQ>jhIEp4 zlm_x?$w+FQH2N)`+uj>JsSlEP6GTqmyd?U1=}!}*&#j~)HzD5!LqUa^MM^dP9&&DL&D(V+z71yP>X_wRYKoZ{;A*aK6q9nYw|;%uyF zzUWh!+{yUd3~eTXD;Kq&M~DLc01LQR&Jq|T1M++JfWpD@uj06Cb%d(28sN@l62Tnd zZ7PnfAQPrXtiG=VZoDB-JR+=WRi(F0*Xd-)ZWvM5T5Ry!A}e$9e$!mvC?=V4{`Ea5 zo!fce9ir0}w>55-IXb125+Wuuev>ghCN6<<>$i-yV|~qe+bc#72a%0R*jinPN%m6VE&7|z%EijUr=$bq^ltDaJbJYBl%UGVFXwE=aZblqzzj4i&kFd0` z?n7T2qk8jrN~DGPF8(a$wvZ#w9KzIo3Pkvr(x8v?80;4$%APnXca36+bh4`{XQ(x$ zKcB90eClB3=R`&Vc)+7-LH}<;-ark4ziqv;rfW<`If&>sgd);O&W(wxM^tUGb@M9Y z3t-C(0|$=7&kw;2xL=uktQ`g`E}^_Iah*K?b>pU`3cFCB|eZpFewMKPtKut>HI0lGfj`DRP00j?MH zck!(H;d7Y{>r^9-#hzsLuYwtYQ9gwpnXmRGI`uVy$)uUg@VVvG_BZ2LHi1i#8GO-U z|f43?DEZjN@xRAig0oL&=g$O-=a1KB? zF2RagS(ET7zZkYUq`_N9?{3|Gmg_8! z?My{4`cUt8k7*De6I7da#X!aE$5By+_%U9)6ld2@{jRv#URNj_v z!zwifZbd{a}AnEI_Vu_=mR)eB9K}(QT4*?6elJDOG9b$*z*9%dT zf3L@*428F0Wn$zCyy}d1&RKo)PK>;%WLUi)O1!5p>flSC0XlPF?Heh1X>lh(n7V$r z_=ACscueZcSrZcS=uru$f~r@!fpw~LOCl$a+I>d2>j{kNpgj_1D=)$pXlO;k6O41b zx#}#L8~kkHWh~{0SFYx-E0eKj7hiy0WI40;bJfvI{j~OTe)TK41{#3zq>xZVFBtfk zXdEqe4iz}jsFkfU>O^`jXBb1-3qzLz?kyNyCi3UB+Z8BOl$A8(t z;hqLpe=d8=Gdg9S#{Q z7EvO_gZXFPfcj#x#}-sDaF-S;%8L-3akp1#%Hzu)Z+S=<#zHf2sEIwv}wSw@Fq zJ{dW=%A80ZJ{u&5_%*lq>!GJc#_|f~;CEzz#rAk#IVl)^Q5*`y5svHv7dZDq&y~)h zx+kkWE7B(zNx>9E&xwB}!BTw&f+%RfeSK9D0MkQJpL|)HX-=>|0D9Ih;Hc7k>y2(;V7h87q`Lg%=iSXu`6fcj0VHkcsqmF|@GqH>3N0Z+Lm6(Ou_I_)Wm@~X z@aNdI4m`}^2 zBXsJVHAXa6g7LYY_-$cEm>p;NLh{cG`%1R8V7(Thet6v${(oDHliiu6P4|X{wx4`ly|KVOrKm zl##$I+tEYtjX#*lF|8CC-?xHJB??i|W+At_J%taKydAypJ|8u}8|-ERrEM5{lacpO zYG!egCGRms5BVXs9Fa47FP-$+Y8*( z$N$m2!D%ke&!MGt73!5?uDu0)<;{=c&IVnq-?y$my34R?UwU8`(8c^yFXaZRny7d7 zXA76&$7>s<7CfWvd8S}~-rULZPTQj@KJrh=o-Vh4D`ZwtO1v0)9ccIpbe&ApGfB-D zuj!-pzUOb<7@zo=dkNOC)l!%aYtQZIW}S$EKuguF&tX=9;ir*#(Y=)Jd8HfFyOu58 zV@oc;n0d01PE&wF^-<~E|6)#{zH~Q?`{%iS`#+(Eo&m7ba(4iiu}ki9Z(xmpo(A^I zs={^=rX+$#af&(Gnnu;^YZpJ4skAtG;UNqj_q5{>ZP+%PHzvHXmfsS)Xyc}O*GbG! zn7ERRe72xZA!P=+ubR}0Kb7W|=}lj07JhU=AMoa1 z@<@y&9oIULYX&Gx9RKp#m)o}EhA`VclmXuEM~;UnDkxAASs+>@#}`1PId9AW&^N|d zK~I;iY5&e}SlfSa_tQvz9C!4`lkx$?{sYaU{oj84la>5?G*SeLQKiy0ucLev4eLfSA`5gxD?|%kDls+JC7u;v4}Z>x$;idR0u81K z5FATm`|2}GZ`@}I`zOL3i+YrbjM^HSpEOwz47`J8vKSiO89f> z*vH8=cg|#WL!D+ix=%J0k$>tw46Yls6+~;M(Wt*kFf(Z907cEV{iKYx-keRuzET*x z&T|4vpjv7@6f{>NX(1A+YAsOgK8p{`#|#mLT#U_t) z=4scV#)oSMGz_DXk`03|D#`1(+Gaq)KMBt4@OxPuzl#kmQh=x1)U=EuYJFir?iDz) zBP1}03hnqWAqHpfT?KS!%Ovnw&T*h67E2+DuLQNMBIK`<8}>q)rkrWFh46ak>q1Xoew$$B!pr60;Es^AC!%#BP3r3y zK>G}L2D;h1m36rjKC%nI7rwO9WTHzUA)hHu>ir>%&HGfnD@g>kAgOl@om1zZ$u6^hW&4b^XvhQUT+nT=+3;Yyeb*0$gzG+MJ zGs~vJsR0~4WA9wX4}>RIVF`djFm(mc$X^G9+t3s&R{T;fwlQ0i$3awh41zj@7Oz)?2?!_f zoPIuLd@%X#qxsWD$@!kl-$u8I*0>2AM%zr>+WnsPbDRqv1Vj&0#0P?JUeY9I4IAn; zG9hMJ%c479t?MIML9g;=9@y#!chIE9OSeGIM61XP%BCK{^?Nq7`u@-BheAk!dyGvl z0d$nvDIabyRL)-zz%O`9FTmgx#!PqH_JQc;n=g3Cr~Xsln1@6uJ=B?loTyUHPTm33pSz^@B)D;7 z&_E&b@3miW)afHHntJ?-50j2PDpr;qJJsI(r{4|*Yh|LEER&6dx2-F>WZu&|ds8t! zR|YKTg-sIpex)qdP&X4KZkO_REx`*{yc83^~A7mbCx~jK-(9W6bV+C-|vP&pfI}8U^2@E6d*L7qxb&Csx-s-Y)Fbhdtvj(g( z3$CdRH-6V6Q6z%J75c=m$DU~Z1%P%n14~gA)wu;Sfi!>lX#VOxYq0t1;TK~@ZdXlm z1_cJjqlB#)uk}=lIub1!&lnW9Q{OX#Frx`S5JNe~;AUX+Bb}(p&E8MsFQ2fN4uEF= zGE^SZ=uRnV)u`O(!5H?tQ&cfJKTKgG3#gZzWMo`RUpxP05@%~KFE=&Etv$qK&=vUg za1qO;+tU0fv=;cCvZ`6t4I8U$s&LgS7?e20esT zWjyxRC##To@~D_(xHdtw~^NyIQsBx%?yb1jj)>Q~+b=wr7{&Z@aC zB$<2JSA^HSl`;3OT^e70iUu+}KI$@Q&Tr-Qh6QQ1^`xFHQZ^uhPE?@3tji`-%w57a zf3K?5X4{Pg-3}6#B-$)WU2g>XP1++?6AA}lxe-WRvK;zRqa|0fH2TB?P5PM%ayLL= z*l_lX?BWUqqowL!YsV%D@DEF?^H-Cj^d@UI!t!Szv2W}oOC^g`3~Fvfd`BFq@^Rb> zMVw-N8Cngt8oZy_)OV3E*I^2{g@E?hcg$zMM7kWLdy}&z{d4ZVkym;WiS3qZn#xby zqY+R1yy~*kEh*|*2G;$HnSB*<~cc9wwSJfJeSI#*Ykx(EYH+wGyZ|GDS z((mY#y(IcbY&r_R8dwSf7kH;ahk$xhOVMNO;H|l<&o{@;v1R92Sb=($yp|uRAN@ld zpN2XOcrK-(cFsyNbF&cKB%i+R&PWRvi&_LOS;T&&TLAkGORR)t z-DRl`zAFX(jxcl(Ui-e48q9}L^-dlbt10N(A0n*@Gf0eywV3qd6B%+J{=hEQm?`s7 zL=g@5PZ1~DecHzgA<(^}+?6RV_BcW0AJ}fO1X(#pn0WGL#!i`baFBOoO8s6^RHh zY_n}TyWW2;x}pA{DwoWG?0iIJ(k*F~pNa9qk9WeywrL{rU9ydZHEY_hsg7e$geq_H zqC{df8WFV|O`hC=AYKZo+H*>e%D`0QxZoibP7diB(G9+4H+g3Qdm3S%e zPy;&HjFk75CMDl6u&E$=<{S4o1^cfYT#BpDBw=xbkXOd3Me@83)8emWou^30MDu7- zaP1{ei6WjVq6nB<%=4{*i+jpGJJI5HRQ*(a5?jU78Nlc;*AlIAQb?G^_c}$R@1;^@ zHG5(Op0%3)EAqr$#Tm0g^><7@^j7*m3NOcw^?h!v>TAyA6Ck55tGz;Giv2s)rZ-~1 zpbL}BS29vw1%}IxzHCPp-z6GEufpmOjE)$9L?Byp^@+X#kY3=Nu{wXSs@o$r5oRMHgWk=Ul+2My{P?%9#4(R<(la zAdJf2MA-w2qxnBuZAjFYlccE2_mZ5|HK4pa`DTDlgOkAeUTeM&k)K`UsOZXKxPrs; zGoM@O(}0`2HDu*KKa%#v4vw*@u-Z;UEc20-I-X!@P3`K;`!j{eLIMV!*l3%M1hWQ$jr=% zp>HVU1AvqNVwzPz|PZ?W9`yNamBKjXi2>FKWSB$~geb}@hhO##7C-~kMI zIMxfmh+;Vxumqh4g%g@(Y7+_XCDm9d54$ahZVwyS{_HkL5`OUR-c7x68_N--?(M7? zodMC)iRDNgcJ(JW&xn{A3^pqyUZoxI*9~$EOw`x!+U+bpUrH8ioH($}p4?1!D<=Ia zRV3IbQEK~kPf30IU>l0F9 zA@2Kw?I_jsEuwJmF=!3Kyd4DgAQbj*BhHtJ&Nx&kU=St-69WsvQiya;DUZU6E!y9F zSvGq0-S2`3k3!3y`I^motV$MKL?0zl>69l=WKa9=`7@ zMZNr!RENQ$yQ$P?6)6r>O!d>civIK@?p`2{nf4SnHB#f$-SoPQ6zYUWE`$7#T=KOa zDyx@DU+aFyeAGWCwa}DJ#7mDYH(hjosE5@4oYlhM?Tlzzt?OBw!)M;tpncr zzqlM1NVUk`4*^nVSm2j)=P|G-ECpHQuLPo0&5Q#Vye|qluBP{%J|T(!$f)ZOrQNiy zit=E8$zUULA0bLs=TPd6udMSrFwcTqNDjZ|Nta(Qo~k&}#%Bx74<1cSq2BAs725q= z_}>DFwb!SfL%a1%^XKes6Y{@Jk)Vq08P5hM9dhwnbN5I~z~}JPJ063aRmG?^ptq(& z>jpUFi1RGWHK=YYOhUNQ$o@}o2FY@+H0EUkvSo@630uEvQw543-hWUBSLnf44l&mH zs*x(!_j#?v+xW=`?&B>4Gwdi20hb3k4zb8=7p+;8k*KOu%mj3NBU71rfM`2h4j2W> zxt#2c8^(yxa+7yP=HY^Udx_aA0RQ-isrf z4+aECd`@Bq_pRG<>{@;+hmmMOVQ=QW;7zmBploujl%t!*;|f-KXM-Z^?%P0U+@mWs z35|S=D23Ad9!SijMN1_ixcW%uOuZ*+pI@w}w;5n$)C?dO40ejlWhz1(~w_YTB|MU*r^#c=C_#{ zjF#>#^rWXFN$}&w$MLKZyOlK&OW*hY(4Ja$cO6oe$+(&Z@rwvUjK(WylT)8DxF|Kb z3P5w6_v%QKCrPJVDGaBK%0x+NSaQg7hhwZ*3J7F=F@&EQNOY>3hyl`q0KOPlJz&NL zaOv<=EJ$bVpU2>i!44{U5CnYK|LSR#gLkqbjnGhX2*6v5U>W=LlXz1b&kg)!EnV%2 z+UKb>K_vKMP?^Vcl*o`E_o*y18_1k46=Y$|YL2}2Q=Z0e^@HJY|?w1^|%OvcC{Sssgcn+76r{?VS~>+f()`)JO1u$RmNb_Ry zUDhP9F|6oW^T4S)|KAFh&nAZVv#1OT#64IS~TsGf(?^}R% z(*rgSrWEJbK`4gIFX#BLHd{;FD_pPhuH1z4FnyOx&(DjL@D0Ey%hENF_cFS1I~&1L zw%39y?Z+A9HwN;fR@TKVE&IB8;&rQv=l0HSjS*T?rDAstWo)9sy zDn_!)4Ni4NT@X@{vUJLH*#V*4^+w+bu#BVcM|>P>ML*!i_EOutdk(+H2=}fD44TNKGQk*8%T##7@nUAy zYicu@`opOkfx+W4!?BL--GdF95bSTC`<#^54q|t@EI4Bm@je|ZvsF5ZY99^(Xw)S( z04Y+_>__dXDc1eWi^FFCC9_UV*FxSo`H`S!N}F4G&;=m0{3gH)8c1NsZGFVV5cA@0 zBmf+EYI}(_1}0V7>)zfGKSI8E{PE4r{D*fBea1S3+^6Hdfg!&W!segvlz$a{a1w~B z*fWVFIJcHdSvbN-&M|8BZwGW8#e+q$<5O8rHZWg$Q0HF+-W8ZeW%_t%&A7n*_RWy$ zM;XGy%;=`x9CDE)6fcUWtOz=G_^>JgqPL_HJ>A$EUBX>w!(5&(DJ#H$?;1bTlktoD zu)tA*qwdRj3iR=Rp1Q@Q5CyPkTHm_1b2%2=U+%+x&jq9#O#vV-sWZ|fk+uG`r8e^g zuTV06NRHaFroD;ye@uOOG}Qn1KPg(QQQ4Ok@)jZt!jMpjQ7RF}mVIBd4k>G*C^8sJ zOtK7x>`V5ov5%eXjD2h~#=O3-(dT#0?;pL-IH&iW+kM{sJ|1V8iWRP^iCNf+`k&U_ za~3|W=-wSM`ULax`Oodkk-WYqp#$sUuv7Yn<>AYtJ`IgW*IXh{MUwDY{@T>f(nW@_ zcCBRnIF5s^u^*9v6ZIBXKJ#W^!(_x6*chxJ_m)NcU)`I!3bHbUxA>>_XVj`)*sayK zV9M?8pM2!<=V#}a(KjfkBoEGa)_T;w#j*FJS~Z%8rrtrxqNsClfR%!S$j6y^TiWqQ z)dV^^Tq4hub7)0}-~DsvezxUyrA*;(EKW!;|HxfAoDTJHxgSn?F$#t(i;jmg{s#l} z^QQLP6(^Z4Mu=T)Q4_}zoy;1s;7)nGE|;#~T+#jR2YxF#5)vPhS8Da-7xEEwFYIf| z7NJ8h21Y;KaBWo<0$RnQO^-oa-SK9k;o;N%2*rV$&mTBTdoSF={9J!0VvpIZ0j1ae z-zg`!YQ6NY%MIF(KntKHxSUwvSpWF`NS8?Ln7*W4I@1nqx`q|bO#STm1)EdtciM`s zOF#7x*3GzR7Or};(z@+!n|^Pa)XS*55A2pYweB&-PsjMzOH}HRxxuLHXY|6J+ z!aiy?%kS;j_bE3243Cd(uf*C8`-PJyD(FuKBxYoVUUpTFAExsaZS-hU9a1tL&o4)o zX7!qo9x(6Gtd%b68fj>o!j0b$Z65wJ^<$R;EFk}FT@#aM<;ds9f!m|H@xuy zi~mMR8Mu!6CBQ_TaO9=jm)OK6!ULldo#Zvd)-%mTiQ3*NVOvtQEgAqM7IntA(tE%9m_iSx0U3|7{7ClDgQG zQ}Lv3{^+H4#$zXZbyH!fVPex{4&7nYdZRDNFfb&mpEE$iN!TO!=$!(wm*)v{#s$=l zjl#gxjs2)%Vzi$}M3q--F!X0LZ$ zp>p8RyuB8;nDm!m{MMOF8QiPwY#i$%=(#&zKQJw;!EGB@{ERH8Pc|@r+_=OrrmrG^ zle*X|e-}Z!Ujni4|BViOTz1);)K4q>0aNhkOJjIY(vPs+cKldO=q_}Jb2e}VJ?k~t zgpH8YJv!6_eEdpms!YwqsTnQIpXw+k{&(bn*e9l1g91`NgC+rcvM*d6fDn_)<3$VraX+?=u`x`c18bdYCTz}P3f=1kAEClJrkxp#Zu{HyXYERBX8T2 z;mRxbZEHKXar?;-??=1Y^gLt4B}|ih3D=`qi}E`i_~E?bUu82_zn`e`dql|hGe*ii2A(Vev$$>B(1gdR(kP`s8 zPrC){lb^Mbg91!>h!0|KxQ<#}X12g(lk0Qz%(s10#lohAGpu_hP1I#BegolEZU2Nk zPjOY|iNGyi!rdXru46vik#8k)-113uD#SkT;9f_19o#q)BDV9&2|7yE8`O$>HPpqG zUQ-c=T4r{;K~GtA<zWaeY3f``e8pmzo<}_qxO+R0Jk^99slQQ?3o#k4LFv6X3 zwftxCyoUP|i#MOMA(Gk32bO?1Dm(yWG=rJ^3h+@LTsk*#YfmID!#}-vSDVM(v)Fab z4z;)Gqh@*7fqOQouL5QnE*4`$ps4Cs;xv|9JrOWwnD z2R{7Hy6+J7KxQv`LMP!M6m>$+M`sVpEX~;2d(f|xa1~;7+56^@g8grjs1Yj1`P@m1 zSEJCZ@V%{`kdl*Hyn*+XkWxx&(wn%NFj9Wst)ie(T% z@=asRyZTIN78R3P_tFw3to1+@0tqbOhzIHv;Y~nfw~$+($GP zR!j+aU%28EsLHnsq_ z$g@((i!F1_fopHtLR1aR91E3V9FQ)gQ1KYScxY9N<_UGj?oKTk6=_k&2h6|PcRwbs zwf%mXQn}whS^i$+*0v%`W5GjO#_%q?uVRLmNGcBh;cWPO86nlyDJiAwM#A>hE3Kwi z1nt5P^;sHOgdOwiTD$P8{br__%!BS%(kDC%yjs&D^|>R7ASJa8rBwh+b-L2to-czx#9gkLiCC(u zymsdf{YjKX;hXyzvZC4T8d>Gv(|?*L?@l~&y!Y_jdgOo+?}=hETyzpfR&$wtj4bd;swAYKeYs{ zQe#T|TBTI{$1A_}w$p}%K?oD|4(B)`fc6SK6itKDCQtLybkLUp7#1N4*18cIV- z=pXmAw^*G&t$2<;u1bjOV`whvgfDV+bxaE)n5ocgUX}bjx}7W}kSCIyB*GvVX6F^e zlUY_)$oXef-BEYl)Jja&#Q8{h$*e*;2VEfz?0R^RmOrOrzkQ@FQ<11+_tXMZ{)n>4y7-BVl%S!&yPZCF5xulC863D3?(|Pc_ z?{?QR;Wcrkw>Mws2!E#3R978V@%GuvXqYC$%oh`^`>QMwYNRMJr_73>j`JWy-Es2< z3D{AS5@W&IbYSw?uy!g35us|XXDhC%6p za&EfzpF(}D`E!1sfD0L2^jwxaG#GlgRbj`rhN&6tw6KvmstUMwYpD9`N+Fw+S}aImsosGC#hLezr(@EBGebkhj31{qKHzToVC_u}JGXQ18l$>W&C z*C9!e+O zVb5m@KEGp5Vb^SVYs!5d#udzcyAZGAb`|8mTj5po7>DzTg$jCI&rdAKtprJV_OOS5 zu%1VS)I0r55cLThOfG|37f|VfdLDllly(;oNag)NgV2|)n?SG3#sX(etx423GAKC;V-oU&@+?)x3#RX}^Tx*E3e@S!` zx;TtzAif|l+70aYABQOFKL@yw4iFB2bXyr7@i6*$3mV^|#7%{@?&N59&zKq}VVP4u zm9IXc^Xs@-zqr0UXaDAgZCD8X8K;{|=KV!mVJ+u_Yw1)LPm&9AF2PH?1(i{H90NHfx%2w!2Av1FcY@qzTnpZqz+ zF}Le^k$dP`6JJGwpu6hb1XLh?<%PRyL1MvHTxfX-Dm^F_!0GQ4_;53a?!9dcK>5NU zB3sm6>&DPmlOX2f3(Vsg74=OFf-`0+Ve7#z4sLVBia$6q{-9qaqQ7NCkoa9dqVdqJ zufaSlFl*};%$plYP9D?aDeo#vc!Ikr`Za!`E;DN@AeQ`B(Y3k2d!$!RzI`B)2=JHMajLDP z;uR@^t3RMzVBiO#t6ou{(?up^D~|T4a1VAl8%1CT;HWo9KIL77A#=Piki<}CO11Zg zx>y>WO#VDy5D$Kfbd(v*sq2EeOJ_Hn+3BN4Rcv?}?Xi8UxH}=pBnRF9N_-Q(75P4! zZHs=b2eu$CsJc7zv(_fHj~?ml(qRG#AA1l z`xFiB?#m7Nd5=Bxd#P^$pD|hrMecNc5qjDTeI%aaJRDWfHTJ4VcFxPY?8>@Ga!(Bt z!TQ_RA={FYioZc8VrBJrf8*vht;UsDYD&O;4E**}dc!O`clmC^Ac9-Pml&Il2e2IR zjyth2)&~juJDp$94%|~jV%oq@<|SV1w%ute>;NcbxG(`5vruOn=5!3@xByKCQ9lDa z$Xee_K+H!y%FGnFx3S$R8Ly^{^Q29%$YN8RlF@Y7x8q6g%k)YvUDn>B(@x23TIa+%Zv;p`o7-nEd z&?F$ZSmC1M^+IaVEdUnXm~X~BA{mz$h;q>t$u1r2@v1-ON2`YnW?B1*nm1?vYmq<2 zpe+6_m#3RcI_b2(@A=WD`^e6r`V8}XN^7MNd&}Z^P??4Gqg`Lxc=ThNG$g)ZER}ue zUYPEZP-8Kpef|`=!*@k&bBVt+mpe;QQn^(qI-@-JZJ`C`Om$V{XZfcrUUmX_{7WAq ze|dxLhH+VDj_m>u^BYkV&g^)icbpV@z_SL)(bTvJ_E)>XAFZ$!0H63y_;m3liBko^ zaf~`Ue$n)!cY7oP>_1Gd*~uyue9-I-lThRt)38LZO~Y|Hsb6A#lPPTG)qG2KVpb8+H`gZ0;Ath6*TYCjF3zlWlGkMEY9(s@=8bTB zD|WBmNsb5b_(<&`NmXj(7t90}s?xN64TBCrl1jzoQw+v!N$`xk&46#C1PM&dAAmPl zf=hl|(@!u`1*bMB~TUy-8_i@{*^ z99F757wZgGaZsJDxeDH<#I@RcK8-70%$FXRG|D6KKN>ha9Uyl*fA`POm;=JYS~fG^Nw+$S`WIR;<(`!*}yoO6snrt<$R_ zozi|likRC5oO}xi(Y!9m&+C%;!+hJ)6n{RU zXd?$NU2A>Qj+u_e8pZToSNO$HSHx_8(TJ__C5_+zU5)-y`}3X!1X%~(r_XiN+R8-7 zoGEBFWgeG^(cwZLSl__kqPH_v$1q-4*9yIO8Z)jj0J_Km%0olahjK1U-mpg%Y_6LU zS}fuD8!HLEzPHDFL-qZ#2~{$ApO-u|-w)N-Q@7Ld*uWqAAPA-L|B3=rFl7a&?1~f+ zyy`S3cY#;F?pO2e;q%D1nKA3~Ci(&dMP`-60^@i^0`IRMLiQ8Zv_#R!VBa<(``wjT z)R_6;0Tyf0SDBGWm!NK&vI-~mVZt?J8jmKWcgDpi>ZrNhr%0j3BkAE294j1^JWh(& z<>xw!!qR-VGo(7qc$R8-2iWOeN@JFKz3&B4rsylUJ_YE9k3TGR#$P!C4FvSeO)n{9 zjbs640_w#vwh{t$oM!`X$%vEOdhtQ-37rFOa#zor2x}I8S-igZ*Tc>+L_)}@an-01 zwPje@AiH~aydCAn@>&O>KbIJ-dwaE8Vj&M}pnlfXk=#41a^cl~GO5>toVU5&T;qwl z_T0tufx+R+(^=3mW7^5vaWz8XKnTNV#%r1zi~5-xg*B#wh6cF@F5C@!Nit#5gknFUY#i31h~E<&2=zVD4{%5Dh8Zmj+2UxGzhXOdg8TF=V;&Lmd?&ya7Hin^j^3c z%D=n(NcCQ!z$>gscIc^3>PYLu@2u<>{4KrI?b8D0^zP^{1aofe2@ZwqKljFkUAjsc zajIV&;ZX7zlk;uq8y4%%YR(CqBPYZfkI9mTp2+`_UCC$R|D|@t+Z2E8^9hkvms9Nn zi;Kd{r;cQjsxZY~jX`6H3Mdc6%mZ;9MsNt_T<)2E*kXPi+H6C?`m^Q{FLC8wJ9nc0-H)!=xRrcRl!eO2Gusg`4$5-9oaS}%dq>9H*R?{~W|_~r92uk?!# z#`MS_ZcOL3gS*Y2y}tZ_B-c2u?kZ%M>lH&jw6v9;%#2{2#wpHS3Ev)?>lU;VQDZ)1 z-(I80;c-+&r|$K@zBFHiyK73w8pLn6{`iZ(Bzl9NB$PZ za~xd2wYF+4i@bglQtGI8d-nbzvExhJk1VKs(m6*vpFawoP^b6+)X{`J5v~Yt3#p%EuHF z%k9p(S=xIunU@zgO}Jgt+ntX??EUy`?5W6!Sfw!#IVv5$lnH1n$NK^uqnbWTwO9hG z(U+g*4(0sj`OkA8_WB@szI-_pZKRF4AU6{&dx;6uuA~$AgBscg7jl%Dw~h-&(5huDv~c73?&*_2*+!bt1Ex%ACqU`dY3RExEgtH^h}t-@cH5r)-=HbWr~!oCMUt z1t;?(R*+)~WYK-u2~p&v^DhgU&Kr9BF}0UFK^K4mi`Q$bH!6Oz7Nd99gTLzBTv*SKW0pT}?nadY%NypyIIG*eQLi_3b} zOU@Q~-MgrwrnuYEF5x1F|H|0pc3Q}6U#y0V+@4q(Smg&uo*zPbHW*O zH$M}O2ZKN(RjbEM$(0DOTRq6W0BBJIj|+tbJaTM^i4(bOj6_4>gefoAqdgD1BIUp3 z96S12X|UUy5EegaTE%>8n)CG9vwfbvPCemgT7J3rgiEGNJLSZed7FY3+n~br z0RbJA7ndp)qLeKd5>yChe8|YwzHfo)4nyG`eO3G-`fTu7b0Sz;2{=rW1cmM$p07S}G5j)bvQJ1~zTw;E zXbG|r(&=ojYZI_e`INj(b3nKb8k%>qXc2Zm(I zNb*cd53;ZyGTiERn)ut8!p5Y@<`bOM4#VOTEqIpvn9v`U-~UWS<^Zqm2KA zmi-o5ksFL{%Anhxcp?YMo{X>qH02!Ya1p1ba4ToB})U=R+Q=rt5{IL5`!-y-z zQHbl#JzKk_$!j(qR)~oJrYiy0M3@~emA}jGM@o2z#$T?NJOXDrBC%z3-SWue8l5MnLO2p?# z&E7nBQ@%53CuYUik7mx|1{5t(k^9)E_Z8Fd>d1D9?*NZg?j;7DLVr0j&G#Hcg)hZGAi{F*QGjZyp3L&~hMVR^?#*xQpa#sjTRlY$4N}u;+MNCHI z{Xpe~`yK*|v?hB3j=*gO2PNIoJK{1MTW_nYKZAsp8Ff3s;H9(#JJkvJ^@d7eK#Xcl3&?d5VTN9s zXA+u4c^uA5jno?rx65lBCdiV;KHln zNw;R~`}5^z@$0O|`s@E<_Fs;9sUOZ4*4E?qjqej%A2J+Idzf7}wYzj->e-^^zKh=p ziZkC4m~;aE)G|xE8guENprCMdq^^Hg^#^X?3efeTennn88ztFgq?vWq->UB3VNPNi z1uU(wBB*Xw1^#>1QX-_CKtmSMm#&ON@%l{S1&@^$F%KEVs%qV%GZnV!#O+%KzRc%@ z_X2jWlbSaw)3|MP#cZ<>jFF{_Q63S2ZyhuX_N}03=!BM;%*kr+Grg!%?J=|;!;nka zK~y08$SCzr-8|&TBlS2G|G(4+3B(01093F)ghCKKg`o8$hrWmDESu8&(`Iii(w7Z~ z-B&3;l}9n7OOcV6@j)%4BsG3v`p(Y`DLkWAF$H}C;qpV34op1H8(>F@thlfB!5Q5z z@h9B+JA}$3$22ep$!Y(EezxAM;7jp+;3(0bjH7d~`=$##LO93muJ3i$r)ZcFRQ7Ka zSEU6PC?tpQKBDlKth6isYOL6DqHIw2tBxB2puk}F2;IGaxI}Hf5fA!_h@&sVhNzsc zG&;J&fVl5%DSyXzj&ug zi3sJ~iG(zr0)i`HI4q7IeH6~q{+)^*bDW!j6e~cP9pxoec&KX;Lhsp=N3`AHU{z93erGR>_z)yY;&xN~BQ)&C^Ew}27=y;=V(P@jQ} zsj0YU|C}%6pEm>F-c-{k?HL8{He#PS1v9ID@e}&8WOLQ7xH>Mm*BIX570Gv?A?ha2 zaj}>$M((0_=JM@s5fk4SrsuakKZ_XM?j4lFuqf|W@G-Sjy9Bv8Md{cN4qMOGRpU@L z@xxdAjwI{4)Z;fY8k34lio@k$Jals3BgSk(rsD`?r70Q}Tb}m@5}UW8-D;*trm6S% zc1B-~UTL%&x;B4i$~VC z%KYhRkC5*LZ}s-p*vwkWCrpi#DkxUkp`RUctHd1NTt#eTk1&PaKX}r)Xkfv=!&DnI zU%mq?ZhYRcEziP#VX$C=nfV=lS9_a1ZCs3~yZI`sH*AUq2)OLOo7M7o$O79jabKpP z`S2x6jdW?aTfs2&z#jEH6Ut!mqF`$LNp!4kmVK|#Jz-s=;vur7&T$-u4cf$rr;BCDy}{mnm3!c*(h+=_mF7O?jpI44-8n1}I+6o+K?2CUte zsVzigSZ|qSefmA0>fOHRkeVXtpx)t@3cn@9&*|TD;8IL}u?Gr=!GV)9FZbGfCeSA8 z(%JVw-6GK7%>uBexO#Gr>Y}$STVV~y7Z<&d#>7y+{_ELGEWcr8sG-7X6uBeF<`4Hn_m<&4(tUIM*?o`bi{q4rY%T-AWJ~tr2!ji)rmwL9It%t zgY0~czzgysME-{^UNk*G!mQ5i^F~$a8x=L?5lH6!DEhpZ-BW>EU#slioH9qlOID_p zm_aD-hil=(zPD+haN<}xON@#aoTSJ!LsXIPeyl@JlN&bXgZ`n7~@(5bl z3NEmyD=r9?w+c@6Th$69L`qGN0zVMZw?Sn+4JSh1fPE6y7jKA&?V~|FC?SK)aUkmk z5)a^Yp_ay4NYG_0=oi%lF8C^@0~lVWsvB zQJ9FeOW&$PT?<;vwu%aMuO)q^?<>+)j;kU=JTN)h4&!fr!g@P3!@`V8W?Y@+loLP3 zs@pA`%r{z(8IeEn=EPU=fof-nob%&Doi*(mx1*h8w-UPV_=5bkjJ0orWOWSq{y`yU zfBu^;DNYzW`7KlN2?$^}5r~}!W=ZLHG97MQ6wo~L=*)o?-h(HcVd4$%hH7l18*zB` zUN&rtInv9M?{{^e=@30kT^`q*U-rBxF0k3TT4A`zPjqJMjMX{GNs)vxjtGb>F`#|w zE}72mE1-&%X0h-3!R#Sf`;Fc?4HW?CG0!NiQ?clG4M}~UHd&qCotnE>)nz` zaVW>s2P8;sk5*GEKhc+{>1%<3djE=X;8bhXBu2;4^_i))X9K@u3utq<>H^m#JCD-vI)+52kIb;e5&dJVQpI!-w*^#chWd1Q>LGzaC9n zb!>cS{y9T+g5;5|P7(onDeR{wbfosBsD3p%ZJ}mG7O3H)`dDb{KYM^uyYtQa)IDVe z$mFezTh6qiuF>caUxzY>{;!g>zH|&4>tA(8-%LvK89tQDH171caNZhY#j?VSLhTAuSd`njp>SM$=)WY3KX5Qw)>%M8W@#Bp~|#NkRh z`HgSf6ZqwSc}TMMKEmDiXCg{l0Mf0i10C4-h?dSj&JzFSTyV^ zCUaMsY9Vf%{{0jL@vrw_)Qr0_9abqU-_Wn}z|DC9*J9={b04q2E^IN=Ug-Uj-Ql_{ zDn%UKNBigeIa1cy1UlL4#Xj0uTtB#Bq@WdzNE;ba_=9(TUs0=QXLzC5Xc{XRPEjBu zkqP$#f>=A`qw-f`l6XAM{a+IbTts~hkj4JfHWYRm5Yc&KbrfbIJS_ypT(c7koDMKZ za_8Ht+Fj!}5xd#^H(-R|`@SynpaC&TB9lIiA_jDoGtK+AbJPf=cX`tj52I`7Q_Ikm zN+SrxoyZ0K2?4B4TBT5wGMmoPtQtI^7ibJ31t1&y`TuTOZG6KQA;!?uQ5Q4-Jk~)> z!cbsg^X@nS0N^XU#UXr$w5Ev*-kiY`zm7rjMc- zFE9x>UGz|u9Yq&@>1My&drMT{=BF0cGq=1}t~qf`wC=u=u3m06vkmN=PM;XDeeQd~ z--N$UbHOD7y5g7oYOG(OrqIu7xN~`LS=i~34Y8umdMq@59>KrzCxvMQH)4cIY;l6w z!}vA!BU7KA8>zE1JJERxv`(I>^3f;1WJ~k>otRI6A*DC!na?xaBoMMj&K?eQLMe2{>6T1Zj@qq zT>9Rv=vJWv@z&dU>n5aWVJ8pMH5+FZL7h^b-IiNOWqkY9ddb5Uq9(Wfp{s`y|6>8d z6qQT_RPk}84gof(zM&hyHUnBVa|8kIR13lpho$}-XV~K**?iR2fr5LO|Hf6fmxKf8oajP3HzvXNQLIS`|;IEHo;#FWuT+m+y=GxsY^2SI+3x-LQkBC`qR#U61OD zvhA@Z-l94)OGYjpv%o%JG`Zds9^yal$gk_?{kZ~g zvTLmZ%bk)NQoxJj+X?_P0!WO4dL5Plx`hb{@Xi(Gq$Lo)4q7x^mV#&p7*hF4V8%f2 zbf4Ymm+||~pFPt3z976|#MCXV}!UD4z3wFKi?ne#k{ykHJ!NA;#L|mv)S>Vz-1O!CMXe3X8 z#igPg;MQY7;i)_R4YpW5AS{-jufU(_1AeA>-A9{2E&KRj8}!+ zyiSynDb6{#3oE0m+`{s@ZgIsx z#-pJNYdJ^%4J-)M)GA9Ql%{$!$0l0!<`I*O1p-&m-bjMmgLUt&1Y(m`Vxn0DXa#KIAN9sw^4m{Zu6a5;6q{FIBH zk*#8R-OVUiD&Zwqgc#9*XQ?NPK(iN8sGl+RN$XOQ8-k9$T`Q+0mTl9{9UEJXeldQZ2<_@uu^A zM6D;CuOi(jmSeyds{1e7%DC%Hd+|6|7dK5xey@u5PgTF=fpyxfR9WetDOEwOD`!9P zdViE#yP}dznn@PIcj~#ke~J_q>2Ql!bD9>|`+_(CqZ$+n_8u{Q;M3c980Z#5L`)*K z|K~9<9wOl4lH<5!_DJpHhi|`$ty|8BZl6`!?`rw;-_4^=!3u~mEtd2ocWK%s$LYKh zGxukgeEp>y#%gg$my}6jjLmibv)@5}){XQe2Gl9txdYLCy3&bl4llDmEpYVg#ek8u zZKgW6o{o$k&YF@m>qv{dnqGJA*CL-gCLxfo7hMfK5OGP-{fevLV(kA8gl?xIB|t~^ zzb1qK(M0mBDFHa#LLr2`ubo5WT!%5spK~i0TsnWi`YtN4#zv~-mFrE{_uig5O15Jq zJr|{MOi8C8(LM5pcg3nv3}!brt=)E&RvJ(m|G7P|^wioSxSAq&?S}J*TjW*TOm~;< z{ny0lZuw38?9G8i!fJn=V@h~2@hC4b#vzt@OE+=P3G%fQ`zhw=KCoi5mw3=Wnboa7 zj(1N2^r)0CnC|1(1@ieq`Tiwo2+K~gi-RxuFB$P|cIzm@=l*X}S#JM`e!rTdsFfVs z(R)%!7%Zp5#Uh4pog6hfcGh?=lS`1-vy+dK&-Qni`RzWppVJMt{VCMvhVs>W=81sg zJ41w}8$;HRXUDww$t^Ta^OphPI)s@onIkSJ$5_m0UMb@Sg$44a|B*ZQ<1zfDtpuju zXTxh$CNS@v;|yS)afPQoWq%Uc>2O%iC=>f7tprk#J5i9VO(@e_z*Fi=9B=@2?(+WF zMN@~jQ=zfuoNddUUz zt;!V}9J7Cu*X`EQh8*5+ai0`IZuJDa5Jy-woz+c6BZB>=eq(k zDyw1-{tqp+mMuY@O>=RFR8YpZ^fLBzz<)zhE#J;KaX3i=}0EVn}n@eiv=Bl$H+p6HcnIEXws;mcaYDPYcIu-9Fc|^zP5@)%!fQOgBgF zAoyr@FvREGAM46b$=wcA-(j>5D`Ou=$}#r#F0F?hw#AOV0a38yXkuR73UC+r{h~2c z>OrA_NpCEh&CT~-mD|L59#be`U2Sp~vajVa`$4U&Ig?IkPwC>6QMmj-dUP{re$>L^ zblY>5J@7xk*b8_bI|z&#=*|F?6A=8KFO=H_9Fx z#0MN1Uqy`Ozo;U&OFd!-TMX3MFBViVmTIl6e65y@gt}8VyATfGZWuTo{BvYVMyNV| zV>^w*j^T9g-i*G@eGpm{P&+M(es=Jr$!l&BUn-VxhnH9@dNzJ!g|$k9Cn~dbtNkg1 zYOR3J?#^hx6kTIxglhl2YRA#__6eH6*qGGmjP=ebc^%^S+iuWRwy2VGl+I2q zS_=p&>L4PE8tbM$0k|nxWsu=LUgi^ZcUx&^{;0AK-whd|v8xrAhIRU%7-TBBF(da? z@A{6ZXu3+p#BYZ`H7|bIDY!y2nJ4uLk~|RvF^dvL+zZi94c&nnE_br`icLhzHz2n)afN@$t*fxLnQNg1tvpEEEZvopx!X z6z1NM0dEa-K2%xc-(~w_h${0^9r(W6Dqp=ZGgIMa+w%!iox;j%c4jx%J99zoTiysx zPH`6!q>XC3IkFc}8&vpZDpsP7mj)fwkIsQFhjugLOc3Y%ACU7Fe~1+NRpX;06c4P! z8k3q6nUMvTF29D{jzKF;fTY7Ipmg>kU5G871(Y|)n+;kD0$!zp1lIo7c$_%~BAdz- z-R6u%v_xE4>hQaUB;zZCahRUd>wAt26rzMPhV9D8GM8R38Ly(q7BB0(CWRYEw*YqX z1koiU$+|(KUCEjd#Rr|bb3**N>1-9Q0i8HBZf zgI*d5ly-sXuq1VK;R2o?q^qyar%lBGSQl5%%kN=Pnb4t9$L~|_?~ZcM2MW8A?z+6& zht18X?K_P0`yQkeRi!z;r`Q<~$-YP3SVd*NuGYQ_{yJscd^0W%Bh8VtK>2>dGk->< zFOK#kqx0CUv`Hwxq1fJj=+Gyh{0%>XCuIPBjnbmogtH`dC>|wGR)H8CR9-cziGty6 zBeY--)GkOPEC5pkKaORHiFKg70C^vOllQlq(Z)<|A*Gnz=SGFl9eJm&F`cT7gz+si z$y1-OEQhjbUQB1Y3E2m@!;|L9vf}U8L+(KdqEOzHa4&JQ+`oU#94ib^n`yzg{p>J1 zg3L|n9EYM)WO^B?snqq66nKSF6Qzc2J!6Q7-;*fHd~NJ}vX`Z1Q0r2X27^oy%fZv~ z_oZie6lrv8WSgeAH9@fEDe#ax=zl$^DI@}9<2lYD>#$z{!d5r|$T-(~Rh@@k!#>tQ z-A-4=O^LU{<d3SobUN=j#D=Z5P_j)B(0L*Hglb+K3^^pX!kfK8`Idzb41s zO)4_pENKJPe`PD4p{jj#xA-^%$i^f#Hy@Z8jOrz{HIoqFV#Wdr-whm@!n+YQAo>EL zm+C7*VFchd2pGZkNn2iWdzUksqvDYC)Jv|zKyPLmFUqc1tyrTTXfoPi+7z(;Gx>+1 zKewyjdqu?~xPrCpekq2=3(vo|BFLpvz&{b#47ey+-{R;r_*6TiZ7=Wg#Rc)@&vrXI zd^7h*&u_{60NgHnk(wqWhwCsHl%^+4k-+vdbSYlsI3(9SL{R?%s-3RAB|`ZZ5D*Ir za0p^rmOi#J=^}`!8ADL0fdJDK9M1H~oV?8Q#PR;%QF^9xBEfH(28ezp+BJNfkG~B} z$u5SDWdSo{_LJxXr`UeiWaUrU4cxDYJ8s4f-|%@sWiR2+Zxx2(tIW4-@g)7bNS&tL zuWopqTsoZn#Aj@tNL52yiZi1SLm8Se+V&>QaNVV+DUz4e7+Q+ovA$XD#2mBhYP@-PwuxJ!@*yUSXme>*qjYc;aNABr-endrogw zY;CDxr`w}#D$eU?yAN(hyu5i?SzdmX_~5p_r%rKJ8T^n1XG(DwyoV_Ag-enKrH%VZ zDt9iAJ_|I%DEIhlgpvj-BoDK+Ptj9?)1EHUiDhl6DZBNMBp}ox807K%=OB)K9JLn# z#LfU$Xym!A9QZ-36b;Tb4tZP66Ji4Tjf>|(qa#`|$a%To%=&;+WMAT%OzeM$DxA?* zm3wFg+k+%3>3sRR>))xf7Kj$-`I>x{q7>hLWP94UqIk~rLEKNtuR;)F&j9lvf~j=} z@-3r3d5vq)@_ZY3EkPNAEkj<=6x>Ad&L>xoyi9RPTZc*MJKr>tbiZ-rvEo3e>pB*+ zk(_5us2e*T1zouaIy4mT7XX?Fut@yw|M6#dsQ&t$kgvWga`PVaM(%}gGXqyq#rxZi zL(8T88F7Uc8A2~^D}H+%w63OWbkjm0Wvu77-gTOvDL|kk`tnxdE64YumAOyN)_z>m z`C?J|+o>maWPsb}M>ylB$E!INze0MJ+HxF9TZD3V21f+;ca)eonR5az%Ob~b_@BAi z9VlnWjx%bcePjNAJY9D@)!+X&3dt(U%t(=vku6+NB-xdbE%VxYUm_zJQO33BrEtks z+(brPJLB5x8rQzo<#K=TtIzlMkJjVS# zv{4=w+|z9UdMMSoB(v?_Loxd^1nZ zVza&{{gxHV!Tv0U4vXkGXN!ZQ09yvu>Hur8ox!)};LN;%b}Ip(kw%;yW9m%wZ&2xn zkZX2B6WWdWZBOdnPt;T}u3;*iJNE&h+rPfBmyRk}1?73g{?jR3!Xjcw$8sDOT_@@) z@_st8u82?dyPYpe|Ne%?k`%{8KSTCv0djRnBVt*LtzhC{3awZ)8GAcmOl%m9D^ETMXYc=0Z0GrQUJ(h=0}IXyKL z-MGWvfbU)hkMKWn`$lR)DsQHc_0yM)d(`Vb-R0>udp1j~pNwylr(|*1=ywB6NpZ<3 zidYv)Cu|yS97?nG+9Wn&;W#q?uW(b^ay!qAR;3362UanF{&aXGpZ(X=S<&Vi#D3*h z)N)HBAg%Qc`R@cs!Woc^Lu#DP;VmvsX#_+BafP3e)N4C%Y0}Eg+U32R#OSApNj3qJ zRJ!aRW4G5HVN$r?O?}>O@B84vXcvgsKl)=H$l(j~LgMNe?0F#r9kqv-Lo&I!Of(Sv z(cTLJ>Z}#2t5{{Sosj?FslhG^9*|pc+f;6G#Oh z323bu#QwxM!39kqXSTDG%xivKc4+`iy4^h_dvr%bV08KKirce42J|lhhLhGo-`gSH zDE?>FH%>&0#TaFGH69;IWDm3%2O^soiyWLheQKgx8<1m;S=S|vYDlZ5rx>#9R?oIr zxB`D1c?W*otv!5Pqi{qqB^Kz8PYiXX=eL9LGGnT-D2z_jCfp4;o2l+*uzK z7spF2jA1&b#R(@s+z0)Wtp4X)A!(At6=w+NSqI^4i_kkRhs25he6&sS;PCWy z)9uDOteI=4?)Sc|Ot&x-DwuBlk*d!|LE+v2j4Lqn{tI<|EOJ&5#D3_@VQGgA4d$fx z2D&l8LAZ;Ch`EVAG0BGXXX9oho}?0B|8nsO93hbq@8|2E9I_N3jf6~?&mIIK71(zl z!zPAq?})r83RJ)eYb9E$oia-2F?dt~nWG=pag=cyG`4Z{95MW1}nw6&wzzT#dnD)n=K znH(nwAac^r2K0E`&>?b5y4a?R!|N8Ams8xaqJ+8xFCu9eAcJ&{ApLKT1$a9%Cj<;G zWu|4|QtwYbYFBE9S+CpM{>X@)2)1uqYU|!Ne#@MeUOPk<4ItLQHZ(k~d18&htvK-LtjwfpCg6^HT8@@g>l{cDQBaF?XT>D3z@rd_sXR? z3gOnEn!p<8cvaYPKZe}}|OhY!X5Hyv0>iTxJ+O#iwM8O`XOJ~Z=9ybr}xNa-wS|ate z$QF1?1<|l4Xvjt^pqeKHl|Y-(oo9rH!C1%v@cko*;0`GQJPh%sI$*6ZS}6Ow3SKTH z_B|MW`L2T2qQn>`FN2!ZD>#^`N$j#BBC;(z(3#ELM=1%#RUu!za12AvNQk$tR>!V+ zk7u}-U;IQ4DiGC1@YHHGY-V-F>Jf}jhO}_^+ec^8UQGqMA33k+b-NvrNS}R}tehG6 zI<;TI=IZ1MNlIFC{Q$fDyHB9E2*Ky#n3A2qDMHvH8s~Q+Mq#M=-*v*|u=GeYAuyFN z1H?{8nsMpdq~z>14Jo`|K3ZP!H!*`6jx2F^0iv~Z^kkO-cuX;E)+IJMNRZ9d6iGW) zOQ{#kW)jY{%6+-B>DdiFJ$9yC7RPes9HIx-h)S_1`u4NMq7Q=UI=$$msEwVmz1d>J z`Q0a#*YQ1%Vy5lsSDUW?M4u*{esNmb);{#&jSXI5hQLBQu*e)B_5bhNjyY{VZw}1h z0TK5Zph*L|^gk_;yu9nK9+QE+`zVrQtgKPEt_YIVvA8@bj_l>zL8gTpN4K-aBD-4_ zr&@Il_~eH)r=^F}8KdidqP zBmeVJ1lSxQjNi=E_T;i2>Q}oE6rtw*N3Sjk$@&$59q~VorzkhpD|ptL>~Xy4uqT!a zZcHP;n5_(7z<;gK%VJQe4zn|s@uzHMqwfC}l8$8jtLdn)^v7$E#`<(J+t(QhHOjT3 z76*%91ztZD?wk#fZO@oUdiBd7OX+Ly(Q4M1gWuq2XF4^!MSq6}tlOR8_|~6sHE!IP zEf!u<6w6DVM#({slr@>$e|FOKShx839`}jy&^9&3M zBsl0V_=qc8zEcN56N{Tjt0rVoMa}bi`1tbaJhPLJXIFQxEN2bKVq%vJzE=mVMC#T# zkHKy<7*=n#+4z)S)I7F-D%5$S4hUuEm4FMG^zcK@y;Ooj`tf_M9bhYr@83Uc^`;TN zAeIQ^mMjKWSbP==T3h&ah1K^jJ>NDy%Se&4=*n)PR%=5^wNK3W%F(y958*JYpRe1j z=-m>ZXZr3}2CnrpU;Li*u-(shxAD&+Oh3vphCMtbo;^B9bf2wClGMmpDfkeH8U9{YKdN6M3^T#vz?fhchP zYo{9-dyVIHR}X0P-{%3^V8qiCAlw9;t)&+a$Y)F6k?KPL_;+DFP3gGV$R|4++?O%G z_j?@!9s5S*%MF<0S%1^5YR^$|bkUqtP+n$mV@>?o?xd027U+;kCwub-J|10l&@R0m zd*r`ax34jc3m$^!T!`?XJNglwaSXp8f|)scm8liP5!vWjxnsPRf-%X;ivfsOC-nc$ zXAo&m{{AO%h9$0%X5I(>ra=-|EF~a90R3T|^~dCmw`^bgFpQkxr=|uT1v`?^MLs{$#}1jeyvI4aD5`3ox3p>|!jR8XxfCxv+%&vcyn(L-R8i#go|5>kls zx!fRo`c@#3!3S^_grCzPam3yR{myTQ3}Ct01Y9=cOZy6A;MHoGCmzXfA8%W%1YZSL zX~}X^1TsBz;H8T#d!4m6@8z1BtH^sWmL2$6IxqAVU6|thAk5H&{Bcs2yC$1PP%)C{ z;P1>t>SL`g{iKAbJt*H3aNgok=;}``4QzSm1$)?vm&wkw=^6(bT_&8gI_7cIi<1DU^iv z`KVGp(N86LGbxo&Jp4L%;8_*_jEe@DZx|Q^;&N!}?M_1RmwkC6q1j~xQ-fDsFPtk> z(^TH9B(+95D)_YO_Ng-Ki!0OMgve_Km}AQrkeQo9+6J{c-4c^ylq;3<`7$X|VdbMQ z`}Cau_+k5ohR#*-JmUs43^hyUspIo54hWn4+mXRU- zA&T;$(2-T?99gF?x4jCA_%Pa03DQq0D` zo=lI661Is=ZQz}7p+U%qf8i^g(Az--)Wk2DK`2#6f8;ZM)!-&6ZGvIlB-XA;Wq-(m zE{}2B6GU=QHoqHvxJx~TW4x}&ubA2I?t7>pbcST((NV>IeT-lIpmX@*m*CV|O>z*F zU8&sgGG|CI+c5Ij+SDr}!a=kj$a=qe+aPAAW~1S4hvi&@D$~XbA{koEoX+(yU~w5Z zkXIRQX5)YJnHhjL`En0L?gp?eGDpCYc1T?)XraRyJF3nkyf&v6eX`hCw8NQxYvYfw z;J~eEOK@voNf(0_06}tRyHim`onquEB7tiD6zQX_r>@T)edt#4JC`TlWi86~v?Wx) z&rtHhm;5Qc%`w}letAWf$oiY%l#4rGWyV7AN>hJd`GnCLR^c4irq(WFvv&$kRf$kJ zVwgHlQUGJjcFQErH`~txyZ|G9S8ZLBJX&N>#ugI2!X=dxu`$%j+MLuzRWA|G1Mwp2FjBkiu+OC?nRNc#1kq+4>2!tm=|+!eT}H z>?vvii~Dy>h%As>1A1-{W}@~08sPvi?p`5q8J2eU`G>_~XI;IcLt!^LPk&!fZTsl> zE?DKFFBsJa_JGKKz9gj9t}T>GFr zF1CEr+92_r3dShRciHRlQ}~kQ1O8Dl1UxjOQ4|=5ml5C0vnaF(;lCZ=6!7`A6Su8# zgs(>gb8;y)qpnZ`w#EGcaq#upDOE12T0n4`LR`=}Z(0C+gZ2M%ZvqIYVK(2qpC|e07lfdGa_5`fm8E-@=?pdbzkeY} znTP*MCair9)xBWFf{m{%4hC|h2w{2ew_Ll_gr^2u(8r;jfYc?iq_lHFa zHDL<{{KIBhj5F+)b-ZX64Q4?5ac9QkN$6ju86VTLy zON5X<1K0`3I1*=O1EB}R&*$D2$vta~DT_OjD6tw^b~|k!@}kq4Q#lNe)4ICzNxT@- z0ziNy7^G=*UHrbJ)IwqDjPKAxcTF)Ay)T~nE=u@ag(=^^jQ_)acHl88zQL%~ev}4T zxvy1jp9D>XDE@&BPS8H_U~mf;6iQ&Zyg#FsoW~CPtvV0Ex-mqV(F~#1nRn%xt8sIEjOabzcJ8_T+W&D5J@=xMpa8Tt;?Yz(Xi1 zC3TD+!02+EoB|myf6c?+c<>eyW-kn%ZCuyC% zTR9EdBi`?(v)XiL$c+ud_Fy0|&7n%B%z623zh;*~``wm-?c-e*PFT z81eqyvAiEI@{}XeqmOx}FqU>CHQMMs}+lBIla_&YGIek4$PJSt+SJMAkIy*;%^B|8lJ-2?>=k&a-Gqy({uD zB@ARd;720!_dWs+p#mUshlJw*UKF!YAgMqE0zb0P^5Ow{V*;>#N^e-4rpHom6Y6yd zMV2HFpB;EUK($rL2>m*1N28iHkO zEtxe=>9r+)9IbO|0?8`*Y8E~```%-onfb}2SHJ(K&^xVG928ot&~V9u5do}&g zM($Bj@W$oR8H(mMiCb!Nu-1Tng}CwIyy_Rt4yG-g;M0pn6kQ!Tbz$jAg_M4;-BwOS zS|d zChV~efeBG1V3)#uR{B>l@e=q$kVv^l_SJj=UpnezgoY|;%Ab8W;UqEyRC2lUTcyfo zQqfifDdn?bx+672bv`-d0en5(jm7+SKZ-so=0WUBHum?ypvA=d(3%F@@uK%4J z9$Y+*CtSc2Hnt#y6Hxa{Ci%OL;eHu34&L8F#hwcEY8NYA<)i(DMKOpS%oPTE{9ddJ$nQ)6T-imPx%G&narw9@+b`xICWe)z%>tfYHS~1Cmc`Vd;lNO z2zYgBN~4zjJy4<&+rj542Jx_5={VtFB&eJ?!zR`R_B^z)n2-Ur{KH*u>6Ldv zp>VS{_p%|1ZVa;DlPvt9A} zSL@#LU;V$!*#)M>Tzrc*a;ylJVS2Thb{WM?%eXHzo6k%ZjJEdpb#T3dn*|Np1JYFD zM?nMuMv~niLSQ0F+m`78*bFQp4!G%E-n({Z+Nx&K)%}8ZB9X~AZje-m^5tjh&I%Tw z@Nds{oXcoB7MjsoH(%zSNGP#iun8tSQD|(Uv5gKm@xK<4>AmAi^St08OS}k!cHJWMpSjB)52`> zi`7Kt-t=IHbdK+x3|_CvA-NZd4VL|U6Ln#bazhGZl({W4r!Ik>r~P8gE85>am~gX- zZ|b94@3E)zuUEJ~Lv7@eM{M*vyZ-tfBhNRI^;h|8WEiwgs=YR~67@IIe>iK|So>D_ zm|k}Cn5Tt>IjYHUW3PljqVF(O_DyGGMepLA%*He$W0EX{?^w+M+1HlIwQ zE6=n#_ue&vz;{4U!Bof9!jE?H=Y+wP4T_;vQ-Uq{=f`*CAKxueg@mTW`|R2tv`vSmTT zO~PkAgyw&6otJQc_?^q`U$-dU;_M+IbRUfnywqfKMj$x@Ep{2&f1qKyWFQe0!F~%C zaz!Um8dp#TeqlJ%g3K{}w5E6S`faO;fVmS1hwo?CoJgQrUk7;rfH(x50wUDzUILNF z=FEP;EGM%hNX{}DjQrlbWHc%Bx^i2M2NV-4fT0d#C4b9miO@yuF*x?2SM9Z_6h~nJ zuV>!Se&bx#ilpjOgE-41)~62LH)MtHk?dcrc99R9GN(8$`MQxj90C8#OT6j-jcy44 z`uK!{276%Ul)aO*L%`|3Xxy|-dYsheWfJ@BmuFCAw_>A8qJ$oaT0OedOe%eV=>f>) zW%O7zovd=`uqrcoIfynzuRNum+DY*yA)&@h4@NbCJQ2@XQ zVEb6tg#p%$BO*`Ar3j-$KLZ5$48jhAaDu=N8=L6r^;~>5d;IF@m_cmvTZ^yataJGU zy`7h0Bh^o$WCM$iV(vc*3G)ZdEY!6KeNT)}WOw+?AxE3NsWw$`Cd8jO;cn{0>pf)_ z^4ttow7frtZP;*es2!)-WAZA|EKL!aK12?=${fj<2+N1y9bDv4n}I<*`hNEt)}24` zQ@l0<-ds9iq;Hj&P4%dD(bfPRWXLzCvvZ>c{rf+9Ab3EM`S{-5KTMD5SAvC)r!yPqH`Dq2K`!=fSQqk!h27bSf;DhV&J*Sxp*{%EE}OA3px80LNQm z3I^aXrv+GRG{+5cHJVHNPFz&@Gw79`kxX{xh0=7FCE zUUtvY^4XPrvZdJjN;=9S`u(YS7|rp=(0usq4(f|mmRSkxoLGkkWlp4@pw&_Z1KlJS zv@r|T0gosG?$z!7;a{#>VW*qU8L>agG@SXWX?shO+A4Y+nhqb&)(f~M zASi#<_Pg-w%Fywn(HyRWm%|Ds#AFIMJW#(ko%it1YcgT)Vlh5@k$? zZ>oEp$lg`yJSP)$iX{JZY}hB~hfAZm()(`1Rpra~XSx%P(2|>PJt-xFuiLf1?|CDA z+gqj<_TFxj;YPJatVz#rxYBJIK?Ue!pZuh|n9S0<1R;}bNN;pl9?OUCQi~id^CG5h z40g@!)36ET#nXXGU3_>&VnqbS49)d6w@f3^N)`2_w%mi1txEc5#0tL$0X_f7013*Z zs2RYdOOzylivmGRs}+a73mf9131vr^?#2D!H=&m?`1LY>@JL37AG zSxBjT9$iyv{R8-hl+yt(3Or(=S3v-`n$x)viV*U`8Ue>NDu=(1hlogPyp{a(emyu( zm86O_`OdWn6_XUKn(49X6#y4_s|1TumdaP_{8o0UlNJk%sva~)%fHTbyQ64bQS`A| zV)>xka8QA=>oMoZS!LMg(Y-DwR!%#2W@7-&pV-^O@UKa zul_aX+xhfk!OJeKzjkB}rSQ>NG#^}0lxADU&}HU-OSPlklO7I3NNo?OPB8FDVDPJ6 zGKk-Yew$de%0-K&(MC^MuHLfgj~NEyqNhbT!nQT5OQ&k9 zw*BwZDaw-uKSkL&*6uuZDj1LuRd9ipgD)n)NDVngF-~QgVch#@Hk2cq3{`$PI3zzg zu?~&y|24Uv?vVVb{YQBX?S+m0uD+egm?af~2I`$5T0{9mPvym==X8Ao`(ek@i!uMW zXaQNqbL`{4st9cc2jCi`-vGG$4nPZ2q9S_-s$x6uYsd4Q!ZH0YH}@g`@TA1w>oF^v zBp-@))CXATzxGSiuh~P3Em* z#R+v>SOn%A=0&G?!;x z?9h>1OZkqsQ6&12laGQXd3{Oi$n1@EWF@U>xMD1|<@a*-9?G)(A$OyI6^&Tz-rw>C zNtjb4#vfjo(X-@Ivf>gvpSr(?FJjI@z;4x)%FTBN0uFK(cFHf@;fd z4tJ69=-rYlx$;mea+&h8hh@2tzj}C7EX~t+Eoup{! z&7B*WdMI~dU_yV6gg%c$N(4i1N`$6kBrZ&jAx$CKB! zy&vzLI#DJ$D28h$5j$k>F49@BEqkorE+^_6cAD$E{O*)f#8o4s*fJ}8q>}`2_ z*t-v8zCP7FHKbEQva2wr9GmVWget;+2S0c9T)XivFc1xv2qT4L5r30IRI4FO0Z?6w z>+X}PiUwEm68JK%oG>;;?LLmVWXRe*=TVkBrpSFU_1<ZFMaXn^eIuV-1haxmF<&FhOXMXg7u@H%PG8I>uNiuQ}79QYdIxm13 z&Mm6N{cz9Rs^Syyk|d8+j5c|ToP54A$VOWUZ))n*k#+KMQ$v2|6c&77TYSxhgzYOX zMb3B>7}@>rMQj|Wpr_v{o&EV1#eqkb~$KXB+Uf6 z#z}~?t95x|)4%QDmfOfiK0B)8bPIY~(sf~4u{1Y~M4_6wkv$2WZ^wa*g_Rik4Hhd? zj&^7HvNVJGC%y*DKBhl2O}QEFKc**6PtF7F%XGoU`vP-D;&hpr*kPIhP{l9*D{<2a zM}9<#nQ2LrWrHU^N@*7|X4p2m+U-d=)?@idX^y?144%Qm*=?SKr{2;k>sqfXQzTQI zLoL83Bl)c6=_smzcK_TQcw9D@nTBKuKD6RXTW!DOH6N8QCjrm)3U9wk>2Zo;82$3@(Yxhaoi!t(YP>Mt0cZe#`(UU$H<9cnSxHB)Xx0%;N-)6rEYYA_sJPOy#s}QqLJ>atU6h^J5gF z*R<%u2E+YH)#W2jrcxZg=_cQof&*R+wCCIb@HP>@2@%V)kG5EZr4%8`WZ|4< z5yAloNI^mg5RUiXFQ~Vxvi&LO#tB;T-OP)$n)T1=T9vxUERRd}{d#{E|AK2_+OI2ExAI+%n& z7jky6F7~kt?a%t%YdXQEPEmx~gVDys6GIoJP^%cNKCZQI4mTwuN++ECb?Dox=VR>< zvaqHeV=WY$RlpZy;GkBQJv00tI`KcxasJCF5uV=R(gr!PwIsikDZd^b5OjUzj-z*M z?j=iCcN2-GL@M8!hSb?X4nSRYZQOk8m$_bxcfZT20VO4TfODZJSm1~)acxZ1wszMn_IHb6|3yDT1CJu*>+-ep9NlI3khl?}`1%!a_bxNcl=Ax=n-yhL;r8 zZndj+K~WV4D~O*+zQ|)`+spU5{*!MX9~Cjuuz1_StaLI;c;k01za}M?c@S}&g`t;_ zp?ihWCp0b(BLZja1Z~cfAD6R}RF?rXqCkZxAi)J(WIACq1~8LG;oz$TuF+qbisJJ{ zOso3`$5QkGW&!Rqx6z-wy3u4CvZC8Yo;)l139H|wzak~dy{Zh;M{7@wdOqA(wh6wD zgnMPT-iKFOr13f}%JD1nj>35X)m{g;)v!t-y}d9%cUbogN|F`n3Y>(~*NN%`jwWRy1)={2?`AcXX^N%%3Zp!u~ z1Te4&1phyn=4u^q_z%Q6-nr8u9N-~8AK|{d`l3$)XS^W2$q_FkP$)uuAR*{EWy9;h zBYwoQouZPjDURiM_@;2IirSLbiM>IeokYfHwhQ+_BquHU#?y-6vU0v7&Q9Kf&|8Gt z3L$06x|9wLd|p;s;o&;Y(r)zI-wtzxA6aX8O9Yx&W{!4!^;wqx^fx$1>sg=Oq(+$+ z!-G-AnyI%pY!k@+rEd7q9{f2AC7m43r+Eo%a{t#Y{jP%%mA{F z8^)w|+hPS*E?Fss-V)@GY81ac+GiMy)5?ew0KN7cPyJR@CHivtbLk^R3JPX6Lq_JF zYe`&oPmNikJmh6QbELE{d99nAeYarn$$Vv+({zJu9G^!1_J(^H73<3I&?DLOh2+|x zC5LC6@GQ;At*wa!Pb*><}n^0`}uT-E%0r=J3! zAIujHozG*4RztLG3*z1a6&3_w0Qm@n6^=zEKK{!APw_b`#rqSE9hvoHfqbeF-Ltrf z$$oe-&6u$A`v>kGD71g9#zBgb&L^hIsHXMBeM7wm;-gC#s|t+`j5s@W>w8dNfr50D zx<@}3yR=o*-9Yw1T=1l_`;z`bMnF=*$mV826C+A&C52&QBKCtfdwPC}UvsYys-Lm+ z<*YFpg5h--INW<8bn(F5%eG*k#{HXkGAn z6mIc(B0}=XaRR9rLm%hkzs(Lq_DW~c;#k>-A7hP2zJVCP1Fj?v?8!X+iw%3xax@=h zUVLp!I6wuDaP$Oi*ZH^mjitihy%W_Wv&W{J4Lfd*HqC zgoRs1Pd2p7|D$ck@%d1Xg586~-Rcn?#eOQm3kg^T z2vC;*_8kG?0EFQAYXq!>kiJc52~nXx{Mqg&V8z>u>ECC6^PB=|6!a#k*nDl`-c?N3 zl}Tj7^f1}dve%8SKadah_8J@R!IFMfbSl>YrUJX*Y0OaaDGZ39mKCV?8LZ+iBW; z)@d+!JtULL9A_c9?e|Obk|rCtY(e5z?3+*g;dahWcn&3S{{W}ioXcHq-9Da5XJu`+ z_cDU37AwO-4R^IFMWQIy`OQnsc9dzW=&WyCty@8bFYJP>JGEOCgT>JT!F==SkuAR- zeUyA)7Rut8V?9;Foa}U*%h~m)!EG>Z1V63t46!7!BJV!FXrCiII5MvrUP%w|?+g>m z+DM#!+1D+=!d(DuX24pq(b+`R(D<1ULcC+W%ppr;PbftM4@SMb%G`LS}5xB ztG&|9w|FH%_R;1RjN>iTfbXts2>n2DBe^JZx+96HmTR^22X=3?a%S;IWg8Vot-pLA z2hQCeYb^Qr_Njz=eR5lQRr+8NN|cr33syPnVvlVd=6S9`E^AtR=?~H#cZE|y+tHlQ zvNpn{;2!cg<5qay=k&49*=2Pq5b~vlXz9EmEl76md6+!6@m9QQDr8@Ot!2_N6nF&0 z_(V{^r*P?z_J4fR)0gs*jHV@_=yhb)+p!HJDc5?w^snlUd~wRr{_Y7;r!{m>guCL4 z5#djGY^TLN+r_uCC)nL%q4CPeXDo~!43+Yk_n_%EWL4vN7hOMMN5 zj|}(U#?RuScEdfJY~!HQ7-tnH;oH80_o#I+kvmk3GIlQ1UxPpA?+Zyij+WRc;;N}y z(hneJw!~}^;+ly=ESz^dq$oEaK4Mv@tb07(n0iVPei|!Tw;v;NSD39Bb%)DcGOt7 za;NbZlT-*}0;M=Soot=yw1j^&H-&Gclp}6S>k2trv0LO=0~IOYI_65`tjtdgEuQj)Wch8C+VcrNkGR9q?d&{L=y zC%Z&#__|u12Uk#j3p82~eE$|ZC{JPacjMK|&^2$S6TLQ@`pPat=mQqj8^g-;ru^_4 z#>PM9IDD!y@5}<8A`Ja9w`uxKRT075jE1IA?xMW4h|5v_uNs3q` z(jCtO`%HiX>Q=$uIwOS6)+$QOJ~trC^;3iS$vc_GRvMR z)O#}y_Z)&7QHv*06xskcW|(3Gm6I(zu4r>g?_h;a?QotW;15!Kk-X(1|83#O;ECRt zr1i?ux#OPHe}R-Z4enqglIC#z8*c}czoIz@4u_G6t?=zIGQ4O_BHJOb)=@PgsH)M;lYNq&-pHP8gML2YV13`zp+IuokiwhG;2M=@FE$X*}j^8yg za6Mc6GiRaIprg%VStu(dSEvD5 zZHF99L@@%dGd2VDGggu#x?2_@vxu|RD;#NwmZBsArWNf@d( z#E)HW>$843iyE$(w|aWTH)x#0tKw>JUX9^H(vA0|UU~8J_iEI*97VzOQSHd=kz0BA zbxus(?%O$*D;td4n?|c;3Pw+rCF z3l?+Kp?=9=#0YW-2ow`zKKniC}RYT95+oc2iFv?8mi zC)NG5Kf}wYUH&<%=2OOHqm2e0{}_#f4ReuzGwK*9xa%AfO{_W2-!Oo|bTz>1ngPOD zbwt|HTwKa7f#>@(57ACzrH^E~{gq@g0NDw)K zf$3`_Z+S>I&u>;9zqx{XP;RX^XZ<5KStH*;+bMRWYwp4F*{v6Sm=H_OG+6tzBU>>E zpO-nWL$Hy&OPs#u!%pGs39rAcjcyu`{ce^iyI8I`a{p=GVM^Hq{VuN=m5p&OYeB`- zFZ@9|9;EEUlow)r@fv@Ad#4gKi8b8-g#*#G13UhaxW1;Se|p?5XA8^Q1bP+=SJj-A z>}UlEhsUq&G>mqF(gkT>L0^l1GhFs^Qv5|Bpa2h73%gNc-%{gOTt<4=Lze=xY~O_o zk1LT0E#D}?jzzlRP;qRQbV?2rv^_<0{7x}`@_gcDy?}&O>;qx2#&L=P3-!L+tj1sd zuusPm!OA(jaNCVa=ZU0jcB;$lJ&ztc_N!UqQAC@go4lW0FO{yN7hs!E@ccj z`j&VhQ847(ymyF7s4ApQA!7GPl_|*IeOi15WA5BxJ2nifzW}EA19k2%(3A8hdmE8E z^0^H&lRzQNcJ*hsih#p$qOnkC^#J9p&2xOD+-J+nV_zw*E;F#JBhdFoKLpLXL?#=V zS#K!@+gYL2NBpPBUD(TeD6OugE1$kcc!jAo;o<{e6czM2e78T}o)Q*uUm5CnHRD^K zYY)$jYvklPH)oi{aP)?i#jzaqDqk| zQ-&&3Fb}_4)FP2jmowY^b2RkbbBl~n|DC4OvjPIpoT4GhW4{eKK z!`U?0WstCl^=tEl%C}DWJlhEPFRV}C-hLqgm2PZ{a zhmn>igsj%naFJaYNWX4R#fhgLbY#0Z&w17HZRnb&=Wq+H23-x}eUB39WD7Qh5RK*> ztX6h%b3u!=bg_t-Q!OVP_h{y~eKVz$J@rRSG29ZUmKtYFGkX`)Q~;k$kzCj;(WG3` z4(N(qv7RZjNb|F5Nz3PHWvSHR$NX5Nh#)x;!1O_NW*j4?n`-FpK44v`1luuzVga=; z0F**(%n;{~7H9vpXd-bb1}TIcMjSy=savnn^F`@oOLE@jdW>Ag)!y<4`S!alvzkV_ z4=2lQu03QMVrVj2B4gO!;h5GcPm0KVF!suLxDeSRyU4AFNIT&n2Tzh$(3qp2?teHD zU~PF5mn_)~8!3vo>_~U5?B(MiXq<2RBzq3c8{>4;cPlP$UMM@0|0^)FTm(&BsnkLW z=e?a)%~gb<%Po)Lbe+yK0cDq8Xo_x@eS*QF{i@;ro`C^9Et+7eN~}=Mqg5+jtab*- zdG4(Q=1GmeU`2{7d@@*RAjo_;^59`F1G=%*pU@*bbf5-u~!D%rl+p zY_)(2(Shm`I8!vZv8iOCdeif%UUCaBl-ZoE%Fa(s;kW0X$kLg0E^#lgO%l9No^zhC zmK#=B1*_n7aq4@rhxm=-VNMc}s=N=fwE8=1PDs5MdwYSob_5q?Ct+W<(5yy_9RF@y zEEL-`;B-cRj3kT_SB$KKa37BTVK>(%@Lbivp&{Qq3;^FrkR)*VCn_>>h|gXfV{(v} z@A5Jla|78M#)=;ZS-zz>puf(DtiG8w`Vn)xc0(s2@JHAaxhR>_K_AH(bLSlX9BWTe z9xgqnZYZtvv0PiuNv*}ehJ`|dX5ZJD?%=l~3kj{8MsJgZ>LdN_RZqnrrRpBf$Nr>7 z98V67&HPxLzrgzy?FZ!Ar5|fB{#_e|U{j0@jHiK$TXC;moRfHVA`a+Zd^Jls_emyk z=ERUY^Og`F=<$F;m9^(*mQ%#jM5c(E2#k2e^XC-G1F@NjcH&pqUC7_FrE0eoX~ikc zRLwrP^GYb)##r_R7v2dO+O+Y}ZK!Ay2^FQ0q&~#5ZOnPe@1!F|dgmV4-ow?v2lUHr zk*PD4^jsrR$e=%`>g*v?6cvF&vu{93%F$2eZ|ueFr)Sgc>e$R5-X+9Y82zFU9~>dESFUx)2VDzz7FxuV z9Wc6&@!FM}ef{LaSXRbrh~drZu_>HPcb}UEZTLH#8=3Kfd|K*G`q`mXp;_K-2N1|5h=)~r-sH0ad(z+G+l2ikuGpSd+6Jn9qV zCd;|LHjB;@9#1)&UjNzG)$1*`<-gW)-WDb5NN>U4;bwjjWix?b3i-GE*L`O82XYqm zOd+#N$sv!QqfD`i)a^q(`;M9Hv^aV8g(kc>gOl3U^CGTWL1oq%)V*GsP8W9*8{Qjc z(`X(I@M>wY8u5nqfP3h{15I(5koM5is$fBK+n;A_Z%r~ZIEOaxSBQ;(0B7BFzQ1&HBik`eexX8cmX-|S$Ob_Tnf2ju_9)O&_C z^*vp~C<>w!6&0l;3Zeocy(M%+s-hw_(n~1PI}uSpsftMN3etNo0qG^Q0HLFl&}(Rc zkn^74?|(n)K~$_RQ=xGiwzfL-x*p%-s0KFct$3YHK>Y6@vYlJ@BpO#>{w& zF57%r9>WA&bN>p594yRA#+Z6AcVf?xZNZ|s=8fU6!p78I9mC+&2~0zqoriSO`p#$8 z3@B-@5u4um>qk$0|M@y7j-=}CN@~=5nraX7eB*#KOdl-qnNe!5zZpyiwt9$Y3w4?_ zawsyVb7B&w>F!t?k$+I^Qn-O)zC)RGMRJnbkLHUf+g-MF*G8pVXV2ckIKNZdHryEy za+EyhX+LDF*D&H@ljumd{@i)Wy~C2MPPV^BaU1%NXErSL0l%+>l)LG7!XtZKFrJ(>49)q~EiiHYfJ{EZE(3{*a9(fZshkXqSt z2lcpHvBPAp&$lSMbmK%UKcL`-8tu31)SvU*3YE;LnMQfeG;}w1)Lh+H(vf_)Fqsp! zFB`QuFv_Uu8jTqgErrw@_{vQTB}o6SA8*#7#pcPwg~svoj$j3ow^ZY~&WJ;Bl5O)| zw9-JwxWEf=;ht0ADQsuOA@Dp59NmP)c!aBrKvOBnTF?e67JcnK*)MeRDp{|67L(y69?<4p9P{b`PZLW z4rTJu+;$y!E&fiaQe^cTv4jV$fQb#(rBv8{u$KX|mmEg0+6EOU2@na1jPr8-}&{S*Uy6F?5AzDi=G}{sZY1|mP?3Fzx6m>a^GwJWbn>O zkdV7)m5{|V%4z2!CBb`0p+{$yR~O3o?#~y-Xxm!{2q-}NuWx`Yb;cQfLi|@P6TQki zk4ILg_V_54(+Y@FHJ2x@JYK7j==IZ5au?bLQAE<|0~o^jxQ&UGVy71flFI-CW4Alu z91#~2nwgW;D#(&uHHl!M-WOw^6=uXFo&%OO&VJF73r4Wics!Mga zijrQ@oS`e|KKL3VRY?=w4ZNwpdhdgBk?=^qeKFi2#7J&awZd?$Zr?R7`A$Ehp`qeO zT^mehQwv6Q=M3eKjDfbax~jRcYRPYn*!dMibc=G0JJ=|JdGV1HW8k|3cvfKf@GZ<>YHy z!Ccllv|P4#L*;SJ`HY;x0<5SQA&*X35i@LdNaZd2fy0-)oHk*)tDbh9n6$U0h}quO zo2JKhZ4)mp&KvPtZqUV3dEX+gnfNy8c<6F!`HuhDzbuIb12i8> zSNDbdOOP7E2>;7`!eUoZMaS z%GfWq8ub6woVYp?9|^JbQt=HdrqkS)S>A(_X|YB4Pv-BHkw8UozfmBu670YFmm@gI z3r=h#;eq~l&Vs2-7)HjhYWK1C!hbcK=Q0C6r6Wx*Us>p6ZGzbM!{6o^XHE^~#rUl} zx6=3JRv)L1?|v54qGc!syZB39?u5?ARU`0qH5dLS%RP=iDt>Z8?nT$bwC&lq>XW$p z95LwuUyha9)Ef&|O9$%qbSI_jUH$|<7TA(IN~+oG?TE1J6LRe#EN&T8xZL|$Q77_< zOg=DVnv{K$hQLTyV_v0Gw;2EdztF58D-EmzP<}F(d_z>;zcIQ6cJ?W!P&uDlneiY+ zln1`!+;?XaXJ^jBb=T`1qjXe1X{Tn!pXTEr2jaR27GOQ)lXR@V(wG)Y@Rp9t-bQcf3BmOWcEj=bwLb|G#? zO`Gf~_MM39JFYF1*ZIeNSq>;y>)u&1b@%#ki_3ZNqVm8rnM?@A%K!_p8BgZ3w6oUv zOCMHk-#t*=QQMXl@HD~}#{r0vHGgk#8IAVObj^wY$z)&fBEBMyx;O-wra+^fq3t0F zmC3u?oZ3jc#A!+nJ_DF-XoK(ZzU40J?N}XhMNXa$wYA@bTDPo{zWLvN4dfceYN6XvG-;d6=Zc5mkQ$_;0|lA8Oa@SjR+y^L%QZ=ySc zM~+_r?$sXd^ZlQ^U(+s!m53DhV6%gF1pT&OQqg(Ee9tse+>Ao`&~+%k(V{rivM0ej z;LajNNsH_F2RZ}mAI2p>Zjgp+Sik{vCFz90_?>g-;A3^?swWPv#$DgaFYunbEv;>cMeLzngm=?*Y&y0SZD2mF6=st&|s9HphB z(~8wB#pPCBHACnKJ<_&xbW)hmlxiY#lk3QL!k?4}G0?WA%l(K|&J!{Gc4 z0qgZ?**f?kG-iDW#(-M?WJOzIo}nAFnBufOf^GK0-f5WSyi?dev6n&{l{F0)W*0lp5;AQN1GmrfX0%=c-HUJbf$`Qwk=~O79rTFZf5mUWJ^EvHlD3ZIWJ>){2P- z`pQvs+`y7d z*IX4IKtYU=9yzWNak<%pwea9w3mjc_%5b!c_DC_I9)0Lbe!Tt`ee!rT*+zy$%>o`d zq)P%I9as=Lnz$*pnM?~6?`~ssXkAND-I#mS{0u|$c-&K) zf0#KbOcef#I%Z@+^!BK!1AJs&|3J#u9-b-x-SH9YGA=m2mNzE;(k+wC*$1Ky)l_vx z|89z~{f}+^)hZ`t?$&}}-p?kaY&nODzy7Z~3p5P`!wh(XXG18Q-&(>}_?HD2s_V!J z$K}$S8#22Xct^m^q@(gKwsjT41B>ltlqL}=`hhD7by*3D zqFNeF@qo<;VFr#)0e38c4F|IWcNXCLKr#oAy!}*A9Xi6_y9W+Pv|S3|F*_g9r>%gU zc04aw(04b^1NuWoTcH4vA|8j4MR7F!+!PwHn*AcuO@HsGV>MfQPAzGfZeJ{d%yV%$@Wi5DFyl>DKDduv#zJ`7puEBKgaxJf77 zQ6&*({?^)|U3!aR<=e?5WdmFOcYoOX7Wk6R21{{}aP433oAxAo01N}bH#mKoAjK4L zgavGNLb3sD2D_fKeNcc}x`4t&7GKT8*qTPmX!P{&G9}fmt05u`eePQA0eM%Q%~|638$f_HlMM@S+Hc*69dGgEQ*4@^ zc%RK$3=YZ%ycW?D=U$yCoMc|3DQ_;%GOBZu&4=?A*rD9&H5~UwcY|Z%D*}fj7jTz@ z#=Z^J(ddphtupW2q5b0?VEq`%A#b)hY-QJOSooZYHreC{?L1~WA|hfP{@mX$`~t-H zXWw0S2;Gu!yH@Kn<_vMMi&I zu5{FUpEQ$lBi{n=1B@|03u*6@(qlI(a_xWK{>OFg)>S%8ZxFn4Ndo!VLR|NA5XY^W zK=0b$CC2G;Me{~?Rqq`NSIr)f-TN7H*fx5cB;X8c*Q0((vhw|mxX!>~%obR-aveD$ zfP7qT^w)Bzq9#bv2^C)kh#KFjEzIY5R5@ngZ7J!P!mqb@a>vW<>K*Y==W?G{HXUcq}RiG@j zyTTLR+gr?obn{VM)ahL;?=z)2Z@iq(8-|>~2!M@P(2*7nWh~Iti}ZvP`u_jBoMIM0 zRX>oT)X&EtOp@IUr#XSQ@Pm#_bZ?J;Q^~NSU>kr4^Ri3r8Quu|q{1}DzB{lUg#1GD zCCjw0l|49J+?S@spkc>#LHrKFK!^EbV8R{ha4JI4y zi0T=IuIWgx&yrz5)qI}V+);$+1x=z@=ny2x(kT8}kf_~xTVC~0j-&Wxl>3xHDceAd zptt6nFzEYqO^JP^doUPIK-{D4KO-O7>IP-OzdpO;tZMe2$K*WTppOYO?0JK)*gtubpYsyGlSNxs6(Z{T`p$fqn8@2sai)ukZ?t~K z8P_sRn!`H!l{9M8bY0jeK%V72+2SDIZ1?aJ%fqw#ufhroMR?YFG%;j$rUn=bT*G|P zfY81h+oT}v#_b;>YtfWp9Qzo24`7~~Zw%hMB7BXBo*;=biT>eb>OT)-N;;lWe!>7- z%-?Jk8|vJFg2S{$A_1p)a`E|_Uut}dTAoi>6Y3kCm(4gSzLwJz$spVUsGjH*`NMdmw)`h~C-r+=q?9ABXWanseqX?S4^jqP}z4EB1^{sVS9OO46lP z8nu=G6yAg36B(JH?&7v9y?(uL`jdv8_cyy}awVO_tf~0z^=UVY?4grSN%O4#Rm8x+ z0~X3QPrV7)9!aXo@LH0WnaK*5IOfRF@TE-V_3@D1mi(Jkh{20jrnC?AP3e@UZ$~wp zb&F_-`#u>3FF1(jq>c5wrzP&5uR5V^RO<^5n>Q{}(P)@W{t~Cp(!1`M1GV!bMrDRK zAL(zEhBy`I7A+`JP*C<&Z1Q9(J(2o&7g96njL7=5+I6|B1~Om3@Nq1oTM~O(*igy> z)obrUP9r;|q~ccTrGEzy%KHeQYX@A3P>?Xun?~uJMG5AZkQZqfhIrcZ!uy)!W}#)Y zw0aSIbpA^D*wcFhqUrCA2Cs@fyp-BZrk^nO#?xyg%E#-~3g`aCUpl3f`xef8oEH_Y zc##nur=7cQ;~kGIUvEuK$rX^Yjn$266*?DFlgairoOi#@W3 z2acNCV3XkmHR|v7TRYfnayO=%&w^MF8p8XK3;8v!MGKY&XrA7L-mXeg`~9XG#7_j+ z1F7MDwiVz(QgsmAc?6t}M}Sf%4n#IQaDhz!p_B`zD%tGHVUQfZrDr`=$pszuYtO0d zrOP?lb*@;feX@LPubYOa7RpNv zv?mSG_rpGT;y9Y-F?}Nv-)CQ}sjhwq zFTjlZ^J1~aeXj&jw}dTle5kCLrSKk{49u1S4IIR8+;;SsCocxlfmVQ$V1Z|3XxK#=3oCD8V17 zeBr2|US9Y)c_NLc;U>=#2g7E#27Lmwd;u=m(h9pZd1W=`_cumPov~3*Ubvt+%kc-d zrw$9%eX<0+rmJv@X0v)k`UCqXRm#WirHF+Z^tMF&;B|{Wt7;kb)*XIR<}X{CDykYb=O#vI&4&A$|rAR268}J+~Y9 ze%8~j_sH^70a-=5qqM@0(awXI!Y>tk-k!XF+0;`jM7;$c=_zd?3flSOH)*s|b-|UO=h{3k6xC(bAMaLFA493L6TDCN zIffT>6uPz4B&0_8)VM+QZZKO#Tq5F_n0Y(G`uF=?by8cg=>6dR&i)@;QPe{HYdOCC zz>hEt7a5b+32taF#4_-j+l2ez*XpkKDy+3x{aM2L)KpjIs6HJJ=Epbe&Q}%B46pn; znWvAhk>JT&i+NYTwlcxL-=*VyG_a^TZ-~LPYoPb=v3+9BxuT!kHTzHq1d0Hi?;rq& z#>9hlFzH0%XM_w%&C{a5un_|ZW&&vf*u1)aJlR>^;<}N5dl%Vh<`iKc0qMU$wSoSA zBP5{&>P#c_GrxDnYUGu`3{HR#kUzl2Z=XEjo%_D$1x>|?X$?n=_*)M-j|KZn7&e#q zzW>y8#Y7ULzHhTj$@JOPf~9JI-Cu0P;Q?(nEc3kMH%^DEPWF&P+Zj<2%;VzYA!w;L zV((JQ+6s+jhnH}^mk97%b$oL6O-d}{iYc*MLj0dC|A%m(fQCK-KtUk&q|Nm`NHq~6 zZ}1DW0yW~xgFD!nwq;>-$I7PsE-<5RxtxFLeCsLAf97FBTW!&_0b3A9c|p7M z1&quGH^W?z;qhtgz4OCuYAl7g!(&uD=CX8mr)_c-kEBz+l*$H0_u_))(%rU-v4H^9 zl84JC{0&q&HZ<8$-{oc(TRA$H%Pf5#vl$@QTf;bNIGbnniZeuGU6W2UQ>y<@4FkN% zVpBFzz&7|zy6esag5>khf66ncvZIza!~4sAQbFx(oI`8RmOB47S<5bKa7P^F0tFSSZInvC}~dmSt~^Yo(4U)Zd0|# zchQg3^9_U#5tC*(-&|F`^;&!>eFQ5uU-OrLbvLlhC;=Q4rS5>|m-N#btqh`3Mp#+O zk&2-IhA-LvojKAv!Cpm78~|JYfmb~$-Y>;ThXkE(L;7*y&OWB-I|5G;E$Dr6Abr?O#Iy<*`IcYgduy0b0I+at3 zjxi>`@9tr|(c%@JU(^KncSL3^JtdV+sVv48K^37~q7{9djgCoJ|)$#3YCZ`hV z@`keK?m`kGc3G2c3@*8G!6$u2j)G;#;h)=y;Rd)?zq(e|BdoIU&UiKiHpK>$>`DzP zTyPj+B1!}qTN6QPo*6<6DTPk}4r+$gzzYb#9D{e*JiQ6^HIV*l$pD*<8QnBc|Fhh3I!D z!zoFm=8xzXNA4GC{N6Z;bVjFd?|&4mN(u8yUTx3hxwDBb2g`q>~Y}>)YL#-MRZMPe41WrhBq`-AQjo| zzfbsfQyv1{7p7>EYQ3+gD|z%#G)R0RMU#o6861AH%+gu=89qA)u_G4u5<=|2@b%ZZ zbYkg$4cPo7u|LoZKqFu?ynWR~40(No`#wt@qZY%jBR%;3cr^Q-ie7wd37>Bv4xjba zBqHl0S=I%&Ber-CPdRVKZ!Du;E^jFJ`6V%_TD3ijU=xIg{v2A_FcVjzMLPmb_p94P?@Vtd!_o>k^tkxLF;OaB=5?H5d6slA9)IirdJ7s z^Dl@pvd_5mOxm(XEyogQ|oCrLn0Oz>(5F3+>~N*3^Ia6=mE5v&_TCOY!5 z66u@W>Y}l_p0ae#R(X>?HVDBB`mj)0o4p#o0E8fkL~f204@6Lagw9$Vs6+-ZM&M`W z6M)H62M5aOEs}?GP>_fDddUsS7TYfL2YcDJ!mnbk%OKBIFup#qI*Du?p#CN^H_%@E zCya;@_OHYhew?CMaxG|yeB<=WQeEj}K|a2chuCf$jIw8I^sX2A6Sff@a8BO%5j1As zsWehd|8w?YQ6S^UV(>l}dSO*8yC}kQnAuj8qZnp?ZLBtm-em*kov@dw4#oQoJ2G2j zY|xXAB0Mp)k1%uG1K9mn(yl%&&V#p49UQ@vF&D2I zQ~6s*AU}ah@2XZs)P2D<0Y8o^E2@)fU;O zIz#??Y~CF4B%oVMf3dKynp`6io@G*bubG~2U$HdMy7ci>+NCI_R zu3x{P`I1jVeKH?f^VZjAI3urUxA~jJ%>t&IVdV!o87s-^PjJ)I#N`L|&(x`JmODxq zVE|Fl?T;CgzZ&zvm(WxP7Y)OJFNAOhqx*juo##pAUm)YmF(~9(YtfhDx%~C19{&0e^XNrf1$*71$U!OK1)AEh+ZCv;y`uhhO`#R=v|0C(4H_!m=I1LgQ~yK z*Y2bI^KAXsjIBw;5~Zb(#A>IXQUQ0{%~|uUMK|?J&=5j_C51hE7QxMNtNbD|d2Pjk zwKukk)@{^5;$G}=TJeRV))bo&1Ea;7rWUxi(8B~Qa!CjP!Q@jE2onXaKM0RG0KX_* z0`Zm)!2uq&swWv4mkiEX&PB7s%FJquC zpN-P0yX6eGuL?*d4DK%2-Zf`T3^)Rd3#2Yr9D-jEC;|CMK<@h0!)`nbT9@I^_O+Pm zH!`?Ex7K$+#xIF=+~eU0BUilDt4-O%#=dJw;T#f_h&C$u&yUJBx2sDH-(7z+gZ(1? za8X=KCqPR%hV9dXqVnAJYbe2${?E1i58k*?#aWlu#x3QJzi!OJ*L_)t7nM&Cc-!Yy zbCSu`vs%&`yTgS()D`&Svy52B__=**5~$(OvG`&y0vs?7SQFi$piajVrta@}1c|H; ziC3n^LVun%KmZaw0J0t6uFkk*HrdW~hyFW|NubbG*^uCe%YA+d%OL-X$ryMrD2eik z&u;!@C-ZT(^l$v_bCAU&o$#6;%4?dJTi1&_&RBH?J}~;Ea!??wZ|r_ScP`k%irzL?Laa3xrWo_8Wh|=U;E+cOs*Vz9_jENw`6;UEei!&k%_LzIN zt{+Y=XHe8z=cV}r+FD2C66xX^=mQsAKL=?rYQ2Ntj5;ObH(xU_JyYq?{|*r#=&?IW}2h3E

    XH0D=v%917Sq3P zzxkR68|ig3CQ9PzMl*_|IXm%oZ>EudtP-Q}uR*TG^=Z+D@%mqBSoxr@teOIfiE#HJ zPT`fEoeb%z)^bCT!)nvv$MnFWc?-s50fIxkm6bFmBFiuYWcdU*o@mnZ?=<%PkBDzB z1)*qe@Vl$c19H!=3;#(+q$Ps6aF4EOVGr}3z|@Mz3vPVkP6oQ(HaF^#KTIbs|Ee-Y zXFWgiTkzb_9Lc1v+cRSjD2H+DF(HxE)H|-cP)^a(?84rRf$C30cC#S^FY*A9lU4Na z(lq4}xBOQ`R$6hv98SjztkBaRQQFD+NuFz&@%d#uZYnj@cj)OmRmHYb$&x-na0k`V zuw17JQu6;$Zv^u632|~*i3ct_%G1DrHU^f4kq-7-JARKnie1lcl-ZYsEFO*J?&(`C zt^uKF`74$pf-#|+$_HjnT4xF0j60NQ=WpADyR5gQj>J0C`JSV!wNW{ldSg8}fIWI^ zW*DNdf%5qc^fz_7d^&kdw%e!`@rpT6ZT~lY%Ty84kF#Wa;b`m-opybk{wmsbpP#0< zUFZkYWvfC!q`8xTIi;FIvoPI*q&>C=M6@o4(8ihQ*pszVmJ1o! zine$~RN=t?=3`5k$>lO+mba~h$0yvMd%fMrW*3L}MB+dJ8%1?+u!3h%cn7mA(xK${ zHAwi1VFI6uF$DJz6oBjjD4CPuCE{^DHBWXZ6uIBk$FbZV4?uxIT$;>N=Z$oYe~CG_ zuauCpdqIFO*}>|0^%;?KLOs~>4rS9`ZR!jS%va5mM6gkrvkTpb(uf~1=+rXQdxP7H zICha~Y`5C)Lm!P&c48l>&n7~inK@jaaHRXRL4k{g%%^I2E2>s<9legLOIRL|)n#lvSz)z`#K&Xgo?Dcb3Y^oX5%G+?V}uqL0z zY#r6vTplWsZ2K#-Ao7{BmLzip6Rgzw?F~eC$h;kMFaL2+9Um$P`^-B5X%#Qn$NlK+ zuD}EKq}m8@jR;k^%rV_Ch`yQ8G5k6%_?-Ez z$%NT;nQ@JtY(Fc>n!R)7Dp#58MG8K%CFzuKlku9ynz*b>Ui-W+Z<{YOiyxJ_N^^#W zHq1Bdk7P%hZ#;T0O>Le5t%bCvzeiiH8%!8DIB0m@FMdai`tcm`E6K~cia9Z80%m(|6v^%G`K+0$SpV;|C`{Piw9Z>pzKMzYOB#Z!sKR;qK*lV z5z}S$WVe*?e6q*igp4QfzXI6jPuBL^leajIGJ3mW2PdraFq zPNi2afe!8eEH(iF_6l_8f-Ymg;6d>R{0s!hB_NhwiX@4xyx*+&&aJBEBh*X@FS~4; zYTHwFTNRPRlg@t!_67F_UG~91{YAr#){|-qdHx@f33mSX%%-dlD~@8}qg3U>n^|FS ztJNk#fqh~rlbHEZtLNccfQotjOt~*3BZr^dzFhzh&d3t|hiUrU*@jhJY?BWiv4q1B|FnB!=MO6}g%0B>B~J(|gVN_(N|ig`MX?`4Na+j_^k&PxMz?w}mZ z?Etrcm(x)paYVExz4Nv@@1e8$gdg?7zS7Y(hf=@Ru03O-b!9MUD5Sln!_n2Qrh_ZS zA_FPBK^s?&1)`D>A*cMaV+PD`FXxm6d`K^Fo!WcVAAqtyS!KS+YyzG2#pRy3!MMbF zRn~-(ckNcsRSYZ~*Stz@*zxK3<8kvzJB74i%o)G3CMAN;;Dsk#&~~OLjO)-mU8i5= z9y&o{V^6Iyk)KE5(@9JNL%JAva)H0=ywdSG-yFu8*RfGq4W|XY1i)*6kYZbh{tq*N zCxH_);HqO>!I@3`yE&?&tPFy!_Ua!5Kd$qoB`53WuN9?KJEca5k_q8M22;C`sWs^v zcQD~cABwKk1w5X%8q7TW{mw)5S4eUm}|}|J(ll8RDL;kyS2Fn zBiw0T3-hvJV&7Kkvpy7E6!kUqWj(@w(*fhJLs=ZKnbm{PEw%lR&?W(hVO{}IM6j)W zz?A5~v@NV*CH@7T(zA`L3?N;urj-SD9R? zMczp4p*$m1NSAoqrAHY!$6s?VV07x`YrkJ@-zEP6%67hut-m#&g)yMto+AgWH8EM- z6Hup89#H|5sWVz?3?XV;>w5(YkQz=&!rI_cpcvj-EHF?&`f-6%C32lDfCKfIuUT89 z01=kjBpk%~SCiY^p^~-Y>i2=QxI+fRQjROsdv{zQK1P~r1(@Lv{bf#=C3D<7GTTvP zGl0lfJF&-{^SI|Qxn>D5s~7WNSP&i4Ql6hwO0d0olEIaJ9bIQW{hIlIrWlBY>@3Ws}e(m>vWhoTTkL))hi zMKxqk^zRBEk;UN@Imq1+14%`FQ3J8OF0H1cxOcQ_0R;>S4o6GzWoR)?*Dh{5@fNLs zvBUXeCwcMwRcvsuUcZ25Sp9zFU!~fqXY51prChiE(jX0=7T@Ltx%`*9OnVlmAj-^o z`RTnAAfB%L6oWkgg@bMrp+onaea_@zE}X1Z`8BUnTMxOkoq4uj9G^Dthg-I$=bX*%e!(9z~)ZOR#v`L&~$yO(ZzN}QFfOsvMQ*IG!p zBlfeyNl(=yv8;xtJ_~KmVq!y|rO%WQ447;LUNWp>6B)=-cDJ~GK?~?J*vFwII#z=^G%d46w+|TIGYo8 zPo+i_mQVmiev9m1UOIcVwtKqf5qH1_*{$mHRDUkVb3>i12&Lo;LPZw_qsfVhUufHO z!Xp_(oG^8van-PoY$s&HhwZh(<(2ktog4f!C2`37 zjM7YDC@T*0haa53cTQ?M+K7F2>|z}(%`lK}-77e>zU;In+UevB9xT8sBC-cLDhPyW zlF|kcqWAfiJ-CAmzbYi2ahr6%rFQ}Q&WV?Hn=3RITOt||dNC=S#B%1kJ?D--9cM?q zgMu;KVoS|rOj@+Mi?8b%kLW~00KykIK|Mqc=me=YYCb{R5Ev&qxrIS)-vxqjN7tK3 zSvO_~st7+258UH-FqN7gCcrZ1+Uan}W0KDV7t>7WX2c;zKz&G3ehZWCftq;v2FR1e zq5{3ri$k@wA^hq)5(}=9@mbQP=td*Sb4lLI&K<-7tB__(-yG4m8W`H8_{hG*_NWsN zt6~be40Rgu_IM#YKWq5$&19Rmc?*$QnM35ya;l}CIk>p{ zQNUV(9VYLF5&h+wO`-_%;8ssXQ14 z4cT3(dA^$Y7xNCXY~!@$Vk-=pd}6hUCI%-1CESIJVFBZ2&hF$|ytu}JI}BdDUaY72 z3l@O}@jvK6Jm77Z43ZN4%MFk;09)A0^LZY&1=lUJ6%UN4(h5Y2ZyK>w$2Dvz^odtfAll`$q;Wkl8{S=^6Ng>%1=eae* z5VRY~>{eJEev-DOu`jct+-xuW)lXL#Kl$}!fTcs9VIpxa@Nr2W`n;X?*}J}7Vq@*^ z7*S*}TcMNaqovZdfZnUz6!#9omUMNGQNSRH#PvVqw35 zpuBjz$logJf-J7E;#q3hZ`|slwK%cY*KB#zRxbF3*G6uJbI{b-)m|KplcY((e1UC0 z?Km5-`;B00Hg9U>EblO}JDFAe2`n~UXHWCc3&l-jzjLV5!23wJbZnnc{T^FN9K7^k z5o2i-g4G+CSdgH!+^uI0%hXN^w27AP=Ci+0XHB!MGc9k~8L<*|v*rlQblIHzB(Gzk zPi3%(xPQ4p8`xxp;BF(Ff@;7|0^;0fmF6d-R|W$bJIz+Lt~gE{w@qJMyKfP1QJ|rc zu$>nH=OX;r-kT4Dbw8^=tL&KVsVLR%f7fd`9P5;>bcQL%T)_?`YNn8kFB^Tv@;KE& z)?JMpZe5G=uL+@G9}pX&{@$Y@`DQ(EZ?z-gl@Xd*R3Imb>cn;g<1m(agL-n^A}}pW z;L5ovO_rfaya0eP2dx=*YRpJHvH*<5h(S1U^)3$93lb)~5)cY&nxDfcXA>mohC`ElkW91C~7vGN5ydSkF z6l6WWavUXhs0%wbi3-y{{G;O+AMg_WTHH*hxHWuyBXHj$;z&`x!1n|Vn+`D6p~$6H zY`Z*82M+IMaZ9LsLU2;{hc6SxdoUaDR}-LYGUn$3ju{xiHQ0S?YBA0Y5OsUhEfZOF zd)jJ5Se?#Y_!O}0HYSSJdc^`0B)7r?n)d0dfOC|<;r@DpT#CkpjmJF~-ju1UIWN`3 zfcq#p~M)wsvSF_$QgKPC&wwD z*aW1^;2j|DnA<&oTP#3)1RUt$koypp|F_vbV7&tiCDIU~qf)QG$$VGp>6;v+N(kCe zXL~Yqq@E+Cg2ZS@h zACxm>Cn6CSP296s(=wp_{T3+wY4HXa#oJpO%l?(4~2`_teS2nK7gq;M8y0e*pzhLqER{+eM@ za{&Mws}No3=NVjYH?6L|cD(1+vb`L6R$#L_RK#i||lYh-(^3IXP1;_evehiyQ+%w-^ zE2oDig7RKTYC_7ifqM|UzY;J@?I_-?IMI1vnBUnRX{hU9qwV$F*Ck$vfwX@||9Oi4 zq;Ap52Mwd(EdzD{#&5u32RLG3*10XzvEP|aO~>`ZH>E&&-8#bHQqm>rrB}6ueY2wJ zH76wvR5WePzh~{YU(8sY_TaK5>w*_k zkVyIdJj2m`K391(gieIj*?p;VW3lgP-B-<{6`Nyu;TVq7dYmZGN;*lf{?osZBj9-g zyL16pLLuz2*L}Gs^rGz%7dJj1y#7{}4=G!|6Byk5C_|d4ZnAOwagz{#DTU5Lw#~;=y`&4QzAu9fX$tqzau4Gh}bO8~QHBjQzTJ<5L8@TQC zj|^4Y({{0rZ`)8m!HxYNT(|XK(bJd+bFgMC!~*+(D#$f<@Mc-Zca+^(dj!EMRtYMl za{YMn_=1SEI<8b}K~F?di0<&h=v3g1gKl;cYK{gS+hEak6#t>YV%w*siN(S609iX3 zB&|vPnQw%mkw~rCFi4QUp%52imU1P;bPlK8Suk*WE1!r6H+^cVSOP3?( zlp)ING3${W>7pIqZYF&X-d7Q!w4BVg_jZdSuLb8JHe*4ppX!h%f~pai?f~yK!QP;h zn2o!jy-@n{k=k&(lK~t_y+BBSLoT4#Qzh{m+>7-XW>UbNq2^btSRsDrm;C3KWEXk5 zP{1D}u9QaFV$Zm2ByU_N?YoI<_tLF@*+LF^{LpL(exYgAD)@0z!SU)UCrCW}_)}(s z$qQrVftLG68bzfedbxOwn90x@4*KV%UvqqvPnR}MP)FW<6`oPObFB7 zlV=Mt6F$FDCui-Y?)X`GEasO&f}Df|Bs^_2ll{@>do2%>~2DjiZHNXY0I zh)PL`Uy<(aZYF|sDM}3(9nwfk3euxxbTe9nQKRnX9{PL!Z@6*t;_P#u&&lgt2f_?mnBM-m51Q4lVgZjHky}yjCaqeOHQ*lJB{SZmw%`@zH0u$WZcl$)2V8ki zW^{2oyW~ivv3f<BoFKx$w!&RYMaMz zU{sOd;dTZVBXMJyxS>;W%)ljvB4z*$to~`f2oGm~xQpdIe|jshze-f=^Q}MXT|+4m z;{h{gopt#J0gaRo&f5;JW)C&`u@|9M|9dAZ>yD^#8NFjs_R1#VJNDs1d(8LgA1O z^DpNF9Q)54>T7W5h&-Xc#|%!9#sI(x4A=qA$?07KnnWw(mt;n7@EDL?C=OByad})< zv~zt=Wbko0lUG>}r4oREtf~{Hbp5?#6L2CKEkV+=S^3zb$l>;jT8T>b=mBngrBQg9drobZFEuMDQ zy-n25zcFb=;VU{{7fgi=1QUTl3>txxulXnm0C(2mKog9pS2%`0T=~gKkM4?pi;VtK z+-IL7Ze2IIZt7X`-+=+Urja&yySJuv)X|S!m1@Tytr|r@iG(3(?81d_gB08rBw@cJ zpEE>?+ROjy?~$=qJZ1wlOw#QjeLeTbJ}_j>(hU!7js5X0k?Y$$VRKYW>GLZ%qRKHd z5A~nzGEJ{)v-|y-WM2yfHw)EmtUS@7&KM{s_jGOM)5!prdR{O_eVA>QcB^_L#-8NWFf-?7B5rQk_}4|H|!W?vAoXyHjmLuUk1a z8iA`ff(ijH)7=7pz=0i9AM880YaEyh2V&MDs{6Y~>V6X^vWNK$quS$&cPK~E8FPE1 zt0&4eH%@KeYdaLk(!y`23xXM#M#(oPMcZ#QUYemfyBNQY8Mb!DO|8-!oG{d z;-IOi(gK@PI#f^U6FhN_F> zUhwQxbqiF}@r2OzZ=9TB2hy8v#-oD8x>CrK9Xuc7ga26zkRKu((aN)xTcl+|=zC7J)zl>HvL^ zB^dP{f*}y^AquxuOH~Sd2e=*_5(cqRt?vV>eun|%Gmu$<;Iz{?(Eskg5RN^4PW$=#}D0in3&Zb~gzvHwA z7K-b{h+WuUKrIE~JBsFbl@#y}jXz`3<>aK{sH-_qoQneaci*u_oa!u!NN=of@30V= zn46$|$k-SvRsY0JiO^Trr)@nQu`DU|z1kA=t=A9l!)kW-BwoInBZ9=G9&!9laXa9c z-K4duxPR@Y@?KY|h{8aTNG9VCGisFZyBPEN0(6HR_t+k5Ffhs>%M-2L?XcAu53k+4 zj5|sX$DV*2M=ym1n~IlD3~;&&WRSXHZS(Nr(mqJBrv7))mKt_5zy0tP1?Wm!746`f}psUi_owCE`(D=od=a;jxW*?L*V?yHUj7DU%EshsSGLM|8QQmQR!kx6r7z*GlrT>$eEb z>Z%1)bxOydozh4-3ENYr8(Xk95d9fr>XAfh=$9~ZY*UeJD?cT~R3u3D84XR77_272 zb&m<#f1ler>g*~hYgm-yL8tC04?%Y90t01zCO|EyGP|%T>4PqU%J8?Sg=R#xM}uaj zITAP%D5vmQ@<398H8eTWP=xhTtawSPYQ(6AP#$Zf`{?hjPZ96)5j;dRy~BINrUC?n zw!fau{ER|NAYSm_d;iUNc%Y^rO&< zB3V0p{zO2sfJXF6D*1&wEc^$MpF>&nyjic;16`gL-8^S@_b1eYXypVI6f z4Bt&e@Y=1|2ziwRiraU|ngkra(O7EULP;j%J}@0Ms=i|Ggr$5u_}aM%BGg|aho6uZ zV=nzt0(o;+SYW5%xf|D6QNiT%Ghc2MMq=M1*2?36dmo&)>(0oj(^N&RiHQA^$V6#F zvySs7Bud+&0?pZ+>{T6N8mUfOa08m{gP^rTLx&TvbAq_BD-hayx6S*qNdiW!wAf2V z{HHH@JbPmfL=3q2&(F6(|l|L$6H?ai}nEzBUc z0cRcRYbk6q6!(SO~u4p^0}3xy;%J2BvBsi zoG;O@`-`;eD)vFsI)s&EzQtN4P+eX>ijXYYo)E!pN3b>sP%eE>1PQ3O1cA5gPM2kt zzt@lvd;ptg015^i!2t5-hRmvVhQef=rp7xho9#Y&oh{$9|9A^sMZKgMW`PHH9`xGA z|86MZAB1(>xoW=p1m)U1{qQ8KN|io2uivBN{l#|W^HB*GAk-xl->0+HzKK`pE$^sF zNd0vQi!CZ7 zY~Ib_gkdsqFddola~SXLS2nwJyuj*JDQfhAgM3ppN7SdefN>U@#QiKv9y>Li-5H3s z)P!Dn|Bjs21KAG;{R|?c&6$N^UK=Nzs>^(z_x>{>`^Ds==+KcC5e6&Fo#-r@xLZ0a zvfsUAmW$>llVx}7J~6`=?G=l^uy7C-5|LLdwGrUcKlIU$pveWjAnuU=R@-oKi8JV0 z07N?!1pL4In40YEpQ(;E+Ual(*U$+$x)#mO==Ic^NNX)W8)ZDAdy%CBRbjnDt_~B)vOZZ z=!Y&*!jh9P9)q*Kyo0Y4jy80GfN;P?X2o-23Lk^J2;v4hlP!|3jF+A|5jLYV1PmuoMv8dK6(S~AqDho3#MI9c`(3Ur}; zI}Va2l6pMb9(qFJnLc zq^rK94SUnC9$tOXe)!s4@D;|ti$SuJ!)^2hF}ym&o5;?ImliITeVnCKzos39#b&E) zQ7Aqwb9H%$mx#L1RR!px-B$iUc`7tWph=D?ap&NiKPh-~Wm)Wob6-{6xv9XT-8SPcM5_}6VcRpw}WRWF+2MkEcS+@`1@gK};W_SA%WQp~f?{I_aM zcQ%^uoO|9XV$G_Z+Ys03kEdd4t!~%7DQ0D##w;__lT}j>~+@2bLoZq~I3oK|wDUlgO@x<UT|RhkE*lqX&N-X@Ec2< zg8w)pTKY%Jd-*zC97+UnPG>FzAiu6;q1zzy=_>UVqIZPuY?Yxq;Vd-amgA_>*DI$o zj(c=s0;-Qwx#eHa_YTw)GpTLW-Kjfs#ph+tG!L-Aethxjd!hPxpR-@Sd(Xn=IML4Q zxzV2zxzGZPP{F9MO{Q$JH%}SHM*rJ-d4ObwpF~jRna;v~BeiYtU1xq({2QA+19%%{ z%E zp%yIYI_8f1w%8jPvRjsTocR#^Hbsg_IkZmtBZO`EaO%&7F2}qBHi4>QM;5TnT6CU z`Nd$`P|@5Qb~RNrIb?Hk$z~wG&EPbif@w*8dQ)AugP3YjG!f`Q5{A&t`CsaKx!|b8?(4#Nq zi{4(7a2f)M3)_jWKM$N9)Zo)V9PVh3U9s_IakLv0uF`jl$d~M#wnW71`_^KY<9_)) zF-)D6c!JvhV6t+63GPmLLWqv=Q@kLI5WSJWwmR6t0H-;M)wcs_bRhq#!nnPvaG>hv z*?kHS@D7%%8Kq!c7tp8kQMB#9iX2lu7`*?+>3Yl5=`P_oSl^C`;>)>oPYDXLtO-;rlFJ{;!V!RJ(&O&EW!Y zzW@gXR{;D_GnO0jaU1$lY%Wv{a%f+vQfQezq?suE{$mt54KEUF4rKBXszli zJhmfhZ>>q=s%LGMn|fFDE;fM%fia9Yjrd*EdT`Km01-lEz0hIQtACN@5uMzS!yKYI ziAt9DO;$ZLxnGJlZQ(YV#}013`*zGsTLd4^a2V6}5npy$zrQ}fzoA_8*@~Lxe_{FD znZs%@mP6pL`vTXQn4RUGUCv;u3axXKOE0pP`JE)94rs20fy0!UcZC?Dn6r*oMrUKJb453Cvy5$KeSdULwMatbX~0_bg8WPaA$077o7Q6`ti zxFZS9%S3=cKai)q&R_3uqz+i4z*K)F3k&#QVSa)5(HtaEdOq~GHTj{y7Y>ICK@?fy zis+3|$(JuvlIf*-`7A4g^m{Ydg=%fF*YUQr)jmzN^Ig%rsp1l?+9M=B1ku$fEkcg% zXRXHQP5hLFdKeGBB>FB}GV(k2NVUyq>q-1?o>K3o<*hCA;_bBe{pge1?FYQfA#m23 zu-}hWI(`KBO_;$d@gub#3N9W~`aHhT9R_-+!2`cItik)*3%2$%7u*_Tic4d|gT`4N zB&^+_3xJ)2(c}^EC+Pj%tCXbkVZE_0Z9kYAMu}W|CT#trBI7Aum=9GMr(8mIrIQ~+ znHG(<^YDl1iC=X6CFx5HYHapSuk`EksI_Sv+S87z-dv?##Bk0!8$~+#e&s;Pc|104 zxs85M5)$IxVPr>r%t5Mbus%<1(o7LwN+xvc9+d9cWZQU+cex1tX;jR~QeD67CX@SR zrRuL%z)s(~UzS}#c>!=Q=n?`rTYV;zxQx_tDI$!MsgTK4J}_53b)!a?dx^!L)|8?t zTlXN3?N$mzI;p>gA$|3@Hup{f5oGU|G$Rt_x(#RrPs*lo-?e6NKpFJ^_dIVWhy)RE@(otMs_bi zi^Wxiqk`5wU-s96uB6;j7B$hkFRqnBkcMiFDnT%Ru>x(fHj{}j%;ls;lBiL>dUz}I zMJ07soqA~Vy`T|k&di0KD{tw7m)^vc^jmYe3srl&^Ir?r+^|164bbQ!2xzuJ8sTk1k}CE?!8<)W7R-Nb4ISwybMjQJr$;sdN-)>*)uzXIN7@^9HcZ+P zP;`()bWhI7x-G8Y0J_J^gZ*C+4#2Jer4EksS5sYE}>n;j)Jq} zY2gKSS~|XuDCr(3^Pn5;Y@5n!5?|AQ^UCBr`IUyAr*Dv>FN#=>aE}%h8!bK_Y6v6$ z)m}T!WxH=bQ}4c^gn{VRyT9sXvvA-&B z4~BaBE3$P{&CpO9tuV9hii}l#4oq|#2-h16Zr9inA{yYGQ+}D8XRKi$>->T-HTXr= z*v3N%gFk6D)n}2X53Bj6CJ7T5I1gTn`{?)&aC)Z-5&sk+SuvBpac^ie-mT~Hr>UWd z=*E~YoxaU`tf!uoDifWfCKonM!C2HenlU)rkOB?vSpY>Z;s=Dqy>La6?7lOL;>%*% z!5sRs>TdrF%iv18MKu*yL8>nXT7X22j5)~Zmf9CT&Ngv8aYh|DRJiAU z%HR4VurA=2pJpC|1@0fiB3MUCsy4962>1;iT)GUu72 z#?9vKkVET!M5-EF6%cC*rQPo`Z5fBJBR0=_?w>2@E5^xh>5MSEqt<)*HK{HDI@6pZ zkO}+Im9-ucmwMQ+yl0hfM-sGe-ab`YNt?Yf?6LXbbzw+62;#L}Q0P4Hqni^*kmC(+M=D zY4FWW5b_u4c7f3ylfVSk6ISl#cAONu$}_r)j_Pw4DW<~JE;F+t8MGH@HE_AGLkPB% zUo-HpEe2@+00D72CV9+4_ZwJSayYNMvxg2^^KoBUXcd&IOR0$Yz*remWi!w8hx;8_ zTG;Zv^Dd2{=UwnxMY_rYuR#;zKNX4U7`z~r9cQSUbVARWaiCUWlpZomf`D+UFD$%6RPqPvi{HqS?5R!O|IU(idw-8zm4ZY3# zDd?tgq^}jiFZta)46O4qk8H;A;emr0zJ#vD=hnSvb2u^*oKe~9rsIRc1Oc$|AD(TY z{yjHmUV*6o&24BsdtBzA1G}%J=xA|rZ0MfgBQf2dgX0etA$o-22DV`U^EC#VUaBlw z5j?=h*ga|~z4T5RX+(V!0U4x#+GN81IyECgE#~wgzZFBy1s-(M_v(jnDoqO) z`J0gss+$mxZo66BR*}rsPVlGy9dKbP>1j8*ka7A-GfY7$rek3AEw5kSz;z7o@V|ws zU}_25VE$zdMyVhl%;fl)#l>54eURYPVF3v2XkYhE{xrzf&n5qO`9w_R_bS(z>fYN?9${4w`eU^D=t+4M8%=dfP$N2)LE;VU*emCebqVJm{xL+_0TNT?M@ncM?W zrAJEQ=dRr{Ca)~eMk5@emL}PD2fx7Sg>YavB_xq(>Fo>JabhEg8>QVO{^oQ(ehx{R z2E#M>B&Vpu;yC+Dlz65rrk;Muh)<}Iil~tdx>c83`b&;O$${Hm8{d@fK1>J)NLR}wqF=Z;p%wnxSl$L7A4XI!KF+f3IH%4Kg1j`a~Tm)AwlWJ9ukB9dw`0JIT9h&y5a% z3JYR03((EDx(>AD-+Bq?mUUV>2k3QR4M5>BAk9~*ymb1JnEF`w`}^Hw2FrH|?{u@= zo%K!}eEBC_D@Be9q z^}feEfbnqb%56p3a&sPlvIoNzbKrjs&a?^gXG=g@fV z&4Vf{qrQsh^k@5`vt(%678lsZySKj!-F8#>O?CPvBE;r|W&_>?L4A#ql(AEe9%tE1 zL8n~^c1#!2WXPUVBBGGG09Ar>Yg0x{q@HsFq)`;s7s7yS!7((qofR^IDzR=e0xbir%lW|OoohPi;!`Mz?{Q=jQ_FYxwmn9z`OB1 znz$-mgWnb#?}{Z1lEXfP3}gx~1tF@M!?*;qEBEWpa^6^~e81*B#E_YQ4T(IVmMVay zqwAt$HyoFwwFS-nWrM$w)Lifkl4OjW^wC}&xBjx4VOAywU+AE*bQog5v}5+g6KUDC zD>v0v45#fOC<~zv9XJHC>Ay-b7@mM5R^V~tet}-d9s}9h`}*kP=`ElCEX zYQ|Q!J|MH&lR3Tm!&HFjPv%Fy4CY?GXGMi!IdyMrNksjW8o2E3N@O=)q|4Q*(1iSX z3=LtQ@#e9sP>H-r`Yre(S^n6!0-lUcp(p7Kh!F|iS44Y8aLF2`jq)xb`5>M3z^t~( z``=D^s>vDmYW5@cQ!3sVD~KznzF4Z+ha8ell!}3_pV#UC&!$|$3BgRu;sU@w21*Lwaw+N6nEx!c+1|J9b+>fQV10{<$83aO zF+O&rauZE)y6?f{PLmupwu2|b>nDV4FrKe88hAQ2Pw@)ck&VnHQHvNYS>`@x;&^_? zhDtf9(`!8Dck=#vZ%NT(u}o@`u84{X+t7Yyrx&OJ&A!PI3@4*HreebvWXz8UuEK?} zX>rr)vO!qh@_#ibIPhu?)N1H{5H{wx5DO07$??s5d1SGd=>?i|t8QK~!ArSX$9pKF zk>>wYcI{M`mV7XxapXWOES7er@aO2l5ast{X}XLi*Itd6l@Yp>^QAU2;xo5KT|%vd zByTa3GThzEG&srjrC0WOaikO#Qj<}u0Il=+|6&@2T)j>m-2 z*s8f$gMW4zw@(pt*#>8q*-Ih#XP{1lL>0I!a9{yoe89AA%f~WbZRA{fotEZdT)`57-5Pb!rm?#gO}Y8rnaWq0++=pSBl zOyQ80@v**tszHQDB^&(67+n{pOV%Plp*iG(9S=!_w@F}4+ zpzZcbUFdegSzo`<(pJBKaI%k8xn-hdYhR;bSPG?b-_ebVik|U(bPJq%z@tqxZJDIr6TjOR9brdPiu{Oj{(fj*7YV{|496QE+v$^E$ zx|O>PXs9tTIoa|jK}0~9qdCb2C+hzKaUdPX=s{h0Y5E5ElL3P^fQUZ(VMB%b@X!$l z%lSz_74^*Zbw5@QV?Cz)%Bpplt5mwe&z_WY4mYy{kUwuDcCW-AADFTq{Wn=QQ5cY9qK9yt*a{zL|>#7DZ`TsZ~^k9E%$Mo=nnT`C6_-Sk9 z?MyM1D4Fl_!BVNyzA=Pk=mJ*PeN{K=tfu?QE5w;X7707kcl6$$Wb{%ILaJ2nX(S|? z_kSnMy0~2^uO@CbucRU@2A@^Gvfpjn&TxI{SKw}`X2tC%E|AjETx=-)TXe;KK|{i= zLyqjwf|SB1!nB~2E;zb(v;jTnARYd<8x$xx!{Ev3dAV1zDSePt^SDS%y!DVZBLj@x z9zpQG0p7o4F;;=kw@B%kKYZ$V=uIxGLhCc~$)`h#a?002Rnb4cX1O?EYgsddz$IBq z$wY9s;|__o5LS1d=Dci+(7h)2*k4T5XEAG3Ye}TR!RWs!F_QYX@PU{>p+i}(Tm}p* z2R9M&Hz@-){?&}8K&e0goVuONs-|o0re=T7)8|ZBo+O6V&#_(QwH7yYU zQuztKbdki22yNVntjw~h3zAx#=4%`bktIBtoLcsSkQO%XmcZU0{wLeioFIW(%{EBq zlq{?>9zdt@0Q>x8!fhpE95eerkDcv=Sy?9Y8a^lu)sRx2q(>iXpZ7Jdb;$kIRcMFV zUmiDmoUBK;!A}923jmLZSNv9H)Y%hOkkIqXJxk8F3N$~T`YO;+r8kpq5IMRsxps!1 zS4h5cICRwC^c^lCBbm8V6&8F?Z!b?&uk8xfxGj}%97ywjCkm^>)yz*IKril-=DPq8yXc{MFqsF5@b%SKZ%b-0coz(z?N7k> zQ}w%M&1yMe{>e)Znx$s<#IvjGXx)xdKfY%>hD#Q{3BmSE_Va6e>c*aSTlmG?BMm`xlS&QG#AlNG z=c-K8^8h^_xe**M4KI<=MG~q4M>`Q_lJt+`8h4}Mux^DWVEqhc>5?bAYzleMWRW)8 zDMZra#FlX-e^*zi;+RsZp3wGo<(T{7H+d}o(#LVF5aKfSPolh0ITNDS#pVhkL{pJW z&%X_XPAU<5bbU)atH)y$9`W)$gFq%3u{ zy#64EU>-7;QFF_sWNumaMC$j+OMgS|M<1J3n3Qs6J_LRuZ*R}gsC`ZE(u{|TgRp;3 z9AtXaz3jBKo#6sGK=zmsEPFzgWcG@MdcHJV-IElm5^~qh z*Z`%r+4~H?zueQ-I^d&nHI~lA7U_D0%k@^2Ig_=ND)v908Sl|_+9#Arf{%Ap8~0em z*vx;u@x4+;p$<#4C*IyB8I=i<9!g#PsaX!Nry=Duq1&Ch>{8t$pBzO7bUD9aGV)mZ zpnl1qtcxHw{T&>x9(T&X5t!x~T~K@j|81jicJmB2C?}uwpv#Q4ice(A!m;%6txuU~ zHv%cX^pDj;UCiC|sMgH@Lu}CFWU8LM&^#G<^lkRc2 zFZn^zwdYOMfi~3m)-9fQ<%Q5m!yO!1)@xyS2z*NXtf&Rk;zaNH1#=tPoqOb56l!IMICacNqH8?SY|Z zJ6OVXxd2=KH^7~plu|t*I)+cvk!t;%YO*vX15R`|RTD$5E6*kAk|l6Jb+c^P4&`Xi zbGkD`Rhmp39-UaIqx{heH|u+bi(H=N=N9`1hzX0PJ$e0xBy|1Y=|$ELTI0O-m~#O& z>yi+J8uU*moTBZwceq#5hLWvEx&UI`B*l4df8h=7ubYx5*;Pp1f#>bJ#Cv==y1dJi zhEA^Wf~wK%3p(n#lgqCF-7eY$3%b~MfltlU*_X|Nq7XX!eneJu$vSt&T5gXU+@@2` z{FuFTWnSzgvXR1gY$08N)OtHy1dcZ;xENS16mK5tRu^V&FqNWX0_FxZM8$Uwtcftd z!0ZH%g8lU5y@^8y1m;S-!NGBNDoRh5^}hQ9Ey;>(YCVS+kzd362!y2WQOW%0(aiaw zgMvWQO<2}wdxu~++JDR@v}(;h*iiT^OB_Z8`RSik_q}OZi2w1NdJ^|49PF&%g6Yjm z9OAzjf=i#ma`6mg;}J6-Nzo8`oMFXJy5wdl+kzcD@FGLT<2lYm-YA^(+wO(EMBg1< z79`}V7o{9d5XvSLunylqwTnE=*F126{a(WEyG$V7sv@`&w9;y6_paYKvS zlc1r|0FzFf$pn8*xWICN$s@h|w-Hay>u_b-n~o#|<#+)dPq%WUZK=pUzC;hs z@3BD33aEC9T;3nb&FJ4N$wWROLM8v^oUmqXuTt?S=VO2n*pdIDR)^J*EwMkN*o82C zKWIfOI;J}ql4ejJeY*ORx`JaaYnEwDYFCm`I*Xp{%VL7)U%=bCgiyF0EPbH%>A_nw$iVH;J_98-+fK_PcVy2a#l7t~uQ{jP8U*4&)m|TZY zxjmE@@JU@Au^(y4sOF{hP0sV`mC{lkFsDC?V%dJ2J|RHB+%}rbBDaOq8j-4}u@x5E zKNxeMvNjR$KDxe5l1Y)zyQl%xaCMw_@KbCIwIGFu;ZZ3+<$Ksw_SZHQ&Kz7$2wm>R z18aS3d;pXmfPIMzgg=+3zQXPL-jmIEIJ#(xCgqe^<;sns)JnKQ9GdQ(jnXZ<+qHCW zY?n8uBkAJ<8oqG6zq)#_S%}?kT^oHioS6JgD5oy5khcM0xe@86M(fh%D?8UiE2;|B zYnJaPhM3&k*ATtVdGxAzv}u1VKd=EQd1^IAd&6ywX@PY8I@&C6U*q*X$P2$ubu*#g zG^z8B4cvm`yN`E9&`{pLZ82Qg0e6vE6pSuD;)6E;rg+iG+kEyUXTehK@DMdWLH=R$FxZ^W_%D3GyB81qej(Z_c(gRgl$J z%S_7kw}NzKqX9h3~)tdI#m>y znk>ztFUh|4QNa^a`NXvz~0 ziTiv04~QbMEB8gc>7p}jO#2)KDyaoZZRZ;ZVKhGI?CZC#+>oaCEn`&Q{CpayU7yH{ zu!DXRe%4Gj@C69na|J~Dz6K%t!{cbmnNh_e-2qz*2X<7ky*#DhdA3Di?;AvN{9hyq zegh<++6_+N67fcI&^)_x^Td9x%Knb)gx4ca6n9RT>aAY2jJ~idyvJg(WA!1mDqwbFBVUp2tTV^Nk6MYc|_Asu<-&MoC&c>F07Jp6p)rc1I%x5$LZB=g9f}xv9K&$8V1%% z*iT;RoLnq}6+pn#B@qCcj~QXW=^PY<0FCLiG)p$Nrc)6u?0lL=&ufdj9MeI}UftgR za;u$RRbeQoL2HVgs=j(t?9A1(g~z3i^j_N1EkpZBR)!lThy7ElB9OE8i@hM>L%e#z z(W8yeiTAH0qe4$tD<1URX)IZ-<|vY&9Mfn_&lzdLt_&t5E-FjC4MBEVJ=B$|w}~jO z?X8&!LITxeXDFM1@xJEc>tI0`=R4;LM$U+G{-*D+U672e1-GrQhZxeEuet~s|JA^K zgT}_EzI|E0R7Orcu7ud+(|2|)h1ZfVKd~Ba(}ozy0htM_Pi9f4Ji_ljYES;)GVEh? zc`#_C1$`|>OEHCN6Dpp$5P>{4^iQ)rP4iqU$cfrq3Z8eX`__G4+3L1aV%6`|NdIXI z(ck~QvM&Vg;6Yl_JiMbSEOmLWI?=c_u|vHsXh8qp;!iXHjza=YXJCGItV#3%g1Ny! z7+ex&8Pc{zbFNphM4cY{?7rm7j_uMGfZDAneEWCN3|#!nC!9rg%ZPGO$AIZQ%FX%!6gl*o5GqHI!h4(%rxyR z0Hu0aObW@z6{09UX3eYA$1DUDn&d zJXcn*yKo5mS$c!LB{^g?$31>_zy;z(MZ-dqzP{NrM945!N~07#IvZXU8a)WdmV^F#e-SdCXxOnPL$1)U77zWFV_b^cn;c(hXguL_AO0ILdr zLGPC?g}mcFlp0`s*cJIbEXlK~X^hb@lw0NN$IO`Ax_Bl6DRaLQA&r~x`ttt-oH!a- zoy;}c^*m4Br%}9$&2O{rT20VO+}U!dGaQjwx~G(eIQn__hS4*V=-7p^W0Ga#Cq!kE z=8c*~wAU+Du6=OK?&xD%8W+;HW1XxH=tS)kY2+A?`Pci|h*-l~Ey}+%{?KOX_Zn1W z9R1JJsI;f*S~dF0u0~9*E2y*Nr)Z%6-|njB@E_hd8-X*(fD6d=qx1sEQE~ak`lVxp z8DC$<;=QHZ=ViCwoPTyP2le4eWh~U&8ac5UW7v7Dgk^$Fwm4y>+hKiPan84N{(Z={ zke9Lk&EtZo@_flCYzFldW-Edq)ot}jF-n6+4EUz<>lXD^K(!nd;@EFpa`|)eL@%>c z-tmq#Me0Q^IfIM;+c+BSvGKMUn&K>6uFx$0PqzQno?t6Z$p9i8AWv&~|KL$+-babl z=u%kUa5_~$79+KN%h6Po*Fs6AZ}b=xiWp0uiet^QTpA8)li@!y{FdA|vPm{XJJ@#F(EQk$>Z z&+ir}8Qhn3oy3=fBe3479BXwJ^E5X6f@wB81a}@S+NY@#zDyu$d~rD3X_|2?M%x5B zi#*1Xge!1993B97%>Occuw5g*z7(?zl*;!7g$@zaNzND>4~^o9Pif>s+TMM;rF&2P z#?w1FMjz9qAA|>2I$6z$>jcxfst-uu^|nF|@u(jj-cwpq$|-Fuz;jzWwCZuW71=R& z%c2*Zck>!WlaV&@Zf&m+u7pe0=@#5J(50T~pq6~6 zDF1N|k3uqL!HC>umTH8PjayHhee7kR2TFT6s`O9j)e|TSPzt>>74RNSP47!mq*bOe zQvF^*J&!4SJ_l?TNZ(CS!9TYY7;*SaU6)1`EvdY^=pNh9n==|@QytI~Y{IQP8!;|B zlcX9|vzDPpmQzb)Mr7)ff3JghUDmqk$NJtu>;Uq}OoCy5#c*z;;n{SP`AwvL9I9Ga zN=cuwZ}W|!F+(q@tXo0AzYcRbXfcLOFIJMVuuyQ~0Lat5^eKSLg#o#UrP_Ogu=*fZ z1!|qwpMu7-@?suy<(VhAd0p&w=UbaUA)Bn;)Tx2^?41;7WtY)0E#15ji2mg|%!;QI zqpb=KDsHIdRj@9z--?2jPe@|7>=hk|q^+0r?fmgLRjQP?Z`?S~p7HEj=$5;$q-hhS zWIX!zd$L=TA_9qtvI92{rG4K5Upk|zs07#$|IYjO^@A9Zxidtf6>b9p3|yy`qRbB| zVHtxvWOkY*BF~>-uu^fKR_op&g-T8A;+qWlD&r7IFZruJJ%v+;l*CCECf4>}DCn{A z{OTE*Y(JKG-Pz{Ydw`Evy&H#qew5((_CBObtvCr9=E6jd&uoQo-3=b+#NMBi9ijD5 z&CdO`R$;#$BQCd;o%Q{*`-J9X$nD9i3th%}KiKUHC~H@1&;yD%Wwxh8DHZ}>Ov~5g-=MSt-K#$GnZ8E}>{==k zD$>RgkFabL(JX45n0efdcghAv)2~H_x*K-aar#VF<+qMKOWx%6e9}Tit2VasV(Mxb zB7?)sW}vd1jQU5?9FO~UREs0yQOoLq{ll7{D%(%wg^JhyOI!U>G!rTtxf}IiVp~rC zU_Gy+jN?wZA-T(+$tlvYk^#`CfW&71?pyP~UtNZQBrvd77f>EK%2Z-A=HRC-x#0FE z`NbEb%XiD=y(vCdSF|Rj09Fz>Mdng++rXP~`?I*WJ+{?E<<8W3It;ihb))kw)}<^)0|()YU3tweiYT*v!t zoV=`Z%%%KLy2H&cE%}w*GrRa!yet%X;FH?t;qagOe+Gmr`I=EDi{c5)bDQ4p1A~={ zHS8=SQBBN9v3jFhJ{P~c)ictRkvA&e`GHIa&&d+*ttCmwQMIc$vDoxzctla-3%-V- zp)P6MIq^2zgY}YCf%i2hNLU9VS#WY;0o8DVFgHkLv{gUeh;ruq5EP=Ap= z_WLwG>w;tFCn&qe{7Z?N-1y~A>f+NpKKOOCA_H&}S~(9jsNajvd05#KglziS0@r>b zuw98=#c@jF0A|3yhy)BnfD-C@{k&nlCD@t%8ECAPj7Yd|=B={D{#F=PeD_;cV{KD= zKvxM8Q*-PS7d6;_gSSW4;lMBHNZ^6HU+3y`DSTu#P0yibsh;D8U$a_j9qcjBxM-E+jwI=LGv(IQJ4eI% z_UMVCcxci!#{8+;J)x&hzxS6ONz7TMB$VPcY9#!@H_#}ggVS5t7ymT%U4uKbD2bN| zPt;I-(urQT5qC-oE{XrZ1-;|7V@#d7Ftk&p;?kG#pZ(PYST!Dfi1i&X8tI_;zv4j% z76Hl+8W%>WFtF+2m>+n1cRG#R>0uE^U_&(F{J>PD`z+RBc^YrDwIWT(>}kofc;>_9 z7p1+iG*Ph`*G2^MUeq5(=3%b5L(2I|GfvCos`}XD1xa4V>4S7?Gh5KnCdsrtd8D?^ zdInF8P9F!cy2B$K-nrWhn^DMb##+YqpUrvW;9fNjdo$Oh$ zjo#yAI_2NU`WvHtZRXz!I)g3_AfMW_om(5(geB&V5ylR#SDtTwZ}s-@_Egz=d8Wf| zq~lXFQd(Z(D=3*NyjpbnIl~aNcM;8Q|CU;r;n+u4aBKiLHE}%y&Uauyf=HTWtlQ!r zFBPu`**2=HSFbgVu|BjVsJfGtL>$777+wx6cdI7o@)QxW1EVG{NcstJsxl-IU=1*@E7jL+px42dPy;1o5pUBiPV&s;Ru5 z#npV7#fMELm}wpBfQwa|p?l?Q)oWYMAd4q7AzR|_QG*gfApvN>w(rbC2&duYn3*$J z=$}YUI9FxB+Wey)lZsmC9f=(dKh9_$l;AiI!b{57=TYt9lB5aO=IZG75nESU0$@ja zoz`}dGXldhu(~&ZD(u3Xq{x+NjrgPF_XAwG2=#6Popf}2Iy96vL~|BP=rWCMB7_`# zUDJDBWt7z4>X<)z#A$OSZ*%?LYSr9C92e1q&%`s6&m1jT)Sjc?NO^LTE;6a>_cOrN zI$@3CpigN|y;K+M#92Zw+F;MQSRQiksXX ze1UGQfB1S(Q2l;~0F{OS-ROX|{jW~_o#Y6yRjG#w$XuC+qnm!r!NRIJ5BP|=!vre{a zb)r(){iVi7a$u2g-SCh1n``rpvxLqk%Swbp<{E+x<#hpx^SXyrN~ahttvvH9=Hy?F zy&gC1tQ|TgM%vSxn8uj-MzS?M$m~8i(wCbRB2+mr({sjt@u+;|bs|+?ABI5Q?@t0e zWN?`vSIPhENNF+-xQxNMmZ46$B_^gf%^jaf`JN^-&&42BRY*G=MdVBQ|CsvDu%@~uS_K6Q zMFo|PSU^N6(xe7N#RiC|NDW1L@13A1AW{_2AT1Q7NC_aJLqvKFJrH^ey@mt=A?Kdp z``vs0XvmK|`|LA&X73yf`eP71#@6 zn>=VzgCN_~;k5KdfWbr2?uH(-k$^&3WwkQRrO$ z173Ti_tATFg-dK4ZJQ#jgK}m-XQwtJCU@SorOCK`0M6lQwE84k0`Aeiu&vA-yWU#A z!jL*n|Gs^O&2_Mqq6=Cx{J(ip^ayy{h46g;HQE1|K0&z#1~UWBK8fT9S*BY>A!de8Q|pgj2Kch@pr? z#%6_Ma`5ik9lKq_rry-O(>;anZym*G)Nc1;lHA&-UV4o2x6Itz)HTe0a<5;g{PrlF z{DNCrhxg|%fdIIa-Yj@ ztyzah50wdi`{4+2x>{e9#~+|AIQT378YAvG)}EAPj|yN+)ag2(Dt_ip(AM;dZEsL( z-K!-Ls!+&GxKG4tqW$sR^XyV5;&8v8K9smAQ3^d<#loAivKT+_Q|!$d%5AS3YX_BW z0Er08ybnEExuyiTdYTQ?|BtI>)0{lP=lsljG_n4r&XNTyP>b#B z6vW>O{UwQ!m0NSqzi&9wFeF{b5-L$rWQMlc;Hfj^H#uQ1EB?_#LAHs+u4_J*S?7PB zH)3St$3Yg=B(hmqWh6yoMBAx)^?mibRumovaiZ?lBDYAKD&`OEV7 z7LeBUxttwxrXg-8H+2;Ir{a7vT_c+1h+x^D$7R}VrF2dzj}%r2ie+Bg`KIUcp2|aP z`6h+qYIaSQ>hmQbF2?hpxqY!Us~p zMU>G?D;_>c9g*9te!mtTb9a}FF>z%xcs#z@@npnY3+sAve5bKusgt;(Ggthnl>#2O z=op3n1@j%N!xCyD%(e|IpAPP-Z=nxZqSU4Z8(P1iQX-9NAA^JzL2t8Ff!?bbHpR!^ z6sVtjb+-GpD(_asRVZb{AN%5XlYjJs;itl*Hw8mg=!%}`xfH#{ink@I_OS!m!J6Tu;RY8I}=?w8VXSY1D9!}OB)x8wU~ZqQ2y z*WBUBunCEQ%e7;qzHy(CdT;&a>3`)%MhG6=`srV$H19`%`hyk<;7bzBwWy-QhBL@AMdaAm2x@1lvQODt8p zn&@P5*w(yPC12VF-iVnqI#mqRN@a@e&62Y&tfmI?I%|o9AeL1Q zvj@+@y;pQ_hFW1LP7=w=Xay|?t-uu0cYsidv_5S916DNuj4&{%0y%MshlK4wC;?qt z*KcGvAqg@>LvL_PPhaQy8xCc>(nopwZ6CUJ<`r0V2-AxLuA$GA z+cerm$Ug`JS(nzqbz??>`3U+0&AOwfVf)uIoQ>a=%b+!>%TVA(kT~6Uk+)p-XN$$p zKr}TzOr~=h$8yO-t#90wSI`(`Q}Es!_)*O3X^@Jf+ZZj?JRMeZn#Dn};iU;T7K=)t zL`dv$A2o(&9+PoczR+|@98c`)yqvvH*g}Vv;X34JpAEC|dpV^}cxP~?r}4Ig1vHR3 z95UKcKMlbYJO-ihcLJ4Gm+A{-;WZd+$dkdex!Wu>Z?Y)X0rQF|)&5@@@**wU3nfFr z4lX~4-)qcK{ows<_3IydUm4im%UGkM=UJ@fWG>O)H>*tj#D5haB2K59n|r7+G;;L+ zF;xp-JkVE_S@SHAV=x3GJ-n?8(I+-~uGh+IXhbMjIdu?#Ww%#5Gmw}Y* z@!3GzwM4FG^)k*@0lR48vvI@hi_4ZP`tWfWYshCpM$e0-FM(Gr)J2hYYD;(S81ly( z(AEuZGDvZ8?)^UtPlP2%1H=IeaFv3bsM~b5&d?rZpTy$WS+bCJW8L2FqMjUQ=symn z+$>e*1}Z}8m$NM*TsoRf19E3NeOVHPKa5PPOTy#bnH~IDcC;pIGuWMoAwgH`^$AUw zJt}HG=R$Il^^$9w`HI{gzNFQ`zj@O!tlrTbk6!w{`Fn3y9@f@eNxBck^Xqp2dQOLx zU5~>b2VDpn8x5K_hW6{UL~7y>(A-d;YuSez;)VC6sT#d&(@|Ivre-SIB>tvW5ABkO zzv?if2pPt}+Q)_=D_Cy^(_^VU4F<}X<;ju#7kSeei>3bVq#p5Tt`|G5{`;f;7Qq=k z*lRvU%F~hKB7>L7zUaW(8*2h^PtJ+Y%6G={N_U2`>TNGWEY>}kB0t!rLHgl*-GzL> zWv5)R!Us-)_rrH>D|ix|XY=|}1jTm;BR5;M;sH&+0+5IJ_CF^Gw*w6W%m4vje((cO zM}b|+zP5Gy&dlfw_vb17MxLd}D@8p>yI?=^jWevoi6KsHD_z+I{8WI#Q*nD7L$&>z z*f|l^iNHXy043(gl3Qv;M!^gj_;dkJpuhC!<@uD9(jvyDhA*BcBoF3%__ATiwkBNj zQYlgf2@p4-`n>JOu_Nh4oVYRO7bx+lFNHId&)zZyS#~^e5z@AlU$UY0CP@4+1?whI zRPdw_w2%L4)c<9zO{UbD=FJIeSljtG?&|o9gHn3-8!>OLYGRRun=u6!jci;+zCBhp z3eCLLbd1pZ#q%<$sY6vZ(JogQVP@mr;aKS5OXOMEdd?ZYiBfbwa}Vyslvhw|7r6(S zgLElveN|($!75-FNR_brZdO(SN}>hb6DvT<9R#ID*;dO4IYE5cx~3lwphUrN2pKsX z75QJs1+-$=bzl{$eUx42U3-?kRQ%;vY)^up*%z=5LyZaDM0x8YFGmYD@wPV`()Ms! z8H;=2U*+}sE$GpC)_7DuZfJqB_{SP8|D!%lPMw>lcjn}cR=X6tP>&NU{h#@LG}LbK zCzvL~-|Y9Pc<)hq-ycmMkd z2jj$hTg%G@A(`V_-UN*v-C)Dg%BkB`M}I6|#jC?6TpSeOMRY5gPDyuR8PWBGA0Ow5 zF9VWO*1o1JZt*=&^ukRvUi0OkC*}$L%m6+pkzM{ycozpO)roE6ZH9M9-Ef-g1!dX} zD|E2#1_EuNfYRY_AC?OyHZY7lS{ju{T~DOi{V`wJ6p0y?TJTMGBSX59vub>l#M#j| zgpV0_e*9BqJYNkMdsIhz&@;Q(uvxJ2(EAi0G{&nDWj`Z@K9Z?vHf3q&Ctz{Df0Yqb z4+y^uI(4-@fko}nvMg{g3yfjUjCgx%*!ow#ZK$fFCCIP?aX{-oJS+@rNuAjD8-GJB zvjhFbDFRXkup&} zV5Q#&f8+EcoOdpC+VE%#HtM-&Md+M-U3#qloIelCS~NX7t2%zQb>danSfh+}X-(&m z*G@!3mQjtB*JyfS>1a(a$=9zDbVUr8sq(xd6|jS4=kcvTp-dROk2Uk8Mg z0L)$GV zOKi9FyKX#o$&j<`x4aen#C&*y!OcVdHqs?~%GXw7YPxJC7ByOr7jh+3}{MupN z5$qTjtU0CbUF4IG=AN~0k_)tz!K)JRAeankplQ9}WPp4K0Yw6 zs5@l-pnS&t-y-AT8sRc>Z&J<`oLs%s`t$5TtiD6Z=XdpvS?2ke;jhbFi4|ok{7&JX zlx#9Z@M@^Tls_W6vD5P$uMkbGPA2 z_XQMZs9MO#{QN4s$Gwz824!lJ!eEZKXu0$w)1=dMo`}r#8eAl_8m)am{N#qmOpC}-gXiL$hO01wQ9 z^EJSTvD81G>g5MM2l#Q*f;zJ^1*ox$Ap}B)IP_Fb@D#&2TN?^IoHOgKL$01tezVNW zhP77XiE0ga?*HK`iZH5@K5v?>*{Ut}2Gb~W4{@nw^>wVAv7AL@NmqXtf*4C-wADBly zZ62oLSbu6H>F;|M)&F3xpnZZ1uL>}A03!a9ap#~iz)i+jh4QDYQg<-h^m6H zF2jss!x(QunahCra8I1u5uQ_3q{sHl0Xv_*xjVR}9T|9g?ZN3(qvh`AKmCp&ZeI0V zx6d?>Iz8(j*@G*yZgOj^$1Mxor1^astPjGA2V6nu2xJ2MCi-7KkOXLhP~)D_fkmqW zIe7jcne$n0`DT-P88XlAoe78U7smc1GaC|8tB%Ad@5-%J=X0ZdTZ7c&|lxuydH0%Ye_j~RCZpct@n*rTT z;A{`Insb6x#zaUkaq@O;E!_a`DMUeVa_@I+Gw1nmfzI5(lA{b=5{o^&oamMBzeJFW zJ`@p1)&=bp@sI{SGqst82HP2YU+dYHc4B+rpo&T?I}DvUHT$qaEo#on5S=}*pmN$; z%x7Opb%ysfHevN-#u7-P^9)uZk(iZMHe0brCoMd$V4$T=vY`5pjjmr_zV*GLAU`cq z+O}#JOkMy5kjC^X=+zR*NM#PcFy=_wlr+tbK?T@oOvSYh034y=zo9V(ms^-Vv+o8KR0`B^a zUHYc#+Y7mK9f`7=&f?EAHC#O^nv-vUor43imkB!dvVowI_y{eVfqj0kdgvxV{{a%f z&x0u=P`}F$>^4J;KVD{P)4L*mtkg3=(6#G8oUdc_YeE09XXDi@l zeZt;tR4eaxcg3+mQ<*vVN{1axPjX%8`!)U>&`8-LyiU7CH2mZWw*u!p{#ByMU{(xU zXW|(TX;INDOKcj$I$dg6IN_RiS#L`=f6RCo@0%Eg+J2sn$juu0YmBrLR|9DRUsy>= zRy1+X08|CJmVy0Sm+JELZ2kt5UgEnau18xIKWaWq%_!mzb(2DkN|Ejc zJTZ)B?jb)Ov(Y6m!cIQN<~jIdaWS7VmEXJk?(sK{i9g-?$u>;3(xco~iJx`g>}}n< zOD#O^#1+c?(|U4N?YKXENgvx-fmf-UMjr3R2x@)yHp`xTCQYy%v;*K21pL>D+5wQ0 zXx~6ypvk)CV1IoInAuB>{G*mAlw4iVy7!i-mhkz}O&KI+W;S;1N+~j6j{M$P%J~*N z6mRHfaVNj*;OVHl6PXPrnM(9k^8A^(SVC!A?MGqvq+ieJ*FwlQ=3^fbKbbdX`e^s; zeV4m?AahGQlsmwKR9bB=7En8TqGY++_9=`}^F{k0{}4j9VQYK0x457&Kw$QO4X(wr z+_#j$Ka3@V$MJueuq?1Ihcc&D99FQ9`hO{e8ZvU;fC|wUiMh$4_eW*4FQqthbJJU@ zeqn$|KCFNs@F8L4?^>>Qh1A;6WtikG_vN64kg*HqYAQ!(O(#>rt4<@8U(E;}(XEs1 z96pw9l(X1s^iU0kXYZ8Kl#yx>)U`qA3zfL6$|TJ!%Pp($t(fwb3Mphgk-vT)M#7z; z5B8iGN?}ZST`z37WtfQVicVpng%d1D+rtl52s?nx9t!qOuQDnD7%v6)JDHV0(>4Jt zC@_`kQ#U>#F}CLU^C{IEK2d&CW)EVS=zLdSIMXz4gR# z(!d;c{)%lLJ@WK|_nj0jRqjinznL(e8$2tP#+9E+@`*||R-^I}guS@HcDzyNP2c9= zwXU7n$#m*xjwXWqVB~5UR)h8+%Dx>#%AMWrQn^D z{zJ8c(!m*5A5Ge@^)iK4UvPP7!qyBwmG@zwUEp~5b*PX$bEo=*ym;c#%2xl3RTmXl z-Jot1a?LMZWS^&{E?^^rEcW2dMzey^QZDCgE{k65vKE(idmr?s}5 zT97B%MC?(-cLS=3|@kUO|`n|*mHIL@u(qWOT?`O>C?_ik;t2nQbJi@bPPjVurvFaa`PH#kt?`~-Bf zBNcfq=kWT;FW_fPdqjU}P*DUnIn5vt8}Tl>>H0+UP~GmUDG}A`BL?m~IFp29I8ig? zy$B~L;YR&qlB7#qJrXN!(~~zpX&$RFYkywh)3>av{A}~MnW^VlDE6(b9JOoC%JM4P z@$*x!Nd=<$xDZN4Q-O?5g5tBp+mM(1D~k!!R@X9p?zCbMT2{#M6U4?_zm7I9F`q~H zRpMj~qq^XDZkH5gbSVT3IVZe-@#P0pb|6Eg5!a?*8D)wC@nQpvdWE6?t6?42Z1I zLwnx5h(}j}+wZnz`>*r^Ui-*bZWugYn04a^{Le+ip>$Q2yy?IfQn#w$ThG8!F9--@omC;l87mL*bmzP9 z`rYX2IIIfp*Hf^x+u$GqG>&phYSE>`+;3^wizd;14e_pF>NC|Fb|M=(o-Llz^)oSS zbkroRushYf;d& zvkVhi^yQ5^dv>qgAzQ>xb${t&bg%BF^etlgY-qFEdUG(|OCC;R<$*y!XWR)0f>NZ1 z#cbGEVNyKsinh8Z@nj4N4dR!Ftg;2Jdu-U5 zpIsKl&%`Z832WW!dujW1$cnArHrr<{FCG1Ho?{HOT05Uh30E{O!Wa zPql*L06#8V)9vO9Gi~!7lZ=zx)H6H3F(R#qr@l9q{#hW9;N#Ff_OY=*i>tHJ@_GH- zr;ft}0=$WUhFjA$M;j10ygz|o13DmmDj>-cIVyFZK}LS^$7_eQMlHsjKOU&ued)K+ zS`P>m8)TjmGhb)V9V3O=Un(6_*RirjF~4;*ztuzt>}wL!PlnQEcX~bymGOlfUw@sQ z12&N&P(p81&b}BjnRp}izM+trtyNnuIzSOq=~3_8QXA)A>GRaMJ!a#<>A`j8W~{hFa}RVB~@H2)-_9)=s7+9uC` zjQhCoVqo&Yi6`ZyDZYVeIpsTJ5^sWB)=jQR`t(R;HvCqo3_W+cH8a7Me*L`lt%c2U zTZx3UY{#|@MW&(K4L?maArKV#Q?1L({@%i4(>5#hh07ry_HL-{?qQi@TIwV=Jy8Ao z+BhZlK0;$uiNDa z`O)p&>30>||17uL8<`zuvz3W*;JC3owQn>g+sOz!D%uGfF!>LeLJMe++9#=?!In7@ z#QcEzdWvij*usF_pNqSx1S$UVvTrFukJ{x%O&sOt+%(kE5ejb4vbM<>8Ckg5S$TZR zfz{mNIi4st0Z}>#m!;3L{(z|?Y{-em8a)+)-rS9YbyyWeSAWCbb<}LGRCTvw^R^yP zbh~Az1VJ$MYWA@iM2im!b#jg*xt)r0A@df?Bw*}1%MtIJtLTHbh*|_s4$EIKo|W2V z2<{#205yZ)B?`y@xmQdbQfCArtBub-W7z*? zUM8E?(jX~JKA&fJ(U1PyOm8joF&S;0IMmvne)NUC_~8D6tWTT12XP}aDtMfT*2(aK z9({MB4=;z{HT5O2Hzt96-luSUJTD51#$Gg)nJ;$i+*Xlh2r$b+aitqXzpWEbx0v;x zc-NFQ^{UqKL#>hi_hrEp#ViT?^{S)v3Ob!aa5KA>&PH0|FyW*bc^D-oXt%vkGCK0` zRKo56{JP?lwyyaPZ-ca273HQA-Ucanh_IZ8tP83BoHY834Z?*-$8${ByN9ls{-qDb z`zAAYk97|voIj%8qLLOB0YS~4N!bdLL;fz3Sc+?! z{UR$o7)Ab?;8_33=kM~CNG%B0Hwu_og>eKKMP^n*pRmeT8G01iYc&-?L-RnRV1k%~ z84%RN13`bt*h&B|RWOAP$l!MXEYgB%dGsJnD`RtqV0c1a>B$7?C)qMBi8CU#n#+$R z?;W2T`Kuteo-l>wyN?|ho$1_z-9cK?@jFpympsJq6t8^g}!d6q^YAqVZ2fPkaHQElr0z zX4P+Xc{`WCJNsJZi$*=(=K@TGYdc?1#SL!PUHBu3@>uQbgC7NW|FBh|!c5#_j(g2H zaxd1y{rKoW+|mfD2zco9jWfS;Dr8ORwbd}gz5HVrB^Q_vlb#Q+UYvWS3jRYInj-8 zrh3pnoqnh^<|F7E@a^xJf-Py3$T)Mz5aZw($jn-BtL4js(|4IRf)E%2s3?&%#LD~4 zNU03h$g9h^fs0CrY^q(ll^`V+Nf7{K5?^1$sck6q*A5m}xon0MYmQbz=l8$w+{w$d zoxL=vKYkCy=Fy5Pa1W3m8KhKk zoARYV^WOk)u67mE zV2l(J*VOt-x2&6v8035RgnR#y&lbn?Zf(TmdEFt*G>Z{rep5Iu#ZUfrbYyIts zi!1qMc-L@}KbJne9FzXh*9Y#WpNt_9(jpSh;*Yv?wU#EkcfbM9E7(q$QU`1Rq}l-V zX(w?G3?;NAzA>Jhg>XzG1LrC8^if%suz;?n`@s%$4Ug>DJmdWZ3+x^q{Cd^n@%AUS zbn<7a$0jl8qW<~6X*ib7{k2h<6*^|z>|5W*)CJ?6&QO+gtsayZSH@{KX1J>>3H?Yv zBw*gHw(q*9$50%Rqoe}v_X=7Jce~_O+lXH&$cpT5-ChpDCKa!jlYY6tF^?dzUhyJb zJ9A6cHAo$?Xy=RIcP@3IQ- zs^PTEaogw8QQVKtl4f-gSvawIO+G>C_AORw5ZuWXHj?+oiQa*Ii=e$VTh@ zwxfH~zSS^nu&?m}Ji*ha6NNJm9TXnOrqyCm z>y?39c2vY+g&Q{0PJv_2;$g&9MlsL(mG4+23OOIBbswDqF%H#5Mlp|p;pz=|>uVq- z!~n-dwCVdJx0JZu>Q*f1kVl;8Val2MAqGKkfhtiBlbKQeb52L2lvA+dn&^IyTrt0} zfZJC4#B71eMf31v<~J-Shueu6ZAi4oPH)fAp8=AUc8HP9tnA)zI6W*fa6HANjW}sV zB3SMN}-&lJk1TaK`##NPPj1byH^uix97^p_s?VkorHBYfu~)xjoFa zrXf|fqWtg@q!2Dp>YUN88_VKOF9agQKZ5 zfFoFLgPBqlXm@@; zfko6+U3o*s(-VJ2S4aF6^U2c75O@nVw~|t@GyFoo3WL#Id)*v6Ax!T*T-$Zr-(#Xk=sI@BPLwI&AG9BE*7Po9Cpx-3e0dZU<4*c)bVJ^|8Y0dyfN~yzX;|( zAhERnpCUOQ=NCM5>|=mti~q*X*UbGjRj=zCY~A_EfJ(E03ac;Cof7U(Xr1~Tq8n*< z+5s`$m0;mmC2*nh*}|ApY4j(qsA&{7I(KQn%hLx@aNfjd(zs3Y$yEvcu}b9*IN~)`OoKT#-~Fwfn~v)=eE{ z*#t?Jz?Y8+Up%*=#oO_T|~C z1C6!KbrK17TGEm`I@1_z{p01alAvrB8qiiTJZrnu z8BywN{)Fsr%WW&dbs=Hs`6tqJxZYs2tnwhPenbCS73F=y0PY3|8s3vWyg@{Mp}D7Z z`|m)II{`sGyzk=qNr7He1of%?{LRy)DR+y$Bki8NHrG1s^>p&I*c7nvP0E^BSRF>p;?G_2(-LD}_o_toABcHxe)7VurT(nOqHZ$%Gg zaGzPXcb7rG$!H(GI8FW)vdJqm!Q8YyXhKV_);gWzfqFUGt)T}Lt z1ma2ua0Q?+H2X{Ph@yj?+G6FU6cQng?EBx7><%uJ9Frwhu5jMx@z2wU$;%Zlku&+k zWmXO2YBzm(PE=k>EI3exk;4&z0F*v2iUn9)@xZ-$+~4fYH{=l>o+lNtr%?d=MbD*s z(3yE)Nmw6n6Yn8uSrI2GnH-?1{RT?G&*Y^%z zwb%$qWktKR%N`avptTK1@&p!?kY9Cb0@PDo()lDwZ_ZC{;jUSFc1bQ^u7R{imlYwf z(#0bf8Efyg7sqVE@;C2zyJ~dqoT%ucv#u}BwtIG&_2wOv4Ii{ zAC1NtQ>zlT-DkA}`P>!clUv3X@x}QU9siv&#Q#UyJOFaF0LwT`2N259@}T@9`u>|M z?pg~Ewoh_hA1a2E?#D5_RBkU!ofx(rVrcsMI^+dIpGVC8x(c3D24}P{82V9HV)F|3 z86wjmFEsg-ESp{|rC>DeXQ$Zks+@_FA^Xc+>3FxE_6u@jS6?*i$9Pt~y^7o(Zftoi zGjaQMCdno9NDaJ*dApk(dJW%&w4Q7x|LJ8~B(6MJQW)KRuESX!MmuM;Sv6YbMZ=r* z2@b}?Kx#pnCmjVPl?uzbC18FlgKxxd|1>?h%plA5;cfSE&SbRX7`>S9Q>L7A=eVwZ zQiu4z{9KmxB?r`*HCc;)60F@^o#HtsUCm8 z_ppg7)Zx@DL#gI72lpkpeCglDXu|~%*qHthkdnTM$2#w#B|Eq^B{d*ulXA6J>WCTFAY9RIhx@u4GUKUZ! zc9VJ|^)a1QW@XS?TR_*(ey^#q`+(QlfY2~7v>X2I+{Gnbf{V4u@$GD=iWp@5YC`GW z&mfFaw+D{jh-YZTW-vg9AeLNudxm?AlVfswhE^O!)jI4e@0n+P zz-s#DBivz^zTz z8G!iY0WxG}X(1_H0*WmbSdg0f_~6)ADYFyMZqd5S+lH71Hp92x*Y2MCsW&sv{- zZj4JjOHb;)v=m9|5Ge zAy2Ht1AftDWN9aCqZ+hwqyrup5e8oYp_<%GM?lB~%2FX*+V?N-*f!}}ZcCCO-Hm1b_!g#zCaBhonOjFNj*rJA2XU8%&WHr;!W26{VPs=PxH zD=Eg0iO5p>Hqb%=6;*J*|Cx7|BYtYgTu*h0zNi!C) zcQlK!0d>38inyOuWrVeRSj${6`{gDR#Dv&l&)0+7y%x_O%_O@81YWz&y(MDe2J_;% zWbBzx*P2$yz{L2A-A*K_T%jqDi>pO|kcNZb3c3)9d^9x8w^A9Hl=+xVt>?MUs}RQx zI(vrz5qc|;PrD#%t>I=O!p3e)(R60EY5}v8T^CqpYt~KC~EK2G$0d^*VnM>6tLhc;=yv21d z?s~4dppuzWFI^PQo>D;PCLAtv>4U}ybK7-xhh7oapD|8ZP}R1=x(+e5~U^*`4g5j&gEF`vp2G9fNRwoy*`uH98aIeRo}Yf?K{DoQefHbrPzJtC!}fYg-c;8AJ$);Cq&R5 zZmGjB=PVDk1s1KB{Mt_X#p=6hnZUdp-DR)Q%oa>Je|#W|?Sm?xcSNy!Gj>Vt{8Fpa z+qAry!Qz+Czi&^kB=9gGw9=+yTS7bZxOhnlgDmmaVA{UL^(>M%)@t|@E0Y8I(l7Ik zLO6mpE&6ZyH0(hKtc4Fn0}Ya+5s3g%;ZC6hGmA@%a>(6pB%8#IUy(QOBsfW5Z^U29 z77X?jbWfUoIA-A_%GP-^M&=IYrFn+`OF`8|hS!0OAM2OCVj|AVnNX!lKk9ynt$f0q zKKQ9#2u6K`?K289y7e&2B@hZTvxtqd_km1(71BI#6DxOQy+QT-Lb8q zx;iNzH;8swVk?19`UhRED>K_{uw0VYaK|MRZLY@34KS+V>T}V0y7qJVnF3+p0^w!|7h)`Sy5kXB{d+llYXA9~1f@dX2Py8En4aCl-sL&q zSP-goCkHNrKx&`%^%;TFI2fi^l zrim=`Ux@RQ*60VQL3&@K-@|<~aoFsDiUH(P!)=Kb=FQ(n`wiPN+CSiKwmL<;q0Gb~ zI(W^5W#w1Ds{tvF>@%HQxaboE1Pvw&j@1u|0|5xyFfub&{SrnTu+^mjEs!KQZ(e5r z7&`gEY(=!tn|(lfygDUH*3xk(tVsPKHleCG(r_bBYu|wTLVM z;>Xu4BmrsJ*r0=+1@C01bEC{@KhH1E=V@)sPuVOS<9|6z+`hfsCBMPnHF4Q4+EJr7 ziK~-q59$&{U@p$98cYC2l4)Ci80-08TTzQZ&_B(@_~ip%Q6a^8@oz4a*i^e$`a>U` zx|?`W;Pcx8j_$nQdKfH9NXpFmX?O81yz^&KQHB5fGnKl>E*E}saC{djf-*4KJ99Yi zx}KO7v+pUlA}A+1G+rlL&74p9Q6%5=T#S(~bk`&g0cz%c`DP@gpQDHSi%ou^rI3{J z9xpws$@r2{1l=aHW|3QK_j+j@gP~k|E}%v)!?^Xl>Zmu!EA;@qlNJTQd=QIn<$bWA&s++UI0se^l zmPI`)$vQGe?^|CHtzV3-&ek}21A%*=(hSaz#r%GYzowGFY73Q_`b5oKQl$@NzvXu4 zT4-$KEzfkMU!>P4quS-{5gjW$RC?<-{*30`kfY|l?7S^GEK;^tOBlJUODQ@tQwyR` zuYRGoCHB{Oa%OAqTl6L5y9__Rb!}Hvi0jj!WCHi_9Mbv!ujKi5QIPSV^LM&Sb4c^E zz?I|fyou9TmareMPo*b6J)vY}-jFu=U01kVX4Upxt}~^AThP(i?%S=%lk+%y6qO^! zpZB$WzeSe)-QV~5XZC&ypJFCCeTWL^Uc#w9v#qd|Z12IbGX1dJ=*WDerB=XAy=8r8 zFV>?_y$nI@qJEVB^DSRCcutBPYH(zH(dJF%a2M}jX|0&hFAEpJ6UEqngr1GGJ{33! zluYaV9a=fG<6lo3oxY{T{3_=6wI@kUro12Q$)C=xE1kJs-7~P*hv#uU$kEQ^F!qSV zohb1N&tT`mJy+B1-!yTPncuEVnXl+s8MEz^x{;XTS8{~D=>Cjf`$e~_^KhF#8*l8I zQiL4ViZ$mmgIbU=AMy}Fyc!f=(djf6PNzinh1Al_<~H%n1MBkEgx^uW9@#Hg5hj`? zXbL^F*a>O^fXT|8@IcT)Xs8iWs@tklCxqWwTuI!p=fG7;S=PDHQP70j zY*@Va&s$4AbP?C`#DOtWsvS+c8|3*$4@m$USpjW3hrp>Yhveur!)j)&28b zi--QqGfDGqs!`x)E2T>RjZ}o=rE@L95{zcO@?sN=Mr=OUYZOa9y99}L!2SotH=v2s zm%)k}>nRgvpfN-78@5y=*vQzK17puV8rav8XnXMEt?>NoI|n*)xjEh2DNc8a{7FI?Zsh z!UnbQIb@fZ5`1;7_L<${h79FP7i$cZxB^ZyktJUxCl^T2d(sn64@Nvwr~l0)M#A+b&*Km7)liHa zc4uqhfZ;`tGheB5c73{1kUqg_J-PPR#E>s2;|KUz4QVd)SVbMr{d#eRnET|Neny_k9!ooG1Jx5v?4d3$=?ie53eVF zmoZgv)(Cwed-AraQ9bhY=Qm49=@zd1t1uZ*3~_2+fYd3(eQja}mHc@zv_egB(%SDf zcf`*s_HNv;uJ?~GYA7j^`jROKkTCe=P^|+)001FEATm@{na)*v~Vd z|ETYnig&O-?}9)$tH$YN;UYMahi@-aQSWeqnHD9txnJ8+*F6#gzy|`YNB7n*aJIGw zBteEzfh{m;Ttz(J=nXn^JLB#1_pZ+Fes?MEB&^?s3+u$iXIVOlc?9@;5rrCrA9(vr zaQ-@|tt$?u2;OESR*k+3h*XcDxOdqMKD|S8Ia180`TUeJ zr6fLe67NSZ@S73bt;d86H?6uVD?JOVxlIxhg=;EE^LuJWrQ9aBFftu#=1*jMW=|4( zgd($o$*HSmVpp@w`CmD(KIlY|)b7;>gH|5N@^9{oHktz34%!C1FZ0)G(vSzy0G6Ib z>b}a#DIWO9-Jih=Y~|M;24$3A_%p<9dpWFUsAK8^$0dU+sz}?_1Vxsji{)ng*2^Ca zL7siHBfq2@PP7G6OGOzAWntNge9cGullp`za#MO=>HqdH9$B9(lPXBz-|u{LUGgn8 zF6&qF`YPqCBrn6rvoQIH7f-ok_iXK#aOu#LQ606#tgyhLCz#$^aKW_OTs$D^`OiMU zztIisATR}(qC`Uj$re#!GL^@+*jM&&PtEsB;OPUH%q!8$@GAFbac}rb@|2AFtay4@ zoBF@2EidLuij>x)@|}6YxpT1U%EN!3nGY?WjF%BFv&@%IE>Y_o`rUYWFJ#wnUKu%K z)$=%>KLDLs~K3~#UXOOZKeg@Rwlyq=h1md!~CLYOR|AD^%0ot(y zt%SD9k>8CpT`SCA7+JFDhLo%&tBQ)vx9TW?vyrI-L2!p~;pG{b%Bz36G9`~$uk_5i z2Zu20b!ENkDN2Yf&DL>X<@k#mIMIQ?Eg$)_|5btVJ%=UU^{)M|Ksqh{2rp}<9@ggn zL)BXbM7eeE!-Rq;r6@{+k|NzLf*|D}sB||&!+#QNucY7P|6x1Wvs(On7Oln!E(Z1#SKe?xQKBpu;5V0i$OyZ~*ahmC#su-)K5Gn?c=wB#pjX|emy z0H*us6A0$sByF_1uR$Q3!sa|xXfRU#LFLs9Tv(3!9fC_OZ8-07|7fpdNEN3J`{LJ6 zH_a&Mh+a4kYV$kBNFCHHv9br^LPu6FD8O6aGLuM-4Bagq(u0 z_<4N?nR@?yB!Ab7TR`TGNYyGUT)_zRSd4d#m*z!$p=T#_<-A;nLxRCV)Tg;`j?8k2 z>$ErrnfqdF%9pEvm}70*O)XH+-d@g>=wU7ML)uhv`Sjl*Ylbkf%F29geBrPe;)Gu_ zJd9sUj)lau@_@KIcz;CXQ(cUlZOUbB;OL=Nn86vN=nOw-NP!a1onT+EMmQvS zgy)|ofK}F=9~89IZ2lKL{x$aUabWQ!U4Y?714TR}50%9|@dg(^Z-82ym$3zNlaEYj zQt%}{{6}U1kv}V#RxpZn2jm?M`JAA!WNARdc49L?9gosE_>hN>bSF+Fci>MQW%JrDGC*1co&<*JaP4Rt*Z(j zJPAQ>gUk)2QRD3RUMl!|zFU#K;tpVDLK^wuWsQv&65d0*A&+uw`~2&+^RK+p#ny^7 z`;Y$QQ%Z`Mu3AWx)Y&=^Ps3MS!#a}AYDDwvHXHtp-D{3-9Sr)GoLnblMKI+(09wb| zU-{!*$%u2>39_;uFOb(#s>!XOZv`ei9!{EdO1c-b!wIs{v=Z(q1PzI1)CUs}OWBCT zBMQ?ZVv(=a;;V~G5Cg0{$%8WmzWGkB&xyyFp-nGogiL+&pJd1>n>oe5m|SM&e@{G` z5+G(HAwR}he8+Z2N2L_=9W2-^ob%y2556eCAfDaj~}x0suzrX-vVy$p65;j%#q7i-LW`9Fas>cNh_C?DjDc zb6KGYj0s%m7p){y^+<|VCvd1}Y52lDUTLSN0B;4B+o1)O7c9pWj;zfATR*9MRT*0s zF_Hcjj;cD1aGhBZps6kRwk*n=o{wJp?I9Fi;IU>T)QisIB!$!C_##qLb~uq;Yb`$? zj?mzej^(iO?4+o9LT8RLkjmE>;ok>Zm=!~bk0=U7f-0%Jt;uN&R|gK}V!VkGbk ziAT^zU^GA~p!=;JMC{I4-|EfNd@ql@)R2%t&Q9LUBk&P~5hBO=0!r2U8z+vrNGg)9 zNZW5K-O%Ep9keS2w-5Dzq+~*-Ae8NEf6^(m&V38tzaWKllEtZztypg>D|v4p`f=QM z+!0L&!7+!|aaW=ubCeC65VLM$EmO2>fP#D8oIT?R&wlC=PZL3CmBPSh)W&aOsk*Bn zm4C3CeCvQAQtiMW@I?}Vl7kH7uayH;hrkQ})_{+)CMg*{q4yxdn89Z}?}(NfUl{XKD}fw68yGnA zr+9P{P%*-AC_5b|LPs4d^N7PS`N35)yb+V9sL zrlXDG0IMc50IHn+%}|WRwO<7^9F77nBmmCv6Qg)PxKAq;^)3lnwbQG<6LuiGn(e>? zn$Kx0zEsP$c`SXhTkv#UKxB=ANqFYIgzf~tn{ha+>)`yLdZ+0MH*@e*gsu52pC@NC zwthL1ZBM~5OM0P_vZ}_zJ>#_kWd%q(7oK5%YGiaA&*!#YTYa(N`kI~4jW#R}} z)aR3Fq3dQV+2V}6xvEm=d?1kN`+m}1wcuTC!V!X+XwBR)%GZf!?!TNNK=G`_Ixs-r zB<7!9V3N}utxPHgDI#jFX~Rm8fTS=loTdI|Oo-F9*|BNsE@(7-uT08>gh2kBgQbn` z#MzNjYFz?W`|`8BM#{1o{@X>)Go7+Zcr<({MXmX53%xjFL+S{u>(PcBf>OO}0-D0Q6rgN2#@=NzToIM@#gkckbE0-jgvmpu!tz+~nY+36|jry}ZyV2=G4})8~ow;Q?X)S~aTs4cM^RPp#UX;fD_Mxp=4~dpTFq6eI(CWDRmIxyjbbtth z7bA(CzcUu93#8LQzSt&905~%*Fe{G!=hHGA0koZl#J5qKPrKwyTzL`{UscG9s49<* z+{a^%9JGwyv638P*iY}a{!(Gn4~9zoY?VTye;JWxsyER7+9K_GP6LA-t@9PzxZa)G ze<$3;@qBb`ONmrrNkZ@szqw8B#E3$o8O`Yk4b6wA_K6;_!Ny%7TQa9d(w!xZYmDP3 zv!j-DG5MO83oe%}1lXh&kUUJmynDP1I0n~@8@RvQR4`g*rS+nK;sDdIcb%~Hcg}1q zmM>sbnmCrPtZ4VGe|_^GN81?rXVY}|vvlkeGP_x&n0-dWrBwY+q@jZ^<0qo!h^OmO z6Hw4nXcN)9LGT^_bqyqbT=a0GJGkGgiwu7DHj39#x>KR7(>EWZ=3kLJ_4@~bq0A&| zRgPFuZP7ctYQbS#CHPO@XYA7a$IbrdDgwJ(gl+f)f}(!R8Rt`yxAv|+%{fwcMFn-@ zLXY$Hm%!hzz;C3}#^k?~(9z@S9kvJx^AevWvQkCRH4|(RFWZFvIllbX-S*gBjmHmZ zMK@JjSVy~l$2&K@AG$cBprzG5I5-)RTco47rdy&tP#=Zz>MHvXIIHnwPX=d#pzhSj zJ$7!#E5i~L^iBE;onchx<}79@xVqs@rAQ1)T}IAZbUPU{4J;JvvjDXSziWTx+JTX| ziGj_{PyB=brUp;4NSxVMFJ#bSHg($3UJ5;px0ucv%i?)(@zrruQF{gSGVKD)heSt2 zZ{A9#lvsX_581pwk`+{DmINVbl!D07mwQg<*tq~4f`1$}ku&GQJcr3(niM%hiSy22 zdg|2_?bp6Tv!!dQgp)ZYzuBh!7>*QZ$=tsbN5HCq-hpeNFagR8*KIt2orcf@`wF3x zcJ#Vpzv}0q`W(bfg-^1l%em=!1z9)%-B^L{ZBIaBWjm=(hkeG_5{H?yQopvvuZGV( zGrlUC>nAke>#BAxfw}fe1&M`<(<uUww>7nO#L}Rz zhPs>cO9mM*KQ>GIFF0g+@?#*EUwna}hfE9DWuS>!a~Bw_?q={6X!I^ABUzHd#@d@O`tAK}5l6YjZkCB(rcm z#zgq(T7Npq=yEBz^FnjeXQ)6V1lwbDZ3_&5CyucM)a!uCm3BVA zsqv_j>n`U@qK&8ToA)^$+@`TU(+Kcsvg>GnLqHi<`#_nx==6f6TBik)(1+C^lXB z*~#h4j|1?P*=W1ZHRtNzXEC~NTLb_O;G?|4P1dHo`Qo$!%%bfZ-4t~5V~o(PM>v<3 zLvKu;g(bEkygo)Q+V6@e)q}>eB3bF!<_3fgTED&y1C!uetI|=3ji#20A)xqcDk?K- z4L;@QBkK(+5Uo%QA5W~&Wq1RRvSXOvgQ|OKaHFBBLkm^BId^MVuHzb8Xibo9^kv~9 z>n3d;ct!}CrRdF#jCksM(wX%3dRVJJh5ePu&_$x#H9`LRJlk5m3n{COy;3&OL|_O#5uAv}g_;3Aji zZ}fw`*TcyVT7E{sk}!iZ6z7Ag0rwSCqF0UD^g$H_t&j9MNwWj9PoL~gDw@J{>#Nep zSdAlq+)j0bT`tyLqf zpd*W&m&mW_R1u(GdmJ9QC2LzgCcb-vCqxGm=OS5FEP^FjOyZGcCp~tR#kr>j4)R*I zWW_WPQ5*W#eAh+fYq--h#16Z^u8b#Y1JXJjm~IPE4MBix+rxa5`Z+ArR+jA(GH;}Z z>**z+4wQHqCM7GyPb=Jm_B8D7TZ?P?MN-yQ;#72UD*=@tN%};X#T8#2Uknzy4M`>m zdhxo~SFF?!{G4lGHAm!e@Un%?4JWsPfW!lsOi;olWHRkdhzH@WdE{iz5Ji^7#?+gT zG+T?g+0L-}(O>iE8T=L+k@9HWiM}A!PAQ*9M$?Kup!2OaXKZ@+{^bH)qa$_(X^R^a zGlZ=qV{A?_F*oim5)lqJqIi=$=v7>h@sxMVpa8%0<;Va@<@9iCj2^3yh!XSKj}Po0 zJYo1x)t|$km{4AVMTK9Q65H=^bIDcpf`83Ox zEnzFubYOf#_zt&_<^!#CkKDOiBW}~7+F2`Sbrk>F>Wo8DKQ{q-zTx%Q%$#=p_)OsS)aKa@4X}*c56r6U?i*xbWkAiG2Z4@-Z0=Z6Fo?zxxR=9WuDmaNBim4*1hO2&jAV+~cOb z9sEM)BSmSj;IZxF33emGkFz^U7S04IoVe_3!li4P_iEy@{O-wjv}xDb^?AM!%wrP? zZJF!@ssJsv`XtZPzZrMU8pti(*So1ZZ`y#giPm!m})3SeTE3KkE z1o?yy^Po2KrE_eMRf2t`UnmW0a^U1ylOg?)*{VRtyF$PV{b@ydH}Q9^%AIAgy#~Yo z92UX@Y&@!i^|p91n{NS3!c^>I`gvNumMoB)i-}N;P00SvZu$)0NfjoxFWJg^lf-D) zzB*rj$Rv!QW`-1v2FAI+Y0R8bpmV1+wSb}GBN;bEUX2u=*&KgD*&-GiCs(f`3c@QY z^6SNC;mwmrc$dO;wy>Pwu~0AA*+wMqYDqHfy(GxCxmxLsh zHRET2kiU-i|3Bu5j^jC-2#SCOU;rJ$GBykA7{ZX0Aqsihl)%)0(B?4hiAn*%*xc_* zWnYTqXlE&A@S2EuKC=r_q9VOWgUqD%D7aYO!yzJWuRZIITM~9Jj;e}~qiW+}`Uwje zULC7tHPB42f$-A{<&yH|gFcI51L5@N{YwIDI%MmgL*>Z8Y4|~_nZgm5g8G#VkWl#w zwk004gBv!j4EqDeU_BKc=>M5^x5fd6VpryBFWP^=Z76iKt&~OXUcHbf0b^tfOQQ

    B%6}~pmuXty4Aqp&XaH2Q*B+FX_1z%@~V$HoM{`)pcqwQ^bwW8t%3zm%~(Ce0h;T1|D;e@);?0x$*%emx-{AmQ9@@O5xM$E zGs6%1q-%gFID0KRz33Jd0s0T`S2ou~U3Ix_p?_~m=WBulww{J{2LY#R5!8y=q@k@N zPpQTmK;=iJM_VQ74XZhAQ$Tm7%#Zn9LvlSUb7Lgecsd8ArsNk3@OjHi2rPE1DfLnEizC{ zG%@?o*7}8dW7y;F_4zZ&Z+=}hK`$LoMhAmRV#DP272{Jq>GEGv)W&`E4?@Z#=c%hA zeGlplsRfQLQ|~Lk8g`;M54kV87~I^^*zsGJ^&)yKwK#rFGlAw9WZzqL<0;77}_WY8}XWnkKb!5HO2f$13<#2}mxqYqH2WIqJ8u+}n0=HN zPD<7yD8FR3%a#aIl0F7S zjwc+G1mj;uMA+NeH-lBTm!E9#y`w=t$2e@s>g^1EPhdlKCIhRUd^QT;G1*>4C1BZu zmq_|x%c~%hBw%3AHH{BrVaxdyO=kW3H=6+H!vDMViM-HXcemE z42V52xht5GTbAy!BhFt`aq*OJv&#gQ9KJApW{6CK?bT%PBOG^%;V z39p@^-o@X$!i0ody(U$KjP1t2+(*Yg@@U^j#UI9GE+WFH9^k;xtyYmOr*bpdR9W9ZXmvr=@Om2hMou4PS&@hyO&5$YVQaS z5}9!tYjHJks7rXFGaWRm-+S*NJQn<@TeF#^cue9Y1I*2#$!Xm)4SGHl#>#Uh|6%kB zEs`nrz4Lv(4u$6MuO>CaJevlSJmC&0GVguPj|1;g8Y(4#8|$AM;^OMuQ6nuj)J=5y zVM!GL@>pb_qQ3q*@D~Nv>Szk|wF46HfPPl?qm1`Ttpi$Hdhmdb`)kIoj5cz2)EMAa z=|&)QhK2XO2y`I<+%<8P<2LMdnH?6piqm)7!_Rxawh}d^;&F9nBRKM+5%JyeEPl*< z2O%AN2UDL=*E?0@pM={_>1$Pp^xh^!Jl+1*_T_>{3QZG+A1=rc>Pt)&Onb}AP0Z{M z>iy}Wnwd-VZfv-q)|iMQUB>`jy8){F_cH%e%4tSf+8?i-k&vU&6(hnxV3PqvmBCJ$ zV*m=%*i^Z*;_*HaA|;sD{PRw7tiD>| zoCB&13Dkx#>Js@PMsS&XmRCl98ias%fKA!feEl0kVKv~pR|G33k{f+sQG#{qeu@Dn zBi05T!+}4PCTeDXJwS~mT=9jvh#|-0-w;rT`+lNyChnb-p9m@&f(fQhvB%6m`pSuu znA!bk;`@-WoCD4h{fwMh$2q@svRQ}rKI>7M21cWV6UBs7p-+Qq>)V9KkU~snkt3J&8|{xVa}Z-D`S#|JZ5e* zV9nyA{5zgzJ67>zk&vF>v@<0zkL<5wzIkxnCnVMBh8kMI@WvPC=K8b_lCV{B&X5`u zSeZUbgc8nk@a2)RjQMX3l???FgwqT0gZ44WZ2vqfbc|5EP)6iEZMx;VmvBi};Yk%w zhrg+U|8Lx?^?LvVOT-|J-pH2Po!;aQGQMHm7)JdSWobI1IP;QS?KiW#dmzZOycbu# zVMw?G8T0Xbb&=R>!mVoI?_~swRN8m6s(Q&?k);B*ulv;RrWwpCZ_$a?UAU>W*Lg}Q+*CH}kD=Qk=hYcvObtjgK?4;4vC2+=vu zX)Cu3x1dxv@%eyrifyz2K0W?jI-pAkk^$aF$XTdN3?|y{)R|6=rxPNz{HQI@7B8WC zP%D(alIx1V*BP{->7gHF{z+JG=g;lWC*bKLM;ohW5tx|xu+xbTxLhnKm8ao4x0C9r ziz=J;6RIaB^gWK+V`kuovXQ$CjRYyKW0v}!xs)Hr3s=w_e(zt8{C_vawEP- zi8|XW(ZB1wLVof2W4!1-xrf4kAKd0$Y z*?Z_MKqe+L=3l(h=Ea;kMx${)s?M}rMphSg5ke1J-DNAT&om&&+@kaH{VnpA^z5E) z$MLezxn0qM`cM_VNHm|q0-*Y+2Fy~i1Hw8JH5#((_97vD;Ar$y|2@hWK)yos2LJJg z1e4DuS)!9}PiUBNM@*G)Sahc5X;teJW!(v(tTD_BCh5ofHd`N~@oy;cfV4BCc?Hs| zj4twuwD47yA~^7MAp%!=FUHyMbL^8?32E!6{f`p;FS_lO*lSh>>e&}ZQWI_9` z!vuRkq$L^bJEhTjkbPh3_i)zLft%aS)z0v*3!(J-9K^R%Hc|H?_?A>7v&4R0zyQf~ z8{j0De7FYr8Z2@`t`n-j@OpsVz`S-pA=2O;iK3h6gc~t8kN&afEdo3pKcU__tst`H z2eQAoWvf>Eq4v*z%vr}lr|-L4kL2bE)I1>+NU7Cnu^AG*N88cZ`D^*jAG_dNnL94* zx~#Y(kjSX8TCJ$Z8(O_Ct*@FZJP@PKBzMv5Xw!kXsIC63;Wl4b&c4mF=MMHi{JW%f zV3T*oKb^ALcDYiV_w*phoXNU4q_mF<1K#9D7`fO3>%T72Vfv1EF-*DxGQh|;c#AbZ zX7oZ1kfNeG9W>(a%OLVyt+TOZRa?*l3+40c2Nxro4vSWWaPP8!@2GZ7ou=2Umvwrb z%``a*zI@oPSxlXB=P^_Z9%42w`BW54J`9qNh!0%Dowj`@wq(3SZsLc~+QU&TYs(qj zzPl-M=zf$AGA1NIxpa*%?9}XGa0Woi#&wvwP~BSg#8!&8Rft+z0Z>{ zT>ta_WgcP}JRg$@tIK=3jInURMoQ5Km*&ngb5@!ap0OP>M&bcs*>^}@Q7b~owg%Nl zub%!ovV2umV=hp3Mla1KE>!^tx`-AsbJh26RI~01WxB0t#CgpwQl3 zCCWslronpKAhpY&@?F3uf)^kBgiNgPbJqOO13!85N4$Yhi$H5Ehb96yd6-#^Svkeo z$VcSXL1v;>Y-~u|PX=Z3v51p+_!kmIn!qkg&FpnnD7T!B`C(&XxJo2vrm|Ka?3FgUFp!yl*-f))EF)YW!tdrwzZ^bNa?+To zp-75VL=g}Hz*4gYxNT*&p_qCffG|J?y#^$#>xOybz2KnEEY39`GGADwJCGL{0~1(} z2UqP9zt7GsF&APsvCfEN6lQEqS@cJn%kl@_y8xQEl*(jixMLo^PWQg|b8;eNk8Al@ zDmGiRaA^v{Wf0}vW7DMJoxlC<&o{P05Z7b`l@(P_A&Dv1Y@`pj!N?eAw60c%9_hp= z&FEWLDBIr%-*Nf|hWs_{N)>xPy;o>W}nH!wOWANJWThI>;fCm8`4A%dE z#c0E2UIg3!1t25O^Sc-R=1Wqch}N2b555L@N(Lo5?1H{!ZI72`z_W$zW1a<|k#fR;#EeP{WU%x-(4g;wL=g z#9J6x$#r(@Cq=b9RC__T(fIqJ{XMdyXr}foy<9YT+7H;H5Crp(L!ODTBUKhWU@AQZ zm9FsTm21zexqqfd;`<^#Y?G0H>BFqqzgayQk`(`708g(kVa)y|por*fug_?C4_8)_ z1wgDj#yqz;TcN6W#h-=sP7EpHRLJf0ow>?1KH*72T}yVF+#}L*wtexkRqCSZ;68Uv zC$vE={ECn50^|68c85-Z^++{&D(%F1rl$sid|Rh9=nX>xI)yl|3aJovWh!*e)fDw*>h~H<^?|jPSKHua?^kGiwH$-~p0!9FJKB9~EseLiq zMa4ws067}46rz&4KFhjH<$Tq3uK?s-0#RLyrI z&9hH)RP&!Yx@8;TGkphNoR-;3;-JgRjzydQ^J)GH z6`+iM0!x+gGrj8OX}S2hDDUCcX7hp+b`WOfN&UlJ!XE?`42_pkY9)YefC&s}p_OYk zjIUE@meXF3|8x8z;};j9aXPgciB!N|t z0|!iE_LbEy{Xa6BJGs@xG%65=bqy_7d_EmortqXvD~jrlkIr?COyB9ML~jJM5x%HV zM5u1l94jA6H50rOr)&blNLyk|rYC;eI(tQ4vNrj^Du-GQ69IYOzsr+>%b0nK2V+}u zThI(B%yykZG=POzp;oQ8@A(g&$8eSo3)=SZ#$}&P7d;YH{in{|5;9i2Du)dQm1l(M%XU zSNVK(S+~o71w7)Y98EJ-Odo%iSXpRBaC_3l{9{AEm7qPDdUa8J= zsY|2UdF|D2Ht(iQ`(7D)x5gVsc99(DUl&S-2L$R4c7<)NYC?L+;3Q7KLM*O}kk>{6 zgrxqwh6g;o{Ft~XSP13q|SdHc40@-e)K`=h~VTK zO&6Uq95>^s5w6@U;`wX;CHmB~W|FId6V|Pg>du&v5?j8(Y4}ZQWaO7WJPex!mRaAt z*PGF*xtsWru|yi$+PqbrkfE=UHMYMRQB`}} zL@AWa2W_;~M_-f7wp`QHL{l2`o5nBF+F27D+9wDhhvXGVgtVX^BZ#Pzqib8zbfLab z!nH9VXpq#rY541@nBe1Tqk+m`uC@ff9#_{xk)K>4T9{o{g#^TIqfb=M4s9vc_yIpL z7j5)n1Z(fW{{pV!AXebHfRf}-j1iS;fCyzQZmT*kj&SsSwo=Ei5Rh+qjmr<*A7h6i zt7kMra=zA&%M?;XGV)bUH-#t^7@?;hrPVV6az>9`7!C32pjwfoWu8U(vm1oC;(^2B zk*}vmt6uQA@U33SNBKUXCYrCm(dsF1dku!yTMLhZi+I-zXL3B-n>STOQv;J&bx9+9 zc%)iL?%2ZpQ1qx!VP-|iw|dtpB$&A1XCPL>Ji-P{^I6#S0~rpNQUq4ojcm2$f;4J# zTb0M@ZTkFofyR9sVx*dqb~A%1EEdjri%tVva^q#vnkA<#X};<+md^C=#eCC0rP5Mr zDn5wkglZT8qlhDCKj}xpYlnQO&Y!0fjapZ3P;|AXXO`x?9`0z>TIiO}sP_G&Y%8=n zlRhH7F*p$(&q*e(ev4-k0qLO`R4a^DkTFT``I97SJ_vB&SI?cv-cCKMm+$`v8w%BP z+yBo^L>XNGl$f3MnaqS)uLGWQ0Et}kfk9@G7&6wAzPZ+%su&{M+j$_w>G!7;>3_6b z*l9l|HWj}iKa~&K)GQij%pS?UVx7zGISCHy_NaPgKy2~cpo9iz>e*r7&xi9ng4Os; zzAmDczXY1AitRpaAEuq>b8fWeRww(drcSFzO$8hlwEkk1)x6w$ckuB-ZOo)o+B{&d z$*^B?jIvlP8`KQrA3#aZ^p!5h^pKaA?0<8IURV{E`=!3;{4vj8Sv|?~7f9!py8wR$ z=Ka^%!kX7<7#j0DPBBrQ*(UpTcf@Uw&K)NLd&MyrOMlgc56g?~_4zCZ%6k2W)0#jh zuIjMB-M*Y`uzR4RX%nhyS@xK+!ER&XKvrT}Qz>=YRB2kA{p~~FQL>E+k|D5-r@12g z@Zkzr?}8RbP^~OPL&7#Qh~?CCY(f3guGx;P-v>F`I5Jf6>6jt$VbI}oLCAzdp?*-X zs+4Yp(3(*9VO#S9Y+x-A4SZ~xTv-I7d9V!|*GJ(A2$*=XbK$@H^HC7!Evn5#YpB?> zD)39IU{KCX$K#}%QXkXdP&___YHv3Omzb?fXMjW5^J$e_r-ocn4X0v=kds7~} zZm+)*?pj9xD+ziFHL~?+c-pAkul>}Ru@zi%;ePc;DG={Ia~dtu^1?$@K@G9*;Ffyt*}u11>!n{_*olLak@HfzoDV<`m(JcLfB(n z>2^-|BRg^bKwiyiOC;fDZ5Q2r17b_S&MUF z?gW)y-#0H8YkO)cne%V~g7doEO)WT9zXNyyR>gpWI9J(^bsXR_*W?*MnE`VOsQ=^$ z%bI22|MQu7uwXY{jXAcnZ=N;fPAA=2^6DsC^w_7t6`NT|r2D9Q$L~;0nwDYuEQ^8< ziJBYZGX{TZTzErz6dxvbWux_x90fKVaosU;NLvPLoEvXygur5-YFx)?SIzJ~=DsY7 zrr@Eyb$4ZTDl6>Wd9wixBqKq?F_OIO$nfEZTWr^0KgWetpZ=F0cJ0x2LnPDL^X%fbcw5<&x@>$$%geJ}%LI!h? z4EliIw&}=46H#R;O6|};4>->}8y21y9A8?SZq+^+;50HI6?_PYS&u-l5i{CxsUIjl z0Y6H51+n{_c!Aw;7vcj<$ltQ6YS&YE-J;p3M~rgNud?=R@cZ2c}GXi(PF9H*c=AKAlA-X_%IBWaY}SYx9+wDr;_(?PFb_WfQ`Ob+zYnmfVX~s zG5x$EF*y2)eU%Je2i-n6d*@18b6BwY1un)$IEF~Np=USpn}7?t%bd>mRXoyLo$%Od z=RKMHS0noSXMPb&PT&J+1+?-Tb&yuUR_r8MldSs0X{h6ugnaJ<{FA%Fu~l9ag^7aS zDZ40te(vBG4=#NrV?{gOGfvt!8yM~qf6pGpFb!;R?w~%_jRBkhnPA|FqFp<4(AZ*j zAwaupH~=yhx=*2D~&4D|HcR?pKQrtz-z#}ny zQ?RDwUFSpP@h)YC5sGQgvLhB)9qsY{Wn9p2I&)d?Q?;TgaERfKZcax8J?%(McWr}^ z?&c^qvd8Z5A0WnQxzlsuh}CY44(i~=qy%5kqFP3+ua?fyMr5Luyn#P+nkQ&#IQxc^ z?Yz)~H}tEuWLrj_GfCm6+{NMA77FOjPnM&WIJT5vrHzaO4J!!HuG)B?1xim5g*p2D zSj%0KaJgqR{IvQ(%rAcr%{L@_U{jy{e38&m!;f@oWRhDvzSQ5+vYUKbs9F1*=3~Yi z-P(E6qjVgHfa7&NPw#*97AM+ku)qMMw0#Lt4RX3yOKP_ktMP<>*K}9e+&tkZw+XFk zoTO3hYJ^!wj!H9st5(K!O6!DAoPH}xY}d4q0U2Qkm^Zyp#T^Ai_a&GjTP0CPNNVW% zmyfRcjfMgpI^q47{h-kfJ&@43F2fjk$Wr;6EoZXL*<}GEEuPsQ4hB(zy_j_j?<&nYLAq5ylZ806GVe9Eb;CR9Q9E@Mg>0MLO{xyUY24K54%MbPx_c3j7yDzmV zek-CPyZxbQIZ2qWLy(L`dN$?U$xn~1%n|?8xMBjtg)c)m(dpWE zv`%g6Tki~K62Y@3svbG3!RWMC@Q@d4`U&cP^KIjj~Ym zl0Aw2nv=-mnnoXylpt@3ho49mk@4=`AFn;Sb^z{x$v1*2n8D*BF_sw7)1l^H%V$LZ_~&rWjinNg_&W65<^m+0>c3^CLnbL@mj+Eb^S+8h^< zMWSnuBd>_m09B;JbN-X>RPKnXoK?hB=yv|G^JR9eZsNFzT2s|S6{&1I8p%PX4#O{^ zG7DC7N_5pUCXEX*%`hK6wy}TJCxH`-E!82*|IPCF%U!h;-;`9C=NN8GPx3u)ix*icr5 zEmeJ8tz2+Q7kieNM_5PZEHuyaowZH~YNlVGUt)(RnL>harfQV+-g=`CTUY)C+X~(o zrtX%$Vbu*um-8;Z%78Bx(#IoPEpF>SGv>_;W`aOnnwC+zj#qcFP3BnRa7h5e{p)!# zgelnV?xKeC0UZkU;j-7P%zI1S7YB(EPY+XK!3Uue=}E-Q0WUkN@0}W#?g}tf-g1n( z8PS>@UVXXyazeA5G*(tZ$NXk?m~)U%808#A(1YXdrb9%}Bh!+0JL>ASI0C&y7LfwP z;h-+xhg2S?5aJ|fHhcDGKnuvIt^Bir_Rw?I_qLhKU_iJ<*Y-@9#m52PUocXHX5u@6 z{WIf_7uJrOIO#5a8k|D&siaDOvD^rJPysy3=tarF82NRw7I+E%!0?xvt8Wx#mx%`$ z$VB1I#_T-gmjHsDn6@(GUj)WK@s)m%1;*y)hkyca6XWnhmVb{NT1UiuvYDA49pkPe zy5$=o!Bo&w{}66?8zd1LvI;2otduJ~+~9HFrd^hW4++#?+L@!?Wum+bhiOz*J&k*W zCRHM@$kjAWr@gkk(hL|x>JU$s^jmEWp|w^XP3sH%CMCaPLd#Ei%1Z@m1^dQzWv^V zoM71B?$k|SBYv1@o=wQZx!XWnT1Q{*HgtbxEUV1vc2s&wh2&jSd6qLwrDfGC;%XH( z|If@L=uOBTi~m+TR3w?H)a9~6JQ5NmzWiQl$jJT||H>HpCSP$dGlbA<3nKR4(M)t*w@mV{2Ph3NY5-1GKh{rN5E?npUUVDv zV>Smn%B`(GaVb6h(BL#_nE?`Ja*!(9A~k$+k!3@BYAj40-3s|k2=L?c`Mct^!%91YheORv6%ZRCt>6HXl;*rpl+%6gX+fF9lrlhS!Y!|Asbv+F-^ zYDaRaOHJmNzTc6_9yzkYZ+7{FPh>xQHdoYTZi(D)X^nzm_P6l+)*n(;IA1~))7XY| z1a7K^bml6GoTfYI=5KznLJzW>UW9mI#gWR+?<)eGSO2pBfZ26d5%`B$xhOH>7cYJi zR8PrQV#9taHW-%SJo#1@EQS1msZFs7OW)WMr_+${F}gWbLrL>8MEL6z;xh1qQ&xSNLc&3RhIU*%?lht~d zAFs!kZJ|`!1==(-*me1L^kKX!U982b+>oNr_og?`R!1Ou%zoZL z+#h;eBhR+B?82VSbQzMW8YWXeGe#+bsl$qAb)J3C-@>{sf8YOUsVIWP%ZatGlHQiy*hy!i`sbK3E%G99m`Ynf5H8unENKm zN4N2crDq7q=d^ERy6Tm{8bd=oQ)O7!h*)V|{lp>XrVk1kzBAPy?U(m=oDQ&Pp1J?o z3#JX2jj;4*+5h6iA9KQK{m7uiZi>8=JM_@%v&%Lf?nkY?k?I>7x8wZ;jyEsyxWb{r zIg(6SMru8>2hN}hZkk+!X*99TM+(Ns*9hjU-p!!F54zcUrX|jdEf#zm+5lCO*5KLJ zgJF@*KM8tO6fW5#foWGl38R}0PQ}RT*OP;Z5&YkQ%pDXO5>>^0Y}ryA#*5h&g2$uD z#_g_X5&;1VKvLMf{h~V_d(JZ1MzGo1EbMeEfCF+b)+cR0xjTb`8i5a1=6CYb$1Rz+ zCX`#Lx;zt^Ab)kNT*@3xtrLS5d{X+1BK1#AaOM>^;Rc~NQhLj%^`*cJp4#sw@AsVB+MQwN9&)r7qCQdrpT*W?qc6~J4v3%ld2XXKvfY|^_ zlc!HF7Ol+TC3c`D{+9!vY0s`1Nz}dgdpH{6K$63z%35WL01g9A$h(25y zrhT>3VAdI1ExNU)C+*5xG^O!kri^@~xGt%ki}2IFVC|UYn69I@1_c31T*T=>{jz3x z-!)LP7$QQ%&0bPAM=acA!|7=KiElwEMJ$ipXitb#?iA&EPW2`yd-R(~?PN#kz#xj? z{p#>qa5lQ-z-9jjOFJVw0FmsqVXyq7Buq;T2Ki^cwHLR|=W!hAmp9BT%eqs; zxmqI0YI~;%yrp#sNppj0Thjy~8=rY7T@2Xddla7^e0>bbu#^6NH+d=MfRpS{iRA84 zVxuvcgvflu0g@z_v9?rz+UR9;$2+39g~vg{CdrMS^FCpbDlVt$oM#Z4TiK+xY3bCX z1hKRSePF6CWcmo_&=kpz(3ac=wCo>lxJhF6q0}+WBQq{3U`h$rHwTvM4@~?#0dghS zu6f{Z3#|+V#z-_@jn7z8rewK-uWoy!@h05d(EUZHwJb#~K@PEt@tksiAVz*>&HzCD{2uOhi8wi3}XJ6DFZ zKk8`Je1o+T{|DHqJID#Fo%~9i;>7^m0~Es*$MnSA1>#n#A;;iXJhw=pr@L8C>A+h8{2w z+M&=m-J^WNrDy+-sOyfW>i_>r(J<4nZ>2~w%DDDbL?xqCWXs;0%$t-eWt60>Ym||3 z$)1<&xJJgcuX!)7eXZ+q&+lA)zK`Eu$it)edEeK0&FAa+Jgb!$h8nx@O_ENzx~0oA z_T3pJc1rA|I>|wocL_2gj_E4heCt1F$k+4q4bvoDU-l7KQ=<>8GUd{@-e^clR6LQ6 zKk{L#=G*5wNX31dfWz%GWKmB!XfP0(n*pvi(VXQO@O#t`u#`6wp4N4hiI(XvvzT^N zNY0j$PRNSryszf>S1%%iSu>LS`sl-9kZ zYIjL%%z%Cd)Is6}u{dCOf-N6D9qU~kP}Np~rh55p4x((`?3jD(6UT|Q?<7*@SM@HP^&o6^s6L!?~+kO(d3xZ zpx8X6Yotb% zbSD~oTpx8si!$Fb;5>bBH|whRq+sFJcB#t|{!)DB++aL0`28q5on3UQqu>f80Q-Swp! zrkXlx0?#AoN34vyJ9!+SKXT1K7w}`#cShii2n);dw|6|N z^#LPdI?bgQq-oe1TFXfDu!zv4)o+KM1};fOpP6@TEPL+M$sv_=#P51S29d(cZ79L? zw)G(V2Ib*}IEF8Ry0t%s@)Q#6{-j{%!k6u@Y*}ZkPIskM4fdj$T6`p$S@^dY=RL`ar5G= z@MtUtNM?>Rr@q%FnOUA9q1*#IfjvH64|fXFr0}G$EVGyCyBow}H+R<9eJGEDycI*U zHMk{J1jWh}mb{9bkRFOL-xJnxOJs`}UEPt>wS=9xL{csawy7(_coq;(&dC>{f}9F- z)yY15`Ze_Qmd)Pb??xhc#o~FH!D&*)LS+W5rC#>s^MePxs$Ip%r;QH~OFUVesQqXT zjc-Q_f7!p2g^eS|pW1?iTmRL@&Cz7^-9*4+V&9U+-pi#^2QFcV8&cV+Bp%+|t#(7~ z&?{H%IQ=7BeU1*8330#H&nT+jt1JE(0H1wnOA1|v^an@}e^Hc<3EgB|iozdka0LWI zh%p%Gc9wP4K{B%RA(1PHX_Okn^Q7r@05M)sp7fU^aa@~cFOE{K2pf*tQ7W0c_MK11 z*r!sl-AT2~#a^>G7A|2Xf>!rAwB z?ShISXzBhm1^Xv%T~AEBmBv@nmi&) z0;9ju6Me!5{%tcU!egr;&Vv?VVjH5Kz-fOQwj%*)%-%Kb$ZG z&JUQ)>?NE#uj9UPM$Xl>L$<42$I<~8M-c)RD8OIg0ddLY;v;ix!RrpZ7M8 z&t#>~mA-kQr7uONr+G^7;&iaTf-PC^Vg9nVq%%~G?}h7IUv3BXZfKuz$1rvQJfWG_ zS2#Nxc*`JNhAWj7l$vk>Wz<#v^&eTlBvYq?!hvs*8PEYw+Bx5-4}d!HO@ zB`rPJPgN&Ya(S6r9U1 zsfS1Q{=kPLx;a#B-;5blWk!?CCkA_TPP{z!Sn6zkf1ck*>J8N6^2d%$+r7KW%+Kc> zc?%+k7=M5Mp|`zIxb$MdMOG5@Yba1|j|S*xi`|G-cw#dK~ZJYfhO= z%1RmTypd}DthxV+Au4l7^{BO{*X{T_Y4_umuDq0X>$_*THY}wj=fNhk=Uso+**JPk zqiOq%4^JvxA(L+1??H#bp;9<(Zb^z|7&W3@SZ>z$NfE(ctSp_Zg~`gpIbFGj>1Aoo zOLT}eKt|=1_ST%s+F?!~>e)J}w38MsL@{`=5UjmwK*OVf#(V*Gc*tNgfziW$=8yxG zQi}&rQ-H|wgPC*L+#$J~pCltpx-JzKb1+@^dHEhQKlMz3V}vp6o8TKl1dHh8ydY1) z@@E8|bDZKH#7787waU|H3VbcCZ3q?Wd24uWJ~u4S*ER;jrx4CgiLqydC)n@}K{hd2 z0VfwMIO9|9anQkH8uO$7s(YxA=96=v_iIny(VUQ~P8@A9ERI*|VIF+SxUJ4x(W!hU znS4&--@(Oc$V~Cm;3J?9z{^I9+7J3x?Sjo&AZS{A5}=^6_royGo_!~He(X)?5Zalx z{g*%GYf1I5-tJZ~No02Ra!SMSesKCZMy0$HWc($=4e4EYnN>NOi1l7!V7Sb41x82> z=c{3d;EhT=yWdnFCtRXtCI0?=NpfOV)4L^fYKt21swN#8CcF{58Oq8dqyzsE1Q8VvZybM;6A9e)Oln~c^qruzqp#I!H?M4Us|AQ9Hfs(wlG#BLHOihSY7S<1{n1< zd;w3GbMSc{!Y z`mBocA(1c`DGg!o0w8LkIKE1AvH6tzD4iDklBL5yfK#y-NWBRw_(+M(5oF zJ$BaJ*NU73hQ*=3$^%6i3d{ZMmWYKnR{OT^yKX;Kdk1se`WxBMh>BvS`%S#$j#v_v zXEQ6>T5$ils;XrwHh_ywt~es%o;*S5oudkW4sXpGlO(Pmc$X2&wKYyakh}YjzOWdY z)$tfbOM~NkbVYWsWh%`jy+@YreKw!MS*)DtBU zc^#ntGA;ziOc}_y)gKk?y_$QaQ%`l3b-Sg0os zYF#PPltAz%76rYgOcKr#Ti2Cdl|O{dZB><#`_d$+aXFY1{4o1~?SgLrglLMy01z-x!oj8?;Olt!`ohPM1awSW zoPwZTc9D43%eh8O$UnWIr%uasG+wbnX3Mk#<=iaEEmP;0lde;;sxZob zYkJP_pF_8)W(N)M__}D^d{dgg>jxvp^%{OglvUQc-(!O zF9+pGz;b}t3E#4y5=}{F|Em#zC0x>OO$)7N zFeu9A;49D)(`cdyVTU(wabkbuy5yGYUGSs?E&Eqxl`U9S2Qp{547pbIHW_y|q}^2F z&$bUNtl2cpO!4O4BH+B*;&|u+j7oo%vUkXA4hPr^cuFPkoVJ{lJ~Ugj(SKbl@ajQE zP~3i&C<*Y~00yK#zv>HCx0JBIaSA>m$Ybt!bfj4XDQ`{BJT$(Yd}e|v_BM~hY1OOQ zkOUo7SE>52rfTL^ulaS=upI^~kVE2=NyH`IMCUp$;9Nh1>g`^@x^U+%O2Z6LNkIQ7TT0OpO{(?}(qvJyFg_&k)Tc-5VW*_iR< zj`V?yTRu}-V^5+i++ijEhZ&4Pk1#sx?37f(J}iSwFU_W+wiO%lnU&b9o)tN^u}I$<^hF5cfelM59eWyk{`d0d}4vH z?4*kl&wCFcUF3W17GD@ZD{79I5vsD*M9d~Fh&Tx#2W1SpTZsRA7m$V=bhmIPY;`wx z*5M=3vP1P)ax@6g6nDQh@Jco_o9oQIjJW|e@~Hm$s6{1OQ(MubmB8FI6kFbg$u%D{>pJ;N z%azZ-_Pn9D4!136Yb4k+Br`0nx}iNoF?Rm~1yq*zJKPZXbt>j`nnzFgt2A{D61C5A zH1z1id;AR;$9V|v_Ro<{7qo6bjP4l8eX&ROvI3?mqMa&Jn!`BiuN zJHm#zh~d=PE9bo#OsAwxM6%4LZ{bY3sV(9ieoMovTNv@dh3P$2Z*qu$W85nI!depW ztDN$`We{3oJwa=jF^-FK)EXUjEzvOQEh^~askGO}YfR9_Y!$RCP_YeDqq_r_ z&aBJnY7|EE@bAwU-&2&|)U#Bmxj9S7@m20wf0+?jQ3P|R!E~}{4EeZZTJ8iUrC6Hq z2?R6HxWAf!0nl9lG5$kD#j>r-`gVqa9Of5+Y7M&@=A- zzD}A)o;p7GNUu^m@+GW5X{0`yt%30Q>^VA?0HH8C&o3~?r!pxF5xk=Ha!rp`d+nYp zy{(77MhNoWH$x(?8uCf_SPYP^d9n@kJL)EqueH8PsysUY1VNbIv7K{*B}g()=RWmAgw3m+679x%YYvvsIX#u*r$Li)20!-9ApqP zUU;chl@8@iwlynUHFbk(L67ZzcIH!zE_X2E5qy7Bk64r3-KV@5NM{+I%gdx%Fh>x^ zJ}XYk(d^48%<+|}oN3od@cBT0H_P9n9$!^^g>sSb>bp{2M=2@QR^cwPM!3G^O{bn# z6UOPFE4ae@pqS^Kf==o89XGuL!!KkBlVSkvS}(^qw9Bwb4L_e+`mi@6sYZSd`A{W;#9=LD;PE&WLpV z+`g5U(DMEKo)gbA&r<=u7k!iC#krhBb}V`O%E`*SHAmu7;y9~G;M{yA6}{QMWt;T} zb0@GSSaPi**mF(#;oS#Z>YLs*IndzCoxlv}8ev#z!vA_giNKFT-bbK&12|sfWPb21 zQM7G!%igWy_XL}&xX2T&jguPZ{qd7*kq;lVsTjEZEI@>09UrNBFu^KZ|Lb=AB1pwP zt$-z}T-Pp`v6AHHPGNLPG6gB|6;c@87Gd^1Jk6_J*D*vxsBS4dru;|pdSo!CLr{yo zo#};Y9=z=4Syw?-OD+ln+#D^P%}CbCx6D>HVWj1%*_WZ^iyoEe7#f;N8QE z`DhOz2AJ%_=dgxVSEQR?{My_L=a0&t|82!}Z0~1ez*T`|hOK#j2VyX$H06B7!o6G*@h2I1{J?#LAEPHs+m$V`jk`Xm*zgvTC z6l8%K^FnG4GFugW{Ublfanht1nj2 z>+)d5qrB!y&Fz}^La!ebMYGZpD|n3!HIc3p5N0?GpNW9Z;8%bEE-T^?@B_)BDrJ_7 z&LKgQMDJgI*Ehu~eCwjPm7jOumFQGnox{IVN(7whp{EW$`TyOAE#3rgDT0RN$APF4HhbDE7yys}YVh(WNjU75C0TqexJ|dM)(Fqq z&V6}tVXtBnL!3Ki9w2u6jMiL`Wvnt{@nfb~rcjDi&S%F&pN4P(ZzqDtQTHcd^Jam7 zm97-(L#?wZ^Zge${Jyt| z){*iD1oq)3QS>}q`zq-}y8F;08{yF3!?W%TKKXvVUOn+A6L;1PWSiL25sp=t^o%XU z8$=BkjwZ&}G93?ipAo8jJSgI`-ag6Pwc)F~ua+z^Q=hbWv8k?4;yP8s`B#O5?;^7Q zXC>0LM4dOx>UVd;+mOPNzov^$fmYogMC7)nIgQ3W#D0Q$)}gi2JF}XLUcXvP!I*)t zqphDE7PnwzgZI)R+gAYj2|#&WU(?}MJo#cHAxuP9O-Wl~4Z6uP-}cHb9)0)ax#d-#(-k4iSRFns>ahWJ{dv#CxG>sXl*{N5N$%(2R-Y&h3aMZKLwI;&9^N$s(S zr*`z*1gs;;1RC^jRi6Z3l?LL$5cj`whM1CmTNwmS!JpP{CFki8$UlcacKAN zlfVes7EY5;v7m9q7*U=pXPjhkMY8vn4277}-)5nG>7|28(tH|K67~j|NdEqV^~ksS zZDk>Eyz^BSW4d(?*x7lE712r`^-L~-qRTMm=iUcWUWB>o;^$sIVKXbe&vjPG1E{HX z-6=P&NSx)2qOqCWl!=QJlnXp67!$xs5H00IJoHqDR0@eZI}G5jSX<57feTQt%LaLJ zwmVJs$5fP0{7Kgm)Hh=_EV&Ii?I$a^8JFb|UmMrP!kb4L(bQ~3O#r90Hur#kmJ;^oci?RA$&x(r139k3_*Cf z8UIy95_}nq4`^E728jX>?Rn||iM5R$ucT7xllrnT69e%Q6@#da9 z##(i|=L# za@7pGeG+~F*pHMH;Al{k(fW9t=h!)vk>#Xkc2J7I6~@H7*qx7Wt)sr)aG5eK-P$CN zYG-8Bx2Uy})=thFm(}5L2g+sg{rvOD7juPGR-bQwAspS(gulf7(aL{ihfnFhs=B%< z>3=nv@uKWf>v*~5j{T&@42o&?W|V48E-@3b?i(;TF1%;j$LotWF>*cQ@1$DV$A-9c zk>CZ|L?F#YH|{r7-1UdB4MJ*{>-Z$BZ@&$s zU*5p|#!OaZVEHV$%h-Wlt%N+H;=sJzc=d2qij<402I4zQYGB542-f+cJyI9V64b7@uCV>Q z#>F`Dd=T2@4yII>d7*nB=L1@CHxv&ao+ZkI_6|a$YQgbn|H%`3w}3PX26jj;x-}vI zn31RUj!WKPJMQqyrW6XzVyoTuZFV|(9hE%4s%01DPFFW%j%@#1wyRZqfwSO+QzJ{` z`nZH}&r@tMlhqbIK#w-_{Nfue=HDJ5k@u3^-DO7gV&JEYxHC>f>f+&KGAgjR|^9D}X!pTn$)D>ig7SXTVnBfcZ=rqF=>YUC zt==3f7F*KE7$h6VV=sEZ`#l(qQ}P}Z<}(C;Ar-%~9Om26LtbT<9}N-kv7HJ1#OY}N zwHFp7N?`A3Lc1s4(2}3b{Tijt)7jmE^Wn9@FDdJ(X43gEjMa)wi#%J3)%x9Ni??q; z{EpIwEmG&-JGPM3@9vi9WDSAa*;7UO76|Uap4&ABxB3TX4fkRK9Z@a>(1u|{GPLC5 zuu0ZT(|W9WsQ_kqZxA%+4etc>YhaJv+S1ZK6uVK*hGS@%XRs=Y+t@u-&F7>vpsy{CoEy21+8uvY$z9Ut z)!AJU{OIGn9YT1?p7%0(^CH5(&D7;<6~k&Z|6sSO|9noX&WSh1ioY5;=LE-@%P|j| zf@gw2DM9eAUAG_8VhngZUwLrF4V1NarCOlxo#Ep~w1NK&7*dERw9G?gmJfZUSxT!> zehpNsopG%Gv!deRsyBBpd}9QyXrdWuF(TYAXOW zy}SW)f6UCCL1hQdq3YGJcDn*bsn3Zo{Pdia_UcpoHeilm$-dB1VXwTukrjw8vIMoI zz@EM%HCL1*?gLTwrClSKz=PYz7&x!fH^3x=jB+F$0P@t1=xiyKpL)(~PxKRR`h+xV zB}IR!$jo`x^C)yRD$AnxoTUt1T!95%Pm=u5u-(0-s6AZz2*s_0fweTsomwlXO0-e;KoVE}=9Ml7Pu5WqkCEv9YSUQ9=>yk7p z_6zd4$P=$-<-9>kXZMzOYWmi%oXB5unLJ79mh%(Cij^M}#2pLgF75TNSbO*sl_NDs zO;MG<-In%}4Wp@EtSDrCT(Br(>M|W~dS$gem@#m91igO0B_+3_91N9B*;sc8uNmxt z_ou0=`Z*`@{z#Gl>>X3Untc%hB;<5 zp&;kjhD(o^NxkDLw`2I~hSbkKnH8beA;e3q4!?=s^r^koPA11$dzDEFkW1=0^<9zKz%Y zV_6p?93{XVNQ8qN6Reh8SJu*XJ4IjYa028?B_)w@rC`=$cK)XY31xVgk%A1vkXb=ow>Kj`EqCOjo@un~8|7zwZ9SPM==! zT%vqQKuq$@n@zFQsTQ^LDA{u@T zLSAS)TiaTyNi({-s7Y+7i*SvpkV%zOp3*8CmG4s2`RY-vW22Pt@ zbzi*mdeI4-pTZ7-HNe*JJ`zOH()N4w;mJ%S$SN6}0AJKR5vcw-%Q8{#tuC+Y>!XdY z2q%^YDjXq*55F6_k5ae4pCUlpSgXofG|fv1X*#!Y5l#J4T2*2{jK^a`^-H|bn|Ai0 z;xg1PLKq8AMH%FF#7Je>LZ()fbcL)Pwj}SMkU6LKBb*SX^URE(#$oAKb#l>MK!jVv z6j##1SZ|9f*50YX4g3GPA5>#OGY7nxC01m~N6W&sY=z@gbi*%=KKsZ;AG=el!oy!^mzQ{h>D%Ri2jzGB=;EX2 z>UeA*OrN5#aqn}3$8q;fZ}J7^;Nu64H`dhL-NZL!=OnS7lchJIjebpBVg7eq3_L75 zZa?>EEX+#ur#?>=6I10)g;kjeS>D?NaI182))W zF&(nnitLbSWt#=E%WFQ1&pz@ay&^x$^7EXjTygKUKWxT9%=f%rxz=(}*q-q-d`&~T zoQSLENzQ0j^`$o;u0IgNN@GSBjA`i*9vOfE_+}2L@Zf`FZBIAugHnYMJOpeGVRwN$ zj|k@fyy)ZZ zaGFk9+0^A!<>9Hm&ivl_)FNq6ePyxY_RHjoF#95Q2(RUm*%8OE9qu9H(SA$bjYgh3 zTrTc}ec3l?Y;uYrWWzVY_D`jAwv?_*Y38>goPii`k0zUK(+2=xfNc884SDhEh!cozC<*Wjtnl&H7d(D^iX74%OK~e0>S%g5u4UFo zrwH*-KD~XP<(Z{hp^`L1G((#}IHt!ytKK5iqGXO`Ydq@4BLa8XS+#SfVVx7*ce~x$ z@XEb0C>;s!5zXlAux#jgd?mi0rdsu{fY(AY?qv z9hb#tb;60@Ko-yeAn;^I(lH=b?@?F zkp$M$)v(`iYWSb)=_gV%v}U}WUoc}g;zPd|mZ~4CTWn+ClS}rmKD9fd&omLg;8{zs z9Zm!oobF~==Oe;4bOQO`o0_~?IXTbTivu+Wjxew8+b4ZMFA?jw%g>lF#&0uNh^l@K zI%D^ug-hBuG{LIkc%Z#2f4~FRD~ecqyRLQUF~^k>gbYwIn9SNF->=@-py1NM2KIzd zpvwYtG}yoYih%?tg5CgrUkV&3ID)9h*3y;0i_b{FC19VAm!tUx!%X1!@G=n3Q}*g7 zkLY)%ROk9xo8$DqpAh^ZXBwRZU&;9D?f1tp=igmnn9^%3>8PGk`RfgQ?kltye*6{Ue}x0^zT0;GX(~%!E>8EeM3gWK+FJ~@1GOHAZR@dK$J#cbpy|4 zH?tNj)7}Q>AZ&VHeNL3v%evQ_rxm%$)$?@e&%00IP7Fsf^Q_HmrXLy0Y_SCyrfyi} zl7!ikxIYxdlZHqe&A7A4G9MMTiakC$mardxc(gJ28okzjDKtH=IjNZE%BYId;&)a5 z_rfcNaR>hNW8Cvm0?LYCis!sOn{DsPQEEX}xHnI(jXn?*8UaMt7n<4TH>3DCoexU6+;q`YckOPHqn_ll$MoFXWx}{1cQh-|lW|DR^}<<;IgS)mg8a>R@AEGB>6wd|WWLJ4->8+lE=`iaXgRZ#NH{ zb=J9f{h<7PyR{3*z2vL9M7)X+?8ha*vkGE8>{l2{l0vzS%c3 zUr8|iJEd&ysvfKVXP4UT8)TIX4oht=VG${+59$31BG0C+d8D34R_0Yc(&4JtTRy0# zHM?EII?)BaL_B(tX1LOynQ4XqzIi7)X@xXot|@q*4KN$##0h;fQVbcR6Q1~fkDVf} zQ+X^;C`35?T?dg7vhJ1?EUdL?Q7#;4Vl2{Iqvp){VL`yVrfaVIzBM(b^@n9Y%Y$M* zFW#?nH4ZGZ--Nd8HpT{=I)ptw`6d2(hOT;2_C8D$;U{3&&`H&?kPc1d@mUnRbj=Li zVR%pL0smcK=|lY62eOOZmj;?uoGVRSZd z(H7o+jk|uBjmOh_b#3r`yAaraGM|TS&$oe9iGCri@iXwHtV`cCmgmp;02bYa*f~Zf z+DZb(ki?qY^B;i%EjH777vSg@)R?$Btw%=5^uE5WzB?q|nw6-CEiqv%P7#Ne;r%Ox@AU2Yo?1`- z(s*$?6%QQ077WHdS1Hgf99lI9>jszHO9Kyoz&Y<{?89@~^im}_FQrb_$Pf)h?qAcM z6)~_LPh;PjWsm3*N{lFMq&|~!?yTUEcP2`V@3*8RayQk$SC~S}Nl%@Uv+LKcnVYP; zpKt>?&F*vy>R%MDzl`XBQq){;Xc-&L+-a2U@J#dM7x$t;7^9l2V8Q&3 zyBGA=8&GP(yS%(La$cdArcleJ<6ZRPQwkPwCzl;Ot@-7gf_yoBAT`qu|y z&myC-zN;9xCwTFwvchNJ&MG67Z2LkpoiGMS>H5wl*f=v74`wVG}OH4UYMWOUkht0V3wU2sLlz&|9az}js2b? z#LVjb?UroHQc0y8Z(^AqCS!YvwKhIjE`N0TB z*)NM!iy1|fQaQ&;5 zMXtcco)nwF&){v04^8R|dgvbDMfOyz4T&|8>oiDlSPc1R7=RHN?-XuZvl-uiI*yV) z>ZUuNXnB%QsC#i}QWhU7;DBT+cW$W6N(Xlq-4BRIlOvbOQi?g~cjPz`7B+m4!_n1R z$IK|h>=%;dx{b~@UzFR1ez}+&*fCPFZR-K2eN?T7z*K;9o4^yp(@c>A6|W*2eFrKQ zzNzSbY=AH{O|H#c?76)~w?UNlRCb$@Teh8;lb#3!_wrzv!`a7SNhNVVbwdP$Ll6IH` z%TALI2-TSp2CcDm5Un;l!>PYAEVCp%kg0e)eT)3Pe0p-`EFiek0F-?xjT#YW4?r#S zz_!eJ4Rn*EInv+7Cuj$0B>zNBuw&p-2r`zL=Cpu-LuCw_`vR{MOF)JI00{|@k$`wg z^vAWZD_8i`osY^tRj5&(Ggh&ir#ofePn3t2ul60`DJjAj{E5AlH&s9Bci>n3%yp^N zGS;^4EI^0rgO1F0{kHfL&(1ogOIikb48twc~lx7!Zs}riYE*d6oSm>JN*5}pAhcrNG6dE+l0tW%It zzT~8%s-uh;X6ul!x+G=;aKk4oP3EXvTSJf2%7*`jpCOh7y4kkdqoW4C@VNi6>hgno zyNA7E6z#(YjCKKkhk}~#j(_WYGuBU@ix1Dq!CK)I$=Vv8z~Y~FvjWWRbo%=+PfJC< zeFvr&kf+;*Bj&+^+g-Ao`f6Nxj$iMau`DQIeC2eE{DZg6bc|p^CxtXMmtL1+Go$sx-snIyM;a%=j`A&j$9n9DbXp2>ccH6iwDQL>t3+@cU-~AI_*jz7P z2jcENrX#C}ZZhKT@^1EMA)GmdhnC>$W7-bs%EQb%9%% zt#8m6su~;lGnMs-jSq8+P0VHS_CP+Z3v;$i>+KA86$P#v6t6dujDmUAJlI&~hc>Qp zt4lSScz=*@!?H~mTHqvt-yzDfW-S&5`%P=_z6Yz)zh@2BZ#5Lnd1?A(3^zQ+AWn zDPNyyt(DuPPEIAqIlWtbN!8bZrB#`3ivipG_{*%wB8-(A16S$1DpC!s(v#G~yTFfvx028_|#6ZK8=mz0@v z!h_a6$O;9JA-|Vl;dMejy+>GFtddgT|TfxQBGnUL6B6x?PJJGVQV}yUt!bH>j z1Z#>{nX1x@AZdpt4Y~rYVoc)x3Re5_mKyw!PA{N+a-hYx~G@lJG*X< zob?!x{F;%8@RBWLF$v!Ie|(5QC(Ua^0b=du#9vElJSv`#=CRw+uK<*yuhK_HUz;_j zbf#O#+1vF+MRX0PUf+&qGGDfPH7MwK>XxPJ_cJw%Xj7pBoJZz}@`6LRuYb&GEk#o0 zIsI3x4&Xw^bDl_aJOf=@La$7-EmNrDmH6?SIte*95gB7{nM-B|f?M4vC2J@8PaBe3 zdRXp398Baqf&Wx*jlIgL^Sir>+ySvIe_JdJN{w$FJPzHkQd~@x1U&}^SOxKs=V$Oj zhh_r4vAG4?fnNbJ8Il=D4>@+gwT}*N&pxjndGY1(OcnVR0Xj|lX)q6K%^CJ;oBLz zieV4d2XyeC2{^ZQ#d8WE5CaMng6#p?S8$&Utg&$WII!ylh9jVF4HS@;x^UfYFSse~ z$XtSqJc@OXe)3ojHl#B=!UU1Oa?_|t3I$#aeJ+K!Cf`4^G zw?32nm_sd8G^QA8%QmDIC%JV-hA3HeAln=m9}f|yi7=Ac{x?9;p6WLazJp*S@=yk) zep&!5sN8gRMZR`(BWSBGR94=o2>R@#N}!WYzFNlX1`ItlQ>Fbtb*66CRp-krsi+}~ zxALH;jr_(fKjR>f`$w=1(4;GUBVd{$rTCt~Z~EC%E{s=i0;N1z|3Q9p!E!9K8_FA$ zj%_kra;KA0l6o1OWLvkbgH3E^2xP98OEVgMIAffp`dxyhUnszre4b*2Q%BM=j;&hI zq(6gV8}PRO^5_nl+6DkZFJS3sE{C_6u2zaA{-hU!K|UF)2{s*Bd(r_4^-W0&x?Ytl zH9dKa?SW!qi(zY2Q9%Blw$iYde$5Rp?!}ard<%wykifT11;<&oJ{nqKj>dC)Y2D*^ zbedt^T$En*>2#JBz96qvMHq%)gylU7NtQWxcCS)TLU#VB5B>TV>Lugn0gYFN)6sD@TGpsT1B!}2P?R7`H*=+Q8wIT zqs%faSGSiM&;`~7(7p`q&B1~_z0o49F`~X`b)rd1r;63E#omlDXHXOI%(Gl!t21*o zVAc1)VkQUqej;|zXXXaHMWo60geD$6>`0AAf`9)Xs2?$;wtE5q zA;5r#OU_elPZTetJH;v`k~Jx^OUFl1P$KV6QESQbms(EUjgBKCWk1p$c&dz^Z}d*4 zKE+*opAqo|w)4G5dv|Eio+DQ#Qkq-VJLqC7t7EqJhoC9p3w|pn3yxbTl`ae#R3*mj z?aiu})}O9S3oj$r>lTGL5*dWN-wg#QRdq9BdN+sv<|umwfuw!7kgq@xb7_NOuw8 z*6k&D+zy#!lg|2oM16Hwlx_1iB?wZ2NS6{1BHayA0uq9cgusF{ONTT|D2;$1u}F!O zbT=!tbR$cHbl1|g-@W*}zwaO6K=iopYv-Cd=bV{yG)eyDG#lEE7yFu*(h2Jw!0KD? zareY(IwmmJIX-NfC?2cd5zYuDOmrd2tH}%h?!KxjXg&Jx*;ZHKhj( z8H~3lISUR)1r*o8klRg;o!`=P?{&GEeVe6M8NH~#P!iu=MPQuQ;m%J0*Ag{)*FuXr zTST1@5r@$)Ih7?xBS+k#g0ed~qtzEi1#P|k=77%b!y(r^1clj7==99>))ledWC|87 zZJ}gJ$L*A$RA?%()^FiQPs;fe*lDGIR8=B_mlKd1V?GahL@N+06{pdOU?+N4-%bsq zsK8(oYz5y$xgcbxaUTAKZt-$F12rCZftqiu+TQL_#d}`V;b1!YTp5AR8+5V8Q4rm? z$^+mJfDr}E1qHAe)}*O@L$@1a@%t8=c6*wqAsDKStWM=q(sOa_LR*Db*Men_f7LT! zXa3S2n7@}BBI$86u*zYYU>XJsd%woji;XAiZ*~ZN;!QG>UEs5%Og{D;* z$CbGC$xnH}XpDDv&jw^B?$RsQlnWX3wh|dZ4nSLJVPWwc<|ReRTu1G}Tx+?w9=6*P z-NJ*vL^JsuG!@Yte&1n)Sy*{FZ&bTFnwaYFA)dYdIJYK^2W6wNM6o@s;?~2^8_m-b zq_xSkZMk&6K5pstW+4|qZnQlX%F9chaHpFg4bO!=smb^{Ht&gm$yX^OQ(_C%<0?zQ zLy0F<>gw_i{>*-I8lKWyAh+o*R z9D^hprTqrja&Kc1bae7tS*>?pwSx+i;!JY{U<*7&EQ^ z_3-CkFrs2hJ$s>{x==#1KsTl4KZ*j9x$uWXNuo8#QA%j=Ny;?o-ADsq5Yu;k4XHpZ ze_Bn1ge?JQow2vfzKY@`0+X*OyFVNL+6#77A-@L&#khQijINE=2vOo`B8sf(lA-qu zI)s&WSE?Br+`GRbpOfhn5cQueICJFF@09W75F2q3Bvd^B$*0EbTUg_YkZx!cZqVaM zd?2lQ%gS)vciH>s{T_`!t?x6`mCFvceeuXNes|9PQT3ltjXre>Vey;okb5&9Ar&Gc zG2~wQVwT0p%l(DNMSqmDl{6UQ1nBGh~^GPqFIGJayc;%&=MTV_< zjr)>EVIOnt>f(Wwk*5^$QMHWQdGR$bq-`L`=dJYGiECC)t*MAP6ZCKQj^U4`l5GrEKQ@g}xi>G_{mkVqE}inzUWMSc=828h(^Z0cF5U(4|GW~hKKsvi7EQdE$(i~5pimadptX^NrfV%j1e>? z14BiQr)IZmD4>opoLw$YG7*1C#SS&UsR6-%k!HDHAeu7qdfhuJac%t9Vt-Zh*^+C* zU8d;r=|g8$7n?S1ywxQH$i@YT;woyj?aL>) zUb>Qrd_=R~zqtGON7M46_gAXV_R?vFE0BJ>wo8F)#zY;tV6sa3vQ~B@TPukL!B)!bZf4a4dKY$A? z72-qTF}7bTXMaLhEJ?8mVu~l$D!~vQ}nyZPRf7@)kl_iXx=1UmHR(#_=M8S znKs4Y&HBesc!`%Dh@IToZpWkDq4ld*gn#z|SbOHzANQ@^?J6St&LlRy8-;{FZ*~M6 zez()DNRQMRFxwgtSJX7nJKhh~Tf;Y8*)q>K{ilp@7muiKz8%`8?%_YqTzURSY~r6M z4bmjGpF>mak^vDsps7!aKoF%Kb%*v4QfrKIglI#TK>%i*j4I8KHjJ{8UEryd{yG-a zWL%%l_UMIlTx*+2RwF#|qo%&V{eRyi^OsxPU)laPGnCBNQj*Uq-GTB(-YA5BN_Itw zmGK!sPp((0t4h5FJqzxs%cKP7Lp5b9186|(H`RieP=ws>2%%wkmJilX&1QXe=|2`c z3Er!^<1UQHHlWARMo|YMKOXB`j~b^uSeAa&>GYE$V-Bgf@+6Df_ zMb|nEisHe^Np+`cnkcJ}qq85cV6ddb81>Y7(6zFDsgI`{1_-QbVf24 zrjha`rGC@*wV6svBfm@DqZ@zzp;7Logk8jSztRuX_xdr0*SH))&;9gtTfBde{-jU0 zx}^}D(1w;+zrUvQU3#a3_}#Sg+fYfz6$>iGBSrQ4>MO4=M7_*9%E)eSfca7t+x3ah zy4<$6RJkmI>gB4^`7kF=;<}ATw=9oyWR1P70Gt{dmE9kYH$)_oj8 z3B;us#ZujhUfz?kwSvZ_Gfs`OkJFNxS(T6Kmcpi=2Hy_53J{k?UnzaLn$jefHw?Wz z3Osk4%vDd{GStNU_Xw=GhOqs<$CG~)j3TGp8V$VFWIU2eC-$f-?~MKPO}n;dVaV4+}7 zu{~A@e{bSd(Ss@t`<0>sLe8~llTyn^8HOTmdTF-ZXX7_-90{{r#!Q+#2Qafy{Qknr z!cG;21w!CL8f90rtebw?7(zL3jb)lqp5F0sBs2CmaTZ59Z)|{sr5gIX2L!MdnYL>l z^y4p7gre6Z_M@1 zlP3F74GzFJc>fiqb!Q+FDA@H;q%^C<;|9K$%G2leFBIG)-taGt37wSEEHr^gE9Dw< zN9$7MMz^|`%lyG18l`Ko+uV@8=(TLlChO_7LDjmDO@jfiWw(a_{D`g{K2TONO1jr%Z zDWl8iclHds2p!^PN8zAK@#qMTjR1`f_vbwfp}D;`@7_amdzGe`z;=!UPGN<=CW-2+ zK1pSBkkPJ8YDJ^Qved_De186mw_05TZXOG##y@p;3bB4;ZE03%#?11$Lg_Tk;h7=o3yn}&jfbH0%8#b+uo?7St5W$} zRRjsM-W{O~Pcmu){ayR@_AM*{wGXpFR#~sPQ>Z#G_>@49trrUN&M4Vmir7#S3bug* zftwsnuHk08&1dpNtzY4FB_z`yTUa^1O9qZL@e<88R&7~X8~6(<$IG=2N)lE?h5DPg zepsi7n3WkOr2!EW&PC4h%ng*`8$Kw{xNXd<29{{Irs^DaT{AI?b-aD0C$er@$4dJu zzHxFJ zfvKad3pD=D2#3|Q3&icP!7pk1$GZb^j2A1~j%H)0XGIee(VU+jn3Z){OOhSy`*xImD8VlI zmx<5k^O*|RV8VM7$DN*8%*0nUd4W-w_h`bZSIQ&hk487Uy`$y*>NMTA>dzNFE9NdE zbH~NClmyHL8JXqR#ovNPPF4C;8VPGHQl*|6TF+L_07Qn!&y(=d&s^|K@wiB?+sutz z6o8z7{q}#Mw@A%9$bW2q zr{@eePB6BDZ>mx>B&iAaKEc1RY%q+6%n~~L(}XP#4DS$J_J&Sce#^;vLGwp^;tEW^ z{Ue&!*$D49$HJ~jCVhds@ah_j%6jlA<#uz>#z}#BLl0F=Gmqszy(5LI7N~Le0knuqb`M(jmd6Xty8_m-7h1FHN9hAk-43|` zt-WyJ1-#0FJ-U72B0xUXAYPj3Td?VapEf`D{5tBxdl$oLr(^ToZbVt~z{K=aKMQtq zV`mAe6Dn#2CCp4dL#ZxU1ill0VfRehSECfNkN&ca^-K6-#XqiWhvNP!Tg59)NqoBO z+oFW670eAioznv1*SlXSbQK`jDJMMz#L)#Osz!+I(c_!b%T-kI!L=+$WaATts#e5!=W{efQBY#2`)+-Hx>#-i5XzzHzkK6i-#f(Y^(TD;@3N0_ z>+o{m*V#l*>g0LGANaSNfsvCBC1d{T>XN0^c|?RB#_#;pjMogi({c0vhDdak9nBs? zfDz#Dn&=fy05wQ_iyDI5ARsp~Z)Ks?-;|Ln)mWBKUGC-99Ejhi$c(XcRC!d3LpFV% z=A~Ow6!UhHW;HY4#^TITpf4ZWK&0@;wJ>${_dr zSphiQ;^wG8m<2u0SpY2lzDph!AV94(gOBS5?LgV~M5Ih^X>Vc2HgU(w;(x}V_|DrL z^g%p5itiD(g;{U2Lj}9?wMa@hrf9!vN@jVdEr%W#9*({>HX}SrfltiHKXp6|325UA zq$`xBC*@qkB_oVs3e~magxN$IDA6nRby3|rCvvj!ByRcw>CxX!2v>}%A(WvbR;%Oje7k-X_-!@Se+#20J>!p_E7vp-8) zI#I(z?+ZHyhsFowC`V%xzL%S7T3=6AUVNU+_*kG$%p4tGAAc?c|6+E|K||$ZRrvgi zf$hTPNQX!x!w-9U4b2Z#d!gwTO@(WDQd_!L%fn-I81{oCegh0UTgIa8S6$+N4IJ&g z83EMs-!r0S4pE(pmF29-uO_y|F}p5LSd_6Z{Xcb2O%j*?JJDv$=G!6tEfEfv$*{f$ z?$lEj@ICPQ(Z7GDD>;){FEbDF`||zy3^P%&w7}5xn|=|T51MfTnth0k(1|9UGLjV~ zkC%JB;8`K4_JYQO@W*FhAqcSJt^Bmd1#HMg?=i<-LNaOMu=cwY41qt9W=}D7nsN+( zIcrAqWe-N^b6FhshhYbvzp&WxB$x!)69LNuKfvwyY#D@gGn_ToHkY$$+?nBG!XU04;Z z!49bb)*DcagGA368H3L`dX4-Qog43dCNR&v#KR2c-KEPwz zP1K@a|7l{7beD8l-l^s?_^QZVF&$Jt@hA7{t8xG>P^ky3n{iuQ=>L04^p6sPq=8CX z-$P}mw7Scga}?CIMw4~SnoT6>B{{cq{qB{_0z_3g_21M8>9`^++E#OuSC(UTfh-l} zNu^%cgQgF^&;`-YwPGDCBw+HVmdMZQXykF*=YDT2kPnYjSBfr65}Ua z@p04NENlnzlGMGb2b&|6{PCT6v&7% zaxH8vSN5u3cc(hd`Ru*e5LM=#wcL$8+ySyXcz{kQVlrY;JPt1~-IrHrsAwA)2AY40 z@V+7r;(v{;!WC|u#)SD}jqTj7dkIe^D!1fVKZJp%yorCrU_9*ThdX#YmhBDEmpuDL z{S#Yo;Pn!}&Lmk}1C%eykLN&J$ua zDb(hv&Lj!HQ@%nhv<`0X#2CsSV)~bTZYnj*M1T-19z~tz>R%q5W=-;;T#`{+F@U1p zf|3HdOmR?s^mm@)KO`Iji$U=SeZl=1^Uf*Vj9=hBH63VQ}hb~E5FN#I(Jh0lQAT={O5tNYEDW6T+o9n2FIkZyGxuT(vGdmA&tdi++a@;p+y&tkR}su_RuG6#L`6BnEDN%kS= zkxQflfk+EdlhQS>Ddlg50<5sgF%f90{P;YY{<^!=L%s^+=)CH8+5ZApMj{H;y`th$ zEm|+9x&Lt&3pY5lTTX8H*Z0lsXR>>+<4Ui8+lN_(uE1a&-z45-Ey1@}RRot2_B~^n z(QIcaF%?PDn`*AFXzkYYTcX{tdzzf}Ob)T=onK*e24;(K)5K>hD%*j2B1m7pu9dUt zrv`J1MZI=pD^lNN-^sZh;65hV;F5A%UB6mC3^|T$t38qaJRRneJwHa?Yq6*k;aJrlv?6S7cZ=4wq7 zP)30!E}77)z#&MJY_g+hgTS$MXH9Km}fg#C`ObUb}G=4yPYDEXrGf2tU!}4 zZ?bxPq_Y!asl^LOmJnt7TF~xhDQ{e^E=niD>bBckg&c~Ol9|BYENG-yEc0e`Ur3dW2=J*>uW%uBrI z+a?<~>smY@>$*!A$Oq!n>MgtY(A6P;$xl}!8yEJwTf5`S_&9ruQl*2C=i?x7&g65| zIOsaYJ8GN}LA+{Hs^=&tscP@B6961fH<*4gdg+wzS4o6RO)xV4oi|X5b74gvSd%9~0v!F{ zEbtEM+$AhA5S?3C#qc986)1*nVEVe}>lnLV+*9}cDW1o-FIq4?GJ3`4&csn^Bb}@t z-4H=gOz@OB8KdG6{^`+Wf3Beh4{iPDhB4i7%XiqgLfipuB(B;=VWWy3QGR;GzxeJ4 zHBd;eICr$iT~_EHij8WIB=OADojNWgI$Hve%KZBZ>w>79g|=(FBcNJ}k{Lu%(q@A5 z*$$ymaq5@DR7S*;S(vnH?M*REdUkttkszpWpgGov-o^A|JmKWX@a6}-YWrIMc%>Ia z|D#D19R2hYJ+yE(+u*4ABmYBe^XM%1UOyym6$Tu4^|Eg`0U4~W5`fF_k;G;;%Ip0k zGf(B%FG;x6arKBhY1u85@m_fOq0N;^Q+){EVs|?IczzX_CmBh&(8Lo_oj~!A!GWKv@>g`w+=>xJ+yH@H4j~drtYv8`G|9Ko>tHE^p zH4purKLYX<{#(@3GwqixL+S^I4LDYun2+MH&b?X9dGRYOS5tzra_Y>=LowPydde(s zddEM0CSxbyJuqO(GKPN@ru74F@G%@xR^>T+oKUybj>~Q99udga%JmyQ)eO|@3+TMc zG7!KO-b=`8KkiHe3A@d|#JZRY$v);nmaSS(U<#LUUuBMey`Z{Lx9Pn|q*$@7wo$OV z#&LN2Wxb%>tvuRqakvH!*bAfp+isNnT zWapZ;P>UqYkdxTanSPjh;ZIT5WAsw~Uq0P-kwcQ6&RDRxXreTx_4o3SjeqLvZi};2 z^OZjNO&k!!_8F5GYKToFU_8$kfW4;Y&a;-b-3+lU3&FA7i%-m?oXV!ITlS4lF3S_k zW8B@R$lJ*MJQ|Dv%;>hO(o$qVv)SGfPp0_ut%wgM)1H=G=<@xalLv0@BP7Vx^wu#H z_!(t$O0b~!up$wJ1_e^bE*Y3xS9(O7v(rAx96f@|)FxnK$He9bm+IgbWwY@U%H<@3 zKDqHNU5*`*`+7@t74*9Gl|7X)Cq#^jtYeB~sG4|Cu!Z75L}7i-?$kFyQ(~wG|wHnu_rz%d?&UlrOb^%YK7G2|H5`X{f z;@=}hjAW&c8wVcP=e-RtcnQoe8iWmT>sIOP$en%ASn^EU+HsW{%v&CroOS6+w%*cW zZ|3+^f{>2RReE?OyS)X!-8yv#AB(#=)Pv`NpbAU;bg{s#@z-O9T8>n@paa&L6%>_& z-lhhNf=DmEL^+Erm0#xJDD7xQR^@*Q!?9yHbs&0NZ4>!9H;YQQWG*XAX#n5DBTzaQY)%ooY2!)XmJ{sdnlB!%yRL0vyqHji<{$~uFpfOc&Nt& zgAnHxNvyrsun?j_J6oQoq>l(xteFnR9kX+@n++kn+VC0pua;!~pSW=6gv;Cpn!(%@ zLe)wlQHUcHU=Z~Bsw43#veMnkdyclaMX+W@rUz2 z1M*|Ge5e^Mk8c1wC>G{u!-v@uE#=74UEWLyqY$X1#{H%K10lAjC zc&e$wIOv57kN&5A9FzwAY{iAb1H9gf!T}}7_y=3Po@J&C*TGX2#t12zRQbqagHGj# zgLG=~iPu1th_CUnsqs;z;J$23=eHa3QEn0+)n~7;=0~IIs$+V!>Z-O5{_%?Ral-R6 z!Ng;}(Ht3`bF0Oa*kWQ(Z>Yw^+cG*xM9(bVh0*`groURl*H=IVbsGOM&HG+9-0FLh z4x<|K7Vk>07K7FKOW5>@Fb5)Ez+=VZVx6tets~+uUBt*`vI2)oldYtJ#D0g!WeJKr zaqoMOWl+AA>!?p7;!36c;5YAHFp=hKo#m{@zf0V4%XHkW54sP>g*L(w%F}X?&Q*!! z6zc3#&MMvoohAL#j)ASQx{D=-dC$IRW}$GBHQUW83sg%H^~X*J;%~lxYaW`q!|(q) zb4X01IBpkkDesg_1lj9Jq;DVH!jco}zNiZYxY;mZpj@=r-?9pPRlGhMc)u+{J-_mH`tgAd56Re)za3b znRIW~qzb9QzZ_n)i91%?NHkuqsD};oo{M#;l1DcGJ`n9P9bz_elk9#T%)e{s&*oAn ztjq9F7fPMKI-&WqKD_*S(#?z$_?mFj;x1C&_5S|{kL62O9Fq<~dv?-x}-@!wu4 z*;L74#dW)3Ehg#Qid+8N!j2>VCwt0CLf zn59S@FKcHOC9F3Q++wU$I;X_vebua8Win+Jylg!ev3_>F_(@q8v}d|;_tkh6mt2XQ zi&A|I_OD(~e7Y=N#lN#Ieg5z5 zc;J6L{a;#S7SR1e2?FMC`+h)%EFgKAeHkTV@+#FIKBqVJ>D^LiYl8VJ+}I4|h2Kwq zH8pHpyMdDeX>*T0zJ5RYr*Gt;owgGgEBSPu&!Zuc+t|z>=mcAM=Kl8AkCKNQ@3vmq8=O_;@a=Nxf_e7?i+pN7 z>|UyQ8=vtrTHIgr>S^yCXbRnyT=_Tjt$zIN-9iXJfDkx(ndMG&>)>)iDw`z|s7BuP zeWTR?qf08BJgtMggzUSkTXTm#^2*V?VMyX7u)rb^U6#gb2hXHZ{@8p#M}U(`;H;st z^D*s9WK}f$U4=GsSmE(z-#p!wlWAqq35PuLDW8X!s!^b!C3%TdH^Swa5YhQ04HX{= zeoC;+lhac0AHPFIDjlEhth^56O|fE16N3yJ09$8Vi-gng8mZ zzJUuW^_^%*gu1KcO)QE>I2hig-gkHS?i1*T^r{Y+B}3NG`}ZcE2;EX&Lk@pXjV$*4 zie=!I9St!=&WYC^Cd{T@J9^+|6sfNQ!g7=fy*n%5Ca0MB|9f2#T5rAL5}zR{EV5d8Xi5(*w+ zglx|Wb2yzOC(ng(rWP0U{4M7^=;?Zz+J)_#*1 z`H{TKaIH4|Jox8mlUo=lW!ISp} zmcf~!9l3rmI0GGz0F^ADDg}IrM6;~}C^naONRI=MKVDZI@qGd+XcAXT3yvXCJ((Nq zy2WmP+cp{hg%dJ?r~8%BRwD-VUc3;dJtrHNgE-CE!%;!z_Dnk02^ph~=9J7_zO{V0 z&s76sqja{x4JVgPOaDw)IO7=XhTe}57qpqS8bp4BD_wP?qORao{gF7fB-QaZc~>P3 zlr#DSH;$zuyyP~<1vp;eXMf>fvfW+`? zNWd@!`AL-c%PEtYu@0SYwxGe2V-3!yhJeQWJDleO*VUhoF7eZ)t zCjbR3Owb7e%9J~)5OLroU?b#fC}5!aORgsu6cIQ0bT5Q$1KKg0y3fN*hht%n%hH;L z<cL>x?MJPA%C>MZoaq0!~{2MAm(Qg0Uphy0@0cL>` zpZ^_))-DGclz`6zkg1Y^welesjfK91w1D7$Y>WuV10orv;#$ZC!3$^b<61kRZFyM@ zzlS5z55ECR>Y_3|1bOXFD;6u+;t^^(3Lk~LH>x&=18%-7)VcOf;_Y<(+rUAS2X7t1 z$r8i8Sp~0YnYB)TE!;NoR~}E#F15CE2K7*G^)Q%9milICs%q$cNDpms-a6D@H#m(Y zuI(`f;bxyomAIdZWlGF+;^4gj@`bgG+w&=aHofy7LOZ~FK>mZ2?$Z8bfc_=YqVnol z|0aI8M)3Pcl}^54bFg)$N|O4jW<-6un+5hN16u-q9PYCqDAIKn6gj%`m0cB4zpJu7 zoxl>4MWc%u7gJn5V%V?fwNxbbeSTXAZwQ!6qS;*RLolBh`>(pI8hS13wOh=FUK$Cn zOy{m+korAOafOKy4Y(_ys%tG)K06ahjT^dCc3Zh()15`fbVaCBJ%>_B*y=65eVkl5 z{#WofKoj^NfI+E|Sm(by9t7j^vift!T~}V~9d8EpYH3U39}cBLj&7C=(+w7T zb&rRM0%~@C@Kztj&L|UgsaK+U$4%{-bW>~8T=O{6S(?WV*gmYPocOQc1!v7r0@fh2 zfsQA@147Uzyl{>3AH3d2%ufOC5jJuamw_4pq?JQlNm5Ji-$;K&xsZ^J+^dDIRfrt= zi*+3RR`{peZV7td;r)<-&nDe@)2~t8q9IpuZ?@g6{B3t(Ja=u0Gh4$jWt2Uiie0NA z(~9h5PF!4Yu@66L*x1(?F#+o*_kQa3lJv37UP^goh|ktuvp1$seu1?~#?octg3?06 z1R*B9H#s5#*X6hM?5XXZkok%7OsLtH!u(yprO1dtQEcpJvxXo^U}(1pjP0Q4BY}15 zfJX#b2eq=4V`}t($;yp}Znv@ITk{^(;6(e$?`W;7so~i(Jw(v>jZ(j)NwsxT86=JE zj>CJwi1XYQbG@Ckhw6>mx5eCOy9OMa#jtmDv%9B1Y$#Z6L|FF(t4}SPjsyR^oWt&s zn2QS87%?rKRx|2E#9|hRM1(ct_UV#GGKl9-WQy)8YVz$la3PN4!5VPYg&Enq!1JFW zh@su~dte_J1Sn4W-@+gYt0Feg@F(dJ!f*2JjESbFOonacPm9_ zWx#Pz4}wRr5{XhGCy?i3g~)C-GDXZaUbjoEDS$9rq@;; zSl2O1rRkS1wO7_jtpgBdu-`vovn~fK0-r_4Eq3sm8A502lY1JvLJRQAZ$?_!&|6S} zAu~cGtP=pU0N|(q^gGZo23F6omT`FtG}S>A6f>ry`rwU0d9Ax(c{`_wj+5}SPD*B3 zNj1;$H4e;}g$y?BwU4MLIzj^F`0iT)Er@s4&sAV0TxnkFv}|UB#ZNwMk1EFzWsq<4 z+P=aedI@Ou$xYxrk+BkwHelR@1^-0xeTS&|M9NKJmbQ+## z+uHEqCBt!7DwroaV>~z96p2izRN6i&mjAa}sbhw{0pZ__If9Dye}41h;(Ljax1a6Q zg^w$@nIpBzqEKRPmtf*JKSQ6Ar$JK5Ub75NjK$xG&Ia1TnQ~&fI^?kaNfqKZU)&goV ztNmg;rpxakCyf5dG7i$lSpaA4+v;|>&JFYKMegbpT00VjPKO!qo)GxWyRYc5;<$p^ z=GXcby&YBuOHattKDfRK^BwpVH$JOdfwA7@X>0c&O0u=o-(FGf#f8_DA|V+3BDcki zXGy`qt*#iCm}p}n1&URQJ>Br9^Upbsw)HZo9MH0#_`KF6{CSOQ7Y{03GW2xo7w0KU z6mz+N@@j}1F=|kZRol_kKYdWdIkC0x54F2VsiXyQ%JQ~B5+(om>cwLh1fTgr>?Mhv zzF%+k0ebBfaJ*Xfk`#U?x`+!8n16Z#o9}uHA;Cue^tp1^thHwcY+_fw3 zE8#}jUcP>5G55zb%lpr}8`%1#5H7->r0dlN3VEk^Lt9T1hCH@&FRkdJINf=T;R!^v zLXOky7M#9g3)Aw^54#r18ePtZNpvR4q`mwa`DFW+$Y6`+@NEd#!lI7e*>TfHBSnuB^#r($?~kjv-2 z{IjXXi3hiIoo^!>blx>e0;&cl88ipt8y?sG2|_93O}u+g&q&Vy*{@8-)_lv_f{65$ zX0RjN3bD8SaZ4t%+%})1=pw!@y@PnWV*4Z}-rrT~=B05Y@$YzMVWRZ%b=c8Ip#_Y@8*v8#00c z&Ap^Q6ZGQART*rzpNhCFtFNQNg}bD75GPSjx8bLxQo$`hIz^j~uYZ!`c2T)&X;MD} zFMhtt{lz|9NIVtV|Ii>sxEE@OM{krio!2Wk)`?yyz>8A6YnXzm29;K;FW*OIv;bCQ z6}HAW-GSyIu6+T^7Z+=k^?WAs)CP0p>pabdIr%VKa3}!liTn2Y_m^tl&Z-oaOgV< zd?sSI5Y-s3{28^P+`Vlw|5^PcYf?6^{mJIUK1Jt+-K_mjvZG zzWHzpS6BJuY-vKSU`6lo>xIyZq)YAWX>|WT@bs{LZD1zgf1l6c&;jf=f`BMT$C~Yc z=A4u-Fa%2WoV*>ZXpUE(9=|=+kKUDCE;ebB6@1TIraWWOeHwo!BL4PAx4cW8`Ay8N zM&F}it8(plwvfD=%8}C*PJ5WKwXW;jZXm;M_LQ9wnE!EkCwnGczgR-(@ml#BKSreE z#kDspyJoe`P7Q+Ap(b5w^0~;C=vmMydfax-7|GMJicWJ&DS@ZFbJ>sw#7Gp}!DsFo z<#oM|{W*T|NkXd#@%I^@DPJKy6H;p(5f$+goA)y^9Yn^NGEctSC&bXb)cF3Q4)^Qi z-up>6<=Nl^{1R*ydj^)l!%9PdzG76pG9YYpP$Q1YNLIrv1v<{aar=t*xpqy$pA zZ@sPFw5#Q~f?}8c^|j_mQP7)`;t~hJ2!Z z0QT<-->zeJIZ~g=%|5K*{>5Ej@T15bH|iGyZR41;?G_$=40f=z6|xF>HG8HTKFOQ5 z-Cxp~N)T_O|^PW7zK^EMh3D#>+jWaF%d9Vb=egN=Q%eG2>9)mL_%gS2)njrGlb zog9+-(7f;_Pw^PD-e+|DPIaFh6%z~%Ud^nZJ@2@a>_iFNY`?j4*fOQfBX{Jh4A2+? zTvL?uEg+Vv^?LSz7em!#&gz6?yQ;utAdlXN;Az8BMK-j0UEHWIcQ4vH!=c%a>@D{! z){}XX;u0}wOP=>Aoqrug=xrmurOVpbulf)d)qyF$wDUVDjEM#yRvQX!!tur7rulvZ zGeH9COgpm3SqFab#bc$x~ zq0bn#00%gCJ^WuwQ$p@rky2A#?7>OV9>L}xqUo(=ZN+{qw3Z7^wP&e}v1cjrRDC_K ztF6o`b0ZQv5UdJp81wt~u^ThgC7eR|Sg7=#x@u8r67k2pT*u43<;^)Rl=-5qy2d^z z$U?8R%Z#f*dgVkgL+a7%mYP}@Zgoyt^zYKQ#GHf?Tixn1T$4 zen|CA44~mL7`vE>R64Gk;K{2met1UkigvX^tjumEWBdLZN8SFABlOvDd;HbX*?Y~7 zUl~FM`!H5(LNS)~h~G9e{Dzb4?@I;gClW+84&M)$OCqX^T5VYhmSz14T#sms+8&!N zUF5LKWbbPbrSI3e8qH6}|9p5zV#r7%Kivn?lb0&0UON-7{VM5K-leTsp&Sl$d~8?r z=q}C>Td3cA0lf=w|2GE5_#YXGTDyj*#M{McC$sQ|%5m_Aw#$hkNN^V(Sq4+7!xc85 z`F2Gl!75A}d&YZ~<_$Z82A?RK89U1B~QDEKZ^3+5xapcOago2}Snvvc?QjrmGl zenMkU|NXu=$&>`yv-+CT5A}{v&on$ufaV4Hm8DW*)xpYU(v zvfHu$oDh~JyhBP|>0c+hptW<}W3>Dmk2Z^i>ve;_NCOg%UZ6^bdlL;zVDa3iTK2D? zvTkAh_I~sLfzVYUOEdbM`^c_UN#Z$9yh1XC9lmxd4{?|IixEPd#aZYZJPMg?gxb?C z={H>}q)X$|C2JBLAl$eO^H%*x-)F)$X7dj=eTYSPkQv%rc-B2ZaNn1X3<=`{WkpmL_}kOpERF1J}7Tgl9v@$Ly-|OKNbnzV0sr zDnA~dz8=d=YwbqM9qFVzJ-gnxu|HT>4Nd727KB(XQ>C9?8P#XFOh(OgswH+vvVO(~ z+1c6G2tB7@IG_9#ic4IK89$v_8SbiGNY^i5nnIv<`NEgeI3O*_vND%`Yy8PH$S2h} zH!TZW^{7?vO(?v=HmX&tYTyd|$)e0~-6aNYb-RsLcxeQjF6zrVFUkw8$5nkN*axt` z8B3_Eq$oI2j*5V4PE5Rxz|-w^Z}^6B<0@MjEDz;?ZW|E72bvtd_TaY1su9f`Tm&ZA zJnyq?OJG{Z2wqrvAn%D4qA_EppYuABvE@AxG9EAO)dd~NCMq^7< zANi33Jwr#$tK!IZx!Ii<&-SGleyTfoVP=Q^f<9Z+MrGq^oEh-A=(+G@6v?rD7a+tx zG1lqm=js3}V~LkuFVZyop(|L&A^f2$`^F&oayKZoZculwako#88zoQMg3R6?w!Uyw zHRQ}QBed@qR&Jg>-GK7BNG9LZV@i$4+WqmS~#W zP_;1L_4{ha*_g3Mc}t0B0Q|xJmeq2?ht3;xGQ=7Bl)+&%&{)w}8c6NDVgQo{*8_hP zNZhd)iY*r)^bT`K3ls$lLGetLasSM&a~(4R4NS6lFG-#yZd4~7eGM>j(%6gp^OY!v zG~v5th1I~;sMvmK8pYK>*-VHoQ@yp5z44l?yOTOxB6W6XGS$3~=PEeE;yhvdqgH0r z7$5konEC4Dgo41`L%8k8 zRIq<)PJQ@wUdho;WOO$4q*UmF_B()>fhJnC3Mo)ePlcSLyRYj%$)LToOb|c1o(p<( zGZ*!cFP%m#5;xfHcIuZn6wcEs7~M?7Rvi}(v{0-hng-mgZnD^wRes@z1+lfEh3`-lIG0d2 z^XH4qJtGXqeX*c5Q=Iqm4DUul7zZMX)EAjBM;)z;o+T(ncg0et2 z0HdE35klIKMtGi^iNf54&DPr zP=N~VXM_b82ye*fG8dlZLoJWZh3s$BuujVZl&zcW{87R)lQAPr8RutJAzqu%LPGU| z7~)Q9Yd9U8427G&v0^fX%NUA-#~fmQ@ytZv#~5ndlvTM0Q^>H|UZ`zi)8^zTILcv%*dvcO09N~7K0hyljf-&aBJ(Ui(|*>^p5ZyA=p5k2{!7izz* zr%N2~MUU9b3YGwAdpm3|z3d)KKUThcaM{yz4=3N)cjBx_XL{0CxXY$)wO{~I@LLhm zgpBqLC58@`p5EG&Hki_vo-JoK`z+moA9SvbkOo`_M8N!Z`OoDC0^tFa{olc*n?oxg zn#0rG7==sOy0Hj$a{fWAJF7DI393j6IX$-VkB!}DNnk#a30`gqyV(Na$r39C%n2(7 zan+0uT{cYEP=#O+g*R}A61tO|%n^QFWEdG;Qwl*PX6OG>Un6L86kGAy$hqOqXXUwU zp*@Xn2P!^u{cu;EujwC)Ihw!ax}7JS9rvZMZ(A+<*bj*qsb@ussI4)74g|Q)($Bzw z-!aSo*HMSsJin{>5QLL_#@QIU_3m31#>iBZu<_+;wF;_Jj1+=RwFvhZPfw%JrX5912{EcJPDAgiY{e6 zx4Yd&uMkD)9-uBcpCRD*!J*BC$=UCewKT-79IyG9lVHAB66x2GxLmj0p4h?n!T3H? zB4>Fn<23}lP94nfJn%!HZ~iTcBv5iYeiX3^9ykxtcj2d%LN1yWQ=jQ(jQTm1o>C8v z?Gygk$P(#`Rv0q!5lrVduPpt(Nj_f$P2Uai57!yQbGKpaN|W(_yU@V4%kcpGz*A3b z0@L(%e-}VPD2q|FsvIzoBt1a`JT5xq%>e%|;2$7>jFpEI#&{1M8=Xx+Pptbkm&~#+ zagv$Nk6+w))H)6@K@YIFx>37FG(XM#-;O)T&6=F(Cq(+PYX@GgcEluJqisoSkGZz- z*UpB{<-lu7q2GunOYrI(O`LML>95n~rRpbx&KfjAJx6@g5OoIhTk@e1M}bY%A6#u_ zMSco3K1N(l2N38x<;gf&! z0ER%p%e|4c52iJsvG7Ttj+>MrkTT95PMddzmnw&%+5hGUs~Cq)eMT!*pB@P*zlH}Lo%U+Tg42@m&D$m3BPH_NCE{%-|& z9_AnXn}72kdYFIn|Isl2=D)LH{>?w^+x&xkyx07j{}+PJlZ{iJ!_9?q^u9owPJv=` zvpG*-ws%F7rPzIzb$PzNTnM3x=D5>afLzxGKs`a{gr6dsLOk)>V|M#y;<81wjeUUi z=i0oq{>ChGm-${YET$%v-RD&BJ<+|v=#=Gu2)-2^v+atnFu%xy&=a`6Po0~H4L+O-xN&R_DjpF`zR0yE)-p&Wr4K_AxirJ_qXqgyS zs8Q5$`@VkLKyfPZMje!&k~fr&e$2o55A$#S&A<7_#pd7q*J1vfVg3V5nt$`Z`T83F YKfl-#g|40(5dZ)H07*qoM6N<$f>QnxkN^Mx literal 0 HcmV?d00001 diff --git a/Projects/App/Resources/Assets.xcassets/splashCharacter.imageset/Contents.json b/Projects/App/Resources/Assets.xcassets/splashCharacter.imageset/Contents.json new file mode 100644 index 0000000..f6f6a3a --- /dev/null +++ b/Projects/App/Resources/Assets.xcassets/splashCharacter.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "img_Atcha_character.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "img_Atcha_character@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "img_Atcha_character@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Projects/App/Resources/Assets.xcassets/splashCharacter.imageset/img_Atcha_character.png b/Projects/App/Resources/Assets.xcassets/splashCharacter.imageset/img_Atcha_character.png new file mode 100644 index 0000000000000000000000000000000000000000..570a4f978745594dab39ff7c96b961c806650cd5 GIT binary patch literal 1567 zcmV+)2H^RLP)M&t&UQoTizP&fZ6q3m zMk2MZNaF%!%~3!R$!-t=c8B+NXZL3RW`DfvyIt`~@$Jpd?9I3D&6_vxy#V}=`C-f- z??2&>A3}rBU_mhEhdUhjLk8S{2C)!?zvqYdIk>yxs{sw7FkzY$l*E|t8z{McULOtI zfzF24X;MG%gBLi#9u&qBs;T>k)HUrck>#NMgqOP1Y(Rr3Oqc^4;0I0c1dYpp zCadc2li?fwSa%nV(IELuZ460*I*!$$A(WBuBm6k0Ya)V^eUT+Of(uKg{2h(a25QJj zK!z+beq?Ej0S$qb>5P*cBiZ;`wmGo92W)F7HDDN!R+Q zDQLyrl~uNFLq%LG)f*gCYb{RLK8qB0i7}ae^jXPAw<+BwRk;b7IeTZ(pH=J>zxE6odmqbxHKRUupoQ9S_-f zwGpKyjOuibYCXcsKFk?o{;lD_zddqCQF8BcZy9lYjrCWu#*`*Zz;%RHR+|f9-0t@A zh0~JKIsB~$D$2vTv7u_blCW=W(|*+3SD|jaoSwt!&u7s4Xc?}*_DX6WmfRL&aQ0Mp zm4xx(<<`rasV@A|7ViT;NDs(|H4m!PR{dKS4h5UHskL(-f|#FpQiN%ZuY4HaOcbgjHj zO2TB3Nll<8ym3p9tj+23Kf>#qcW#8&r_auyEYOhVN|%tk4;N9BGFZNAgx9hp--)f+ zU_BQENq1PJV=iH#Cbc;lvY~qU>xI;Q13v!pL-^eK1P*@rEYnJ7K&Kt0$gwilm!{2~ z!#{&GzqSf!-Jbk->JcPMT#{G;Fbj?CNCPL;Vn+yzV_44xP8<9C%qQ8{VZ3>SfEFM9;t+fyh-^zpdV-y{p#zAka)4C(gz8OE$pN$%=cvlBr`^aj$av-? zKYH$m{HpNJ#ZE%XSrQI10tU1jWS3THsRj)R*OF2x9U)5)nUYz;Am(Wunz-00{n4eZ zDF8`(C6w?n|7IP@#uHmzgC7GUkvrfFp}Uv_DH=ux2H{~D&`G$XHMYGGe3M;E+Iwkn z8_*Gu^YMUf@5*h7ZK*@VCusrsOvl3~zO-J~!G9hQ>vkfyWrlbtMzqGZT78&slc`;G zOiN@QTDwiL6xUc&58yk{Zcx35DK}&i7Sc7K(w^GO26KPrJRD7>V$2$Vo=zXV$HbyY*KM*dLOu#_na0<*m+8S=@hrh zwpOX;lE{Nsml+`HRi&W;!pss*fDQG+lE09H;U8i9D|GI~rjhtfQ}vLlRytM-O(dOT zychkwwwWl(Jhz8I?WQlx8U z0XBR=yLht6Dy?`5HKEaDzd9lsjV4NC?&Fw!d5lPx6mlK&(5TTO$qU000Ywwj$ciyX zl*AU}Y|(5%n?RXJ^3Ler6I9(YV~hI8MR6tdD}idGWJmEhac9xw|3xZ;{{Sn1UoU5X RD0%<@002ovPDHLkV1oIE=m-D+ literal 0 HcmV?d00001 diff --git a/Projects/App/Resources/Assets.xcassets/splashCharacter.imageset/img_Atcha_character@2x.png b/Projects/App/Resources/Assets.xcassets/splashCharacter.imageset/img_Atcha_character@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5b37b498f06b0e251ec17e1235116094e01ac178 GIT binary patch literal 2911 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 VEhfE?p*R2l002ovPDHLkV1gM3A`t)p literal 0 HcmV?d00001 diff --git a/Projects/App/Resources/Assets.xcassets/splashLogo.imageset/Contents.json b/Projects/App/Resources/Assets.xcassets/splashLogo.imageset/Contents.json new file mode 100644 index 0000000..fcd975c --- /dev/null +++ b/Projects/App/Resources/Assets.xcassets/splashLogo.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "img_Atcha.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "img_Atcha@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "img_Atcha@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Projects/App/Resources/Assets.xcassets/splashLogo.imageset/img_Atcha.png b/Projects/App/Resources/Assets.xcassets/splashLogo.imageset/img_Atcha.png new file mode 100644 index 0000000000000000000000000000000000000000..b19f5819bd47696258ab8af8cac545f75e5e347f GIT binary patch literal 1382 zcmV-s1)2JZP);d}Xi+2GU(E}7ue3C^7$x(Vt|5M_e+Ca^m}+6kmikY)m@6EvLw1uFX0l_>(G zNK0+?y~n3Sf&z&MHfz&CNa;HT28Cg>LUa|dJDQ_4iVP9 zhX_z!IbCiAu{S>7LOR#b)yojiq;Cr`;18g*qx2bN8Y7!|=1~cHD~JReA7ye+oqIuF zBkA}QzCdxVS3$TlH{`JHhZgesD|G#es^a0*I~q-z5UB7+8@3cROF331?F zb#Dy3;NZe`(^OoF7G09=4>YjVkPynFREYhpkhxKeBX!L0IWdUw_a&s`f%14kAMp(7 zh}9DdrCbe>u=Nn_$8d$dHCKjP98dW&;XQU=-1|ycIN=9_nBGw+-n*j~UiNRA_qnoP z3-9yu68yR1SzGVkQ?$AL+)&QVONE|Fp(hV~uTN#sb56>me50>J{uSg~ThFlYMj>+r z3n%mqA}#u!K!FK2w1Svsmh;=uH%KPPx1h&IcENDrDgP(@9Q>z{$tm3kGCV=~BFF>< zQir&(D9;@7u4jFuG2#;>LK6|D0hTY4LEe+D7S2fDWl5F9fyP{rIfT)r@hED`3P2Mi zO}Tir((fVfKwd-asKQ?kwH)l$BKIH@VvrV2SH&%akx2pxq6rzAu6YE{Twfgix#$(3 zCV4J|tMz1*Dw4Z{E{@akO=Adl0UMB8UmfTQxbT|sLBn6d^GSNJZBYLoD!9= z)Zi-aV0tp)`PtnSV++4?7@~!A>{Ca3l}M8g)tW0dCk8Qo^ChHdAuZ@u@kv45)@%zC zVBMfH{+*4|LOfd5nK#+W1w?iiZz2OFh^@$k5GeeOBE11V<5Y;b~YXXlF|uO8-DNOW|~UE{jtQ z-GI2CixGOPJ>?%<>n=~YK3-YwrN^{H-*+luKVkH_EDYOoX*A!15%xoTgNr^qnC|}3 zq)&&xr|LOoc9nxa8FcHeSMW2!u1#nueEM-`d9M=Q8`VST{YM4YQ|N*6v%;+hbwoQf zttb<_&qi6Utx~Q*%Xwvt;Id+V_-pi|!tRty28l3b(wx?34#85bQFuJM?BzGTL9lCq z6^^6ANX8)@e0FPter0No^G5yPzw6~aok8&X??qzs?W8;g8VAEDdOCdE-0jhO=QD^Y zDe3VyiKBiIRlL@*Gd^Tm`fjLU-jP#T^(DTjn$qmw& zLgo+&bi1^j;{7a^0em^PLHK`e9a~Hs@-X?^Tv`q@CWb*)4&|Bo^Lgs6SYwDa@6E%E oF+J1SJ7;vzV_{)oVc{3!EAxJlbAB(9`~Uy|07*qoM6N<$f;d`>x&QzG literal 0 HcmV?d00001 diff --git a/Projects/App/Resources/Assets.xcassets/splashLogo.imageset/img_Atcha@2x.png b/Projects/App/Resources/Assets.xcassets/splashLogo.imageset/img_Atcha@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fb936d609224c21ff28fc1bba3f34f4f229c1e0c GIT binary patch literal 2700 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Projects/App/Sources/SplashViewController.swift b/Projects/App/Sources/SplashViewController.swift index e9f3788..131aa11 100644 --- a/Projects/App/Sources/SplashViewController.swift +++ b/Projects/App/Sources/SplashViewController.swift @@ -1,12 +1,16 @@ import DesignSystem import UIKit -/// Dumb splash screen: logo while the auth bootstrap runs, a retry affordance -/// when it fails. All flow decisions live in AppCoordinator. +/// Dumb splash screen: legacy splash visuals (full-bleed background + character/logo stack) +/// while the auth bootstrap runs, a retry affordance when it fails. +/// All flow decisions live in AppCoordinator. final class SplashViewController: UIViewController { var onRetryTapped: (() -> Void)? - private let logoLabel = UILabel() + private let backgroundImageView = UIImageView() + private let characterImageView = UIImageView() + private let logoImageView = UIImageView() + private let logoStackView = UIStackView() private let activityIndicator = UIActivityIndicatorView(style: .medium) private let retryStack = UIStackView() private let messageLabel = UILabel() @@ -32,11 +36,23 @@ final class SplashViewController: UIViewController { private func configureUI() { view.backgroundColor = DSColor.Background.base - logoLabel.text = "앗차" - logoLabel.font = DSFont.pretendard(.bold, size: 34) - logoLabel.textColor = DSColor.Accent.default + backgroundImageView.image = AtchaV2Asset.splashBackground.image + backgroundImageView.contentMode = .scaleAspectFill + backgroundImageView.clipsToBounds = true + + characterImageView.image = AtchaV2Asset.splashCharacter.image + characterImageView.contentMode = .scaleAspectFit + logoImageView.image = AtchaV2Asset.splashLogo.image + logoImageView.contentMode = .scaleAspectFit + + logoStackView.axis = .vertical + logoStackView.alignment = .center + logoStackView.spacing = 12 + logoStackView.addArrangedSubview(characterImageView) + logoStackView.addArrangedSubview(logoImageView) activityIndicator.hidesWhenStopped = true + activityIndicator.color = DSColor.Text.primary messageLabel.font = DSTypography.body1.font messageLabel.textColor = DSColor.Text.primary @@ -54,18 +70,23 @@ final class SplashViewController: UIViewController { retryStack.addArrangedSubview(messageLabel) retryStack.addArrangedSubview(retryButton) - for subview in [logoLabel, activityIndicator, retryStack] { + for subview in [backgroundImageView, logoStackView, activityIndicator, retryStack] { subview.translatesAutoresizingMaskIntoConstraints = false view.addSubview(subview) } NSLayoutConstraint.activate([ - logoLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor), - logoLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: -DSSpacing.xl), + backgroundImageView.topAnchor.constraint(equalTo: view.topAnchor), + backgroundImageView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + backgroundImageView.leadingAnchor.constraint(equalTo: view.leadingAnchor), + backgroundImageView.trailingAnchor.constraint(equalTo: view.trailingAnchor), + // 런치스크린 storyboard와 동일한 정중앙 배치 — 전환 시 로고가 튀지 않게 유지. + logoStackView.centerXAnchor.constraint(equalTo: view.centerXAnchor), + logoStackView.centerYAnchor.constraint(equalTo: view.centerYAnchor), activityIndicator.centerXAnchor.constraint(equalTo: view.centerXAnchor), - activityIndicator.topAnchor.constraint(equalTo: logoLabel.bottomAnchor, constant: DSSpacing.lg), + activityIndicator.topAnchor.constraint(equalTo: logoStackView.bottomAnchor, constant: DSSpacing.xl), retryStack.centerXAnchor.constraint(equalTo: view.centerXAnchor), - retryStack.topAnchor.constraint(equalTo: logoLabel.bottomAnchor, constant: DSSpacing.lg), + retryStack.topAnchor.constraint(equalTo: logoStackView.bottomAnchor, constant: DSSpacing.xl), retryStack.leadingAnchor.constraint(greaterThanOrEqualTo: view.leadingAnchor, constant: DSSpacing.md), retryStack.trailingAnchor.constraint(lessThanOrEqualTo: view.trailingAnchor, constant: -DSSpacing.md), ])

    5~3q@^3dPj9MeXz}$Ho*j(h;_17@a?veR-q3& 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