-
Notifications
You must be signed in to change notification settings - Fork 0
/
men-women-athletics-ratio.html
116 lines (96 loc) · 3.75 KB
/
men-women-athletics-ratio.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
<!DOCTYPE html>
<html>
<head>
<title>Men vs Women athletic performances</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
</head>
<body>
<canvas id="myChart" width="400" height="200"></canvas>
<script src="https://unpkg.com/chart.js/dist/Chart.min.js"></script>
<script>
load()
.then((data) => {
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
xLabels: data.map(o => o.x),
datasets: [{
label: 'Men-Women perfs',
borderColor: '#00f',
backgroundColor: 'rgba(255, 99, 132, 0.2)',
fill: false,
data: data.map(o => o.y),
}]
},
options: {
responsive: true,
title:{
display: true,
text:'Men Vs Women perfs'
},
tooltips: {
mode: 'x',
intersect: false,
callbacks: {
label(tooltipItem) {
return [
`ratio: ${Math.round(tooltipItem.yLabel*1000)/1000}`,
`men record: ${data[tooltipItem.index].mRaw}`,
`women record: ${data[tooltipItem.index].wRaw}`
];
}
}
},
scales: {
xAxes: [{
type: 'category',
display: true,
}],
yAxes: [{
display: true,
type: 'linear'
}]
}
}
});
});
function load() {
if (localStorage.menWomenAthleticsRatio) {
const cache = JSON.parse(localStorage.menWomenAthleticsRatio);
if (Date.now() < cache.expire) {
return Promise.resolve(cache.data);
}
}
return fetch('https://cors-anywhere.herokuapp.com/https://en.wikipedia.org/wiki/List_of_world_records_in_athletics').then(r => r.text())
.then(r => {
const doc = new DOMParser().parseFromString(r, "text/html");
const mt = doc.getElementById('Men').closest('h3').nextElementSibling;
const wt = doc.getElementById('Women').closest('h3').nextElementSibling;
const getTableData = t => Array.from(t.rows).filter(tr => tr.cells[0].nodeName==='TD')
.flatMap((tr,i,a)=>tr.cells.length===a[0].cells.length?[[tr.cells[0].textContent.replace(/\((track|road)\)/, '').replace('[b]', '').trim(), tr.cells[1].textContent.trim()]]:tr.cells.length===1?[[tr.cells[0].textContent.replace(/\((track|road)\)/, '').replace('[b]', '').trim(), a[i+1].cells[0].textContent.trim()]]:[]);
const md = new Map(getTableData(mt));
const wd = new Map(getTableData(wt));
const commonKeys = [...md.keys()].filter(key => wd.has(key));
const parseTimeToCs = str => {
const {h,m,s,c} = str.match(/(?:(?:(?<h>\d+):)?(?:(?<m>\d+):))?(?<s>\d+)(?:\.(?<c>\d+))?/).groups;
return (h ? h*360000 : 0) + (m ? m*6000 : 0) + s*100 + (+(c||0));
};
const parseV = str => {
const [v, unit] = str.split(' ');
return unit ? {value: +v.replace(/[ ,]/g,''), unit} : {value: parseTimeToCs(v), unit: 'cs'};
}
const data = commonKeys.flatMap(k => {
const m = parseV(md.get(k));
const w = parseV(wd.get(k));
if (/ put| throw/.test(k)) return []; // ignore those, men/women use different weights
return [{x: k, y: m.unit === 'cs' ? m.value/w.value : w.value/m.value, mRaw: md.get(k), wRaw: wd.get(k)}];
}).sort((a,b) => b.y-a.y);
localStorage.menWomenAthleticsRatio = JSON.stringify({expire: Date.now()+7*86_400_000, data});
return data;
});
}
</script>
</body>
</html>