diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 00000000..821c6392 Binary files /dev/null and b/.DS_Store differ diff --git a/README.md b/README.md index d39f2c87..a82e1289 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,61 @@ +# Welcome to HashLips 👄 + +Important: There is a new repo for this code. +[https://github.com/HashLips/hashlips_art_engine](https://github.com/HashLips/hashlips_art_engine) + +All the code in these repos was created and explained by HashLips on the main YouTube channel. + +To find out more please visit: + +[đŸ“ē YouTube](https://www.youtube.com/channel/UC1LV4_VQGBJHTJjEWUmy8nA) + +[👄 Discord](https://discord.com/invite/qh6MWhMJDN) + +[đŸ’Ŧ Telegram](https://t.me/hashlipsnft) + +[đŸĻ Twitter](https://twitter.com/hashlipsnft) + +[â„šī¸ Website](https://hashlips.online/HashLips) + # generative-art-opensource Create generative art by using the canvas api and node js, feel free to contribute to this repo with new ideas. + +# Project Setup +- install `node.js` on your local system (https://nodejs.org/en/) +- clone the repository to your local system `git@github.com:HashLips/generative-art-opensource.git` +- run `yarn install` to install dependencies + +# How to use +## Run the code +1. Run `node index.js` +2. Open the `./output` folder to find your generated images to use as NFTs, as well as the metadata to use for NFT marketplaces. + +## Adjust the provided configuration and resources +### Configuration file +The file `./input/config.js` contains the following properties that can be adjusted to your preference in order to change the behavior of the NFT generation procedure: +- width: - of your image in pixels. Default: `1000px` +- height: - of your image in pixels. Default: `1000px` +- dir: - where image parts are stored. Default: `./input` +- description: - of your generated NFT. Default: `This is an NFT made by the coolest generative code.` +- baseImageUri: - URL base to access your NFTs from. This will be used by platforms to find your image resource. This expects the image to be accessible by it's id like `${baseImageUri}/${id}`. +- startEditionFrom: - number (int) to start naming NFTs from. Default: `1` +- editionSize: - number (int) to end edition at. Default: `10` +- editionDnaPrefix: - value (number or string) that indicates which dna from an edition is used there. I.e. dna `0` from to independent batches in the same edition may differ, and can be differentiated using this. Default: `0` +- rarityWeights: - allows to provide rarity categories and how many of each type to include in an edition. Default: `1 super_rare, 4 rare, 5 original` +- layers: list of layers that should be used to render the image. See next section for detail. + +### Image layers +The image layers are different parts that make up a full image by overlaying on top of each other. E.g. in the example input content of this repository we start with the eyeball and layer features like the eye lids or iris on top to create the completed and unique eye, which we can then use as part of our NFT collection. +To ensure uniqueness, we want to add various features and multiple options for each of them in order to allow enough permutations for the amount of unique images we require. + +To start, copy the layers/features and their images in a flat hierarchy at a directory of your choice (by default we expect them in `./input/`). The features should contain options for each rarity that is provided via the config file. + +After adding the `layers`, adjust them accordingly in the `config.js` by providing the directory path, positioning and sizes. +Use the existing `addLayers` calls as guidance for how to add layers. This can either only use the name of the layer and will use default positioning (x=0, y=0) and sizes (width=configured width, height=configure height), or positioning and sizes can be provided for more flexibility. + +### Allowing different rarities for certain rarity/layer combinations +It is possible to provide a percentage at which e.g. a rare item would contain a rare vs. common part in a given layer. This can be done via the `addRarityPercentForLayer` that can be found in the `config.js` as well. +This allows for more fine grained control over how much randomness there should be during the generation process, and allows a combination of common and rare parts. + +# Development suggestions +- Preferably use VSCode with the prettifier plugin for a consistent coding style (or equivalent js formatting rules) diff --git a/index.js b/index.js index 6618e3f5..679e1270 100644 --- a/index.js +++ b/index.js @@ -1,15 +1,20 @@ const fs = require("fs"); -const myArgs = process.argv.slice(2); const { createCanvas, loadImage } = require("canvas"); -const { layers, width, height } = require("./input/config.js"); +const { + layers, + width, + height, + description, + baseImageUri, + editionSize, + startEditionFrom, + rarityWeights, +} = require("./input/config.js"); const console = require("console"); const canvas = createCanvas(width, height); const ctx = canvas.getContext("2d"); -const editionSize = myArgs.length > 0 ? Number(myArgs[0]) : 1; -var metadataList = []; -var attributesList = []; -var dnaList = []; +// saves the generated image to the output folder, using the edition count as the name const saveImage = (_editionCount) => { fs.writeFileSync( `./output/${_editionCount}.png`, @@ -17,6 +22,7 @@ const saveImage = (_editionCount) => { ); }; +// adds a signature to the top left corner of the canvas const signImage = (_sig) => { ctx.fillStyle = "#000000"; ctx.font = "bold 30pt Courier"; @@ -25,6 +31,7 @@ const signImage = (_sig) => { ctx.fillText(_sig, 40, 40); }; +// generate a random color hue const genColor = () => { let hue = Math.floor(Math.random() * 360); let pastel = `hsl(${hue}, 100%, 85%)`; @@ -36,31 +43,36 @@ const drawBackground = () => { ctx.fillRect(0, 0, width, height); }; -const addMetadata = (_dna, _edition) => { +// add metadata for individual nft edition +const generateMetadata = (_dna, _edition, _attributesList) => { let dateTime = Date.now(); let tempMetadata = { dna: _dna.join(""), + name: `#${_edition}`, + description: description, + image: `${baseImageUri}/${_edition}`, edition: _edition, date: dateTime, - attributes: attributesList, + attributes: _attributesList, }; - metadataList.push(tempMetadata); - attributesList = []; + return tempMetadata; }; -const addAttributes = (_element) => { +// prepare attributes for the given element to be used as metadata +const getAttributeForElement = (_element) => { let selectedElement = _element.layer.selectedElement; - attributesList.push({ + let attribute = { name: selectedElement.name, rarity: selectedElement.rarity, - }); + }; + return attribute; }; +// loads an image from the layer path +// returns the image in a format usable by canvas const loadLayerImg = async (_layer) => { return new Promise(async (resolve) => { - const image = await loadImage( - `${_layer.location}${_layer.selectedElement.fileName}` - ); + const image = await loadImage(`${_layer.selectedElement.path}`); resolve({ layer: _layer, loadedImage: image }); }); }; @@ -73,75 +85,165 @@ const drawElement = (_element) => { _element.layer.size.width, _element.layer.size.height ); - addAttributes(_element); }; -const constructLayerToDna = (_dna = [], _layers = []) => { +// check the configured layer to find information required for rendering the layer +// this maps the layer information to the generated dna and prepares it for +// drawing on a canvas +const constructLayerToDna = (_dna = [], _layers = [], _rarity) => { let mappedDnaToLayers = _layers.map((layer, index) => { - let selectedElement = layer.elements[_dna[index]]; + let selectedElement = layer.elements.find(element => element.id === _dna[index]); return { location: layer.location, position: layer.position, size: layer.size, - selectedElement: selectedElement, + selectedElement: {...selectedElement, rarity: _rarity }, }; }); - return mappedDnaToLayers; }; +// check if the given dna is contained within the given dnaList +// return true if it is, indicating that this dna is already in use and should be recalculated const isDnaUnique = (_DnaList = [], _dna = []) => { let foundDna = _DnaList.find((i) => i.join("") === _dna.join("")); return foundDna == undefined ? true : false; }; -const createDna = (_layers) => { +const getRandomRarity = (_rarityOptions) => { + let randomPercent = Math.random() * 100; + let percentCount = 0; + + for (let i = 0; i <= _rarityOptions.length; i++) { + percentCount += _rarityOptions[i].percent; + if (percentCount >= randomPercent) { + console.log(`use random rarity ${_rarityOptions[i].id}`) + return _rarityOptions[i].id; + } + } + return _rarityOptions[0].id; +} + +// create a dna based on the available layers for the given rarity +// use a random part for each layer +const createDna = (_layers, _rarity) => { let randNum = []; + let _rarityWeight = rarityWeights.find(rw => rw.value === _rarity); _layers.forEach((layer) => { - let num = Math.floor(Math.random() * layer.elements.length); - randNum.push(num); + let num = Math.floor(Math.random() * layer.elementIdsForRarity[_rarity].length); + if (_rarityWeight && _rarityWeight.layerPercent[layer.id]) { + // if there is a layerPercent defined, we want to identify which dna to actually use here (instead of only picking from the same rarity) + let _rarityForLayer = getRandomRarity(_rarityWeight.layerPercent[layer.id]); + num = Math.floor(Math.random() * layer.elementIdsForRarity[_rarityForLayer].length); + randNum.push(layer.elementIdsForRarity[_rarityForLayer][num]); + } else { + randNum.push(layer.elementIdsForRarity[_rarity][num]); + } }); return randNum; }; +// holds which rarity should be used for which image in edition +let rarityForEdition; +// get the rarity for the image by edition number that should be generated +const getRarity = (_editionCount) => { + if (!rarityForEdition) { + // prepare array to iterate over + rarityForEdition = []; + rarityWeights.forEach((rarityWeight) => { + for (let i = rarityWeight.from; i <= rarityWeight.to; i++) { + rarityForEdition.push(rarityWeight.value); + } + }); + } + return rarityForEdition[editionSize - _editionCount]; +}; + const writeMetaData = (_data) => { fs.writeFileSync("./output/_metadata.json", _data); }; +// holds which dna has already been used during generation +let dnaListByRarity = {}; +// holds metadata for all NFTs +let metadataList = []; +// Create generative art by using the canvas api const startCreating = async () => { - writeMetaData(""); - let editionCount = 1; - while (editionCount <= editionSize) { - console.log(editionCount); + console.log('##################'); + console.log('# Generative Art'); + console.log('# - Create your NFT collection'); + console.log('##################'); - let newDna = createDna(layers); - console.log(dnaList); - if (isDnaUnique(dnaList, newDna)) { - let results = constructLayerToDna(newDna, layers); - let loadedElements = []; //promise array + console.log(); + console.log('start creating NFTs.') - results.forEach((layer) => { - loadedElements.push(loadLayerImg(layer)); - }); + // clear meta data from previous run + writeMetaData(""); - await Promise.all(loadedElements).then((elementArray) => { - ctx.clearRect(0, 0, width, height); - drawBackground(); - elementArray.forEach((element) => { - drawElement(element); - }); - signImage(`#${editionCount}`); - saveImage(editionCount); - addMetadata(newDna, editionCount); - console.log(`Created edition: ${editionCount} with DNA: ${newDna}`); - }); - dnaList.push(newDna); - editionCount++; - } else { - console.log("DNA exists!"); + // prepare dnaList object + rarityWeights.forEach((rarityWeight) => { + dnaListByRarity[rarityWeight.value] = []; + }); + + // create NFTs from startEditionFrom to editionSize + let editionCount = startEditionFrom; + while (editionCount <= editionSize) { + console.log('-----------------') + console.log('creating NFT %d of %d', editionCount, editionSize); + + // get rarity from to config to create NFT as + let rarity = getRarity(editionCount); + console.log('- rarity: ' + rarity); + + // calculate the NFT dna by getting a random part for each layer/feature + // based on the ones available for the given rarity to use during generation + let newDna = createDna(layers, rarity); + while (!isDnaUnique(dnaListByRarity[rarity], newDna)) { + // recalculate dna as this has been used before. + console.log('found duplicate DNA ' + newDna.join('-') + ', recalculate...'); + newDna = createDna(layers, rarity); } + console.log('- dna: ' + newDna.join('-')); + + // propagate information about required layer contained within config into a mapping object + // = prepare for drawing + let results = constructLayerToDna(newDna, layers, rarity); + let loadedElements = []; + + // load all images to be used by canvas + results.forEach((layer) => { + loadedElements.push(loadLayerImg(layer)); + }); + + // elements are loaded asynchronously + // -> await for all to be available before drawing the image + await Promise.all(loadedElements).then((elementArray) => { + // create empty image + ctx.clearRect(0, 0, width, height); + // draw a random background color + drawBackground(); + // store information about each layer to add it as meta information + let attributesList = []; + // draw each layer + elementArray.forEach((element) => { + drawElement(element); + attributesList.push(getAttributeForElement(element)); + }); + // add an image signature as the edition count to the top left of the image + signImage(`#${editionCount}`); + // write the image to the output directory + saveImage(editionCount); + let nftMetadata = generateMetadata(newDna, editionCount, attributesList); + metadataList.push(nftMetadata) + console.log('- metadata: ' + JSON.stringify(nftMetadata)); + console.log('- edition ' + editionCount + ' created.'); + console.log(); + }); + dnaListByRarity[rarity].push(newDna); + editionCount++; } writeMetaData(JSON.stringify(metadataList)); }; -startCreating(); +// Initiate code +startCreating(); \ No newline at end of file diff --git a/input/.DS_Store b/input/.DS_Store new file mode 100644 index 00000000..31f1de3d Binary files /dev/null and b/input/.DS_Store differ diff --git a/input/background/black.png b/input/background/black.png deleted file mode 100644 index c7dc38f3..00000000 Binary files a/input/background/black.png and /dev/null differ diff --git a/input/ball/.DS_Store b/input/ball/.DS_Store new file mode 100644 index 00000000..cd626b12 Binary files /dev/null and b/input/ball/.DS_Store differ diff --git a/input/ball/original/.DS_Store b/input/ball/original/.DS_Store new file mode 100644 index 00000000..bc9aff39 Binary files /dev/null and b/input/ball/original/.DS_Store differ diff --git a/input/ball/original/grey eye ball.png b/input/ball/original/grey eye ball.png new file mode 100644 index 00000000..f7b86106 Binary files /dev/null and b/input/ball/original/grey eye ball.png differ diff --git a/input/ball/red eye ball_sr.png b/input/ball/original/red eye ball.png similarity index 100% rename from input/ball/red eye ball_sr.png rename to input/ball/original/red eye ball.png diff --git a/input/ball/white eye ball.png b/input/ball/original/white eye ball.png similarity index 100% rename from input/ball/white eye ball.png rename to input/ball/original/white eye ball.png diff --git a/input/ball/rare/.DS_Store b/input/ball/rare/.DS_Store new file mode 100644 index 00000000..5d68ca2d Binary files /dev/null and b/input/ball/rare/.DS_Store differ diff --git a/input/ball/rare/eye ball rare.png b/input/ball/rare/eye ball rare.png new file mode 100644 index 00000000..f2bceee8 Binary files /dev/null and b/input/ball/rare/eye ball rare.png differ diff --git a/input/ball/rare/green eye ball rare.png b/input/ball/rare/green eye ball rare.png new file mode 100644 index 00000000..fa6e2d71 Binary files /dev/null and b/input/ball/rare/green eye ball rare.png differ diff --git a/input/ball/super_rare/.DS_Store b/input/ball/super_rare/.DS_Store new file mode 100644 index 00000000..d9aaf3dd Binary files /dev/null and b/input/ball/super_rare/.DS_Store differ diff --git a/input/ball/super_rare/red eye ball super rare.png b/input/ball/super_rare/red eye ball super rare.png new file mode 100644 index 00000000..822a979c Binary files /dev/null and b/input/ball/super_rare/red eye ball super rare.png differ diff --git a/input/bottom lid/.DS_Store b/input/bottom lid/.DS_Store new file mode 100644 index 00000000..cc07bfa0 Binary files /dev/null and b/input/bottom lid/.DS_Store differ diff --git a/input/bottom lid/original/.DS_Store b/input/bottom lid/original/.DS_Store new file mode 100644 index 00000000..469f6b25 Binary files /dev/null and b/input/bottom lid/original/.DS_Store differ diff --git a/input/bottom lid/high bottom.png b/input/bottom lid/original/high bottom.png similarity index 100% rename from input/bottom lid/high bottom.png rename to input/bottom lid/original/high bottom.png diff --git a/input/bottom lid/rare/.DS_Store b/input/bottom lid/rare/.DS_Store new file mode 100644 index 00000000..dfbf20c6 Binary files /dev/null and b/input/bottom lid/rare/.DS_Store differ diff --git a/input/bottom lid/tilted bottom_r.png b/input/bottom lid/rare/tilted bottom rare.png similarity index 100% rename from input/bottom lid/tilted bottom_r.png rename to input/bottom lid/rare/tilted bottom rare.png diff --git a/input/bottom lid/super_rare/.DS_Store b/input/bottom lid/super_rare/.DS_Store new file mode 100644 index 00000000..7696c59b Binary files /dev/null and b/input/bottom lid/super_rare/.DS_Store differ diff --git a/input/bottom lid/low bottom.png b/input/bottom lid/super_rare/low bottom super rare.png similarity index 100% rename from input/bottom lid/low bottom.png rename to input/bottom lid/super_rare/low bottom super rare.png diff --git a/input/config.js b/input/config.js index cfddaa7f..aad063a7 100644 --- a/input/config.js +++ b/input/config.js @@ -1,82 +1,168 @@ +/************************************************************** + * UTILITY FUNCTIONS + * - scroll to BEGIN CONFIG to provide the config values + *************************************************************/ const fs = require("fs"); -const width = 1000; -const height = 1000; const dir = __dirname; -const rarity = [ - { key: "", val: "original" }, - { key: "_r", val: "rare" }, - { key: "_sr", val: "super rare" }, -]; -const addRarity = (_str) => { - let itemRarity; - rarity.forEach((r) => { - if (_str.includes(r.key)) { - itemRarity = r.val; - } - }); - return itemRarity; +// adds a rarity to the configuration. This is expected to correspond with a directory containing the rarity for each defined layer +// @param _id - id of the rarity +// @param _from - number in the edition to start this rarity from +// @param _to - number in the edition to generate this rarity to +// @return a rarity object used to dynamically generate the NFTs +const addRarity = (_id, _from, _to) => { + const _rarityWeight = { + value: _id, + from: _from, + to: _to, + layerPercent: {} + }; + return _rarityWeight; }; +// get the name without last 4 characters -> slice .png from the name const cleanName = (_str) => { let name = _str.slice(0, -4); - rarity.forEach((r) => { - name = name.replace(r.key, ""); - }); return name; }; -const getElements = (path) => { +// reads the filenames of a given folder and returns it with its name and path +const getElements = (_path, _elementCount) => { return fs - .readdirSync(path) + .readdirSync(_path) .filter((item) => !/(^|\/)\.[^\/\.]/g.test(item)) - .map((i, index) => { + .map((i) => { return { - id: index + 1, + id: _elementCount, name: cleanName(i), - fileName: i, - rarity: addRarity(i), + path: `${_path}/${i}` }; }); }; +// adds a layer to the configuration. The layer will hold information on all the defined parts and +// where they should be rendered in the image +// @param _id - id of the layer +// @param _position - on which x/y value to render this part +// @param _size - of the image +// @return a layer object used to dynamically generate the NFTs +const addLayer = (_id, _position, _size) => { + if (!_id) { + console.log('error adding layer, parameters id required'); + return null; + } + if (!_position) { + _position = { x: 0, y: 0 }; + } + if (!_size) { + _size = { width: width, height: height } + } + // add two different dimension for elements: + // - all elements with their path information + // - only the ids mapped to their rarity + let elements = []; + let elementCount = 0; + let elementIdsForRarity = {}; + rarityWeights.forEach((rarityWeight) => { + let elementsForRarity = getElements(`${dir}/${_id}/${rarityWeight.value}`); + + elementIdsForRarity[rarityWeight.value] = []; + elementsForRarity.forEach((_elementForRarity) => { + _elementForRarity.id = `${editionDnaPrefix}${elementCount}`; + elements.push(_elementForRarity); + elementIdsForRarity[rarityWeight.value].push(_elementForRarity.id); + elementCount++; + }) + elements[rarityWeight.value] = elementsForRarity; + }); + + let elementsForLayer = { + id: _id, + position: _position, + size: _size, + elements, + elementIdsForRarity + }; + return elementsForLayer; +}; + +// adds layer-specific percentages to use one vs another rarity +// @param _rarityId - the id of the rarity to specifiy +// @param _layerId - the id of the layer to specifiy +// @param _percentages - an object defining the rarities and the percentage with which a given rarity for this layer should be used +const addRarityPercentForLayer = (_rarityId, _layerId, _percentages) => { + let _rarityFound = false; + rarityWeights.forEach((_rarityWeight) => { + if (_rarityWeight.value === _rarityId) { + let _percentArray = []; + for (let percentType in _percentages) { + _percentArray.push({ + id: percentType, + percent: _percentages[percentType] + }) + } + _rarityWeight.layerPercent[_layerId] = _percentArray; + _rarityFound = true; + } + }); + if (!_rarityFound) { + console.log(`rarity ${_rarityId} not found, failed to add percentage information`); + } +} + +/************************************************************** + * BEGIN CONFIG + *************************************************************/ + +// image width in pixels +const width = 1000; +// image height in pixels +const height = 1000; +// description for NFT in metadata file +const description = "This is an NFT made by the coolest generative code."; +// base url to use in metadata file +// the id of the nft will be added to this url, in the example e.g. https://hashlips/nft/1 for NFT with id 1 +const baseImageUri = "https://hashlips/nft"; +// id for edition to start from +const startEditionFrom = 1; +// amount of NFTs to generate in edition +const editionSize = 10; +// prefix to add to edition dna ids (to distinguish dna counts from different generation processes for the same collection) +const editionDnaPrefix = 0 + +// create required weights +// for each weight, call 'addRarity' with the id and from which to which element this rarity should be applied +let rarityWeights = [ + addRarity('super_rare', 1, 1), + addRarity('rare', 2, 5), + addRarity('original', 5, 10) +]; + +// create required layers +// for each layer, call 'addLayer' with the id and optionally the positioning and size +// the id would be the name of the folder in your input directory, e.g. 'ball' for ./input/ball const layers = [ - { - location: `${dir}/ball/`, - elements: getElements(`${dir}/ball/`), - position: { x: 0, y: 0 }, - size: { width: width, height: height }, - }, - { - location: `${dir}/eye color/`, - elements: getElements(`${dir}/eye color/`), - position: { x: 0, y: 0 }, - size: { width: width, height: height }, - }, - { - location: `${dir}/iris/`, - elements: getElements(`${dir}/iris/`), - position: { x: 0, y: 0 }, - size: { width: width, height: height }, - }, - { - location: `${dir}/shine/`, - elements: getElements(`${dir}/shine/`), - position: { x: 0, y: 0 }, - size: { width: width, height: height }, - }, - { - location: `${dir}/bottom lid/`, - elements: getElements(`${dir}/bottom lid/`), - position: { x: 0, y: 0 }, - size: { width: width, height: height }, - }, - { - location: `${dir}/top lid/`, - elements: getElements(`${dir}/top lid/`), - position: { x: 0, y: 0 }, - size: { width: width, height: height }, - }, + addLayer('ball', { x: 0, y: 0 }, { width: width, height: height }), + addLayer('eye color'), + addLayer('iris'), + addLayer('shine'), + addLayer('bottom lid'), + addLayer('top lid') ]; -module.exports = { layers, width, height }; +// provide any specific percentages that are required for a given layer and rarity level +// all provided options are used based on their percentage values to decide which layer to select from +addRarityPercentForLayer('super_rare', 'ball', { 'super_rare': 33, 'rare': 33, 'original': 33 }); +addRarityPercentForLayer('super_rare', 'eye color', { 'super_rare': 50, 'rare': 25, 'original': 25 }); +addRarityPercentForLayer('original', 'eye color', { 'super_rare': 50, 'rare': 25, 'original': 25 }); + +module.exports = { + layers, + width, + height, + description, + baseImageUri, + editionSize, + startEditionFrom, + rarityWeights, +}; diff --git a/input/eye color/.DS_Store b/input/eye color/.DS_Store new file mode 100644 index 00000000..4c98bb0f Binary files /dev/null and b/input/eye color/.DS_Store differ diff --git a/input/eye color/cyan big.png b/input/eye color/original/cyan big.png similarity index 100% rename from input/eye color/cyan big.png rename to input/eye color/original/cyan big.png diff --git a/input/eye color/cyan small.png b/input/eye color/original/cyan small.png similarity index 100% rename from input/eye color/cyan small.png rename to input/eye color/original/cyan small.png diff --git a/input/eye color/green big.png b/input/eye color/original/green big.png similarity index 100% rename from input/eye color/green big.png rename to input/eye color/original/green big.png diff --git a/input/eye color/green small.png b/input/eye color/original/green small.png similarity index 100% rename from input/eye color/green small.png rename to input/eye color/original/green small.png diff --git a/input/eye color/yellow big.png b/input/eye color/original/yellow big.png similarity index 100% rename from input/eye color/yellow big.png rename to input/eye color/original/yellow big.png diff --git a/input/eye color/yellow small.png b/input/eye color/original/yellow small.png similarity index 100% rename from input/eye color/yellow small.png rename to input/eye color/original/yellow small.png diff --git a/input/eye color/rare/.DS_Store b/input/eye color/rare/.DS_Store new file mode 100644 index 00000000..a90d7b76 Binary files /dev/null and b/input/eye color/rare/.DS_Store differ diff --git a/input/eye color/pink big.png b/input/eye color/rare/pink big rare.png similarity index 100% rename from input/eye color/pink big.png rename to input/eye color/rare/pink big rare.png diff --git a/input/eye color/pink small.png b/input/eye color/rare/pink small rare.png similarity index 100% rename from input/eye color/pink small.png rename to input/eye color/rare/pink small rare.png diff --git a/input/eye color/purple big_r.png b/input/eye color/rare/purple big rare.png similarity index 100% rename from input/eye color/purple big_r.png rename to input/eye color/rare/purple big rare.png diff --git a/input/eye color/purple small.png b/input/eye color/rare/purple small rare.png similarity index 100% rename from input/eye color/purple small.png rename to input/eye color/rare/purple small rare.png diff --git a/input/eye color/super_rare/.DS_Store b/input/eye color/super_rare/.DS_Store new file mode 100644 index 00000000..4c70a594 Binary files /dev/null and b/input/eye color/super_rare/.DS_Store differ diff --git a/input/eye color/red big_sr.png b/input/eye color/super_rare/red big super rare.png similarity index 100% rename from input/eye color/red big_sr.png rename to input/eye color/super_rare/red big super rare.png diff --git a/input/eye color/red small.png b/input/eye color/super_rare/red small super rare.png similarity index 100% rename from input/eye color/red small.png rename to input/eye color/super_rare/red small super rare.png diff --git a/input/iris/.DS_Store b/input/iris/.DS_Store new file mode 100644 index 00000000..940d4d42 Binary files /dev/null and b/input/iris/.DS_Store differ diff --git a/input/iris/original/.DS_Store b/input/iris/original/.DS_Store new file mode 100644 index 00000000..8c635dfd Binary files /dev/null and b/input/iris/original/.DS_Store differ diff --git a/input/iris/large.png b/input/iris/original/large.png similarity index 100% rename from input/iris/large.png rename to input/iris/original/large.png diff --git a/input/iris/rare/.DS_Store b/input/iris/rare/.DS_Store new file mode 100644 index 00000000..438524a8 Binary files /dev/null and b/input/iris/rare/.DS_Store differ diff --git a/input/iris/medium.png b/input/iris/rare/medium rare.png similarity index 100% rename from input/iris/medium.png rename to input/iris/rare/medium rare.png diff --git a/input/iris/super_rare/.DS_Store b/input/iris/super_rare/.DS_Store new file mode 100644 index 00000000..7f8c15dd Binary files /dev/null and b/input/iris/super_rare/.DS_Store differ diff --git a/input/iris/small.png b/input/iris/super_rare/small super rare.png similarity index 100% rename from input/iris/small.png rename to input/iris/super_rare/small super rare.png diff --git a/input/shine/.DS_Store b/input/shine/.DS_Store new file mode 100644 index 00000000..66cc9a19 Binary files /dev/null and b/input/shine/.DS_Store differ diff --git a/input/shine/original/.DS_Store b/input/shine/original/.DS_Store new file mode 100644 index 00000000..9432c1b4 Binary files /dev/null and b/input/shine/original/.DS_Store differ diff --git a/input/shine/shapes.png b/input/shine/original/shapes.png similarity index 100% rename from input/shine/shapes.png rename to input/shine/original/shapes.png diff --git a/input/shine/rare/.DS_Store b/input/shine/rare/.DS_Store new file mode 100644 index 00000000..8d2144cb Binary files /dev/null and b/input/shine/rare/.DS_Store differ diff --git a/input/shine/rare/shapes rare.png b/input/shine/rare/shapes rare.png new file mode 100644 index 00000000..a59f759a Binary files /dev/null and b/input/shine/rare/shapes rare.png differ diff --git a/input/shine/super_rare/.DS_Store b/input/shine/super_rare/.DS_Store new file mode 100644 index 00000000..e70f4ac4 Binary files /dev/null and b/input/shine/super_rare/.DS_Store differ diff --git a/input/shine/super_rare/shapes super rare.png b/input/shine/super_rare/shapes super rare.png new file mode 100644 index 00000000..11e29b61 Binary files /dev/null and b/input/shine/super_rare/shapes super rare.png differ diff --git a/input/top lid/.DS_Store b/input/top lid/.DS_Store new file mode 100644 index 00000000..c60bf9a7 Binary files /dev/null and b/input/top lid/.DS_Store differ diff --git a/input/top lid/original/.DS_Store b/input/top lid/original/.DS_Store new file mode 100644 index 00000000..c2126183 Binary files /dev/null and b/input/top lid/original/.DS_Store differ diff --git a/input/top lid/high top.png b/input/top lid/original/high top.png similarity index 100% rename from input/top lid/high top.png rename to input/top lid/original/high top.png diff --git a/input/top lid/rare/.DS_Store b/input/top lid/rare/.DS_Store new file mode 100644 index 00000000..da9c21c0 Binary files /dev/null and b/input/top lid/rare/.DS_Store differ diff --git a/input/top lid/low top.png b/input/top lid/rare/low top rare.png similarity index 100% rename from input/top lid/low top.png rename to input/top lid/rare/low top rare.png diff --git a/input/top lid/super_rare/.DS_Store b/input/top lid/super_rare/.DS_Store new file mode 100644 index 00000000..798f68a3 Binary files /dev/null and b/input/top lid/super_rare/.DS_Store differ diff --git a/input/top lid/tilted top_r.png b/input/top lid/super_rare/tilted top super rare.png similarity index 100% rename from input/top lid/tilted top_r.png rename to input/top lid/super_rare/tilted top super rare.png diff --git a/output/1.png b/output/1.png index fc13e0e0..4e494fab 100644 Binary files a/output/1.png and b/output/1.png differ diff --git a/output/10.png b/output/10.png new file mode 100644 index 00000000..f0993645 Binary files /dev/null and b/output/10.png differ diff --git a/output/2.png b/output/2.png index 98d7140f..0c434923 100644 Binary files a/output/2.png and b/output/2.png differ diff --git a/output/3.png b/output/3.png index 8c080771..bc0af8d9 100644 Binary files a/output/3.png and b/output/3.png differ diff --git a/output/4.png b/output/4.png new file mode 100644 index 00000000..fe872ace Binary files /dev/null and b/output/4.png differ diff --git a/output/5.png b/output/5.png new file mode 100644 index 00000000..a98ba59c Binary files /dev/null and b/output/5.png differ diff --git a/output/6.png b/output/6.png new file mode 100644 index 00000000..47888b0e Binary files /dev/null and b/output/6.png differ diff --git a/output/7.png b/output/7.png new file mode 100644 index 00000000..b5c34985 Binary files /dev/null and b/output/7.png differ diff --git a/output/8.png b/output/8.png new file mode 100644 index 00000000..dbbf41a7 Binary files /dev/null and b/output/8.png differ diff --git a/output/9.png b/output/9.png new file mode 100644 index 00000000..0a85afef Binary files /dev/null and b/output/9.png differ diff --git a/output/_metadata.json b/output/_metadata.json index f7b205ca..42dcfc74 100644 --- a/output/_metadata.json +++ b/output/_metadata.json @@ -1 +1 @@ -[{"dna":"0111022","edition":1,"date":1630012363570,"attributes":[{"name":"red eye ball","rarity":"super rare"},{"name":"yellow small","rarity":"original"},{"name":"medium","rarity":"original"},{"name":"shapes","rarity":"original"},{"name":"tilted bottom","rarity":"rare"},{"name":"tilted top","rarity":"rare"}]},{"dna":"121000","edition":2,"date":1630012363937,"attributes":[{"name":"white eye ball","rarity":"original"},{"name":"green big","rarity":"original"},{"name":"medium","rarity":"original"},{"name":"shapes","rarity":"original"},{"name":"high bottom","rarity":"original"},{"name":"high top","rarity":"original"}]},{"dna":"181012","edition":3,"date":1630012364315,"attributes":[{"name":"white eye ball","rarity":"original"},{"name":"red big","rarity":"super rare"},{"name":"medium","rarity":"original"},{"name":"shapes","rarity":"original"},{"name":"low bottom","rarity":"original"},{"name":"tilted top","rarity":"rare"}]}] \ No newline at end of file +[{"dna":"000000","rarity":"SUPER_RARE","name":"#1","description":"This is an NFT made by the coolest generative code.","image":"https://hashlips/nft/1","edition":1,"date":1630062402020,"attributes":[{"name":"red eye ball super rare"},{"name":"red big super rare"},{"name":"small super rare"},{"name":"shapes super rare"},{"name":"low bottom super rare"},{"name":"tilted top super rare"}]},{"dna":"020000","rarity":"RARE","name":"#2","description":"This is an NFT made by the coolest generative code.","image":"https://hashlips/nft/2","edition":2,"date":1630062402374,"attributes":[{"name":"eye ball rare"},{"name":"purple big rare"},{"name":"medium rare"},{"name":"shapes rare"},{"name":"tilted bottom rare"},{"name":"low top rare"}]},{"dna":"130000","rarity":"RARE","name":"#3","description":"This is an NFT made by the coolest generative code.","image":"https://hashlips/nft/3","edition":3,"date":1630062402725,"attributes":[{"name":"green eye ball rare"},{"name":"purple small rare"},{"name":"medium rare"},{"name":"shapes rare"},{"name":"tilted bottom rare"},{"name":"low top rare"}]},{"dna":"110000","rarity":"RARE","name":"#4","description":"This is an NFT made by the coolest generative code.","image":"https://hashlips/nft/4","edition":4,"date":1630062403081,"attributes":[{"name":"green eye ball rare"},{"name":"pink small rare"},{"name":"medium rare"},{"name":"shapes rare"},{"name":"tilted bottom rare"},{"name":"low top rare"}]},{"dna":"010000","rarity":"ORIGINAL","name":"#5","description":"This is an NFT made by the coolest generative code.","image":"https://hashlips/nft/5","edition":5,"date":1630062403415,"attributes":[{"name":"grey eye ball"},{"name":"cyan small"},{"name":"large"},{"name":"shapes"},{"name":"high bottom"},{"name":"high top"}]},{"dna":"120000","rarity":"ORIGINAL","name":"#6","description":"This is an NFT made by the coolest generative code.","image":"https://hashlips/nft/6","edition":6,"date":1630062403813,"attributes":[{"name":"red eye ball"},{"name":"green big"},{"name":"large"},{"name":"shapes"},{"name":"high bottom"},{"name":"high top"}]},{"dna":"140000","rarity":"ORIGINAL","name":"#7","description":"This is an NFT made by the coolest generative code.","image":"https://hashlips/nft/7","edition":7,"date":1630062404211,"attributes":[{"name":"red eye ball"},{"name":"yellow big"},{"name":"large"},{"name":"shapes"},{"name":"high bottom"},{"name":"high top"}]},{"dna":"230000","rarity":"ORIGINAL","name":"#8","description":"This is an NFT made by the coolest generative code.","image":"https://hashlips/nft/8","edition":8,"date":1630062404553,"attributes":[{"name":"white eye ball"},{"name":"green small"},{"name":"large"},{"name":"shapes"},{"name":"high bottom"},{"name":"high top"}]},{"dna":"150000","rarity":"ORIGINAL","name":"#9","description":"This is an NFT made by the coolest generative code.","image":"https://hashlips/nft/9","edition":9,"date":1630062404938,"attributes":[{"name":"red eye ball"},{"name":"yellow small"},{"name":"large"},{"name":"shapes"},{"name":"high bottom"},{"name":"high top"}]},{"dna":"050000","rarity":"ORIGINAL","name":"#10","description":"This is an NFT made by the coolest generative code.","image":"https://hashlips/nft/10","edition":10,"date":1630062405268,"attributes":[{"name":"grey eye ball"},{"name":"yellow small"},{"name":"large"},{"name":"shapes"},{"name":"high bottom"},{"name":"high top"}]}] \ No newline at end of file diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 00000000..eae72a6d --- /dev/null +++ b/yarn.lock @@ -0,0 +1,448 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@mapbox/node-pre-gyp@^1.0.0": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.5.tgz#2a0b32fcb416fb3f2250fd24cb2a81421a4f5950" + integrity sha512-4srsKPXWlIxp5Vbqz5uLfBN+du2fJChBoYn/f2h991WLdk7jUvcSk/McVLSv/X+xQIPI8eGD5GjrnygdyHnhPA== + dependencies: + detect-libc "^1.0.3" + https-proxy-agent "^5.0.0" + make-dir "^3.1.0" + node-fetch "^2.6.1" + nopt "^5.0.0" + npmlog "^4.1.2" + rimraf "^3.0.2" + semver "^7.3.4" + tar "^6.1.0" + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +all@^0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/all/-/all-0.0.0.tgz#fb2aa75d4759d40e39ecbb118fabf0cc11ff554f" + integrity sha1-+yqnXUdZ1A457LsRj6vwzBH/VU8= + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + +are-we-there-yet@~1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +canvas@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/canvas/-/canvas-2.8.0.tgz#f99ca7f25e6e26686661ffa4fec1239bbef74461" + integrity sha512-gLTi17X8WY9Cf5GZ2Yns8T5lfBOcGgFehDFb+JQwDqdOoBOcECS9ZWMEAqMSVcMYwXD659J8NyzjRY/2aE+C2Q== + dependencies: + "@mapbox/node-pre-gyp" "^1.0.0" + nan "^2.14.0" + simple-get "^3.0.3" + +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +debug@4: + version "4.3.2" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" + integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== + dependencies: + ms "2.1.2" + +decompress-response@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986" + integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw== + dependencies: + mimic-response "^2.0.0" + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + +detect-libc@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= + +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +glob@^7.1.3: + version "7.1.7" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" + integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + +https-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" + integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + dependencies: + agent-base "6" + debug "4" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +make-dir@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +mimic-response@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43" + integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minipass@^3.0.0: + version "3.1.3" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.3.tgz#7d42ff1f39635482e15f9cdb53184deebd5815fd" + integrity sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg== + dependencies: + yallist "^4.0.0" + +minizlib@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + +mkdirp@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +nan@^2.14.0: + version "2.15.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" + integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== + +node-fetch@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + +nopt@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" + integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== + dependencies: + abbrev "1" + +npmlog@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + +object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +once@^1.3.0, once@^1.3.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +readable-stream@^2.0.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +semver@^6.0.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@^7.3.4: + version "7.3.5" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" + integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== + dependencies: + lru-cache "^6.0.0" + +set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +signal-exit@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" + integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== + +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== + +simple-get@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.0.tgz#b45be062435e50d159540b576202ceec40b9c6b3" + integrity sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA== + dependencies: + decompress-response "^4.2.0" + once "^1.3.1" + simple-concat "^1.0.0" + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2": + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +tar@^6.1.0: + version "6.1.11" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" + integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^3.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +wide-align@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==