Skip to content

Instantly share code, notes, and snippets.

@oguimbal
Last active October 7, 2021 07:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oguimbal/cbfdfe24a921cc7efc7a7472506737e5 to your computer and use it in GitHub Desktop.
Save oguimbal/cbfdfe24a921cc7efc7a7472506737e5 to your computer and use it in GitHub Desktop.
A quick & (very) dirty cloudflare worker script to compute probas & display your celopunks
const rarity = `
Background:
Celo Dark -> 15%
Celo Gray -> 10%
Faint Gold -> 75%
Character:
Green Cyber Woman -> 6%
Blue Cool Woman -> 4%
Red Burning Woman -> 4%
Lighter Normie Human -> 4%
Light Normie Human -> 4%
Dark Normie Human -> 4%
Lighter Male Human -> 4%
Light Male Human -> 4%
Darker Male Human -> 4%
Dark Male Human -> 4%
Lighter Femal Human -> 4%
Light Female Human -> 4%
Darker Female Human -> 4%
Dark Female Human -> 4%
Goddess of the Night Woman -> 4%
Female Orc -> 2%
Male Mummy -> 2%
Female Ape -> 2%
Male Ape -> 2%
Normie Ape -> 2%
Female Alien -> 2%
Normie Alien -> 2%
Green Male Alien -> 2%
Aqua Male Alien -> 2%
Female Zombie -> 3%
Normie Zombie -> 2%
Male Zombie -> 2%
Ape Male Zombie -> 2%
Male Orc -> 2%
Male Vampire -> 2%
Normie Demon -> 2%
Male Robot -> 2%
Normie Skeleton -> 2%
Ape Male Alien -> 1%
Eyes:
Small Shades -> 15%
Regular Shades -> 15%
Classic Shades -> 10%
Big Shades -> 10%
Male Earring -> 7%
Wallstreetbets Sunglasses -> 6%
Nerd Glasses -> 6%
Eyepatch -> 3%
3D Glasses -> 3%
Empty -> 25%
Head:
Beanie -> 2%
Cowboy Hat -> 2%
Top Hat -> 4%
Fedora -> 3%
Crazy Hair -> 8%
Wallstreetbets Dark Crazy Hair -> 5%
Wallstreetbets Hair -> 5%
Male Wild Hair -> 7%
Headband -> 7%
Bandana -> 7%
Cap Forward -> 5%
Knitted Cap -> 5%
Pink Cap -> 10%
Blue Cap -> 10%
Green Cap -> 10%
Red Cap -> 10%
Lip:
Burgundy Lipstick -> 20%
Flashy Blue Lipstick -> 25%
Gold Lipstick -> 15%
Party Pink Lipstick -> 15%
Passion Red Lipstick -> 10%
Purple Lipstick -> 5%
Space Lipstick -> 5%
Pipe -> 5%
`;
const rarityData = Object.fromEntries(
[...rarity.matchAll(/^(.+)\-\>\s*(\d+)\s*%\s*$/gm)]
.map(x => [x[1].trim(), parseFloat(x[2]) / 100])
);
addEventListener("fetch", (event) => {
event.respondWith(
handleRequest(event.request).catch(
(err) => new Response(err.stack, { status: 500 })
)
);
});
async function handleRequest(request) {
let { pathname } = new URL(request.url);
pathname = pathname.substr(1);
if (/^\d+.png/.test(pathname)) {
const key = 'img-punk-v3-' + parseInt(pathname);
const cached = await PUNKS.get(key, { type: 'arrayBuffer' });
if (cached) {
console.log('Serving ' + pathname + ' from cache');
return new Response(cached, {
headers: { 'Content-Type': 'image/png' }
});
}
console.log('Fetching ' + pathname);
const resp = await fetch('https://celopunks.club/nft/' + pathname);
if (!resp.ok) {
throw new Error('No image');
}
const data = await resp.arrayBuffer();
await PUNKS.put(key, data);
return new Response(data, {
headers: { 'Content-Type': 'image/png' }
});
}
const ids = pathname.split(/,/g)
.map(x => x.trim())
.filter(x => /^\d+$/.test(x))
.map(x => parseInt(x))
.filter(x => x > 0 && x < 10000);
console.log('Fetching ', ids.join(', '));
if (!ids.length) {
return new Response(`
Invalid usage.
Please use like that:
https://celopunk-rarity.oguimbal.workers.dev/1234,4567,89
(where the numbers are your NFTs)`);
}
const jsons = await Promise.all(ids.map(n => (async () => {
const key = 'punk-' + n;
const punk = await PUNKS.get(key);
if (punk) {
console.log('From cache: ' + key)
return { n, ...JSON.parse(punk) };
}
const data = await fetch(`https://celopunks.club/nft/${n}.json`);
const json = await data.json();
await PUNKS.put(key, JSON.stringify(json));
console.log('Got json for ' + key)
return { n, ...json };
})()));
console.log('Got all jsons')
const result = jsons.map(x => {
const proba = x.attributes.map(a => {
const p = rarityData[a.value];
if (!p) {
throw new Error('Unkown rarirty for trait ' + a.value);
}
return p;
}).reduce((a, b) => a * b, 1);
return {
proba,
punk: x.name,
chars: x.attributes
.sort((a, b) => rarityData[a.value] - rarityData[b.value])
.map(a => `${a.value} (${rarityData[a.value] * 100}%)`).join(', '),
n: x.n
}
});
result.sort((a, b) => a.proba - b.proba);
return new Response(`
<h2>Probabilities of occurence (smaller number = rarer)</h2><ul>`
+ result.map(x => `<li> <img height="70" src="/${x.n}.png" style="float: left" /> <h2> ${x.punk} : ${x.proba * 100}% (${x.proba.toExponential()}) </h2> ${x.chars} </li>`).join('\n')
+ '</ul>', {
headers: {
'Content-Type': 'text/html'
}
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment