User:Habst/WorldAthletics2Medalists.js
Appearance
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
Documentation for this user script can be added at User:Habst/WorldAthletics2Medalists. |
window.data ??= {}
for (const day of [1,2])
window.data[day]??=await (await fetch("https://wpgiegzkbrhj5mlsdxnipboepm.appsync-api.eu-west-1.amazonaws.com/graphql", {
"headers": {
"x-api-key": "da2-juounigq4vhkvg5ac47mezxqge" // note API key is intentionally public
},
"body": JSON.stringify({
"operationName": "getCalendarCompetitionResults",
"variables": {
"competitionId": 7176907,
"day": day,
"eventId": null
},
"query": `query getCalendarCompetitionResults($competitionId: Int, $day: Int, $eventId: Int) {
getCalendarCompetitionResults(competitionId: $competitionId, day: $day, eventId: $eventId) {
competition {
dateRange
endDate
name
rankingCategory
startDate
venue
__typename
}
eventTitles {
rankingCategory
eventTitle
events {
event
eventId
gender
isRelay
perResultWind
withWind
summary {
competitor {
teamMembers {
id
name
iaafId
urlSlug
__typename
}
id
name
iaafId
urlSlug
birthDate
__typename
}
mark
nationality
placeInRace
placeInRound
points
raceNumber
records
wind
__typename
}
races {
date
day
race
raceId
raceNumber
results {
competitor {
teamMembers {
id
name
iaafId
urlSlug
__typename
}
id
name
iaafId
urlSlug
birthDate
hasProfile
__typename
}
mark
nationality
place
points
qualified
records
wind
remark
details {
event
eventId
raceNumber
mark
wind
placeInRound
placeInRace
points
overallPoints
placeInRoundByPoints
overallPlaceByPoints
__typename
}
__typename
}
startList {
competitor {
birthDate
country
id
name
urlSlug
__typename
}
order
pb
sb
bib
__typename
}
wind
__typename
}
__typename
}
__typename
}
options {
days {
date
day
__typename
}
events {
gender
id
name
combined
__typename
}
__typename
}
parameters {
competitionId
day
eventId
__typename
}
__typename
}
}`
}),
"method": "POST",
})).json();
window.cache??={};
if (typeof nameFixer === 'undefined') {
const script = Object.assign(document.createElement('script'), { src: 'https://unpkg.com/name-fixer@1.0.0' });
document.body.appendChild(script);
await new Promise(res => script.addEventListener('load', res));
}
titleExists=async (name)=>{
const enLabelTitleMatch = await fetch(pre+'https://en.wikipedia.org/wiki/' + name.replace('|', ''));
return enLabelTitleMatch.status === 200;
}
getTitle=async (id,name,evt='',year)=>{
const words = name.split(' ');
const lnameStart = words.findIndex(w => w.toUpperCase() === w);
const fname = words.slice(0, lnameStart).join(' ');
const lname = words.slice(lnameStart).join(' ');
name = fname + ' ' + nameFixer.nameFixer(lname);
name = name.replace('LI', 'Li').replace('XI', 'Xi');
if (cache[id]) return cache[id];
const pages = await (await fetch('https://www.wikidata.org/w/api.php?' + new URLSearchParams({
action: 'query',
format: 'json',
list: 'search',
srsearch: `haswbstatement:P1146=${id}`,
}))).json();
const qid = pages.query.search[0]?.title;
if (qid) {
const entity = await (await fetch('https://www.wikidata.org/w/api.php?' + new URLSearchParams({
action: 'wbgetentities',
format: 'json',
ids: qid,
}))).json();
const sitelinks = entity.entities[qid].sitelinks;
const enTitle = sitelinks.enwiki?.title;
if (enTitle) {
cache[id] = `[[${enTitle}${enTitle.includes('(') ? '|' : ''}]]`;
return cache[id];
}
let enLabel = entity.entities[qid].labels.en?.value ?? name;
const enLabelNoParens = enLabel;
if (await titleExists(enLabel)) enLabel += ' (athlete)'; // todo awb job?
const otherWikis = Object.keys(sitelinks).filter(key => !key.startsWith('commons') && key.endsWith('wiki'));
if (otherWikis.length) {
const positionals = otherWikis.map(ow => `|${ow.replace('wiki', '')}|${sitelinks[ow].title}`).join('');
cache[id] = `{{ill|${enLabel}${positionals}${enLabel.includes('(') ? `|lt=${enLabelNoParens}` : ''}}}`;
return cache[id];
}
cache[id] = `{{ill|${enLabel}|wd=${qid}|s=1${enLabel.includes('(') ? `|lt=${enLabelNoParens}` : ''}}}`;
return cache[id];
}
if (await titleExists(name)) {
name += ' (athlete)|';
if (await titleExists(name)) {
const el = evt.toLowerCase();
const parens = el.includes('mH') ? 'hurdler' : el.includes('high jump') ? 'high jumper' : el.includes('long jump') ? 'long jumper' : el.includes('triple jump') ? 'triple jumper' : el.includes('shot put') ? 'shot putter' : el.includes('discus') ? 'discus thrower' : el.includes('hammer') ? 'hammer thrower' : el.includes('javelin') ? 'javelin thrower' : el.includes('steeplchase') ? 'steeplechase runner' : 'runner';
name = name.replace('(athlete)', `(${parens})`);
if (await titleExists(name)) name = name.replace(`(${parens})`, `(${parens}, born ${year})`);
}
}
cache[id] = `[[${name}]]`;
return cache[id];
}
mark2secs=(mark, isField = false)=>{
const parts = mark.split(':');
let ret;
if (parts.length === 1) ret = +mark;
else if (parts.length === 2) ret = +parts[0] * 60 + +parts[1];
else ret = +parts[0] * 60 * 60 + +parts[1] * 60 + +parts[2];
if (Number.isNaN(ret)) return isField ? -Infinity : Infinity;
return ret;
}
const medalRows = [];
for (const dayData of Object.values(data))
for (const eventTitle of dayData.data.getCalendarCompetitionResults?.eventTitles ?? []) {
if (![null].includes(eventTitle.eventTitle)) continue;
for (const evt of eventTitle.events) {
const isLastEvt = eventTitle.events.indexOf(evt) === eventTitle.events.length - 1;
const isField = ['jump', 'throw', 'vault', 'discus', 'put'].some(s => evt.event?.toLowerCase().includes(s));
const stages = Object.values(evt.races.reduce((acc, r) => {
acc[r.race] ??= [];
acc[r.race].push(r);
return acc;
}, {}));
for (const stage of stages) {
const isLastStage = stages.indexOf(stage) === stages.length - 1;
const isFinal = stage[0].race === 'Final';
if (!isFinal) continue;
const isMulti = stage.length > 1;
let medalRow = `|-\n| ${evt.event.replace(' indoor', '')}\n`;
const results = stage.flatMap(race => race.results.map(res => ({...res, raceNumber: race.raceNumber}))).sort((a, b) => isField ? mark2secs(b.mark, true) - mark2secs(a.mark, true) : mark2secs(a.mark) - mark2secs(b.mark)).filter((r, i, arr) => r.competitor.teamMembers?.length || arr.findIndex(r2 => r.competitor.urlSlug === r2.competitor.urlSlug) === i);
for (const result of results.slice(0, 3)) {
const pl = ['DNS', 'DNF', 'DQ', 'NM'].includes(result.mark) ? '' : results.indexOf(result) + 1;
const name = result.competitor.name;
const dob = new Date(result.competitor.birthDate);
const id = result.competitor.urlSlug?.split('-').at(-1).replace(/^0/, '');
medalRow += `| ${id ? `{{flagmedalist|${await getTitle(id, name, evt.event, dob.getFullYear())}|${result.nationality}}}` : `{{flagmedalist|${result.competitor.name}|${result.nationality}}}<br>${(await Promise.all(result.competitor.teamMembers.map(async tm => await getTitle(tm.id, tm.name)))).join('<br>')}`} || ${result.mark + (isField && pl ? ' m' : '')}\n`;
}
medalRows.push(medalRow);
}
}
}
let out = '';
for (const gen of [`Men's `, `Women's `]) {
out += `===${gen.replace(`'s `, '')}===\n{| {{MedalistTable|type=Event|columns=2}}\n`;
out += medalRows.filter(row => row.includes(gen)).map(row => row.replace(gen, '')).sort((a, b) => {
const evtOrder = ['100m', '200m', '400m', '800m', '1500m', '5000m', '10,000m', 'Marathon', '110mH', '100mH', '400mH', '3000mSC'].reverse();
const bScore = evtOrder.findIndex(evt => b.includes(evt) && !b.includes('x' + evt));
const aScore = evtOrder.findIndex(evt => a.includes(evt) && !a.includes('x' + evt));
if (bScore === -1 && aScore === -1) return a.localeCompare(b);
return bScore - aScore;
}).join('');
out += '|}\n';
}