export type Departure = { id: string; routeId: number; routeNumber: string; routeName: string; destination: string; type: string; scheduledAt: string; scheduledTime: string; note: string; source: 'schedule'; serviceDate?: string; originStopId?: number; originTime?: string; endStopId?: number; }; export type Route = { id: number; number: string; name: string; type: string }; export type RouteStop = { id: number; name: string; sequence: number; offsetMinutes: number | null }; export type Cancellation = { routeNumber: string; stopId: number; serviceDate: string; time: string }; export type Alert = { id: string; title: string; message: string; type: string; routeNumbers: string[]; routeIds: number[]; startAt: string | null; endAt: string | null; cancellations?: Cancellation[] }; export type Stop = { id: number; name: string; direction: string }; export type BoardData = { cityId: number; cityName: string; stop: Stop; departures: Departure[]; routes: Route[]; alerts: Alert[]; alertsAvailable: boolean; partial: boolean; updatedAt: string; serverTime?: string; serviceDate: string; mode: 'live' | 'demo' }; export type Config = { cityId: number; cityName: string; stopName: string; defaultStopId: number; configured: boolean; refreshSeconds: number; timeZone: string; passengerBaseUrl?: string }; export type Place = { stopId: number; name: string }; export type FareTerms = { price: string; payment: string; checkedAt: string }; export type FareRule = FareTerms & { routeId: number }; export type FareTypeRule = FareTerms & { cityId: number; type: 'bus' | 'minibus' }; export type Settings = { stopId: number; demo: boolean; mainSeconds: number; infoSeconds: number; holdNear: boolean; rowCount: number; routeFilter: string; theme: 'dark' | 'light'; colorScheme: string; lightColorScheme: string; infoServiceEnabled: boolean; infoWeatherEnabled: boolean; infoQrEnabled: boolean; journeyTranslitEnabled: boolean; infoPlacesEnabled: boolean; infoFareEnabled: boolean; lastTripNoticeEnabled: boolean; weatherHintEnabled: boolean; places: Place[]; fareRules: FareRule[]; fareByType: FareTypeRule[]; showNextSameRoute: boolean; longWaitEnabled: boolean; displayProfile: 'tv' | 'street'; viewingDistance: 'near' | 'medium' | 'far'; nightMode: 'off' | 'auto'; nightWakeMinutes: 45 | 60; adsEnabled: boolean; adSeconds: number; adTitle: string; adText: string }; export type Scene = 'departures' | 'info' | 'ad'; export type Timetable = { version: 1; cityId: number; cityName: string; stop: Stop; routes: (Route & { stops?: RouteStop[]; schedules: { dayType: string; validFrom: string | null; validUntil: string | null; trips: { arrivalSeconds: number; destination: string; note: string; daysOfWeek: number[]; exceptDaysOfWeek: number[]; originStopId?: number; originTime?: string; endStopId?: number }[]; }[] })[]; holidays: string[]; calendarYears: number[]; updatedAt: string; expiresAt: string }; export type Weather = { cityId: number; stopId: number; updatedAt: string; observedAt: string; temperature: number; apparentTemperature: number; code: number; isDay: boolean; windSpeed: number; hourly: { at: string; temperature: number; code: number; precipitationProbability: number }[] };