Added Crew and General Aviation Filters

This commit is contained in:
2026-04-20 22:30:34 +10:00
parent e007824fa9
commit a57775e141
26 changed files with 559 additions and 98 deletions
+105 -4
View File
@@ -6,8 +6,6 @@ const DAYS = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturda
const MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
// ── Date part cache ───────────────────────────────────────────────────────────
// Intl.DateTimeFormat is expensive. We compute each flight's date parts once
// and cache them for the lifetime of the page.
const dateCache = new Map<number, { year: number; month: number; day: number }>()
@@ -318,6 +316,107 @@ export function getTopAirports(flights: Flight[], upcomingFlights: Flight[]) {
return result
}
// ── Aircraft ──────────────────────────────────────────────────────────────────
interface AircraftItem {
label: string
id: number
past: number
upcoming: number
}
export function getTopAircraft(flights: Flight[], upcomingFlights: Flight[]) {
console.time('getTopAircraft')
function countAircraft(list: Flight[]) {
const counts = new Map<string, { count: number; id: number }>()
list.forEach(f => {
const aircraft = f.aircraft
if (!aircraft?.designator) return
const existing = counts.get(aircraft.designator) ?? { count: 0, id: aircraft.id }
existing.count++
counts.set(aircraft.designator, existing)
})
return counts
}
const past = countAircraft(flights)
const upcoming = countAircraft(upcomingFlights)
const allNames = new Set([...past.keys(), ...upcoming.keys()])
const sorted: AircraftItem[] = [...allNames]
.map(name => ({
label: name,
id: (past.get(name) ?? upcoming.get(name))!.id,
past: past.get(name)?.count ?? 0,
upcoming: upcoming.get(name)?.count ?? 0,
}))
.sort((a, b) => (b.past + b.upcoming) - (a.past + a.upcoming))
const result = {
aircraft: sorted,
series: [
{ name: 'Flights', data: sorted.map(s => s.past) },
{ name: 'Upcoming', data: sorted.map(s => s.upcoming) },
],
}
console.timeEnd('getTopAircraft')
return result
}
// ── Routes ────────────────────────────────────────────────────────────────────
interface RouteItem {
label: string
depLabel: string
arrLabel: string
past: number
upcoming: number
}
export function getTopRoutes(flights: Flight[], upcomingFlights: Flight[]) {
function countRoutes(list: Flight[]) {
const counts = new Map<string, { count: number; depLabel: string; arrLabel: string }>()
list.forEach(f => {
const dep = airportLabel(f.departure_airport)
const arr = airportLabel(f.arrival_airport)
if (!dep || !arr) return
const key = `${dep}-${arr}`
const existing = counts.get(key) ?? { count: 0, depLabel: dep, arrLabel: arr }
existing.count++
counts.set(key, existing)
})
return counts
}
const past = countRoutes(flights)
const upcoming = countRoutes(upcomingFlights)
const allKeys = new Set([...past.keys(), ...upcoming.keys()])
const sorted: RouteItem[] = [...allKeys]
.map(key => {
const meta = (past.get(key) ?? upcoming.get(key))!
return {
label: key,
depLabel: meta.depLabel,
arrLabel: meta.arrLabel,
past: past.get(key)?.count ?? 0,
upcoming: upcoming.get(key)?.count ?? 0,
}
})
.sort((a, b) => (b.past + b.upcoming) - (a.past + a.upcoming))
const result = {
routes: sorted,
series: [
{ name: 'Flights', data: sorted.map(s => s.past) },
{ name: 'Upcoming', data: sorted.map(s => s.upcoming) },
],
}
return result
}
// ── Flight types ──────────────────────────────────────────────────────────────
export function getFlightTypes(flights: Flight[]) {
@@ -346,8 +445,6 @@ export type FlightStats = ReturnType<typeof useFlightStats>
export function useFlightStats(flights: Ref<Flight[]>) {
const now = new Date()
// Pre-warm the date cache as soon as flights are available so the first
// filter interaction doesn't pay the Intl.DateTimeFormat cost.
watch(flights, (list) => {
console.time('dateCache warm')
list.forEach(f => getDateParts(f))
@@ -380,6 +477,8 @@ export function useFlightStats(flights: Ref<Flight[]>) {
const continents = computed(() => getContinents(allFlights.value))
const topAirlines = computed(() => getTopAirlines(pastFlights.value, upcomingFlights.value))
const topAirports = computed(() => getTopAirports(pastFlights.value, upcomingFlights.value))
const topAircraft = computed(() => getTopAircraft(pastFlights.value, upcomingFlights.value))
const topRoutes = computed(() => getTopRoutes(pastFlights.value, upcomingFlights.value))
const flightTypes = computed(() => getFlightTypes(allFlights.value))
return {
@@ -396,5 +495,7 @@ export function useFlightStats(flights: Ref<Flight[]>) {
flightTypes,
topAirlines,
topAirports,
topAircraft,
topRoutes,
}
}