Skip to content

Commit

Permalink
Merge pull request #39 from Shinsina/scheduling-improvements
Browse files Browse the repository at this point in the history
Scheduling and Subsessions By Track Page Additions, additional corrections
  • Loading branch information
Shinsina authored Apr 5, 2024
2 parents df9b582 + cdd1821 commit 6a10546
Show file tree
Hide file tree
Showing 11 changed files with 464 additions and 3 deletions.
3 changes: 2 additions & 1 deletion src/lib/layouts/standings.astro
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ const finalData: Array<Record<string, any>> = standingsResults.map(
incidents,
points,
} = result;
const [, year] = season_name.match(/([0-9]{4}) Season/) || [0, 0];
const [, year] = season_name.match(/([0-9]{4}) Season/) ||
season_name.match(/([0-9]{4})$/) || [0, 0];
const [, season_number_of_year] = season_name.match(
/Season ([0-9]{1})/
) || [0, 0];
Expand Down
2 changes: 1 addition & 1 deletion src/lib/layouts/subsessions.astro
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const results = subsessions.map((subsession: Subsession) => {
aggregate_champ_points,
};
});
const keysToDisplay = new Set(Object.keys(results[0]));
const keysToDisplay = new Set(Object.keys(results[0] || {}));
const { keysArray, handledResults } = handleResults({ keysToDisplay, results });
---

Expand Down
25 changes: 25 additions & 0 deletions src/lib/utils/determine-start-of-week-for-date-string.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export default ({
object,
dateString,
}: {
object: Record<string, Array<string>>;
dateString: string;
}) => {
const d = new Date(String(dateString));
const day = d.getDay();
const utcDateString = d.toUTCString();
if (day === 1 && !object[utcDateString]) {
object[utcDateString] = [utcDateString];
} else if (day !== 1) {
const distanceFromOne = day - 1;
const dayOneOfWeek = new Date(
Number(d) - distanceFromOne * 86400000
).toUTCString();
if (object[dayOneOfWeek]) {
object[dayOneOfWeek].push(utcDateString);
} else {
object[dayOneOfWeek] = [utcDateString];
}
}
return object;
};
46 changes: 46 additions & 0 deletions src/lib/utils/generate-season-weeks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import determineStartOfWeekForDateString from "$lib/utils/determine-start-of-week-for-date-string";

export default ({
seasons,
}: {
seasons: Array<{ schedules: Array<{ start_date: string }> }>;
}) => {
const seasonStart = Date.UTC(2024, 2, 12, 0, 0, 0, 0);
const seasonEnd = Date.UTC(2024, 4, 28, 0, 0, 0, 0);
const startDates = seasons.reduce(
(
set: Set<string>,
season: { schedules: Array<{ start_date: string }> }
) => {
const { schedules } = season;
if (Array.isArray(schedules)) {
schedules.forEach((schedule) => {
const { start_date } = schedule;
const [year, month, day] = start_date.split("-");
const date = Date.UTC(
Number(year),
Number(month) - 1,
Number(day),
0,
0,
0,
0
);
if (date >= seasonStart && date <= seasonEnd) {
set.add(start_date);
}
});
}
return set;
},
new Set([]) as Set<string>
);
const weeks = Array.from(startDates)
.sort()
.reduce<Record<string, Array<string>>>(
(object, dateString) =>
determineStartOfWeekForDateString({ object, dateString }),
{}
);
return weeks;
};
27 changes: 27 additions & 0 deletions src/lib/utils/generate-track-map.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { Track } from "$lib/types";

