├── .github ├── FUNDING.yml ├── logo.png ├── metrics.json └── workflows │ └── main.yml ├── ducks ├── beak │ └── 0.svg ├── body │ └── 0.svg ├── eyes │ ├── 0.svg │ ├── 1.svg │ ├── 2.svg │ └── 3.svg ├── hat │ ├── 1.svg │ ├── 10.svg │ ├── 11.svg │ ├── 2.svg │ ├── 3.svg │ ├── 4.svg │ ├── 5.svg │ ├── 6.svg │ ├── 7.svg │ ├── 8.svg │ └── 9.svg ├── items │ ├── 1.svg │ ├── 2.svg │ └── 3.svg ├── smoke │ ├── 5.svg │ ├── 6.svg │ └── 7.svg └── wing │ └── 0.svg ├── license.md ├── package.json ├── readme.md ├── rules.md └── src ├── DuckColorConstants.js ├── DuckGenerator.js ├── DuckStringParser.js ├── SVGUtilities.js └── index.js /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: fairfieldprogramming 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 14 | -------------------------------------------------------------------------------- /.github/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fairfield-programming/ducks/dfcb6f7602658b66cbf1508e0b3e333a6ba69732/.github/logo.png -------------------------------------------------------------------------------- /.github/metrics.json: -------------------------------------------------------------------------------- 1 | { 2 | "directDependenciesCount": 0, 3 | "indirectDependenciesCount": 0, 4 | "commentCount": 85, 5 | "lineCount": 514, 6 | "fileCount": 33, 7 | "score": 100, 8 | "grade": "A+" 9 | } -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Lint, Prettify, Test, and Score Code 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: actions/checkout@v2 13 | 14 | - name: Run the EaF Linter 15 | run: npx eaf-linter 16 | 17 | - name: Commit Changes 18 | uses: EndBug/add-and-commit@v7 19 | with: 20 | messages: 🦆 Code Fixed with EaF-Lint! 21 | -------------------------------------------------------------------------------- /ducks/beak/0.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /ducks/body/0.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /ducks/eyes/0.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /ducks/eyes/1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /ducks/eyes/2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /ducks/eyes/3.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /ducks/hat/1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ducks/hat/10.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /ducks/hat/11.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /ducks/hat/2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /ducks/hat/3.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /ducks/hat/4.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ducks/hat/5.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ducks/hat/6.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ducks/hat/7.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ducks/hat/8.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /ducks/hat/9.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /ducks/items/1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /ducks/items/2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /ducks/items/3.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /ducks/smoke/5.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /ducks/smoke/6.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /ducks/smoke/7.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /ducks/wing/0.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /license.md: -------------------------------------------------------------------------------- 1 | Copyright 2022 William McGonagle 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. 4 | 5 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "duckgen", 3 | "version": "1.1.1", 4 | "description": "The package for dealing with all the ducks created and managed by the Fairfield Programming Association.", 5 | "main": "./src/index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "patch-release": "npm version patch && npm publish && git push --follow-tags" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/fairfield-programming/ducks.git" 13 | }, 14 | "keywords": [ 15 | "animal", 16 | "duck", 17 | "ducks", 18 | "svg", 19 | "generator", 20 | "procedural", 21 | "images", 22 | "profile", 23 | "picture" 24 | ], 25 | "author": "William McGonagle", 26 | "license": "ISC", 27 | "bugs": { 28 | "url": "https://github.com/fairfield-programming/ducks/issues" 29 | }, 30 | "homepage": "https://github.com/fairfield-programming/ducks#readme" 31 | } 32 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # ![Duckgen](https://github.com/fairfield-programming/ducks/blob/master/.github/logo.png?raw=true) 2 | 3 | ![Code Grade](https://img.shields.io/badge/dynamic/json?color=green&label=Grade&query=grade&url=https%3A%2F%2Fraw.githubusercontent.com%2Ffairfield-programming%2Fducks%2Fmaster%2F.github%2Fmetrics.json) 4 | ![Dependency Count](https://img.shields.io/badge/dynamic/json?color=blue&label=Dependencies&query=indirectDependenciesCount&url=https%3A%2F%2Fraw.githubusercontent.com%2Ffairfield-programming%2Fducks%2Fmaster%2F.github%2Fmetrics.json) 5 | 6 | ## Download 7 | 8 | Since the Fairfield Programming Association's duck generator is built on top of node.js and npm, you need to have both of those installed as prerequisites. After that, to download the project, you have to run the below command. From there, you can include it in your node.js code by using the import or require system. 9 | 10 | ```bash 11 | npm install duckgen 12 | ``` 13 | 14 | ## Features 15 | 16 | We didn't want to use people's faces for the profile pictures. This was for three reasons: we didn't want to pay for hosting the image files, we were scared of what people would upload, and since our main audience is minors, we didn't want their faces to be publicly available. To solve these problems, we decided to use rubber duck avatars instead of photos. Users are able to customize their ducks by adding glasses, hats, items, etc (and they can even set their own colors). 17 | 18 |

