Public
Edited
Feb 18
3 stars
Insert cell
Insert cell
Insert cell
list = yaml(`
done:
- 8351/the-last-of-us-part-ii
- 6012/marvels-spider-man
- 10480/marvels-spider-man-miles-morales
- 7407/star-wars-jedi-fallen-order
- 4708/horizon-zero-dawn-the-frozen-wilds
- 12361/horizon-forbidden-west
- 13252/teenage-mutant-ninja-turtles-shredders-revenge
- 5434/god-of-war
- 12919/god-of-war-ragnar-k
- 14199/star-wars-jedi-survivor # want to 100%
- 13252/teenage-mutant-ninja-turtles-shredders-revenge
- 15052/marvels-spider-man-2
- 15151/dave-the-diver
- 9136/baldurs-gate-3
- 15460/chants-of-sennaar
- 16790/star-wars-outlaws
- 8308/untitled-goose-game

started:
- 3717/red-dead-redemption-2 # around 90%
- 14343/the-legend-of-zelda-tears-of-the-kingdom
- 11148/disco-elysium-the-final-cut
- 13554/plateup-

pending:
- 14348/dredge
- 15022/alan-wake-2
- 13348/gotham-knights # started
- 6222/assassins-creed-odyssey # started but stalled out
- 11839/ghost-of-tsushima-directors-cut # started twice
- 14796/horizon-forbidden-west-burning-shores
- 7858/control # barely started
- 6015/shadow-of-the-tomb-raider # started, but don't remember anything
- 10181/hades # barely started
- 1944/far-cry-primal
- 4384/far-cry-5
- 9783/far-cry-6
- 4503/assassins-creed-origins
- 9439/assassins-creed-valhalla
- 5118/shadow-of-the-colossus
- 1524/the-last-guardian
- 1537/persona-5
- 1514/call-of-duty-black-ops-iii
- 6215/hitman-2
- 10039/hitman-3
- 189/sleeping-dogs-definitive-edition
- 2846/watch-dogs-2
- 7405/watch-dogs-legion
- 12011/death-stranding-directors-cut
- 12617/olliolli-world
- 9901/lego-star-wars-the-skywalker-saga
- 13386/stray
- 4111/rain-world
- 10993/deathloop
- 13809/lego-bricktales
- 13898/hogwarts-legacy
- 8525/cyberpunk-2077
- 17126/lego-horizon-adventures
- 18035/ninja-gaiden-2-black
- 17732/indiana-jones-and-the-great-circle
- 17486/kingdom-come-deliverance-ii
- 17136/arco
- 16663/animal-well
`)
Insert cell
yaml = (await import("js-yaml")).load
Insert cell
Insert cell
Insert cell
games = cached
? FileAttachment("games@28.json").json()
: Promise.all(Object.values(list).flat().map(openCritic))
Insert cell
openCritic = async (url) => {
const res = await fetch(
`https://cors-proxy.visnup.vercel.app/opencritic.com/game/${url}/reviews`
);
const external = parser.parseFromString(await res.text(), "text/html");
const json = external
.querySelector("script[type='application/json']")
.innerText.replaceAll("&q;", '"')
.replaceAll("&s;", "’");
const parsed = JSON.parse(json);
const combined = Object.values(parsed).reduce(
(h, v) => (Array.isArray(v) ? { ...h, reviews: v } : { ...h, ...v }),
{}
);
combined.reviews = combined.reviews
.filter((d) => d.npScore !== null)
.map(({ score, Outlet, externalUrl }) => ({ score, Outlet, externalUrl }));
return combined;
}
Insert cell
parser = new DOMParser()
Insert cell
ratings = games.flatMap(({ reviews = [], ...game }) => reviews.map((d) => ({ ...d, game })))
Insert cell
lookup = (url) => games.find((d) => d.url.endsWith(url))
Insert cell
done = list.done.map(lookup).filter((d) => d)
Insert cell
started = list.started.map(lookup).filter((d) => d)
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more