Added Crew and General Aviation Filters
This commit is contained in:
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user