/
nobel.js
81 lines (76 loc) · 2.13 KB
/
nobel.js
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
import { useSequentialState } from 'react-seq';
export function useNobelPrize(category, year) {
return useSequentialState(async function*({ signal }) {
if (!category || !year) {
return;
}
const prizeURL = new URL(`https://api.nobelprize.org/2.1/nobelPrize/${category}/${year}`);
const [ {
categoryFullName,
prizeAmount,
prizeAmountAdjusted,
laureates
} ] = await fetchJSON(prizeURL, { signal });
let prize = {
fullName: str(categoryFullName),
amount: prizeAmount,
amountAdjusted: prizeAmountAdjusted,
laureates: laureates?.map(({ fullName, orgName, motivation }) => {
return {
fullName: str(fullName) ?? str(orgName),
motivation: str(motivation),
};
}),
};
yield prize;
if (laureates) {
for (const [ index, laureate ] of laureates.entries()) {
const [ {
gender,
birth,
death,
nobelPrizes,
wikipedia,
} ] = await fetchJSON(laureate.links.href);
prize = { ...prize };
const target = prize.laureates[index];
target.gender = gender;
target.birth = formatDatePlace(birth);
target.death = formatDatePlace(death);
// find the relevant prize
const matchingPrize = nobelPrizes.find(p => p.awardYear === year);
target.affiliation = formatAffiliation(matchingPrize?.affiliations?.[0]);
target.wikipedia = wikipedia.english;
yield prize;
}
}
}, [ category, year ]);
}
function str(obj) {
if (!obj) {
return;
}
return obj.en ?? obj.se ?? obj.no;
}
function formatDatePlace(obj) {
if (!obj) {
return;
}
const { date, place } = obj;
const { city, country } = place;
return `${date} (${str(city)}, ${str(country)})`;
}
function formatAffiliation(obj) {
if (!obj) {
return;
}
const { name, city, country } = obj;
return `${str(name)} (${str(city)}, ${str(country)})`;
}
async function fetchJSON(url, options) {
const res = await fetch(url, options);
if (res.status !== 200) {
throw new Error(`${res.status} ${res.statusText}`);
}
return res.json();
}