export default ({ tracks }: { tracks: Array<{ track: Track }> }) => {
return tracks.reduce<Map<string, { trackName: string; configName: string }>>(
(
map: Map<string, { trackName: string; configName: string }>,
trackObject
) => {
const { track } = trackObject as { track: Track };
const trackName = `${track.track_name} ${track.config_name}`;
map.set(
trackName
.toLowerCase()
.replace(/[\(\)\[\]]/g, "")
.replace(/[ \/]/g, "-")
.replace("---", "-")
.replace("-n-a", ""),
{
trackName: track.track_name || "",
configName: track.config_name || "",
}
);
return map;
},
new Map([]) as Map<string, { trackName: string; configName: string }>
);
};
15 changes: 15 additions & 0 deletions src/pages/user/[id]/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ const description = `User page for user ID: ${id}`;
href=`/Stat-N-Track/user/${id}/scheduling`>Scheduling</a
>
</div>
<div>
<a
class="underline"
rel="prefetch"
href=`/Stat-N-Track/user/${id}/scheduling/by-week`>Scheduling By Week</a
>
</div>
<div>
<a
class="underline"
Expand All @@ -40,6 +47,14 @@ const description = `User page for user ID: ${id}`;
>Sessions By Car Class</a
>
</div>
<div>
<a
class="underline"
rel="prefetch"
href=`/Stat-N-Track/user/${id}/subsessions/by-track`
>Sessions By Track</a
>
</div>
<div>
<a
class="underline"
Expand Down
194 changes: 194 additions & 0 deletions src/pages/user/[id]/scheduling/by-week/[timestamp].astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
---
import { db, eq, User, Car, CarClass, Season } from "astro:db";
import DefaultLayout from "$lib/layouts/default.astro";
import generateSeasonWeeks from "$lib/utils/generate-season-weeks";
import determineStartOfWeekForDateString from "$lib/utils/determine-start-of-week-for-date-string";
export async function getStaticPaths() {
const userIds = await db.selectDistinct({ id: User.cust_id }).from(User);
const seasonsFromDb = await db.select().from(Season);
const seasons = seasonsFromDb as Array<{
schedules: Array<{ start_date: string }>;
}>;
const weeks = generateSeasonWeeks({ seasons });
return userIds
.map(({ id }) => {
return Object.keys(weeks).map((weekStart) => ({
params: { id, timestamp: String(Number(new Date(weekStart))) },
}));
})
.flat();
}
const { id, timestamp } = Astro.params;
const [user] = await db
.select({
carPackages: User.car_packages,
trackPackages: User.track_packages,
})
.from(User)
.where(eq(User.cust_id, id));
const { carPackages, trackPackages } = user;
const carIds = Array.isArray(carPackages)
? carPackages.map((carPackage) => carPackage.content_ids).flat()
: [];
const trackIds = Array.isArray(trackPackages)
? trackPackages.map((trackPackage) => trackPackage.content_ids).flat()
: [];
const cars = await db.select().from(Car);
const carsMap = new Map();
cars.forEach((car) => {
const { car_id } = car;
carsMap.set(car_id, car);
});
// @todo Improve this query to not have to do this
const carClassesResults = await db
.select({
carClassId: CarClass.car_class_id,
carsInClass: CarClass.cars_in_class,
})
.from(CarClass);
const carClassIdsForCarIds = carClassesResults
.filter((result: any) =>
result.carsInClass.some((v: any) => carIds.includes(v.car_id))
)
.map((result) => result.carClassId);
// End comment of previous todo
const carClasses = await db.select().from(CarClass);
const carClassesMap = new Map();
carClasses.forEach((carClass) => {
const { car_class_id, cars_in_class } = carClass;
const carsInClass = Array.isArray(cars_in_class)
? cars_in_class.map((carInClass) => carsMap.get(carInClass.car_id))
: [];
carClassesMap.set(car_class_id, { ...carClass, cars_in_class: carsInClass });
});
const carClassIdSet = new Set(carClassIdsForCarIds);
const trackIdSet = new Set(trackIds);
const licenseGroupToNameMap: Record<string, string> = {
"1": "Rookie",
"2": "Class D",
"3": "Class C",
"4": "Class B",
"5": "Class A",
};
const seasons = await db.select().from(Season);
const schedulesForWeek = seasons.reduce(
(array: Array<Record<string, unknown>>, season) => {
const { schedules, ...rest } = season;
if (Array.isArray(schedules)) {
const scheduleForWeek = schedules.find(
(schedule) =>
Number(
new Date(
String(
Object.keys(
determineStartOfWeekForDateString({
object: {},
dateString: schedule.start_date,
})
).pop()
)
)
) === Number(timestamp)
);
if (scheduleForWeek) {
const ownTrack = trackIdSet.has(scheduleForWeek.track.track_id);
const ownCar = () => {
if (scheduleForWeek.race_week_cars?.length) {
return Boolean(
scheduleForWeek.race_week_cars.filter((car: { car_id: Number }) =>
carIds.includes(car.car_id)
).length
);
}
const ownedCarClasses = Array.isArray(rest.car_class_ids)
? rest.car_class_ids.filter((carClassId) =>
carClassIdSet.has(carClassId)
)
: [];
return Boolean(ownedCarClasses.length);
};
array.push({
Season_Name: rest.season_name,
Track_Name:
`${scheduleForWeek.track.track_name} ${scheduleForWeek.track.config_name || ""}`.trim(),
Own_Car: ownCar() ? "Yes" : "No",
Own_Track: ownTrack ? "Yes" : "No",
Schedule_Description: rest.schedule_description,
License_Level: licenseGroupToNameMap[String(rest.license_group)],
});
}
}
return array;
},
[]
);
const title = `Scheduling By Week - ${id} and week starting ${new Date(Number(timestamp)).toUTCString()}`;
const description = title;
---

