From 058414da5f440bb3cbf7a7a9aef23f55a580f9d0 Mon Sep 17 00:00:00 2001 From: Josh Hoover Date: Mon, 4 Apr 2022 19:03:31 -0600 Subject: [PATCH] Added rarity layer --- README.md | 10 ++++ package.json | 2 + rarity_layer/circle.png | Bin 0 -> 1131 bytes rarity_layer/config.js | 18 ++++++++ rarity_layer/cross.png | Bin 0 -> 1014 bytes rarity_layer/square.png | Bin 0 -> 727 bytes rarity_layer/triangle.png | Bin 0 -> 947 bytes utils/functions/add_rarity_layer.js | 64 ++++++++++++++++++++++++++ utils/functions/merge_rarity_layer.js | 10 ++++ 9 files changed, 104 insertions(+) create mode 100644 rarity_layer/circle.png create mode 100644 rarity_layer/config.js create mode 100644 rarity_layer/cross.png create mode 100644 rarity_layer/square.png create mode 100644 rarity_layer/triangle.png create mode 100644 utils/functions/add_rarity_layer.js create mode 100644 utils/functions/merge_rarity_layer.js diff --git a/README.md b/README.md index 7c3e32e7..dff134da 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,16 @@ $ npm run rarity_rank - Provides ranking details through a user interface after calculating using the codeSTACKr Rarity command. +Rarity Layer (codeSTACKr): +``` +$ npm run add_rarity_layer +``` + +- Adds an additional layer for rarity decals based on the rarity rating assigned by the rarity calculation. (It requires the rarity metadata file to have been generated.) +- Configurable via `rarity_layer/config.js` and uses assets relative to this directory. +- It creates new files in the image directory in build directory with a distinct name e.g. `1_.png, 2_.png...` to allowing you to preview the results and rerun the command with a different configuration if the results are unsatisfactory. +- Run `npm run merge_rarity_layer` to finalize. + Update Info: ``` $ npm run update_info diff --git a/package.json b/package.json index a2326317..ab336826 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,8 @@ "rarity": "node utils/rarity", "rarity_md": "node utils/functions/getRarity_fromMetadata", "rarity_rank": "node utils/functions/rarity_rank.js", + "add_rarity_layer": "node utils/functions/add_rarity_layer.js", + "merge_rarity_layer": "node utils/functions/merge_rarity_layer.js", "preview": "node utils/preview.js", "pixelate": "node utils/pixelate.js", "update_info": "node utils/update_info.js", diff --git a/rarity_layer/circle.png b/rarity_layer/circle.png new file mode 100644 index 0000000000000000000000000000000000000000..9d0da15e3af8bf957b395a8092748b65c4d1d028 GIT binary patch literal 1131 zcmV-x1eE)UP)M zk^~+B9tZk>%Umusz?ZlxUaA8??R#Q zv6qFeb|jn4K5dN21G{YOEO{SzQbbB_CT|-^Hk*CP7&8ZGzh)ME0X!rkzicyGbqo$|5od9P6}|1vdjHbGckkyGcz05s_Ztbvk&%^vT`DV)1yp z30tmOxm>PiWo2a^*dLgd9e4Kk_kUg}6q?>Vx9mu|I-1d#16o z7Rc)A>SMTndJPq0%wS`mb_@=5SH~B(O-@eU8=o1MMk==h?}xf;j~;kfwXU_PI(y%$x#?AL@OPd;^LLnMm3Os#bvjV zN~KcE7gPfY>eV$+%H?wH(Y_kU#gJV5QhN=q2J%NpBECo@5`R`dYXGIx_u=VSQyd)~ ztq%n7oJZOL)H!Q_NF?$}I4-_ea5gkRI-ULr_%0M3OO#R{INQz_tCL-J@xx!qWU}Dw za0YUsyDq+Xdw6)b?v_ytL_|IX&URhN0GTi4J-}z3@$$qarPLu2$+?;As{S!IH@B-)D&>G@eW|(UXW$7D`N-`8PlcRpHv5z@ z<~Xp=tC>p-a3UU$A4#QB7rZR=T#*uyE7+*BKhMTbG&;o@;HZ~faAI9r6OpUf_~pYO zaGm90mVtMGyoj8!b%74m2u0)$rPKqPY0O)I11*ld1bhoDD5d5TiNvXqk&&fNI0RDc x+`KsK*IMrZqDrY!xm;cnkza#2-~a4H{sGNo8jK8l=F9*9002ovPDHLkV1kh25Jmt1 literal 0 HcmV?d00001 diff --git a/rarity_layer/config.js b/rarity_layer/config.js new file mode 100644 index 00000000..14a5818f --- /dev/null +++ b/rarity_layer/config.js @@ -0,0 +1,18 @@ +// Offsets for where to place the rarity image from the top left corner of the image. +const offset_x = 10; +const offset_y = 10; + +// This uses the highest rarity image it can based on thresholds +// (This list need not be in order) +const rarity_thresholds = [ + { threshold: 120, image: "cross.png" }, + { threshold: 90, image: "square.png" }, + { threshold: 30, image: "triangle.png" }, + { threshold: 0, image: "circle.png" }, +]; + +module.exports = { + offset_x, + offset_y, + rarity_thresholds, +}; diff --git a/rarity_layer/cross.png b/rarity_layer/cross.png new file mode 100644 index 0000000000000000000000000000000000000000..c2ea858e0a3affe6c8cd2048d0750d585cc84e0a GIT binary patch literal 1014 zcmVF3IfUp`-G%+Y55;s{Dvnn1Iyee@Ikv;5bFSC3Z zc1{ZcJ%}Lj4=|9BY(hvzqoP8{q67~T1rdWMiIRZhuXMU{=oy(TJu}@i^%4ZXr|ws; z`di=W_o`pLf&Wnql5UlBmo-mhO#r+HoR(zDW%}@ym6dye*MP0S9!oA$AxVRAh9CMzy zATW8Tq)os@U~J=96h+&YmzTc^&1v#RoO9FUhyX~_^f?Po6CvLF-F=34S#VnA$V{KH zr!2PN;6fzb2i)Js<(5{f^>k?7;6j{pMRFi`cm)?SAU`@N;!_Giw_i!)z%RhNXa{5{4 z+Ai1CI$!nyg@iO3jm=4t%(NH2 z3#gVQDv1lgDWC~_B^L-w!0_T8Zz=x8)&2zd=NWEU) zmZs@mvh(%b=1Uw7=Yh32jt|soweLDc2O#MV;2=f?oe?~+2D~BZVt2UQtk4-24tNB( zvvcz=B<%p^$wJG#sWv380G|T~s@3Yj`T6-P&?DI;MNt$znx^S2nW)El`Q9M>3Y;cO z_@k08ZFDHKI7wT8=gEq_XMu@;i_Aj;tOLy`icU>UO`VyWo4eX?Lg`<*T~<6nR#(jc zj}s=pz6YAlx#rl|*r!WNOP9+`9yweZjYc&|l2^R3(|l+aa61{A*P{6_P)I?srC?ECeNEQ)?S(%kCnvuMO={7gOMy@NxO}#- zu<&6$V$8&6J zR%Dh!&XDziJGfM>R*QV~hl1tb(&wGV=h}rIxA`2nkQH{ kyboTjR4O;Kaq-{6H9K_t{to)8K>z>%07*qoM6N<$f}G&lRR910 literal 0 HcmV?d00001 diff --git a/rarity_layer/square.png b/rarity_layer/square.png new file mode 100644 index 0000000000000000000000000000000000000000..f29d2092c7d6ab74e6f385e390bae513e7b14ba1 GIT binary patch literal 727 zcmV;|0x127P)Z&Dx05}A`^!xqDrn505LF8RxZF9IkJ9`vGS3u#LP>K1zTrPj58*Y5HMx#+M zpU=lYb8FKw%NfvAN-ffjYk%w&#;ip^#zSMf-Cjje)B-+9&&(j12*|l1CYAXJJeQc6 zK{g_wz#~cpFu4dQ_|RA)W&)h#A;91E3N~_iSU9Z;As)t0rNQw!xL8oc-&U7z<5J|=N&5pj8_DB-myxqX0L(w8xHf10HIyoq%v=S zSO0w^f&jto=`|QJ1PK3OAcc7#iP%b%Qg?>K;oY+5vCA%&`2!&OW+&V;*`)vg002ov JPDHLkV1hXFERFyG literal 0 HcmV?d00001 diff --git a/rarity_layer/triangle.png b/rarity_layer/triangle.png new file mode 100644 index 0000000000000000000000000000000000000000..aa3b7626ddc6672eab58365ca7fa506599f254d6 GIT binary patch literal 947 zcmV;k15EshP)JN9Ay~CKksIf)wEWMK@_Al7KiJi9sD>`v>IGb0LSJt%#VGR&>cl@Sx^ki5Q8^4m-0RHe1ppo89@fiMXHJyze|e zzVkdY`|blRTBJf-+5seWS(cS`UALHKoNSuT*ZCCq8@P~W5R;~JNvDB%pbVUnbSI7z~Jgf{bJ2f@+a9Z(F69Rk;JhS2Y=*r5sLiT$!mdKY*vgvryEW&Q5D?#(3PC-OujJpmMe zgCR{cq@jB*Cm~gn@6nHl5_z033w`I9(OxB zI(mkNhW?1^AZ|q_h%W-5%k#X+I1VCL#J261gCMv;f}e0>%xn34{%RE4NJ&gjPv?Rl z_&Tb6Ez0GxBWZsW+enElFE0-RJyC4yaG1)eIW(bL%eL)fK@cne9Z>={K#<8~UL74B z{U(f2C?S$Ez;)o2Fm@4G1o|YcHEIy5wTv+Xq%Q*CIpCu(1`St4(jnkS;E|9?MWqDv zOS;|2&0#7sL-RyH!@Ne5~?$lai>>UvRkCsZMi?uelt%#)K!1pv~$Q=q} z%$xaq{>qm1%?pyUz<0ol%}6W)OSxRGcW`j<&y9;)TFV&o0ee>jz>~#dabol00~HA| zVB2lVz*$N2)rE}}F~0AA&fXURl>&Sr|M^VJIju?B3r zjSsveX`xz?&-m|&fXd0_lH)k-M$$vZm}Z=8*UIJcy)+!>a=Aq2$1Pg4Xwl;T%fEcL V;8~1YVB`P*002ovPDHLkV1j|1wZ{Me literal 0 HcmV?d00001 diff --git a/utils/functions/add_rarity_layer.js b/utils/functions/add_rarity_layer.js new file mode 100644 index 00000000..e673a3b0 --- /dev/null +++ b/utils/functions/add_rarity_layer.js @@ -0,0 +1,64 @@ +const basePath = process.cwd(); +const fs = require("fs"); +const { createCanvas, loadImage } = require(`${basePath}/node_modules/canvas`); + +const { + offset_x, + offset_y, + rarity_thresholds, +} = require(`${basePath}/rarity_layer/config`); + +const rarity_decals = rarity_thresholds.sort( + (a, b) => b.threshold - a.threshold +); + +(async () => { + try { + let rarity_decals = []; + const decal_thresholds = rarity_thresholds.sort( + (a, b) => b.threshold - a.threshold + ); + for (let i = 0; i < decal_thresholds.length; i++) { + rarity_decals.push({ + imageData: await loadImage(`${basePath}/rarity_layer/${decal_thresholds[i].image}`), + threshold: decal_thresholds[i].threshold, + }); + } + + if (!fs.existsSync(`${basePath}/build/json/_metadata_with_rarity.json`)) + throw new Error( + "_metadata_with_rarity.json not found, please run `npm run rarity_md` first" + ); + const startAt0 = fs.existsSync(`${basePath}/build/images/0.png`); + if (!startAt0 && !fs.existsSync(`${basePath}/build/images/1.png`)) + throw new Error("no images found"); + // read json data + const rawdata = fs.readFileSync( + `${basePath}/build/json/_metadata_with_rarity.json` + ); + const nfts = JSON.parse(rawdata); + + for (let i = startAt0 ? 0 : 1; i < nfts.length + (startAt0 ? 0 : 1); i++) { + const nft = nfts[i - (startAt0 ? 0 : 1)]; + const rarity = nft.total_rarity_score; + const imagePath = `${basePath}/build/images/${i}.png`; + const image = await loadImage(imagePath); + const canvas = createCanvas(image.width, image.height); + const ctx = canvas.getContext("2d"); + ctx.drawImage(image, 0, 0); + for (let j = 0; j < rarity_decals.length; j++) { + if (rarity_decals[j].threshold < rarity) { + ctx.drawImage(rarity_decals[j].imageData, offset_x, offset_y); + break; + } + } + const newImagePath = `${basePath}/build/images/${i}_.png`; + canvas.toBuffer((err, buf) => { + if (err) throw err; + fs.writeFileSync(newImagePath, buf); + }); + } + } catch (e) { + console.error("unable to complete", e); + } +})(); diff --git a/utils/functions/merge_rarity_layer.js b/utils/functions/merge_rarity_layer.js new file mode 100644 index 00000000..1ad8ceb7 --- /dev/null +++ b/utils/functions/merge_rarity_layer.js @@ -0,0 +1,10 @@ +const basePath = process.cwd(); +const fs = require("fs"); + +const files = fs.readdirSync(`${basePath}/build/images`); +for (let i = 0; i < files.length; i++) { + if (files[i].includes("_")) { + const filename = `${basePath}/build/images/${files[i]}` + fs.renameSync(filename, filename.replace("_", "")); + } +}