diff --git a/src/lib/types/index.ts b/src/lib/types/index.ts index 2938557..6b95228 100644 --- a/src/lib/types/index.ts +++ b/src/lib/types/index.ts @@ -1,10 +1,51 @@ +export type Car = { + _id: number; + ai_enabled: boolean; + allow_number_colors: boolean; + allow_number_font: boolean; + allow_sponsor1: boolean; + allow_sponsor2: boolean; + allow_wheel_color: boolean; + award_exempt: boolean; + car_dirpath: string; + car_id: number; + car_name: string; + car_name_abbreviated: string; + car_types: Array<{ car_type: string }>; + car_weight: number; + categories: Array; + created: string; + first_sale: string; + forum_url: string; + free_with_subscription: boolean; + has_headlights: boolean; + has_multiple_dry_tires_types: boolean; + hp: number; + is_ps_purchasable: boolean; + max_power_adjust_pct: number; + max_weight_penalty_kg: number; + min_power_adjust_pct: number; + package_id: number; + patterns: number; + price: number; + price_display: string; + retired: boolean; + search_filters: string; + sku: number; +}; + export type CarClass = { car_class_id: number; - cars_in_class: Array<{ car_id: number }>; + cars_in_class: Array<{ car_id: number; car_name: string | undefined }>; name: string; short_name: string; }; +export type CarClassMapping = { + car_class_id: number; + car_class_short_name: string; +}; + export type Helmet = { pattern: number; color1: string; @@ -54,6 +95,155 @@ export type RaceSummary = { special_event_type_text: string; }; +export type RaceWeek = { + season_id: number; + race_week_num: number; + series_id: number; + series_name: string; + season_name: string; + schedule_name: string; + start_date: string; + simulated_time_multiplier: number; + race_lap_limit: number | null; + race_time_limit: number | null; + start_type: string; + restart_type: string; + qual_attached: boolean; + full_course_cautions: boolean; + special_event_type: unknown; + start_zone: boolean; + enable_pitlane_collisions: boolean; + short_parade_lap: boolean; + track: Track; + weather: Weather; + track_state: TrackState; + race_time_descriptors: Array; + car_restrictions: Array; + race_week_cars: Array; +}; + +export type SchedulingSeason = { + _id: number; + active: boolean; + allowed_season_members: unknown; + car_class_ids: Array; + car_switching: boolean; + car_types: Array<{ car_type: string }>; + caution_laps_do_not_count: boolean; + complete: boolean; + cross_license: boolean; + driver_change_rule: number; + driver_changes: boolean; + drops: number; + enable_pitlane_collisions: boolean; + fixed_setup: boolean; + green_white_checkered_limit: number; + grid_by_class: boolean; + hardcore_level: number; + ignore_license_for_practice: boolean; + incident_limit: number; + incidient_warn_mode: number; + incident_warn_param1: number; + incident_warn_param2: number; + is_heat_racing: boolean; + license_group: number; + license_group_types: Array<{ license_group_type: number }>; + lucky_dog: boolean; + max_team_drivers: number; + max_weeks: number; + min_team_drivers: number; + multiclass: boolean; + must_user_diff_tire_types_in_race: boolean; + next_race_session: unknown; + num_opt_laps: number; + official: boolean; + op_duration: number; + open_practice_session_type_id: number; + qualifier_must_start_race: boolean; + race_week: number; + race_week_to_make_division: number; + reg_user_count: number; + region_competition: boolean; + restrict_by_member: boolean; + restrict_to_car: boolean; + restrict_viewing: boolean; + schedule_description: string; + schedules: Array; + season_id: number; + season_name: string; + season_quarter: number; + season_short_name: string; + season_year: number; + send_to_open_practice: boolean; + series_id: number; + short_parade_lap: boolean; + start_date: string; + start_on_qual_tire: boolean; + start_zone: boolean; + track_types: Array<{ track_type: string }>; + unsport_conduct_rule_mode: number; +}; + +export type SchedulingTableResult = { + "Season Name": string; + "License Level": string; + carClassData: Array; + tracks: Array; + ownedTrackWeeks: Array; + "Own Car": string; + "Overall Track Percentage Owned": number; +}; + +export type Season = { + _id: string; + car_class_id: string; + division: number; + overall_rank: number; + season_driver_data: SeasonDriverData; + season_id: string; + season_name: string; + division_rank: number; +}; + +export type SeasonDriverData = { + rank: number; + cust_id: number; + display_name: number; + division: number; + club_id: number; + club_name: string; + license: SeasonDriverLicense; + helmet: Helmet; + weeks_counted: number; + starts: number; + wins: number; + top5: number; + top25_percent: number; + poles: number; + avg_start_position: number; + avg_finish_position: number; + avg_field_size: number; + laps: number; + laps_led: number; + incidents: number; + points: number; + raw_points: number; + week_dropped: boolean; + country_code: string; + country: string; +}; + +export type SeasonDriverLicense = { + category_id: number; + category: string; + license_level: number; + safety_rating: number; + irating: number; + color: string; + group_name: string; + group_id: number; +}; + export type Session = { simsession_number: number; simsession_type: number; @@ -195,8 +385,9 @@ export type Track = { track_id: number; track_name: string; config_name: string; - category_id: number; - category: string; + category_id: number | undefined; + category: string | undefined; + race_week_num: number | undefined; }; export type TrackState = { @@ -211,6 +402,16 @@ export type TrackState = { race_grip_compound: number; }; +export type UserIdCarClassIdsMapping = { + userId: number; + carClassIds: Array; +}; + +export type UserIdYearsMapping = { + userId: number; + years: Array; +}; + export type Weather = { version: number; type: number; diff --git a/src/pages/subsession/[id].astro b/src/pages/subsession/[id].astro index 7990d34..0b00c47 100644 --- a/src/pages/subsession/[id].astro +++ b/src/pages/subsession/[id].astro @@ -11,14 +11,13 @@ export async function getStaticPaths() { const dbConnection = await connectToDatabase(); const db = dbConnection.db; const collection = db.collection("subsessions"); - const subsessionIds = await collection.distinct("_id", {}); - return subsessionIds.map((id) => ({ params: { id: Number(id) } })); + const subsessionIds: Array = await collection.distinct("_id", {}); + return subsessionIds.map((id) => ({ params: { id } })); } const { id } = Astro.params; const dbConnection = await connectToDatabase(); const db = dbConnection.db; const collection = db.collection("subsessions"); -//@ts-ignore const subsession: Subsession = await collection.findOne({ _id: Number(id) }); const { track, @@ -65,8 +64,10 @@ const { toggle() { this.$el.id.split(" ").forEach((id, index) => { if (index) { + // @ts-expect-error this[id] = false; } else { + // @ts-expect-error this[id] = !this[id]; } }); diff --git a/src/pages/user/[id]/scheduling/index.astro b/src/pages/user/[id]/scheduling/index.astro index 8dde6e1..ab0b978 100644 --- a/src/pages/user/[id]/scheduling/index.astro +++ b/src/pages/user/[id]/scheduling/index.astro @@ -1,19 +1,25 @@ --- import { connectToDatabase } from "$lib/mongodb"; import DefaultLayout from "$lib/layouts/default.astro"; -// @todo Properly assert types in this file +import type { + Car, + CarClass, + SchedulingSeason, + SchedulingTableResult, + Track, +} from "$lib/types"; export async function getStaticPaths() { const dbConnection = await connectToDatabase(); const db = dbConnection.db; const userCollection = db.collection("users"); - const userIds = await userCollection.distinct("_id", {}); + const userIds: Array = await userCollection.distinct("_id", {}); return userIds.map((id) => ({ params: { id } })); } const { id } = Astro.params; const dbConnection = await connectToDatabase(); const db = dbConnection.db; const userCollection = db.collection("users"); -const carPackages = await userCollection +const carPackages: Array<{ content_ids: Array }> = await userCollection .aggregate([ { $match: { @@ -39,36 +45,37 @@ const carPackages = await userCollection ]) .toArray(); const carIds = carPackages.map((carPackage) => carPackage.content_ids).flat(); -const trackPackages = await userCollection - .aggregate([ - { - $match: { - _id: Number(id), +const trackPackages: Array<{ content_ids: Array }> = + await userCollection + .aggregate([ + { + $match: { + _id: Number(id), + }, }, - }, - { - $unwind: "$track_packages", - }, - { - $replaceRoot: { - newRoot: { - $mergeObjects: ["$track_packages", "$$ROOT"], + { + $unwind: "$track_packages", + }, + { + $replaceRoot: { + newRoot: { + $mergeObjects: ["$track_packages", "$$ROOT"], + }, }, }, - }, - { - $project: { - _id: 0, - content_ids: 1, + { + $project: { + _id: 0, + content_ids: 1, + }, }, - }, - ]) - .toArray(); + ]) + .toArray(); const trackIds = trackPackages .map((trackPackage) => trackPackage.content_ids) .flat(); const carsCollection = db.collection("cars"); -const cars = await carsCollection.find().toArray(); +const cars: Array = await carsCollection.find().toArray(); const carsMap = new Map(); cars.forEach((car) => { const { car_id } = car; @@ -78,7 +85,7 @@ const carClassCollection = db.collection("carclasses"); const carClassIdsForCarIds = await carClassCollection.distinct("car_class_id", { "cars_in_class.car_id": { $in: carIds }, }); -const carClasses = await carClassCollection.find().toArray(); +const carClasses: Array = await carClassCollection.find().toArray(); const carClassesMap = new Map(); carClasses.forEach((carClass) => { const { car_class_id, cars_in_class } = carClass; @@ -88,7 +95,9 @@ carClasses.forEach((carClass) => { carClassesMap.set(car_class_id, { ...carClass, cars_in_class: carsInClass }); }); const seasonsCollection = db.collection("seasons"); -const seasons = await seasonsCollection.find({}, {}).toArray(); +const seasons: Array = await seasonsCollection + .find({}, {}) + .toArray(); const carClassIdSet = new Set(carClassIdsForCarIds); const trackIdSet = new Set(trackIds); const licenseGroupToNameMap: Record = { @@ -98,23 +107,21 @@ const licenseGroupToNameMap: Record = { "4": "Class B", "5": "Class A", }; -const results = seasons +const results: Array = seasons .map((season) => { const { schedules, season_name, car_class_ids } = season; - const carClassData = car_class_ids.map((car_class_id: number) => - carClassesMap.get(car_class_id) + const carClassData: Array = car_class_ids.map( + (car_class_id: number) => carClassesMap.get(car_class_id) ); - const tracks: Array> = schedules.map( + const tracks: Array = schedules.map( (schedule: any, index: number) => ({ - week: index + 1, + race_week_num: index + 1, ...schedule.track, }) ); const ownedTrackWeeks: Array = tracks - .filter((track: Record) => - trackIdSet.has(track.track_id) - ) - .map((track: Record) => Number(track.week)); + .filter((track: Track) => trackIdSet.has(track.track_id)) + .map((track) => Number(track.race_week_num)); const trackPercentageOwned = Math.round( (ownedTrackWeeks.length / tracks.length) * 100 ); @@ -157,8 +164,11 @@ const keysToOmitInTable = new Set([ x-on:click="toggle" > {Object.keys(result) - .filter((key) => !keysToOmitInTable.has(key)) - .map((key: string) => ( + .filter( + (key): key is keyof SchedulingTableResult => + !keysToOmitInTable.has(key) + ) + .map((key) => (
{result[key]}
))}
{result.tracks.map((track) => - result.ownedTrackWeeks.includes(Number(track.week)) ? ( + result.ownedTrackWeeks.includes(Number(track.race_week_num)) ? (
- {track.week}. {track.track_name} {track.config_name} + {track.race_week_num}. {track.track_name}{" "} + {track.config_name}
) : (
- {track.week}. {track.track_name} {track.config_name} + {track.race_week_num}. {track.track_name}{" "} + {track.config_name}
) )} @@ -206,6 +218,7 @@ const keysToOmitInTable = new Set([