Published
Edited
Apr 12, 2021
Insert cell
md`# Algobot Exploration`
Insert cell
data_url = "https://gist.githubusercontent.com/decentralion/c2cbedd69e8e2e33e7016a17b5b2515b/raw/47a22e2662ceed9cea6a67f4f4cbdb2cb08607a4/algobots.json"
Insert cell
data = FileAttachment("allData.json").json()
Insert cell
function clean(x) {
return {
id: +x.tokenID.slice(-3),
traits: x.traits.slice(1, x.traits.length)
};
}
Insert cell
cleaned = data.map(clean)
Insert cell
idToTraits = {
const x = new Map();
for (const { id, traits } of cleaned) {
x.set(id, traits);
}
return x;
}
Insert cell
traitToIds = {
const result = new Map();
for (const { id, traits } of cleaned) {
for (const trait of traits) {
if (!result.has(trait)) result.set(trait, []);
result.get(trait).push(id);
}
}
return result;
}
Insert cell
traitSurprise = new Map([...traitToIds].map(([k, v]) => [k, -Math.log(v.length / data.length, 2)]));
Insert cell
botSurprise = new Map([...idToTraits].map(([k, v]) => [k, v.map((t) => traitSurprise.get(t)).reduce((a, b) => a + b, 0)]));
Insert cell
Insert cell
function findMissingTraits(ids) {
const traitsToFind = new Set(allTraits);
for (const id of ids) {
for (const trait of idToTraits.get(id)) {
traitsToFind.delete(trait);
}
}
return Array.from(traitsToFind);
}
Insert cell
Insert cell
proposal = [162, 127, 98, 16, 370, 181, 325, 184, 461, 355, 86]
Insert cell
renderTeam(proposal)
Insert cell
html`
<h1>My most helpful</h1>
${renderHelpfulness(myMostHelpful)}
<h1>Overall most helpful</h1>
${renderHelpfulness(overallMostHelpful)}
`
Insert cell
Insert cell
Insert cell
Insert cell
missing = new Set(findMissingTraits(proposal))
Insert cell
lossiness = {
const traitCounter = new TraitCounter();
for (const id of proposal) {
traitCounter.addBot(id);
}

const traitCounts = traitCounter.traitCounts;

const lossiness = new Map();
proposal.forEach(id => {
let loss = 0;
for (const trait of idToTraits.get(id)) {
if (traitCounts.get(trait) === 1) {
loss++;
}
}
lossiness.set(id, loss);
});
return lossiness;
}
Insert cell
myMostHelpful = {
const helps = myBots.map(id => ({
id,
helpfulness: helpfulness(id, missing),
surprise: botSurprise.get(id),
}));
return helps.sort((a, b) => b.helpfulness - a.helpfulness).slice(0, 10);
}
Insert cell
allIds = Array.from(idToTraits.keys())
Insert cell
overallMostHelpful = {
const helps = allIds.map(id => ({
id,
helpfulness: helpfulness(id, missing),
surprise: botSurprise.get(id),
}));
return helps.sort((a, b) => b.helpfulness - a.helpfulness).slice(0, 10);
}
Insert cell
Insert cell
md`
\`\`\`
["40000033", "40000275", "40000342"])
["40000075", "40000221", "40000430"])
\`\`\`
`
Insert cell
twins = {
function characteristic(traits) {
return JSON.stringify(traits.slice().sort());
}
const m = new Map();
for (const [id, traits] of idToTraits) {
const chi = characteristic(traits);
if (!m.has(chi)) {
m.set(chi, {
traits,
ids: [],
});
}
m.get(chi).ids.push(id);
}
return [...m].filter(([k, v]) => v.ids.length > 1).map(([k, v]) => v).sort((a, b) => b.ids.length - a.ids.length);
}
Insert cell
md`
${twins.map(({ ids }) => ids.map(i => `#${i}`).join(", ") + "<br />")}
`
Insert cell
{
return html`
<style>
img { height: 200px; margin: -30px 0; }
.bot { display: inline-block }
figcaption { text-align: center; }
.bot[data-mine=false] figcaption { font-weight: bold; }
.missing { color: red; }
ul.missing { columns: 3; }
</style>
${twins
.map(datum => {
const { ids } = datum;
return ids.map(i => renderBot(i));
})
.flat()}
`;
}
Insert cell
function renderBot(id) {
const tokenId = `40${String(id).padStart(6, "0")}`;
const img = `https://api.artblocks.io/image/${tokenId}`;
const opensea = `https://opensea.io/assets/0xa7d8d9ef8d8ce8992df33d8b8cf4aebabd5bd270/${tokenId}`;
return html`
<figure class="bot" data-mine="${myBots.includes(id)}">
<img src="${img}" alt="Bot #${id}" />
<figcaption>
<a href="${opensea}">
#${id}${myBots.includes(id) ? "" : " (not owned)"}
</a>
</figcaption>
</figure>
`;
}
Insert cell
myBotsSet = new Set(myBots)
Insert cell
makeTwins = {
const myBotsSet = new Set(myBots);
const toBuy = [];
for (const { ids } of twins) {
for (const id of ids) {
if (myBotsSet.has(id)) {
toBuy.push(ids);
continue;
}
}
}
return toBuy;
}
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