Store a list of ids of events and slots that accounts have marked as being interested in, and show aggeregate counts in the schedule.
214 lines
5.4 KiB
TypeScript
214 lines
5.4 KiB
TypeScript
import { Account } from "~/shared/types/account";
|
|
import { Schedule, TimeSlot } from "~/shared/types/schedule";
|
|
|
|
const locations = [
|
|
{
|
|
name: "Stage",
|
|
description: "Inside the main building."
|
|
},
|
|
{
|
|
name: "Clubhouse",
|
|
description: "That big red building in the middle of the park."
|
|
},
|
|
{
|
|
name: "Summerhouse",
|
|
description: "Next to the campfire by the lake"
|
|
},
|
|
{
|
|
name: "Campfire",
|
|
description: "Next to the big tree by the lake."
|
|
},
|
|
{
|
|
name: "Outside",
|
|
description: "Takes place somewhere outside."
|
|
}
|
|
]
|
|
|
|
const events = [
|
|
{
|
|
name: "Arcade",
|
|
description: "Play retro games!",
|
|
slots: [
|
|
"d1 12:00 4h clubhouse",
|
|
"d2 12:00 4h clubhouse",
|
|
"d3 12:00 4h clubhouse",
|
|
]
|
|
},
|
|
{
|
|
name: "Bonfire Stories",
|
|
description: "Share your stories as we sit cosily around the campfire.",
|
|
slots: ["d2 18:00 2h campfire"]
|
|
},
|
|
{ name: "DJ Alpha", slots: ["d2 20:00 2h stage"] },
|
|
{ name: "DJ Bravo", slots: ["d3 20:00 2h stage"] },
|
|
{ name: "DJ Charlie", slots: ["d3 22:00 2h stage"] },
|
|
{
|
|
name: "Fursuit Games",
|
|
description: "Playful time for the suiters.",
|
|
slots: ["d4 18:00 2h clubhouse"],
|
|
},
|
|
{ name: "Fishing Trip", slots: ["d3 12:00 3h30m outside"]},
|
|
{ name: "Opening", slots: ["d1 18:30 1h30m stage"]},
|
|
{ name: "Closing", slots: ["d5 16:00 1h stage"]},
|
|
{
|
|
name: "Board Games",
|
|
slots: [
|
|
"d1 12:00 4h summerhouse",
|
|
"d2 12:00 4h summerhouse",
|
|
"d3 12:00 4h summerhouse",
|
|
"d4 12:00 4h summerhouse",
|
|
]
|
|
},
|
|
{ name: "📷meet", slots: ["d3 19:00 1h10m summerhouse"]},
|
|
{
|
|
name: "Karaoke",
|
|
slots: [
|
|
"d3 21:00 2h clubhouse",
|
|
"d4 21:00 2h clubhouse",
|
|
],
|
|
},
|
|
{ name: "Dance", slots: ["d1 20:00 3h stage"]},
|
|
{ name: "Charity Auction", slots: ["d4 13:00 2h stage"]},
|
|
{ name: "Tournament", slots: ["d2 17:00 2h stage"]},
|
|
{ name: "Canoe Trip", slots: ["d4 11:00 4h30m outside"]},
|
|
{
|
|
name: "Dinner",
|
|
slots: [
|
|
"d1 16:00 1h campfire",
|
|
"d2 16:00 1h campfire",
|
|
"d3 16:00 1h campfire",
|
|
"d4 16:00 1h campfire",
|
|
],
|
|
},
|
|
{ name: "Film Night", slots: ["d4 21:00 2h stage"]},
|
|
{ name: "Photo", slots: ["d3 18:00 45m stage"]},
|
|
{ name: "Artist Alley", slots: ["d4 12:00 4h clubhouse"]},
|
|
{ name: "Feedback Panel", slots: ["d5 18:00 4h clubhouse"]},
|
|
];
|
|
|
|
function toId(name: string) {
|
|
return name.toLowerCase().replace(/ /g, "-");
|
|
}
|
|
|
|
function toIso(date: Date) {
|
|
return date.toISOString().replace(":00.000Z", "Z");
|
|
}
|
|
|
|
function toSlot(origin: Date, id: string, shorthand: string, index: number): TimeSlot {
|
|
const [day, start, duration, location] = shorthand.split(" ");
|
|
const [startHours, startMinutes] = start.split(":").map(time => parseInt(time, 10));
|
|
const dayNumber = parseInt(day.slice(1));
|
|
|
|
const startDate = new Date(origin);
|
|
startDate.setUTCDate(startDate.getUTCDate() + dayNumber);
|
|
startDate.setUTCHours(startDate.getUTCHours() + startHours);
|
|
startDate.setUTCMinutes(startDate.getUTCMinutes() + startMinutes);
|
|
|
|
const [_, durationHours, durationMinutes] = /(?:(\d+)h)?(?:(\d+)m)?/.exec(duration)!;
|
|
const durationTotal = parseInt(durationHours ?? "0") * 60 + parseInt(durationMinutes ?? "0")
|
|
const endDate = new Date(startDate.getTime() + durationTotal * 60e3);
|
|
|
|
return {
|
|
id: `${id}-${index}`,
|
|
start: toIso(startDate),
|
|
end: toIso(endDate),
|
|
locations: [location],
|
|
};
|
|
}
|
|
|
|
export function generateDemoSchedule(): Schedule {
|
|
const origin = new Date();
|
|
const utcOffset = 1;
|
|
origin.setUTCDate(origin.getUTCDate() - origin.getUTCDay() + 1); // Go to Monday
|
|
origin.setUTCHours(utcOffset);
|
|
origin.setUTCMinutes(0);
|
|
origin.setUTCSeconds(0);
|
|
origin.setUTCMilliseconds(0);
|
|
|
|
return {
|
|
events: events.map(
|
|
({ name, description, slots }) => ({
|
|
id: toId(name),
|
|
name,
|
|
description,
|
|
slots: slots.map((shorthand, index) => toSlot(origin, toId(name), shorthand, index))
|
|
})
|
|
),
|
|
locations: locations.map(
|
|
({ name, description }) => ({ id: toId(name), name, description })
|
|
),
|
|
};
|
|
}
|
|
|
|
const names = [
|
|
"Leo", "Lisa",
|
|
"Jack", "Emily",
|
|
"Roy", "Sofia",
|
|
"Adam", "Eve",
|
|
"Max", "Rose",
|
|
"Hugo", "Maria",
|
|
"David", "Zoe",
|
|
"Hunter", "Ria",
|
|
"Sonny", "Amy",
|
|
"Kai", "Megan",
|
|
"Toby", "Katie",
|
|
"Bob", "Lucy",
|
|
];
|
|
|
|
// MINSTD random implementation for reproducible random numbers.
|
|
let seed = 1;
|
|
function random() {
|
|
const a = 48271;
|
|
const c = 0;
|
|
const m = 2 ** 31 -1;
|
|
return (seed = (a * seed + c) % m | 0) / 2 ** 31;
|
|
}
|
|
|
|
export function generateDemoAccounts(): Account[] {
|
|
seed = 1;
|
|
const accounts: Account[] = [];
|
|
|
|
for (const name of names) {
|
|
accounts.push({
|
|
id: accounts.length,
|
|
name,
|
|
type: (["regular", "crew", "admin"] as const)[Math.floor(random() ** 5 * 3)],
|
|
});
|
|
}
|
|
|
|
// These have a much higher probability of being in someone's interested list.
|
|
const desiredEvent = ["opening", "closing", "fursuit-games"];
|
|
|
|
for (const account of accounts) {
|
|
const interestedIds: string[] = [];
|
|
for (const id of desiredEvent) {
|
|
if (random() < 0.5) {
|
|
interestedIds.push(id);
|
|
}
|
|
}
|
|
|
|
const eventsToAdd = Math.floor(random() * 10);
|
|
while (interestedIds.length < eventsToAdd) {
|
|
const event = events[Math.floor(random() * events.length)];
|
|
const eventId = toId(event.name);
|
|
if (interestedIds.some(id => id.replace(/-\d+$/, "") === eventId)) {
|
|
continue;
|
|
}
|
|
|
|
if (event.slots.length === 1 || random() < 0.8) {
|
|
interestedIds.push(toId(event.name))
|
|
} else {
|
|
for (const index of event.slots.map((_, index) => index)) {
|
|
if (random() < 0.5) {
|
|
interestedIds.push(toId(`${toId(event.name)}-${index}`));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (interestedIds.length) {
|
|
account.interestedIds = interestedIds;
|
|
}
|
|
}
|
|
return accounts;
|
|
}
|