<DefaultLayout {title} {description}>
<div class="grid grid-cols-1 pt-6 overflow-x-scroll">
<div class="text-center col-span-1 text-2xl pb-6">
<p>Week Starts</p>
<p>
{
new Date(Number(timestamp)).toLocaleString("en-US", {
timeZone: "America/Chicago",
})
}
</p>
<p>This is: {new Date(Number(timestamp)).toUTCString()}</p>
<p>This is considered "even" with the alternating hour being "odd"</p>
</div>
<table x-ref="Table" x-data="table" class="text-center col-span-1">
<tr x-ref="Headings"
>{
Object.keys(schedulesForWeek[0]).map((key) => (
<th
id={`Table ${key} ${schedulesForWeek.length}`}
class="border-2"
x-on:click="sort"
>
{key.replace("_", " ")}
</th>
))
}</tr
>
{
schedulesForWeek.map((result, rowNumber) =>
result.Own_Track === "Yes" && result.Own_Car === "Yes" ? (
<tr class="bg-green-950" x-ref={`Table ${rowNumber}`}>
{Object.keys(result).map((key: string) => (
<td
x-ref={`Table ${key} ${rowNumber}`}
id={`${key}~${rowNumber}~${result[key]}`}
class="border-2"
>
{result[key]}
</td>
))}
</tr>
) : (
<tr class="bg-red-950" x-ref={`Table ${rowNumber}`}>
{Object.keys(result).map((key: string) => (
<td
x-ref={`Table ${key} ${rowNumber}`}
id={`${key}~${rowNumber}~${result[key]}`}
class="border-2"
>
{result[key]}
</td>
))}
</tr>
)
)
}
</table>
</div>
<script>
import Alpine from "alpinejs";
import Table from "$lib/components/table/index.ts";
Alpine.data("table", Table);
Alpine.start();
</script>
</DefaultLayout>
21 changes: 21 additions & 0 deletions src/pages/user/[id]/scheduling/by-week/index.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
import { db, User, Season } from "astro:db";
import DefaultLayout from "$lib/layouts/default.astro";
import generateSeasonWeeks from "$lib/utils/generate-season-weeks";
export async function getStaticPaths() {
const userIds = await db.selectDistinct({ id: User.cust_id }).from(User);
return userIds.map(({ id }) => ({ params: { id } }));
}
const { id } = Astro.params;
const seasonsFromDb = await db.select().from(Season);
const seasons = seasonsFromDb as Array<{ schedules: Array<{ start_date: string }> }>;
const weeks = generateSeasonWeeks({ seasons });
const title = `Scheduling By Week - ${id}`;
const description = `Scheduling by week page for user ID: ${id}`;
---

<DefaultLayout {title} {description}>
<div class="text-center text-3xl">
{Object.keys(weeks).map((week) => (<div><a class="underline" href=`/Stat-N-Track/user/${id}/scheduling/by-week/${Number(new Date(week))}` rel="prefetch">{new Date(week).toLocaleString("en-US", { timeZone: "America/Chicago" })}</a></div>))}
</div>
</DefaultLayout>
2 changes: 1 addition & 1 deletion src/pages/user/[id]/standings/full-participation.astro
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export function getStaticPaths() {
}
const { id } = Astro.params;
const seoTitle = `Fully Participated Standings - ${id}`;
const seoDescription = `Fully partipacipated standings page for user ID: ${id}`;
const seoDescription = `Fully participated standings page for user ID: ${id}`;
const standingsResults = await db
.select()
.from(Standing)
Expand Down
Loading

0 comments on commit 6a10546

Please sign in to comment.