Last active
October 7, 2021 07:42
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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