diff --git a/app/routes/events-team_.events-breakdown.tsx b/app/routes/events-team_.events-breakdown.tsx new file mode 100644 index 0000000..766b913 --- /dev/null +++ b/app/routes/events-team_.events-breakdown.tsx @@ -0,0 +1,146 @@ +import { + Container, + Heading, + Table, + TableCaption, + TableContainer, + Tbody, + Td, + Th, + Thead, + Tr, +} from "@chakra-ui/react"; +import { useLoaderData } from "@remix-run/react"; + +export async function loader({ context }: { context: RequestContext }) { + const { current_user: user } = context.data; + + if (!user) + throw new Response(null, { + status: 401, + }); + + if (![1 << 4, 1 << 12].find((p) => user.permissions & p)) + throw new Response(null, { + status: 403, + }); + + const memberResults = await context.env.D1.prepare( + "SELECT id, name FROM et_members;", + ).all(); + + if (!memberResults.success) + throw new Response(null, { + status: 500, + }); + + const pointData: { + [k: string]: { + [p: string]: number; + }; + } = {}; + + const nameData: { + [k: string]: { + name: string; + }; + } = {}; + + for (const row of memberResults.results) + nameData[row.id as string] = { name: row.name as string }; + + const eventsResult = await context.env.D1.prepare( + "SELECT answered_at, created_by, day, month, performed_at, reached_minimum_player_count, type, year FROM events;", + ).all(); + + if (!eventsResult.success) + throw new Response(null, { + status: 500, + }); + + for (const row of eventsResult.results) { + const creator = row.created_by as string; + const type = row.type as string; + + if (!pointData[creator]) continue; + + if (row.performed_at) pointData[creator][type as string] += 10; + else { + const now = new Date(); + const currentYear = now.getUTCFullYear(); + const currentMonth = now.getUTCMonth() + 1; + const currentDay = now.getUTCDate(); + + if ( + (row.year as number) < currentYear || + (currentYear === row.year && currentMonth > (row.month as number)) || + (currentMonth === row.month && + currentYear === row.year && + (row.day as number) < currentDay) + ) + pointData[creator][type] -= 5; + } + + switch (row.type) { + case "gamenight": + if (row.reached_minimum_player_count) + pointData[creator].gamenight += 10; + + break; + + case "rotw": + if ( + (row.answered_at as number) - (row.performed_at as number) >= + 86400000 + ) + pointData[creator].rotw += 10; + + break; + + default: + break; + } + } + + return Object.assign(pointData, nameData); +} + +export default function () { + const data = useLoaderData(); + + return ( + + Points Breakdown + + + + Total points breakdown by event type. This does not include + deductions from strikes. + + + + + + + + + + + + + {Object.entries(data).map(([k, v]) => ( + + + + + + + + + ))} + +
Discord IDNameFoTD PointsGamenight PointsQoTD PointsRoTW Points
{k}{v.name}{v.fotd}{v.gamenight}{v.qotd}{v.rotw}
+
+
+ ); +}