Skip to content

Commit

Permalink
Extra TS files
Browse files Browse the repository at this point in the history
  • Loading branch information
marius-mather committed Jun 3, 2024
1 parent 3887626 commit 8533400
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 0 deletions.
97 changes: 97 additions & 0 deletions app/table.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import {JSDOM} from "jsdom";
import {format, parse} from "date-fns";

async function get_page() {
const page = await fetch("https://www.sydney.edu.au/research/facilities/sydney-informatics-hub/workshops-and-training/training-calendar.html", {mode: "no-cors"}).then((response: Response) => {return response.text()!});
const dom = new JSDOM(page);
return dom.window.document;
}

export async function get_table() {
const page = await get_page();
return page.querySelector("table:has(tr)")!;
}

interface EventEntry {
date_text: string;
date: Date;
event_name: string;
duration_format: string
link: string;
duration: number;
}

function parse_duration(duration: string): number {
const duration_pattern = /(\d+(\.\d+)?)\s?h/
const match = duration_pattern.exec(duration)![1];
return parseFloat(match);
}

function parse_row(row: string[]): EventEntry {
const multi_date_pattern = /(\d+)\s?-\s?\d+/
const date_string = row[0].replace(multi_date_pattern, "$1");
const date = parse(date_string, "d MMMM", new Date());
return {
date_text: row[0].trim(),
date: date,
event_name: row[1],
duration_format: row[2],
link: row[3],
duration: parse_duration(row[2]),
}
}

export async function parse_table(drop_past_events: boolean) {
const table = await get_table();
const header = table.querySelector("tr:first-of-type")!;
const headers = Array.from(header.children).map((el) => el.textContent!).map((s) => s.trim());
const rows = Array.from(table.querySelectorAll("tr:not(:first-of-type)")!);
let row_data: EventEntry[] = rows.map((row) => {
return Array.from(row.querySelectorAll("td")).map((el) => {
const link = el.querySelector("a");
if (link !== null) {
return link.href
}
return el.textContent || ""})
}).map((cells) => parse_row(cells)).sort((a, b) => a.date.getTime() - b.date.getTime());
if (drop_past_events) {
row_data = row_data.filter((event) => event.date >= new Date())
}
return {headers, row_data}
}

function event_to_html(event: EventEntry): string {
let link: string;
if (event.link.startsWith("http")) {
link = `<a href="${event.link}">${event.event_name}</a>`;
} else {
link = event.link.trim();
}
return `<b>${event.date_text}</b>: ${link}`
}

export function get_html_entries(events: EventEntry[]) {
const short_events = events.filter((e) => e.duration <= 2).map(event_to_html);
const medium_events = events.filter((e) => (e.duration > 2) && (e.duration <= 4)).map(event_to_html)
const long_events = events.filter((e) => e.duration > 4).map(event_to_html);
return {short_events, medium_events, long_events};
}

export function get_html_full_events(events: EventEntry[]) {
const entries = get_html_entries(events);
let full_html: string = '';
const {short_events, medium_events, long_events} = get_html_entries(events);
if (short_events.length > 0) {
full_html = full_html + `<h4>Short training (2 hours or less)</h4>
${short_events.map((s) => s + "</br>").join("\n")}`;
}
if (medium_events.length > 0) {
full_html = full_html + `<h4>Half-day training (3-4 hours)</h4>
${medium_events.map((s) => s + "</br>").join("\n")} `;
}
if (long_events.length > 0) {
full_html = full_html + `<h4>Full day training (or 2 half-days)</h4>
${long_events.map((s) => s + "</br>").join("\n")}`;
}
return full_html;
}
4 changes: 4 additions & 0 deletions app/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export function arrays_equal(a: any[], b: any[]) {
return a.length === b.length &&
a.every((v, i) => v === b[i]);
}

0 comments on commit 8533400

Please sign in to comment.