User:Xymph/AreaRecords2Wiki.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.
This code will be executed when previewing this page.
This user script seems to have a documentation page at User:Xymph/AreaRecords2Wiki.
// run this script in the JavaScript console (F12, Console) while on https://www.wikidata.org/robots.txt
// adapted from [[User:Habst/WorldAthletics2Wiki.js]]
// event name as spelled on https://worldathletics.org/records/by-category/world-records
EVENT = 'Pole Vault';
// include WR row above ARs?
WRROW = true;
// World, Africa, Asia, Europe, NACAC, Oceania, South America
Areas = [1, 10, 11, 12, 13, 14, 15];
// events that include a Wind column
windEvt = ['100 Metres', '200 Metres', '100 Metres Hurdles', '110 Metres Hurdles', 'Long Jump', 'Triple Jump'];
incWind = windEvt.includes(EVENT);
// events affecting output columns
isRelay = EVENT.includes(' Relay');
isMixed = EVENT.includes(' Mixed');
isThrow = EVENT.includes(' Throw');
// column header for field marks
markHdr = 'Mark';
// column header for track times
runEvt = ['Metres', 'Kilometres', 'Mile', 'Marathon'];
// add unit (s) for short track events
shortEvt = ['60 Metres', '100 Metres', '110 Metres', '200 Metres', '400 Metres', '4x100 Metres'];
for (const evt of runEvt)
if (EVENT.search(evt) > -1) {
markHdr = 'Time';
for (const evt of shortEvt)
if (EVENT.search(evt) === 0) {
markHdr += '<br>(s)';
break;
}
break;
}
// column header for combined events scores
if (EVENT.search('athlon') > -1)
markHdr = 'Score';
// both genders present?
bothGndr = !isMixed && !EVENT.includes('Pentathlon') && !EVENT.includes('Heptathlon') && EVENT.search(/1[01]0 Metres Hurdles/) == -1 && EVENT.search(/[35]000 Metres Race Walk Short Track/) == -1;
// collect record lists via API
window.data ??= {};
window.cache ??= {};
(async () => {
for (const area of Areas)
window.data[area] ??= await (await fetch("https://graphql-prod-4875.edge.aws.worldathletics.org/graphql", {
"headers": {
"x-api-key": "da2-jkcja3ykujbf3cz64fs7w5gl6m" // note API key is intentionally public
},
"body": JSON.stringify({
"operationName": "getRecordsDetailByCategory",
"variables": {
"categoryId": area,
},
"query": `query getRecordsDetailByCategory($categoryId: Int!) {
getRecordsDetailByCategory(categoryId: $categoryId) {
gender
results {
country
competitor {
name
country
birthDate
urlSlug
iaafId
hasProfile
id
teamMembers {
name
country
birthDate
urlSlug
iaafId
hasProfile
id
__typename
}
__typename
}
discipline
date
performance
typeNameUrlSlug
venue
wind
disciplineNameUrlSlug
progressionListId
pending
equal
womenOnly
mixed
yard
setIndoor
__typename
}
__typename
}
}`
}),
"method": "POST",
})).json();
//console.log(window.data[10].data.getRecordsDetailByCategory);
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(`https://xtools.wmcloud.org/api/page/articleinfo/en.wikipedia.org/${name.replace('|', '')}?format=json&uselang=en`);
return enLabelTitleMatch.status === 200;
};
getSuffix = async (name, evt, year) => {
const el = evt?.toLowerCase() ?? '';
const parens = evt?.includes('mH') || el.includes('metres hurdles') ? 'hurdler' : el.includes('high jump') ? 'high jumper' : el.includes('long jump') ? 'long jumper' : el.includes('pole vault') ? 'pole vaulter' : 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('steeplechase') ? 'steeplechase runner' : ['60m', '60 m', '100m', '100 m', '200m', '200 m', '400m', '400 m'].some(d => el.includes(d)) ? 'sprinter' : 'runner';
name += ` (${parens})`;
if (await titleExists(name)) name = name.replace(`(${parens})`, `(${parens}, born ${year})`);
return name;
};
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 = await getSuffix(enLabel, evt, year);
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}|qid=${qid}|s=1${enLabel.includes('(') ? `|lt=${enLabelNoParens}` : ''}}}`;
return cache[id];
}
if (await titleExists(name)) name = await getSuffix(name, evt, year);
cache[id] = `[[${name}${name.includes('(') ? '|' : ''}]]`;
return cache[id];
};
const windFmt = (wind) => {
if (!wind) return '';
if (wind === '0.0') return '±'+wind;
if (wind.at(0) === '-') return '−'+wind.slice(1);
if (wind.at(0) === '+') return wind;
return '+'+wind;
};
addResult = async (res, theWR) => {
const name = res.competitor.name;
const nation = (res.country === 'GBR' && isRelay) ? 'GBN' : (res.country === 'BRN' ? 'BHR' : res.country);
const dob = new Date(res.competitor.birthDate);
const id = res.competitor.urlSlug?.split('-').at(-1).replace(/^0/, '');
let out = "| '''" + (markHdr == 'Mark' ? (isThrow ? '{{T&FcalcR|' : '{{T&Fcalc|') + res.performance + '}}' : res.performance) + "'''";
if ((res.setIndoor || res.venue.includes(' (i)')) && !EVENT.includes('Short Track')) out += ' {{AthAbbr|i}}';
if (res.mixed) out += ' {{AthAbbr|Mx}}';
if (!WRROW && res.performance == theWR) out += " '''{{AthAbbr|WR}}'''";
if (incWind) out += ' || ' + windFmt(res.wind);
out += ' || ' + res.date.slice(-4);
// out += ' || {{flagathlete|[[' + res.competitor.name + ']]|' + nation + '}}';
out += ' || ' + (isRelay
? (await Promise.all(res.competitor.teamMembers.map(async tm => await getTitle(tm.id, tm.name, EVENT)))).join(', ') + ' || {{' + nation + '}}'
: '{{flagathlete|' + await getTitle(id, name, EVENT, dob.getFullYear()) + '|' + nation + '}}');
out += "\n";
return out;
}
// build table headers
let out = '{{Table alignment}}\n{| class="wikitable defaultleft col3center';
if (incWind)
out += ' col4center';
if (bothGndr) {
if (incWind)
out += ' col7center col8center';
else
if (isRelay)
out += ' col7center';
else
out += ' col6center';
}
out += '"\n';
if (!bothGndr) {
out += '|-\n!scope="col"| Area\n';
} else {
out += '|-\n!scope="rowgroup" rowspan=2| Area\n!scope="colgroup" colspan=' + (incWind || isRelay ? 4 : 3) + '| Men\n!scope="colgroup" colspan=' + (incWind || isRelay ? 4 : 3) + '| Women\n|-\n';
out += '!scope="col"| '+markHdr+'\n';
if (incWind) out += '!scope="col"| Wind<br>(m/s)\n';
out += '!scope="col"| Season\n';
out += '!scope="col"| Athlete' + (isRelay ? 's' : '') + '\n';
if (isRelay) out += '!scope="col"| Team\n';
}
out += '!scope="col"| '+markHdr+'\n';
if (incWind) out += '!scope="col"| Wind<br>(m/s)\n';
out += '!scope="col"| Season\n';
out += '!scope="col"| Athlete' + (isRelay ? 's' : '') + '\n';
if (isRelay) out += '!scope="col"| Team\n';
let areaCols = bothGndr ? (incWind || isRelay ? 9 : 7) : (incWind || isRelay ? 5 : 4);
// collect WRs and add table rows
let menWR = '';
let womWR = '';
let mixWR = '';
for (const area of Areas) {
menRes = window.data[area].data.getRecordsDetailByCategory[1].results.findLast(et => et.discipline === EVENT);
womRes = window.data[area].data.getRecordsDetailByCategory[0].results.findLast(et => et.discipline === EVENT);
if (isMixed)
mixRes = window.data[area].data.getRecordsDetailByCategory[2].results.findLast(et => et.discipline === EVENT);
if (area == 1) {
if (menRes) menWR = menRes.performance;
if (womRes) womWR = womRes.performance;
if (isMixed && mixRes) mixWR = mixRes.performance;
if (!WRROW) continue;
}
out += '|-\n!scope="row"| ';
switch (area) {
case 1:
out += "[[List of world records in athletics|World]]\n";
break;
case 10:
out += "[[Confederation of African Athletics|Africa]] {{small|(''[[List of African records in athletics|records]]'')}}\n";
break;
case 11:
out += "[[Asian Athletics|Asia]] {{small|(''[[List of Asian records in athletics|records]]'')}}\n";
break;
case 12:
out += "[[European Athletic Association|Europe]] {{small|(''[[List of European records in athletics|records]]'')}}\n";
break;
case 13:
out += "[[North American, Central American and Caribbean Athletic Association|North, Central America<br>and Caribbean]] {{small|(''[[List of North, Central American and Caribbean records in athletics|records]]'')}}\n";
break;
case 14:
out += "[[Oceania Athletics Association|Oceania]] {{small|(''[[List of Oceanian records in athletics|records]]'')}}\n";
break;
case 15:
out += "[[South American Athletics|South America]] {{small|(''[[List of South American records in athletics|records]]'')}}\n";
break;
}
if (!isMixed && menRes) out += await addResult(menRes, menWR);
if (!isMixed && womRes) out += await addResult(womRes, womWR);
if (isMixed && mixRes) out += await addResult(mixRes, mixWR);
if (WRROW && area == 1)
out += '|-\n!colspan=' + areaCols + '| Area records\n';
}
out += '|}';
console.log(out);
return out;
})();