19 | 20 | Real Cool Duck 21 | Real Red Duck 22 | Real Blue Duck 23 | Real Outline Duck 24 | Real Brown Duck 25 | 26 |

27 | 28 | ## How to Use 29 | 30 | After running `npm install duckgen`, you can use it in your code using one of the two below systems. The API is very simple and you can check out the code to the project for the API reference. 31 | 32 | **ES6** 33 | 34 | ```javascript 35 | 36 | import duckgen from "duckgen"; 37 | 38 | ``` 39 | 40 | **Node.js Require** 41 | 42 | ```javascript 43 | const duckgen = require("duckgen"); 44 | ``` 45 | 46 | ## Contributing 47 | 48 | If you simply star the repo, this helps us out tremendiously. Past that, if you share this repo with your friends, that helps a lot too. If you are feeling super generous, then you can find some issues that you have with the project and try to help us with them. 49 | 50 |

51 | 52 | 53 | GitHub labels 54 | 55 | 56 | GitHub labels 57 | 58 | 59 | GitHub labels 60 | 61 | 62 | GitHub labels 63 | 64 | 65 |

66 | 67 | To start helping, you can click some of the above labels to jump to the pages with issues. Or, you can submit an issue by clicking the last button. 68 | -------------------------------------------------------------------------------- /rules.md: -------------------------------------------------------------------------------- 1 | # Rules 2 | 3 | - [Idea Rules](#idea-rules) 4 | - [No Weapons](#no-weapons) 5 | - [No Vulgar Items, Text, or Ideas](#no-vulgar-items-text-or-ideas) 6 | - [No Politics](#no-politics) 7 | - [Art Rules](#art-rules) 8 | - [Duck Size](#duck-size) 9 | - [Allowed Colors](#allowed-colors) 10 | - [Line Width](#line-width) 11 | 12 | ## Idea Rules 13 | 14 | ### No Weapons 15 | 16 | ### No Vulgar Items, Text, or Ideas 17 | 18 | ### No Politics 19 | 20 | ## Art Rules 21 | 22 | ### Duck Size 23 | 24 | The canvas size for the Duck SVG is 200x200. You can use viewbox to scale the duck however you would like and you can combine that with the SVG width and height attributes. But, this is done to keep everything as consistent as possible. 25 | 26 | ### Allowed Colors 27 | 28 | Only the below colors are allowed on the ducks. Colors can be added to the list if there is a demand for them, but cannot be removed. All of the items being added to the ducks, must use the below colors. 29 | 30 | | Index | Color Name | Hex Value | 31 | | ----- | ---------- | ------------- | 32 | | 0 | Black | #000000 | 33 | | 1 | White | #FFFFFF | 34 | | 2 | Brown | | 35 | | 3 | Yellow | | 36 | | 4 | Red | | 37 | | 5 | Blue | | 38 | | 6 | Rainbow | url(#rainbow) | 39 | 40 | ### Line Width 41 | -------------------------------------------------------------------------------- /src/DuckColorConstants.js: -------------------------------------------------------------------------------- 1 | // Color Index 2 | const colorList = [ 3 | "#000000", // black 4 | "#FFFFFF", // white 5 | "#9D8009", // brown 6 | "#F7D23D", // yellow 7 | "#4C89E4", // blue 8 | "#E05050", // red 9 | "url(#rainbow)", // rainbow 10 | ]; 11 | 12 | // Colors With Names 13 | const black = "#000000"; 14 | const white = "#FFFFFF"; 15 | const brown = "#9D8009"; 16 | const yellow = "#F7D23D"; 17 | const blue = "#4C89E4"; 18 | const red = "#E05050"; 19 | 20 | // Check if Gradient Background 21 | function isGradientBackground(trueDuckData) { 22 | 23 | // Not the Best Code, but it is Forward Compatible 24 | if (trueDuckData.color === 'url(#rainbow)' || trueDuckData.beakColor === 'url(#rainbow)') return true; 25 | 26 | // If not triggered, its not a gradient :( 27 | return false; 28 | 29 | } 30 | 31 | // Gradient Include 32 | const gradientData = 33 | ` 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | `; 48 | 49 | // Export that Stuff 50 | module.exports = { 51 | colorList, 52 | gradientData, 53 | isGradientBackground, 54 | black, 55 | white, 56 | brown, 57 | yellow, 58 | blue, 59 | red 60 | }; -------------------------------------------------------------------------------- /src/DuckGenerator.js: -------------------------------------------------------------------------------- 1 | // Global Includes 2 | const path = require('path'); 3 | const fs = require('fs'); 4 | 5 | // Local Includes 6 | const svg = require('./SVGUtilities'); 7 | const colors = require('./DuckColorConstants'); 8 | 9 | function getItemData(type, number) { 10 | 11 | // Get the File Path 12 | const itemPath = path.join( 13 | __dirname, 14 | "../ducks/", 15 | type, 16 | `/${number}.svg`, 17 | ); 18 | 19 | // Check if File Exists 20 | if (!fs.existsSync(itemPath)) return []; 21 | 22 | // Get the File Data 23 | const itemData = fs.readFileSync(itemPath, "ascii"); 24 | const strippedData = svg.stripParentTags(itemData); 25 | 26 | // Return the String 27 | return strippedData.split("\n"); 28 | 29 | } 30 | 31 | function generateDuck(duckData) { 32 | 33 | // Make Sure Everything is Defined 34 | const trueDuckData = { 35 | hat: duckData.hat || 0, 36 | eyes: duckData.eyes || 0, 37 | beak: duckData.beak || 0, 38 | wings: duckData.wings || 0, 39 | smoke: duckData.smoke || 0, 40 | tail: duckData.tail || 0, 41 | item: duckData.item || 0, 42 | color: colors.colorList[duckData.featherColor] || colors.colorList[3], 43 | beakColor: colors.colorList[duckData.beakColor] || colors.colorList[5], 44 | }; 45 | 46 | // Setup the Output 47 | const output = []; 48 | 49 | // If theres a Gradient Background, Add It In 50 | if (colors.isGradientBackground(trueDuckData)) output.push(colors.gradientData); 51 | 52 | // Add the Parts (Spread them First) 53 | output.push(...getItemData("body", trueDuckData.tail)); 54 | output.push(...getItemData("smoke", trueDuckData.smoke)); 55 | output.push(...getItemData("eyes", trueDuckData.eyes)); 56 | output.push(...getItemData("beak", trueDuckData.beak)); 57 | output.push(...getItemData("items", trueDuckData.items)); 58 | output.push(...getItemData("wing", trueDuckData.wings)); 59 | output.push(...getItemData("hat", trueDuckData.hat)); 60 | 61 | // Create Some Output Text 62 | let outputText = output.join("\n"); 63 | 64 | // Replace the Text with Color 65 | outputText = outputText.replace(/DUCK_COLOR/g, trueDuckData.color); 66 | outputText = outputText.replace(/BEAK_COLOR/g, trueDuckData.beakColor); 67 | 68 | // Return the SVG 69 | return outputText; 70 | 71 | } 72 | 73 | function formatSVG(data, zoom) { 74 | // If no data, return a blank svg. If no zoom const, return a duck at default zoom. 75 | if (!data) return ``; 76 | if (!zoom) return `\n${data}\n`; 77 | 78 | // If there is a zoom, scale appropriately and modify svg dimensions accordingly, then return. 79 | const size = 200 - zoom * 2; 80 | 81 | return `\n${data}\n`; 82 | } 83 | 84 | module.exports = { 85 | generateDuck, 86 | getItemData, 87 | formatSVG 88 | }; -------------------------------------------------------------------------------- /src/DuckStringParser.js: -------------------------------------------------------------------------------- 1 | function parseString(input) { 2 | 3 | // Validate String 4 | if (typeof input != 'string') return false; 5 | if (/[^a-fA-F0-9]/.test(input)) return false; 6 | if (input.length == 0) return false; 7 | 8 | // Check Duck String Version 9 | if (input[0] === '1') return parseV1String(input); 10 | 11 | // If Version Not Supported, Return False 12 | return false; 13 | 14 | } 15 | 16 | function parseV1String(input) { 17 | 18 | // Validate String 19 | if (typeof input != 'string') return false; 20 | if (input.length != 17) return false; 21 | if (/[^a-fA-F0-9]/.test(input)) return false; 22 | 23 | // Cut up the Duck Data 24 | const hatString = input.substring(1, 3); 25 | const eyesString = input.substring(3, 5); 26 | const beakString = input.substring(5, 7); 27 | const wingsString = input.substring(7, 9); 28 | const smokeString = input.substring(9, 11); 29 | const tailString = input.substring(11, 13); 30 | const itemString = input.substring(13, 15); 31 | const beakColorString = input.substring(15, 16); 32 | const featherColorString = input.substring(16, 17); 33 | 34 | // Convert the Hex Strings into Ints 35 | const hat = parseInt(hatString, 16); 36 | const eyes = parseInt(eyesString, 16); 37 | const beak = parseInt(beakString, 16); 38 | const wings = parseInt(wingsString, 16); 39 | const smoke = parseInt(smokeString, 16); 40 | const tail = parseInt(tailString, 16); 41 | const item = parseInt(itemString, 16); 42 | const beakColor = parseInt(beakColorString, 16); 43 | const featherColor = parseInt(featherColorString, 16); 44 | 45 | // Return the Duck Data 46 | return { 47 | hat, 48 | eyes, 49 | beak, 50 | wings, 51 | smoke, 52 | tail, 53 | item, 54 | beakColor, 55 | featherColor, 56 | }; 57 | 58 | } 59 | 60 | module.exports = { 61 | parseString, 62 | parseV1String 63 | }; 64 | -------------------------------------------------------------------------------- /src/SVGUtilities.js: -------------------------------------------------------------------------------- 1 | function stripParentTags(input) { 2 | 3 | // Set Output to Input 4 | let output = input; 5 | 6 | // Cut Out Unnecessary Stuff 7 | output = output.replace(//g, ""); 8 | output = output.replace(/<\/svg>/g, ""); 9 | 10 | // Return the Trimmed Output 11 | return output.trim(); 12 | 13 | } 14 | 15 | module.exports = { 16 | stripParentTags 17 | }; -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | const duckGenerator = require('./DuckGenerator'); 2 | const duckStringParser = require('./DuckStringParser'); 3 | 4 | module.exports = { 5 | ...duckGenerator, 6 | ...duckStringParser 7 | }; --------------------------------------------------------------------------------