Skip to content

Commit

Permalink
Merge pull request #23 from johnsyweb/paj/juniors
Browse files Browse the repository at this point in the history
junior parkrun support
  • Loading branch information
johnsyweb authored Oct 20, 2024
2 parents c835f01 + d635dc5 commit c4f39e5
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 22 deletions.
38 changes: 25 additions & 13 deletions src/extractors/ResultsPageExtractor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,18 @@ export class ResultsPageExtractor {

constructor(resultsPageDocument: Document) {
this.resultsPageDocument = resultsPageDocument;
this.eventName =
resultsPageDocument.querySelector(".Results-header > h1")?.textContent ??
undefined;
this.courseLength = this.eventName?.includes("junior parkrun") ? 2 : 5;

const rowElements: NodeListOf<HTMLElement> =
resultsPageDocument.querySelectorAll(".Results-table-row");

this.finishers = Array.from(rowElements).map(
(d) =>
new Finisher(
d.dataset.name,
this.removeSurenameFromJunior(d.dataset.name),
d.dataset.agegroup,
d.dataset.club,
d.dataset.gender,
Expand All @@ -41,25 +45,20 @@ export class ResultsPageExtractor {
undefined,
athleteIDFromURI(
(d.querySelector(".Results-table-td--name a") as HTMLAnchorElement)
?.href,
),
),
?.href
)
)
);

this.populateVolunteerData();

this.eventName =
resultsPageDocument.querySelector(".Results-header > h1")?.textContent ||
undefined;

this.courseLength = this.eventName?.includes("junior parkrun") ? 2 : 5;
this.eventDate =
resultsPageDocument.querySelector(".format-date")?.textContent ??
undefined;

this.eventNumber =
resultsPageDocument.querySelector(
".Results-header > h3 > span:last-child",
".Results-header > h3 > span:last-child"
)?.textContent || undefined;

this.unknowns = this.finishers
Expand All @@ -79,7 +78,7 @@ export class ResultsPageExtractor {
.map((p) => `${p.name} (${p.time})`);

this.runningWalkingGroups = Array.from(
new Set(this.finishers.map((p) => p?.club || "").filter((c) => c !== "")),
new Set(this.finishers.map((p) => p?.club || "").filter((c) => c !== ""))
);

const statElements: NodeListOf<HTMLDivElement> =
Expand Down Expand Up @@ -116,10 +115,23 @@ export class ResultsPageExtractor {

private volunteerElements(): NodeListOf<HTMLAnchorElement> | [] {
return this.resultsPageDocument.querySelectorAll(
".Results + div h3:first-of-type + p:first-of-type a",
".Results + div h3:first-of-type + p:first-of-type a"
);
}

removeSurenameFromJunior(name?: string): string {
if (!name || this.courseLength == 5) {
return name ?? "";
} else {
const parts = name.split(" ");
if (parts.length === 2) {
return parts[0];
}
}

return name.replace(/[-' A-Z]+$/, "");
}

private populateVolunteerData() {
this.volunteerElements().forEach((v) => {
const athleteID = athleteIDFromURI(v.href);
Expand All @@ -142,7 +154,7 @@ export class ResultsPageExtractor {
volunteersList(): Volunteer[] {
return Array.from(this.volunteerElements()).map((v) => {
return {
name: v.innerText,
name: this.removeSurenameFromJunior(v.innerText),
link: v.href,
athleteID: Number(v.dataset.athleteid),
agegroup: v.dataset.agegroup,
Expand Down
2 changes: 1 addition & 1 deletion src/extractors/VolunteerPageExtractor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ export class VolunteerPageExtractor {
agegroup: string;

constructor(doc: Document) {
const ageGroupData: string = doc.querySelector("h3 + p")?.textContent ?? "";
const ageGroupData: string = doc.querySelector("#content > p:last-of-type")?.textContent ?? "";

this.vols = Number(
doc.querySelector("h3#volunteer-summary + table tfoot td:last-child")
Expand Down
13 changes: 9 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { conjoin, pluralize, sortAndConjoin } from "./stringFunctions";
import { deleteParagraph, upsertParagraph } from "./dom/upsertParagraph";
import { fiveKFinishersToMilestones } from "./transformers/fiveKFinishersToMilestones";
import { fiveKVolunteersToMilestones } from "./transformers/fiveKVolunteersToMilestones";
import { MilestonePresenter } from "./presenters/MilestonePresenter";
import { ResultsPageExtractor } from "./extractors/ResultsPageExtractor";
import { deleteParagraph, upsertParagraph } from "./dom/upsertParagraph";
import { twoKFinishersToMilestones } from "./transformers/twoKFinishersToMilestone";
import { twoKVolunteersToMilestones } from "./transformers/twoKVolunteersToMilestones";
import { VolunteerWithCount } from "./types/Volunteer";

function populate(
Expand Down Expand Up @@ -32,7 +34,7 @@ function populate(
)} who improved their personal best this week: `;

const runningWalkingGroupsTitle = `We were pleased to see ${pluralize(
"active group",
"at least one active group",
"walking and running groups",
rpe.runningWalkingGroups.length
)} represented at this event: `;
Expand All @@ -45,11 +47,14 @@ function populate(
rpe.eventName
} this weekend. Our deep thanks to: `;

const finisherMilestoneCelebrations =
rpe.courseLength == 2
? [...twoKVolunteersToMilestones(volunteerWithCountList), ...twoKFinishersToMilestones(rpe.finishers)]
: fiveKFinishersToMilestones(rpe.finishers);
const milestoneCelebrations = [
...fiveKVolunteersToMilestones(volunteerWithCountList),
...fiveKFinishersToMilestones(rpe.finishers),
...finisherMilestoneCelebrations,
];

const milestonePresenter = new MilestonePresenter(milestoneCelebrations);

const facts =
Expand Down
2 changes: 1 addition & 1 deletion src/presenters/MilestonePresenter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export class MilestonePresenter {
"parkrunner",
"parkrunners",
this._milestoneCelebrationsAll.length,
)} who earned themselves a new parkrun club shirt this weekend:\n`;
)} who joined a new parkrun milestone club this weekend:\n`;
}

details(): string {
Expand Down
6 changes: 3 additions & 3 deletions src/transformers/fiveKVolunteersToMilestones.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
import { VolunteerWithCount } from "../types/Volunteer";

export function fiveKVolunteersToMilestones(
volunteers: VolunteerWithCount[],
volunteers: VolunteerWithCount[]
): MilestoneCelebrations[] {
const milestones: Record<number, MilestoneDefinition> = {
10: { icon: "🤍", restricted_age: "J" },
Expand All @@ -24,9 +24,9 @@ export function fiveKVolunteersToMilestones(
const names: string[] = volunteers
.filter(
(v) =>
Number(v.vols) === Number(n) &&
v.vols === Number(n) &&
(!milestone.restricted_age ||
v.agegroup?.startsWith(milestone.restricted_age)),
v.agegroup?.startsWith(milestone.restricted_age))
)
.map((v) => v.name);

Expand Down
43 changes: 43 additions & 0 deletions src/transformers/twoKFinishersToMilestone.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { IFinisher } from "../types/Finisher";
import { MilestoneCelebrations } from "../types/Milestones";

export interface JuniorMilestoneDefinition {
restricted_age?: string;
icon: string;
name: string;
}

export function twoKFinishersToMilestones(
finishers: IFinisher[]
): MilestoneCelebrations[] {
const milestones: Record<number, JuniorMilestoneDefinition> = {
11: { icon: "🟦", restricted_age: "J", name: "Half marathon" },
21: { icon: "🟩", restricted_age: "J", name: "Marathon" },
50: { icon: "🟧", restricted_age: "J", name: "Ultra marathon" },
100: { icon: "⬜", restricted_age: "J", name: "junior parkrun 100" },
250: { icon: "🟨", restricted_age: "J", name: "junior parkrun 250" },
};

const milestoneCelebrations: MilestoneCelebrations[] = [];

for (const n in milestones) {
const milestone: JuniorMilestoneDefinition = milestones[n];
const names: string[] = finishers
.filter(
(f) =>
Number(f.runs) === Number(n) &&
(!milestone.restricted_age ||
f.agegroup?.startsWith(milestone.restricted_age))
)
.map((f) => f.name);

if (names.length > 0) {
milestoneCelebrations.push({
clubName: milestone.name,
icon: milestone.icon,
names,
});
}
}
return milestoneCelebrations;
}
20 changes: 20 additions & 0 deletions src/transformers/twoKVolunteersToMilestones.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { MilestoneCelebrations } from "../types/Milestones";
import { VolunteerWithCount } from "../types/Volunteer";

export function twoKVolunteersToMilestones(
volunteers: VolunteerWithCount[]
): MilestoneCelebrations[] {
const names = volunteers
.filter((v) => v.vols === 5 && v.agegroup?.startsWith("J"))
.map((v) => v.name);

return names.length
? [
{
clubName: "junior parkrun v5",
icon: "💟",
names,
},
]
: [];
}
5 changes: 5 additions & 0 deletions style/eventuate.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,8 @@
background: lightgoldenrodyellow;
padding: 12px;
}

#eventuate #message {
color: lightcoral;
font-weight: bold;
}

0 comments on commit c4f39e5

Please sign in to comment.