diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..c656199
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,18 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+indent_style = space
+indent_size = 4
+trim_trailing_whitespace = true
+
+[*.md]
+trim_trailing_whitespace = false
+
+[*.neon]
+indent_size = 2
+
+[*.xml.dist]
+indent_size = 2
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..65c3bcd
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,11 @@
+* text=auto
+
+/demo export-ignore
+/.editorconfig export-ignore
+/.gitattributes export-ignore
+/.gitignore export-ignore
+/.github export-ignore
+/phpstan.neon export-ignore
+/phpunit.xml.dist export-ignore
+/README.md export-ignore
+/**/*Test.php export-ignore
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000..c213c06
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,26 @@
+---
+name: build
+on:
+ push: ~
+ pull_request: ~
+
+jobs:
+ phpunit:
+ name: PHPUnit tests on ${{ matrix.php }} ${{ matrix.composer-flags }}
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ php: ['7.2', '7.3', '7.4', '8.0' ]
+ composer-flags: [ '' ]
+ phpunit-flags: [ '--coverage-text' ]
+ steps:
+ - uses: actions/checkout@v2
+ - uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php }}
+ coverage: xdebug
+ tools: composer:v2
+ - run: composer update --no-progress ${{ matrix.composer-flags }}
+ - run: composer phpstan
+ if: ${{ matrix.php == '7.4' }}
+ - run: vendor/bin/phpunit ${{ matrix.phpunit-flags }}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5fa7987
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+build
+vendor
+.idea
+.phpunit.result.cache
+composer.lock
diff --git a/Multiavatar.php b/Multiavatar.php
deleted file mode 100644
index 21c6dd6..0000000
--- a/Multiavatar.php
+++ /dev/null
@@ -1,655 +0,0 @@
-svgCode = $this->generate(strval($avatarId), $sansEnv, $ver);
- }
-
-
- public function getFinal($part, $partV, $theme, $themes, $sP) {
-
- $colors = $themes[$partV][$theme][$part];
- $svgString = $sP[$partV][$part];
-
- if (preg_match_all('/#(.*?)+(?=;)/', $svgString, $result)) {
- $i = 0;
- foreach ($result[0] as $var) {
- $pos = strpos($svgString, $var);
- if ($pos !== false) {
- $svgString = substr_replace($svgString, $colors[$i], $pos, strlen($var));
- }
- $i++;
- }
- }
-
- $resultFinal = $svgString;
- return $resultFinal;
- }
-
-
- public function generate($avatarId, $sansEnv, $ver) {
-
- $themes = [];
-
- // Robo
- $themes['00']['A']['env'] = [ "#ff2f2b" ];
- $themes['00']['A']['clo'] = ["#fff", "#000"];
- $themes['00']['A']['head'] = ["#fff"];
- $themes['00']['A']['mouth'] = ["#fff", "#000", "#000"];
- $themes['00']['A']['eyes'] = ["#000", "none", "#00FFFF"];
- $themes['00']['A']['top'] = ["#fff", "#fff"];
-
- $themes['00']['B']['env'] = ["#ff1ec1"];
- $themes['00']['B']['clo'] = ["#000", "#fff" ];
- $themes['00']['B']['head'] = ["#ffc1c1"];
- $themes['00']['B']['mouth'] = ["#fff", "#000", "#000"];
- $themes['00']['B']['eyes'] = ["#FF2D00", "#fff", "none"];
- $themes['00']['B']['top'] = ["#a21d00", "#fff"];
-
- $themes['00']['C']['env'] = ["#0079b1"];
- $themes['00']['C']['clo'] = ["#0e00b1", "#d1fffe"];
- $themes['00']['C']['head'] = ["#f5aa77"];
- $themes['00']['C']['mouth'] = ["#fff", "#000", "#000"];
- $themes['00']['C']['eyes'] = ["#0c00de", "#fff", "none"];
- $themes['00']['C']['top'] = ["#acfffd", "#acfffd"];
-
- // Girl
- $themes['01']['A']['env'] = ["#a50000"];
- $themes['01']['A']['clo'] = ["#f06", "#8e0039"];
- $themes['01']['A']['head'] = ["#85492C"];
- $themes['01']['A']['mouth'] = ["#000"];
- $themes['01']['A']['eyes'] = ["#000", "#ff9809"];
- $themes['01']['A']['top'] = ["#ff9809", "#ff9809", "none", "none"];
-
- $themes['01']['B']['env'] = ["#40E83B"];
- $themes['01']['B']['clo'] = ["#00650b", "#62ce5a"];
- $themes['01']['B']['head'] = ["#f7c1a6"];
- $themes['01']['B']['mouth'] = ["#6e1c1c"];
- $themes['01']['B']['eyes'] = ["#000", "#ff833b"];
- $themes['01']['B']['top'] = ["#67FFCC", "none", "none", "#ecff3b"];
-
- $themes['01']['C']['env'] = ["#ff2c2c"];
- $themes['01']['C']['clo'] = ["#fff", "#000"];
- $themes['01']['C']['head'] = ["#ffce8b"];
- $themes['01']['C']['mouth'] = ["#000"];
- $themes['01']['C']['eyes'] = ["#000", "#0072ff"];
- $themes['01']['C']['top'] = ["#ff9809", "none", "#ffc809", "none"];
-
- // Blonde
- $themes['02']['A']['env'] = ["#ff7520"];
- $themes['02']['A']['clo'] = ["#d12823"];
- $themes['02']['A']['head'] = ["#fee3c5"];
- $themes['02']['A']['mouth'] = ["#d12823"];
- $themes['02']['A']['eyes'] = ["#000", "none"];
- $themes['02']['A']['top'] = ["#000", "none", "none", "#FFCC00", "red"];
-
- $themes['02']['B']['env'] = ["#ff9700"];
- $themes['02']['B']['clo'] = ["#000"];
- $themes['02']['B']['head'] = ["#d2ad6d"];
- $themes['02']['B']['mouth'] = ["#000"];
- $themes['02']['B']['eyes'] = ["#000", "#00ffdc"];
- $themes['02']['B']['top'] = ["#fdff00", "#fdff00", "none", "none", "none"];
-
- $themes['02']['C']['env'] = ["#26a7ff"];
- $themes['02']['C']['clo'] = ["#d85cd7"];
- $themes['02']['C']['head'] = ["#542e02"];
- $themes['02']['C']['mouth'] = ["#f70014"];
- $themes['02']['C']['eyes'] = ["#000", "magenta"];
- $themes['02']['C']['top'] = ["#FFCC00", "#FFCC00", "#FFCC00", "#ff0000", "yellow"];
-
- // Evilnormie
- $themes['03']['A']['env'] = ["#6FC30E"];
- $themes['03']['A']['clo'] = ["#b4e1fa", "#5b5d6e", "#515262", "#a0d2f0", "#a0d2f0"];
- $themes['03']['A']['head'] = ["#fae3b9"];
- $themes['03']['A']['mouth'] = ["#fff", "#000"];
- $themes['03']['A']['eyes'] = ["#000"];
- $themes['03']['A']['top'] = ["#8eff45", "#8eff45", "none", "none"];
-
- $themes['03']['B']['env'] = ["#00a58c"];
- $themes['03']['B']['clo'] = ["#000", "#5b00", "#5100", "#a000", "#a000"];
- $themes['03']['B']['head'] = ["#FAD2B9"];
- $themes['03']['B']['mouth'] = ["#fff", "#000"];
- $themes['03']['B']['eyes'] = ["#000"];
- $themes['03']['B']['top'] = ["#FFC600", "none", "#FFC600", "none"];
-
- $themes['03']['C']['env'] = ["#ff501f"];
- $themes['03']['C']['clo'] = ["#000", "#ff0000", "#ff0000", "#7d7d7d", "#7d7d7d"];
- $themes['03']['C']['head'] = ["#fff3dc"];
- $themes['03']['C']['mouth'] = ["#d2001b", "none"];
- $themes['03']['C']['eyes'] = ["#000"];
- $themes['03']['C']['top'] = ["#D2001B", "none", "none", "#D2001B"];
-
- // Country
- $themes['04']['A']['env'] = ["#fc0"];
- $themes['04']['A']['clo'] = ["#901e0e", "#ffbe1e", "#ffbe1e", "#c55f54"];
- $themes['04']['A']['head'] = ["#f8d9ad"];
- $themes['04']['A']['mouth'] = ["#000", "none", "#000", "none"];
- $themes['04']['A']['eyes'] = ["#000"];
- $themes['04']['A']['top'] = ["#583D00", "#AF892E", "#462D00", "#a0a0a0"];
-
- $themes['04']['B']['env'] = ["#386465"];
- $themes['04']['B']['clo'] = ["#fff", "#333", "#333", "#333"];
- $themes['04']['B']['head'] = ["#FFD79D"];
- $themes['04']['B']['mouth'] = ["#000", "#000", "#000", "#000"];
- $themes['04']['B']['eyes'] = ["#000"];
- $themes['04']['B']['top'] = ["#27363C", "#5DCAD4", "#314652", "#333"];
-
- $themes['04']['C']['env'] = ["#DFFF00"];
- $themes['04']['C']['clo'] = ["#304267", "#aab0b1", "#aab0b1", "#aab0b1"];
- $themes['04']['C']['head'] = ["#e6b876"];
- $themes['04']['C']['mouth'] = ["#50230a", "#50230a", "#50230a", "#50230a"];
- $themes['04']['C']['eyes'] = ["#000"];
- $themes['04']['C']['top'] = ["#333", "#afafaf", "#222", "#6d3a1d"];
-
- // Johnyold
- $themes['05']['A']['env'] = ["#a09300"];
- $themes['05']['A']['clo'] = ["#c7d4e2", "#435363", "#435363", "#141720", "#141720", "#e7ecf2", "#e7ecf2"];
- $themes['05']['A']['head'] = ["#f5d4a6"];
- $themes['05']['A']['mouth'] = ["#000", "#cf9f76"];
- $themes['05']['A']['eyes'] = ["#000", "#000", "#000", "#000", "#000", "#000", "#fff", "#fff", "#fff", "#fff", "#000", "#000"];
- $themes['05']['A']['top'] = ["none", "#fdff00"];
-
- $themes['05']['B']['env'] = ["#b3003e"];
- $themes['05']['B']['clo'] = ["#000", "#435363", "#435363", "#000", "none", "#e7ecf2", "#e7ecf2"];
- $themes['05']['B']['head'] = ["#f5d4a6"];
- $themes['05']['B']['mouth'] = ["#000", "#af9f94"];
- $themes['05']['B']['eyes'] = ["#9ff3ffdb", "#000", "#9ff3ffdb", "#000", "#2f508a", "#000", "#000", "#000", "none", "none", "none", "none"];
- $themes['05']['B']['top'] = ["#ff9a00", "#ff9a00"];
-
- $themes['05']['C']['env'] = ["#884f00"];
- $themes['05']['C']['clo'] = ["#ff0000", "#fff", "#fff", "#141720", "#141720", "#e7ecf2", "#e7ecf2"];
- $themes['05']['C']['head'] = ["#c57b14"];
- $themes['05']['C']['mouth'] = ["#000", "#cf9f76"];
- $themes['05']['C']['eyes'] = ["none", "#000", "none", "#000", "#5a0000", "#000", "#000", "#000", "none", "none", "none", "none"];
- $themes['05']['C']['top'] = ["#efefef", "none"];
-
- // Asian
- $themes['06']['A']['env'] = ["#8acf00"];
- $themes['06']['A']['clo'] = ["#ee2829", "#ff0"];
- $themes['06']['A']['head'] = ["#ffce73"];
- $themes['06']['A']['mouth'] = ["#fff", "#000"];
- $themes['06']['A']['eyes'] = ["#000"];
- $themes['06']['A']['top'] = ["#000","#000","none", "#000", "#ff4e4e", "#000"];
-
- $themes['06']['B']['env'] = ["#00d2a3"];
- $themes['06']['B']['clo'] = ["#0D0046", "#ffce73"];
- $themes['06']['B']['head'] = ["#ffce73"];
- $themes['06']['B']['mouth'] = ["#000", "none"];
- $themes['06']['B']['eyes'] = ["#000"];
- $themes['06']['B']['top'] = ["#000","#000","#000", "none", "#ffb358", "#000", "none", "none"];
-
- $themes['06']['C']['env'] = ["#ff184e"];
- $themes['06']['C']['clo'] = ["#000", "none"];
- $themes['06']['C']['head'] = ["#ffce73"];
- $themes['06']['C']['mouth'] = ["#ff0000", "none"];
- $themes['06']['C']['eyes'] = ["#000"];
- $themes['06']['C']['top'] = ["none","none","none", "none", "none", "#ffc107", "none", "none"];
-
- // Punk
- $themes['07']['A']['env'] = ["#00deae"];
- $themes['07']['A']['clo'] = ["#ff0000"];
- $themes['07']['A']['head'] = ["#ffce94"];
- $themes['07']['A']['mouth'] = ["#f73b6c", "#000"];
- $themes['07']['A']['eyes'] = ["#e91e63", "#000", "#e91e63", "#000", "#000", "#000"];
- $themes['07']['A']['top'] = ["#dd104f", "#dd104f", "#f73b6c", "#dd104f"];
-
- $themes['07']['B']['env'] = ["#181284"];
- $themes['07']['B']['clo'] = ["#491f49", "#ff9809", "#491f49"];
- $themes['07']['B']['head'] = ["#f6ba97"];
- $themes['07']['B']['mouth'] = ["#ff9809", "#000"];
- $themes['07']['B']['eyes'] = ["#c4ffe4", "#000", "#c4ffe4", "#000", "#000", "#000"];
- $themes['07']['B']['top'] = [ "none", "none", "#d6f740", "#516303"];
-
- $themes['07']['C']['env'] = ["#bcf700"];
- $themes['07']['C']['clo'] = ["#ff14e4", "#000", "#14fffd"];
- $themes['07']['C']['head'] = ["#7b401e"];
- $themes['07']['C']['mouth'] = ["#666", "#000"];
- $themes['07']['C']['eyes'] = ["#00b5b4", "#000", "#00b5b4", "#000", "#000", "#000"];
- $themes['07']['C']['top'] = ["#14fffd", "#14fffd", "#14fffd", "#0d3a62"];
-
- // Afrohair
- $themes['08']['A']['env'] = ["#0df"];
- $themes['08']['A']['clo'] = ["#571e57", "#ff0"];
- $themes['08']['A']['head'] = ["#f2c280"];
- $themes['08']['A']['mouth'] = ["#795548", "#000"];
- $themes['08']['A']['eyes'] = ["#ff0000"];
- $themes['08']['A']['top'] = ["#de3b00", "none"];
-
- $themes['08']['B']['env'] = ["#B400C2"];
- $themes['08']['B']['clo'] = ["#0D204A", "#00ffdf"];
- $themes['08']['B']['head'] = ["#ca8628"];
- $themes['08']['B']['mouth'] = ["#cbbdaf", "#000"];
- $themes['08']['B']['eyes'] = ["#1a1a1a"];
- $themes['08']['B']['top'] = ["#000", "#000"];
-
- $themes['08']['C']['env'] = ["#ffe926"];
- $themes['08']['C']['clo'] = ["#00d6af", "#000"];
- $themes['08']['C']['head'] = ["#8c5100"];
- $themes['08']['C']['mouth'] = ["none", "#000"];
- $themes['08']['C']['eyes'] = ["#7d0000"];
- $themes['08']['C']['top'] = ["#f7f7f7", "none"];
-
- // Normie female
- $themes['09']['A']['env'] = ["#4aff0c"];
- $themes['09']['A']['clo'] = ["#101010", "#fff", "#fff"];
- $themes['09']['A']['head'] = ["#dbbc7f"];
- $themes['09']['A']['mouth'] = ["#000"];
- $themes['09']['A']['eyes'] = [ "#000", "none", "none"];
- $themes['09']['A']['top'] = ["#531148", "#531148", "#531148", "none"];
-
- $themes['09']['B']['env'] = ["#FFC107"];
- $themes['09']['B']['clo'] = ["#033c58", "#fff", "#fff"];
- $themes['09']['B']['head'] = ["#dbc97f"];
- $themes['09']['B']['mouth'] = ["#000"];
- $themes['09']['B']['eyes'] = ["none", "#fff", "#000"];
- $themes['09']['B']['top'] = ["#FFEB3B", "#FFEB3B", "none", "#FFEB3B"];
-
- $themes['09']['C']['env'] = ["#FF9800"];
- $themes['09']['C']['clo'] = ["#b40000", "#fff", "#fff"];
- $themes['09']['C']['head'] = ["#E2AF6B"];
- $themes['09']['C']['mouth'] = ["#000"];
- $themes['09']['C']['eyes'] = ["none", "#fff", "#000"];
- $themes['09']['C']['top'] = ["#ec0000", "#ec0000", "none", "none"];
-
- // Older
- $themes['10']['A']['env'] = ["#104c8c"];
- $themes['10']['A']['clo'] = ["#354B65", "#3D8EBB", "#89D0DA", "#00FFFD" ];
- $themes['10']['A']['head'] = ["#cc9a5c"];
- $themes['10']['A']['mouth'] = ["#222", "#fff"];
- $themes['10']['A']['eyes'] = ["#000", "#000"];
- $themes['10']['A']['top'] = ["#fff", "#fff", "none"];
-
- $themes['10']['B']['env'] = ["#0DC15C"];
- $themes['10']['B']['clo'] = ["#212121", "#fff", "#212121", "#fff", ];
- $themes['10']['B']['head'] = ["#dca45f"];
- $themes['10']['B']['mouth'] = ["#111", "#633b1d"];
- $themes['10']['B']['eyes'] = ["#000", "#000"];
- $themes['10']['B']['top'] = ["none", "#792B74", "#792B74"];
-
- $themes['10']['C']['env'] = ["#ffe500"];
- $themes['10']['C']['clo'] = ["#1e5e80", "#fff", "#1e5e80", "#fff"];
- $themes['10']['C']['head'] = ["#e8bc86"];
- $themes['10']['C']['mouth'] = ["#111", "none"];
- $themes['10']['C']['eyes'] = ["#000", "#000"];
- $themes['10']['C']['top'] = ["none", "none", "#633b1d"];
-
- // Firehair
- $themes['11']['A']['env'] = ["#4a3f73"];
- $themes['11']['A']['clo'] = ["#e6e9ee", "#f1543f", "#ff7058", "#fff", "#fff"];
- $themes['11']['A']['head'] = ["#b27e5b"];
- $themes['11']['A']['mouth'] = ["#191919", "#191919"];
- $themes['11']['A']['eyes'] = ["#000", "#000", "#57FFFD"];
- $themes['11']['A']['top'] = ["#ffc", "#ffc", "#ffc"];
-
- $themes['11']['B']['env'] = ["#00a08d"];
- $themes['11']['B']['clo'] = ["#FFBA32", "#484848", "#4e4e4e", "#fff", "#fff"];
- $themes['11']['B']['head'] = ["#ab5f2c"];
- $themes['11']['B']['mouth'] = ["#191919", "#191919"];
- $themes['11']['B']['eyes'] = ["#000", "#ff23fa63", "#000"];
- $themes['11']['B']['top'] = ["#ff90f4", "#ff90f4", "#ff90f4"];
-
- $themes['11']['C']['env'] = ["#22535d"];
- $themes['11']['C']['clo'] = ["#000", "#ff2500", "#ff2500", "#fff", "#fff"];
- $themes['11']['C']['head'] = ["#a76c44"];
- $themes['11']['C']['mouth'] = ["#191919", "#191919"];
- $themes['11']['C']['eyes'] = ["#000", "none", "#000"];
- $themes['11']['C']['top'] = ["none", "#00efff", "none"];
-
- // Blond
- $themes['12']['A']['env'] = ["#2668DC"];
- $themes['12']['A']['clo'] = ["#2385c6", "#b8d0e0", "#b8d0e0"];
- $themes['12']['A']['head'] = ["#ad8a60"];
- $themes['12']['A']['mouth'] = ["#000", "#4d4d4d"];
- $themes['12']['A']['eyes'] = ["#7fb5a2", "#d1eddf", "#301e19"];
- $themes['12']['A']['top'] = ["#fff510", "#fff510"];
-
- $themes['12']['B']['env'] = ["#643869"];
- $themes['12']['B']['clo'] = ["#D67D1B", "#b8d0e0", "#b8d0e0"];
- $themes['12']['B']['head'] = ["#CC985A", "none0000"];
- $themes['12']['B']['mouth'] = ["#000", "#ececec"];
- $themes['12']['B']['eyes'] = ["#1f2644", "#9b97ce", "#301e19"];
- $themes['12']['B']['top'] = ["#00eaff", "none"];
-
- $themes['12']['C']['env'] = ["#F599FF"];
- $themes['12']['C']['clo'] = ["#2823C6", "#b8d0e0", "#b8d0e0"];
- $themes['12']['C']['head'] = ["#C7873A"];
- $themes['12']['C']['mouth'] = ["#000", "#4d4d4d"];
- $themes['12']['C']['eyes'] = ["#581b1b", "#FF8B8B", "#000"];
- $themes['12']['C']['top'] = ["none", "#9c0092"];
-
- // Ateam
- $themes['13']['A']['env'] = ["#d10084"];
- $themes['13']['A']['clo'] = ["#efedee", "#00a1e0", "#00a1e0", "#efedee", "#ffce1c"];
- $themes['13']['A']['head'] = ["#b35f49"];
- $themes['13']['A']['mouth'] = ["#3a484a", "#000"];
- $themes['13']['A']['eyes'] = ["#000"];
- $themes['13']['A']['top'] = ["#000", "none", "#000", "none"];
-
- $themes['13']['B']['env'] = ["#E6C117"];
- $themes['13']['B']['clo'] = ["#efedee", "#ec0033", "#ec0033", "#efedee", "#f2ff05"];
- $themes['13']['B']['head'] = ["#ffc016"];
- $themes['13']['B']['mouth'] = ["#4a3737", "#000"];
- $themes['13']['B']['eyes'] = ["#000"];
- $themes['13']['B']['top'] = ["#ffe900", "#ffe900", "none", "#ffe900"];
-
- $themes['13']['C']['env'] = ["#1d8c00"];
- $themes['13']['C']['clo'] = ["#e000cb", "#fff", "#fff", "#e000cb", "#ffce1c"];
- $themes['13']['C']['head'] = ["#b96438"];
- $themes['13']['C']['mouth'] = ["#000", "#000"];
- $themes['13']['C']['eyes'] = ["#000"];
- $themes['13']['C']['top'] = ["#53ffff", "#53ffff", "none", "none"];
-
- // Rasta
- $themes['14']['A']['env'] = ["#fc0065"];
- $themes['14']['A']['clo'] = ["#708913", "#fdea14", "#708913", "#fdea14", "#708913"];
- $themes['14']['A']['head'] = ["#DEA561"];
- $themes['14']['A']['mouth'] = ["#444", "#000"];
- $themes['14']['A']['eyes'] = ["#000"];
- $themes['14']['A']['top'] = ["#32393f", "#32393f", "#32393f", "#32393f", "#32393f", "#32393f", "#32393f", "#32393f", "#32393f", "#32393f", "#32393f", "#32393f", "#32393f", "#32393f", "#32393f", "#32393f", "#32393f" ];
-
- $themes['14']['B']['env'] = ["#81f72e"];
- $themes['14']['B']['clo'] = ["#ff0000", "#ffc107", "#ff0000", "#ffc107", "#ff0000"];
- $themes['14']['B']['head'] = ["#ef9831"];
- $themes['14']['B']['mouth'] = ["#6b0000", "#000"];
- $themes['14']['B']['eyes'] = ["#000"];
- $themes['14']['B']['top'] = ["#FFFAAD", "#FFFAAD", "#FFFAAD", "#FFFAAD", "#FFFAAD", "#FFFAAD", "#FFFAAD", "#FFFAAD", "#FFFAAD", "#FFFAAD", "#FFFAAD", "#FFFAAD", "#FFFAAD", "none", "none", "none", "none"];
-
- $themes['14']['C']['env'] = ["#00D872"];
- $themes['14']['C']['clo'] = ["#590D00", "#FD1336", "#590D00", "#FD1336", "#590D00"];
- $themes['14']['C']['head'] = ["#c36c00"];
- $themes['14']['C']['mouth'] = ["#56442b", "#000"];
- $themes['14']['C']['eyes'] = ["#000"];
- $themes['14']['C']['top'] = ["#004E4C", "#004E4C", "#004E4C", "#004E4C", "#004E4C", "#004E4C", "#004E4C", "#004E4C", "#004E4C", "none", "none", "none", "none", "none", "none", "none", "none"];
-
- // Meta
- $themes['15']['A']['env'] = ["#111"];
- $themes['15']['A']['clo'] = ["#000", "#00FFFF"];
- $themes['15']['A']['head'] = ["#755227"];
- $themes['15']['A']['mouth'] = ["#fff", "#000"];
- $themes['15']['A']['eyes'] = ["black", "#008a", "aqua"];
- $themes['15']['A']['top'] = ["#fff", "#fff", "#fff", "#fff", "#fff"];
-
- $themes['15']['B']['env'] = ["#00D0D4"];
- $themes['15']['B']['clo'] = ["#000", "#fff"];
- $themes['15']['B']['head'] = ["#755227"];
- $themes['15']['B']['mouth'] = ["#fff", "#000"];
- $themes['15']['B']['eyes'] = ["black", "#1df7ffa3", "#fcff2c"];
- $themes['15']['B']['top'] = ["#fff539", "none", "#fff539", "none", "#fff539"];
-
- $themes['15']['C']['env'] = ["#DC75FF"];
- $themes['15']['C']['clo'] = ["#000", "#FFBDEC"];
- $themes['15']['C']['head'] = ["#997549"];
- $themes['15']['C']['mouth'] = ["#fff", "#000"];
- $themes['15']['C']['eyes'] = ["black", "black", "aqua"];
- $themes['15']['C']['top'] = ["#00fffd", "none", "none", "none", "none"];
-
-
- // Optimization
- $sP = [];
- $svgStart = '';
- $env = '';
- $head = '';
- $str = 'stroke-linecap:round;stroke-linejoin:round;stroke-width:';
-
-
- // SHAPES
-
- // Robo
- $sP['00']['env'] = $env;
- $sP['00']['clo'] = '';
- $sP['00']['head'] = $head;
- $sP['00']['mouth'] = '';
- $sP['00']['eyes'] = '';
- $sP['00']['top'] = '';
-
- // Girl
- $sP['01'] = [];
- $sP['01']['env'] = $env;
- $sP['01']['clo'] = '';
- $sP['01']['head'] = $head;
- $sP['01']['mouth'] = '';
- $sP['01']['eyes'] = '';
- $sP['01']['top'] = '';
-
- // Blonde
- $sP['02'] = [];
- $sP['02']['env'] = $env;
- $sP['02']['clo'] = '';
- $sP['02']['head'] = $head;
- $sP['02']['mouth'] = '';
- $sP['02']['eyes'] = '';
- $sP['02']['top'] = '';
-
- // Guy
- $sP['03'] = [];
- $sP['03']['env'] = $env;
- $sP['03']['clo'] = '';
- $sP['03']['head'] = $head;
- $sP['03']['mouth'] = '';
- $sP['03']['eyes'] = '';
- $sP['03']['top'] = '';
-
- // Country
- $sP['04'] = [];
- $sP['04']['env'] = $env;
- $sP['04']['clo'] = '';
- $sP['04']['head'] = $head;
- $sP['04']['mouth'] = '';
- $sP['04']['eyes'] = '';
- $sP['04']['top'] = '';
-
- // Geeknot
- $sP['05'] = [];
- $sP['05']['env'] = $env;
- $sP['05']['clo'] = '';
- $sP['05']['head'] = $head;
- $sP['05']['mouth'] = '';
- $sP['05']['eyes'] = '';
- $sP['05']['top'] = '';
-
- // Asian
- $sP['06'] = [];
- $sP['06']['env'] = $env;
- $sP['06']['clo'] = '';
- $sP['06']['head'] = $head;
- $sP['06']['mouth'] = '';
- $sP['06']['eyes'] = '';
- $sP['06']['top'] = '';
-
- // Punk
- $sP['07'] = [];
- $sP['07']['env'] = $env;
- $sP['07']['clo'] = '';
- $sP['07']['head'] = $head;
- $sP['07']['mouth'] = '';
- $sP['07']['eyes'] = '';
- $sP['07']['top'] = '';
-
- // Afrohair
- $sP['08'] = [];
- $sP['08']['env'] = $env;
- $sP['08']['clo'] = '';
- $sP['08']['head'] = $head;
- $sP['08']['mouth'] = '';
- $sP['08']['eyes'] = '';
- $sP['08']['top'] = '';
-
- // Normie Female
- $sP['09'] = [];
- $sP['09']['env'] = $env;
- $sP['09']['clo'] = '';
- $sP['09']['head'] = $head;
- $sP['09']['mouth'] = '';
- $sP['09']['eyes'] = '';
- $sP['09']['top'] = '';
-
- // Older
- $sP['10'] = [];
- $sP['10']['env'] = $env;
- $sP['10']['clo'] = '';
- $sP['10']['head'] = $head;
- $sP['10']['mouth'] = '';
- $sP['10']['eyes'] = '';
- $sP['10']['top'] = '';
-
- // Firehair
- $sP['11'] = [];
- $sP['11']['env'] = $env;
- $sP['11']['clo'] = '';
- $sP['11']['head'] = $head;
- $sP['11']['mouth'] = '';
- $sP['11']['eyes'] = '';
- $sP['11']['top'] = '';
-
- // Blond
- $sP['12'] = [];
- $sP['12']['env'] = $env;
- $sP['12']['clo'] = '';
- $sP['12']['head'] = $head;
- $sP['12']['mouth'] = '';
- $sP['12']['eyes'] = '';
- $sP['12']['top'] = '';
-
- // Ateam
- $sP['13'] = [];
- $sP['13']['env'] = $env;
- $sP['13']['clo'] = '';
- $sP['13']['head'] = $head;
- $sP['13']['mouth'] = '';
- $sP['13']['eyes'] = '';
- $sP['13']['top'] = '';
-
- // Rasta
- $sP['14'] = [];
- $sP['14']['env'] = $env;
- $sP['14']['clo'] = '';
- $sP['14']['head'] = $head;
- $sP['14']['mouth'] = '';
- $sP['14']['eyes'] = '';
- $sP['14']['top'] = '';
-
- // Meta
- $sP['15'] = [];
- $sP['15']['env'] = $env;
- $sP['15']['clo'] = '';
- $sP['15']['head'] = $head;
- $sP['15']['mouth'] = '';
- $sP['15']['eyes'] = '';
- $sP['15']['top'] = '';
-
-
- // Multiavatar algorithm
- $hash = '';
-
- if (strlen($avatarId) == 0) return $hash;
-
- $sha256Hash = hash('sha256', $avatarId);
- $sha256Numbers = preg_replace("/[^0-9]/", "", $sha256Hash);
- $hash = substr($sha256Numbers, 0, 12);
-
-
- // Parts
- $p = [];
-
- // Get parts (range 0-47)
- $p['env'] = $hash[0] . '' . $hash[1];
- $p['env'] = round((47/100)*$p['env']);
-
- // Freeze a single part
- // e.g. '0' = 01A; '16' = 01B; '32' = 01C; '1' = 02A; '17' = 02B;
- // p['env'] = '16';
-
- $p['clo'] = $hash[2] . '' . $hash[3];
- $p['clo'] = round((47/100)*$p['clo']);
-
- // p['clo'] = '16';
-
- $p['head'] = $hash[4] . '' . $hash[5];
- $p['head'] = round((47/100)*$p['head']);
-
- // p['head'] = '01';
-
- $p['mouth'] = $hash[6] . '' . $hash[7];
- $p['mouth'] = round((47/100)*$p['mouth']);
-
- // p['mouth'] = '16';
-
- $p['eyes'] = $hash[8] . '' . $hash[9];
- $p['eyes'] = round((47/100)*$p['eyes']);
-
- // p['eyes'] = '16';
-
- $p['top'] = $hash[10] . '' . $hash[11];
- $p['top'] = round((47/100)*$p['top']);
-
- // p['top'] = '25';
-
-
- // Get parts (range 0-15) + define themes
- foreach ($p as $key => $part) {
- $nr = $part;
-
- if ($nr > 31) {
- $nr = $nr - 32 . '';
- if ($nr < 10) $nr = '0' . $nr;
- $p[$key] = $nr . 'C';
- }
- else if ($nr > 15) {
- $nr = $nr - 16;
- if ($nr < 10) $nr = '0' . $nr;
- $p[$key] = $nr . 'B';
- }
- else {
- if ($nr < 10) $p[$key] = '0' . $nr . 'A';
- else $p[$key] = $nr . 'A';
- }
- }
-
-
- // Get the SVG code for each part
- $final = [];
-
- foreach ($p as $key => $part) {
- $partV = substr($p[$key], 0, 2);
- $theme = substr($p[$key], 2, 3);
-
- if ($ver != null) {
- $partV = $ver['part'];
- $theme = $ver['theme'];
- }
-
- // Freeze a single base version
- // $partV = '00'; $theme = 'A';
-
- $final[$key] = $this->getFinal($key, $partV, $theme, $themes, $sP);
- }
-
-
- // Without 'env'
- if ($sansEnv) {
- $final['env'] = '';
- }
-
- return($svgStart . $final['env'] . $final['head'] . $final['clo'] . $final['top'] . $final['eyes'] . $final['mouth'] . $svgEnd);
- }
-}
diff --git a/README.md b/README.md
index d10aadc..8d22f4e 100644
--- a/README.md
+++ b/README.md
@@ -10,13 +10,12 @@ Initially coded in JavaScript, this version of Multiavatar is re-created in PHP.
For more details about the Multiavatar Generator, please refer to the readme available in the JS [repository](https://github.com/multiavatar/Multiavatar).
-
### Installation ###
-If you don't use composer, just include `Multiavatar.php` in your application.
+If you don't use composer, just include the autoloader in the root of the directory in your application.
```
-require_once('Multiavatar.php');
+require_once '/path/to/directory/Multiavatar/autoload.php';
```
Via Composer:
@@ -25,27 +24,100 @@ Via Composer:
composer require multiavatar/multiavatar-php
```
-
### Usage ###
-```
+```php
+svgCode);
+echo $multiavatar($avatarId);
```
-For advanced usage, pass boolean `true` as the second parameter if you wish to generate an avatar without the environment part.
+For advanced usage, you can pass an array as a second and last parameter as shown below:
+
+```php
+ [
+ 'part' => '11',
+ 'theme' => 'C',
+ ],
+ 'sansEnv' => true,
+];
+
+echo $multiavatar($avatarId, $options);
```
-$avatarId = "ANY_STRING";
-$multiavatar = new Multiavatar($avatarId, true, array("part" => 11, "theme" => "C"));
-echo($multiavatar->svgCode);
+The option array contains the following indexes:
+
+- `sansEnv`: Tells whether the environment should be display or not. By default, the environment is display.
+ To remove the environment you should set the value to `true.
+
+- `version`: Indicate which theme and shape should be used to generate the avatar.
+ There is 3 themes that you specify with the `theme` index named from `A` to `C`
+ and 16 shapes specified with the `part` index whose named ranged from `00` to `15`.
+
+Each of those values can be set independently of each other.
+
+```php
+ true]);
+
+// Generate a specific version
+// version shape can be express in integer or in string containing only numbers.
+$avatarId = "Pandalion";
+echo $multiavatar($avatarId, ['sansEnv' => false, 'ver' => ['part' => 11, 'theme' => 'C']]);
+
+// The avatarId can be a string or an integer
+// version theme are case insensitive.
+// The shape will be selected from the $avatarId
+$avatarId = 123456789;
+echo $multiavatar($avatarId, ['sansEnv' => false, 'ver' => ['theme' => 'b']]);
+
+// Test with a specific shape
+// The theme will be selected from the avatarId
+$avatarId = "a86f755add37fe0b649c";
+echo $multiavatar($avatarId, ['ver' => ['part' => '08']]);
+
+$avatarId = "f7542474d54d2d2d97e4";
+echo $multiavatar($avatarId);
```
-See `index.php` for examples.
+### Testing ###
+
+The library has a :
+
+- a [PHPUnit](https://phpunit.de) test suite
+- a code analysis compliance test suite using [PHPStan](https://phpstan.org).
+To run the tests, run the following command from the project folder.
+
+``` bash
+$ composer test
+```
### API ###
@@ -65,7 +137,6 @@ fetch('https://api.multiavatar.com/v1/'
.then(svg => console.log(svg))
```
-
### License ###
You can use Multiavatar for free, as long as the conditions described in the [LICENSE](https://multiavatar.com/license) are followed.
@@ -88,4 +159,4 @@ For additional information and extended functionality, visit the [multiavatar.co
The app is based on static html for the home page, and on Laravel 8 + Vue.js for extended functionality, including the web store.
-The product mockup generator for the [Merch Maker](https://multiavatar.com/merch-maker) is based on the ImageMagick PHP library.
\ No newline at end of file
+The product mockup generator for the [Merch Maker](https://multiavatar.com/merch-maker) is based on the ImageMagick PHP library.
diff --git a/autoload.php b/autoload.php
new file mode 100644
index 0000000..9b27649
--- /dev/null
+++ b/autoload.php
@@ -0,0 +1,16 @@
+=7.1",
+ "phpunit/phpunit": "^8.0 || ^9.5",
+ "phpstan/phpstan": "^0.12.63",
+ "phpstan/phpstan-strict-rules": "^0.12.7",
+ "phpstan/phpstan-phpunit": "^0.12.17"
+ },
+ "scripts": {
+ "phpstan": "phpstan analyse src -c phpstan.neon --ansi",
+ "phpunit": "phpunit --coverage-text",
+ "test": [
+ "@phpunit",
+ "@phpstan"
+ ]
+ },
+ "scripts-descriptions": {
+ "phpstan": "Static analysis of PHP scripts",
+ "phpunit": "Runs unit and functional testing"
}
}
diff --git a/demo/index.php b/demo/index.php
new file mode 100644
index 0000000..4d01963
--- /dev/null
+++ b/demo/index.php
@@ -0,0 +1,61 @@
+ ['part' => $part, 'theme' => $theme]]);
+ }
+}
+?>
+
+
+
+
+
+
+ Multiavatar - All 48 Initial Avatar Designs
+
+
+
+
+ $svg): ?>
+
=$svg?>
+
+
+
+
+
diff --git a/index.php b/index.php
deleted file mode 100644
index 9cc950b..0000000
--- a/index.php
+++ /dev/null
@@ -1,36 +0,0 @@
-svgCode);
-
-
-// Without the environment part
-$avatarId = "Pandalion";
-$multiavatar = new Multiavatar($avatarId, true, null);
-echo($multiavatar->svgCode);
-
-
-// Generate a specific version
-$avatarId = "Pandalion";
-$multiavatar = new Multiavatar($avatarId, null, array("part" => 11, "theme" => "C"));
-echo($multiavatar->svgCode);
-
-
-// Test with integer
-$avatarId = 123456789;
-$multiavatar = new Multiavatar($avatarId, null, null);
-echo($multiavatar->svgCode);
-
-
-// $avatarId = "a86f755add37fe0b649c";
-// $multiavatar = new Multiavatar($avatarId, null, null);
-// echo($multiavatar->svgCode);
-
-
-// $avatarId = "f7542474d54d2d2d97e4";
-// $multiavatar = new Multiavatar($avatarId, null, null);
-// echo($multiavatar->svgCode);
\ No newline at end of file
diff --git a/phpstan.neon b/phpstan.neon
new file mode 100644
index 0000000..6f33fba
--- /dev/null
+++ b/phpstan.neon
@@ -0,0 +1,8 @@
+includes:
+ - vendor/phpstan/phpstan-strict-rules/rules.neon
+ - vendor/phpstan/phpstan-phpunit/rules.neon
+parameters:
+ level: max
+ checkMissingIterableValueType: false
+ ignoreErrors:
+ reportUnmatchedIgnoredErrors: true
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
new file mode 100644
index 0000000..eda5739
--- /dev/null
+++ b/phpunit.xml.dist
@@ -0,0 +1,36 @@
+
+
+
+
+ src
+
+
+ src
+
+
+
+
+
+
+
+
+
+ src
+
+
+
+
+
+
diff --git a/src/Multiavatar.php b/src/Multiavatar.php
new file mode 100644
index 0000000..8937067
--- /dev/null
+++ b/src/Multiavatar.php
@@ -0,0 +1,773 @@
+';
+ private const SVG_ROOT_CLOSE_TAG = '';
+ private const SVG_ELEMENT_ENV = '';
+ private const SVG_ELEMENT_HEAD = '';
+ private const SVG_ELEMENT_BASE_STYLE_PROPERTIES = 'stroke-linecap:round;stroke-linejoin:round;stroke-width:';
+ private const THEME_LIST = [0 => 'A', 1 => 'B', 2 => 'C'];
+ private const BODY_PARTS = ['env', 'head', 'clo', 'top', 'eyes', 'mouth'];
+
+ public const DEFAULT_OPTIONS = [
+ 'ver' => [
+ 'part' => null, // string|int - the version part between '00' and '15'
+ 'theme' => null, // string - the version theme to choose between 'A' and 'C'
+ ],
+ 'sansEnv' => false, // boolean - Tells whether to display or not the environment (by default the environment is shown)
+ ];
+
+ /**
+ * @var array>>>
+ */
+ private static $themes = [];
+
+ /**
+ * @var array>
+ */
+ private static $shapes = [];
+
+ /**
+ * @param mixed $avatarId the avatar id if it is an object it must implement the __toString method
+ * @param array $options
+ */
+ public function __invoke($avatarId, array $options = self::DEFAULT_OPTIONS): string
+ {
+ $avatarId = $this->filterAvatar($avatarId);
+ $options = $this->filterOptions($options);
+ if ('' === $avatarId) {
+ return '';
+ }
+
+ $parts = $this->setParts($avatarId, $options);
+ $elements = $this->partsToElements($parts);
+ $elements = $this->filterElements($elements, $options);
+
+ return self::SVG_ROOT_OPEN_TAG
+ . $elements['env']
+ . $elements['head']
+ . $elements['clo']
+ . $elements['top']
+ . $elements['eyes']
+ . $elements['mouth']
+ . self::SVG_ROOT_CLOSE_TAG;
+ }
+
+ /**
+ * @param mixed $avatarId the avatar Id
+ */
+ private function filterAvatar($avatarId): string
+ {
+ if (is_object($avatarId) && method_exists($avatarId, '__toString')) {
+ $avatarId = (string) $avatarId;
+ }
+
+ if (!is_scalar($avatarId)) {
+ throw new TypeError('Expected a scalar or a Stringable object; got: ' . (is_object($avatarId) ? get_class($avatarId) : gettype($avatarId)));
+ }
+
+ return trim((string) $avatarId);
+ }
+
+ /**
+ * @return array{ver:array{part:string|null, theme:string|null}, sansEnv:bool}
+ */
+ private function filterOptions(array $inputOptions): array
+ {
+ $options = self::DEFAULT_OPTIONS;
+ $options['sansEnv'] = filter_var($inputOptions['sansEnv'] ?? false, FILTER_VALIDATE_BOOLEAN);
+
+ if (isset($inputOptions['ver']['part'])) {
+ if (!is_string($inputOptions['ver']['part']) && !is_numeric($inputOptions['ver']['part'])) {
+ throw new InvalidArgumentException('The version part is expected to be a scalar; '.gettype($inputOptions['ver']['part']).' was given.');
+ }
+
+ $part = sprintf("%'.02d", $inputOptions['ver']['part']);
+ if (1 !== preg_match('/^(0[0-9])|(1[0-5])$/', $part)) {
+ throw new InvalidArgumentException('The version part does not exists; expecting a value between `00` and `15`.');
+ }
+
+ $options['ver']['part'] = $part;
+ }
+
+ if (!isset($inputOptions['ver']['theme'])) {
+ return $options;
+ }
+
+ if (!is_string($inputOptions['ver']['theme'])) {
+ throw new InvalidArgumentException('The version theme is expected to be a string; '.gettype($inputOptions['ver']['theme']).' was given.');
+ }
+
+ if (1 !== preg_match('/^[a-c]$/i', $inputOptions['ver']['theme'])) {
+ throw new InvalidArgumentException('The version theme does not exists; expecting a value between `A`, `B` and `C`.');
+ }
+
+ $options['ver']['theme'] = strtoupper($inputOptions['ver']['theme']);
+
+ return $options;
+ }
+
+ /**
+ * @param array{ver:array{part:string|null, theme:string|null}, sansEnv:bool} $options
+ *
+ * @return array{env:array{part:string, theme:string}, clo:array{part:string, theme:string}, head:array{part:string, theme:string}, mouth:array{part:string, theme:string}, eyes:array{part:string, theme:string}, top:array{part:string, theme:string}}
+ */
+ private function setParts(string $avatarId, array $options): array
+ {
+ if (isset($options['ver']['theme'], $options['ver']['part'])) {
+ return array_fill_keys(self::BODY_PARTS, $options['ver']);
+ }
+
+ /** @var string $str */
+ $str = preg_replace('/\D/', '', hash('sha256', $avatarId));
+ $hash = substr($str, 0, 12);
+
+ /** @var array{env:array{part:string, theme:string}, clo:array{part:string, theme:string}, head:array{part:string, theme:string}, mouth:array{part:string, theme:string}, eyes:array{part:string, theme:string}, top:array{part:string, theme:string}} $parts */
+ $parts = array_combine(self::BODY_PARTS, array_map([$this, 'stringToVersion'], str_split($hash, 2)));
+
+ if (isset($options['ver']['theme'])) {
+ $theme = $options['ver']['theme'];
+
+ /** @var array{env:array{part:string, theme:string}, clo:array{part:string, theme:string}, head:array{part:string, theme:string}, mouth:array{part:string, theme:string}, eyes:array{part:string, theme:string}, top:array{part:string, theme:string}} $parts */
+ $parts = array_map(function (array $settings) use ($theme): array {
+ $settings['theme'] = $theme;
+
+ return $settings;
+ }, $parts);
+
+ return $parts;
+ }
+
+ if (isset($options['ver']['part'])) {
+ $part = $options['ver']['part'];
+
+ /** @var array{env:array{part:string, theme:string}, clo:array{part:string, theme:string}, head:array{part:string, theme:string}, mouth:array{part:string, theme:string}, eyes:array{part:string, theme:string}, top:array{part:string, theme:string}} $parts */
+ $parts = array_map(function (array $settings) use ($part): array {
+ $settings['part'] = $part;
+
+ return $settings;
+ }, $parts);
+ }
+
+ return $parts;
+ }
+
+ /**
+ * @return array{part:string, theme:string}
+ */
+ private function stringToVersion(string $part): array
+ {
+ $part = (int) round(47 / 100 * (int) $part);
+
+ return [
+ 'part' => sprintf("%'.02d", $part % 16),
+ 'theme' => self::THEME_LIST[intdiv($part, 16)],
+ ];
+ }
+
+ /**
+ * @param array{env:array{part:string, theme:string}, clo:array{part:string, theme:string}, head:array{part:string, theme:string}, mouth:array{part:string, theme:string}, eyes:array{part:string, theme:string}, top:array{part:string, theme:string}} $parts
+ *
+ * @return array{env:string, clo:string, head:string, mouth:string, eyes:string, top:string}
+ */
+ private function partsToElements(array $parts): array
+ {
+ $reducer = function(array $elements, string $name) use ($parts): array {
+ $elements[$name] = $this->createElement($name, $parts[$name]['part'], $parts[$name]['theme']);
+
+ return $elements;
+ };
+
+ /** @var array{env:string, clo:string, head:string, mouth:string, eyes:string, top:string} $elements */
+ $elements = array_reduce(self::BODY_PARTS, $reducer, []);
+
+ return $elements;
+ }
+
+ private function createElement(string $name, string $part, string $theme): string
+ {
+ $colors = self::themes()[$part][$theme][$name];
+ $index = 0;
+ $replace = function (array $result) use ($colors, &$index): string {
+ return $colors[$index++];
+ };
+
+ /** @var string $element */
+ $element = preg_replace_callback('/#(.*?)+(?=;)/', $replace, self::shapes()[$part][$name]);
+
+ return $element;
+ }
+
+ /**
+ * @param array{env:string, clo:string, head:string, mouth:string, eyes:string, top:string} $elements
+ * @param array{ver:array{part:string|null, theme:string|null}, sansEnv:bool} $options
+ *
+ * @return array{env:string, clo:string, head:string, mouth:string, eyes:string, top:string}
+ */
+ private function filterElements(array $elements, array $options): array
+ {
+ if ($options['sansEnv']) {
+ $elements['env'] = '';
+ }
+
+ return $elements;
+ }
+
+ /**
+ * @return array>
+ */
+ private static function shapes(): array
+ {
+ if ([] !== self::$shapes) {
+ return self::$shapes;
+ }
+
+ // Robo
+ self::$shapes['00']['env'] = self::SVG_ELEMENT_ENV;
+ self::$shapes['00']['clo'] = '';
+ self::$shapes['00']['head'] = self::SVG_ELEMENT_HEAD;
+ self::$shapes['00']['mouth'] = '';
+ self::$shapes['00']['eyes'] = '';
+ self::$shapes['00']['top'] = '';
+
+ // Girl
+ self::$shapes['01'] = [];
+ self::$shapes['01']['env'] = self::SVG_ELEMENT_ENV;
+ self::$shapes['01']['clo'] = '';
+ self::$shapes['01']['head'] = self::SVG_ELEMENT_HEAD;
+ self::$shapes['01']['mouth'] = '';
+ self::$shapes['01']['eyes'] = '';
+ self::$shapes['01']['top'] = '';
+
+ // Blonde
+ self::$shapes['02'] = [];
+ self::$shapes['02']['env'] = self::SVG_ELEMENT_ENV;
+ self::$shapes['02']['clo'] = '';
+ self::$shapes['02']['head'] = self::SVG_ELEMENT_HEAD;
+ self::$shapes['02']['mouth'] = '';
+ self::$shapes['02']['eyes'] = '';
+ self::$shapes['02']['top'] = '';
+
+ // Guy
+ self::$shapes['03'] = [];
+ self::$shapes['03']['env'] = self::SVG_ELEMENT_ENV;
+ self::$shapes['03']['clo'] = '';
+ self::$shapes['03']['head'] = self::SVG_ELEMENT_HEAD;
+ self::$shapes['03']['mouth'] = '';
+ self::$shapes['03']['eyes'] = '';
+ self::$shapes['03']['top'] = '';
+
+ // Country
+ self::$shapes['04'] = [];
+ self::$shapes['04']['env'] = self::SVG_ELEMENT_ENV;
+ self::$shapes['04']['clo'] = '';
+ self::$shapes['04']['head'] = self::SVG_ELEMENT_HEAD;
+ self::$shapes['04']['mouth'] = '';
+ self::$shapes['04']['eyes'] = '';
+ self::$shapes['04']['top'] = '';
+
+ // Geeknot
+ self::$shapes['05'] = [];
+ self::$shapes['05']['env'] = self::SVG_ELEMENT_ENV;
+ self::$shapes['05']['clo'] = '';
+ self::$shapes['05']['head'] = self::SVG_ELEMENT_HEAD;
+ self::$shapes['05']['mouth'] = '';
+ self::$shapes['05']['eyes'] = '';
+ self::$shapes['05']['top'] = '';
+
+ // Asian
+ self::$shapes['06'] = [];
+ self::$shapes['06']['env'] = self::SVG_ELEMENT_ENV;
+ self::$shapes['06']['clo'] = '';
+ self::$shapes['06']['head'] = self::SVG_ELEMENT_HEAD;
+ self::$shapes['06']['mouth'] = '';
+ self::$shapes['06']['eyes'] = '';
+ self::$shapes['06']['top'] = '';
+
+ // Punk
+ self::$shapes['07'] = [];
+ self::$shapes['07']['env'] = self::SVG_ELEMENT_ENV;
+ self::$shapes['07']['clo'] = '';
+ self::$shapes['07']['head'] = self::SVG_ELEMENT_HEAD;
+ self::$shapes['07']['mouth'] = '';
+ self::$shapes['07']['eyes'] = '';
+ self::$shapes['07']['top'] = '';
+
+ // Afrohair
+ self::$shapes['08'] = [];
+ self::$shapes['08']['env'] = self::SVG_ELEMENT_ENV;
+ self::$shapes['08']['clo'] = '';
+ self::$shapes['08']['head'] = self::SVG_ELEMENT_HEAD;
+ self::$shapes['08']['mouth'] = '';
+ self::$shapes['08']['eyes'] = '';
+ self::$shapes['08']['top'] = '';
+
+ // Normie Female
+ self::$shapes['09'] = [];
+ self::$shapes['09']['env'] = self::SVG_ELEMENT_ENV;
+ self::$shapes['09']['clo'] = '';
+ self::$shapes['09']['head'] = self::SVG_ELEMENT_HEAD;
+ self::$shapes['09']['mouth'] = '';
+ self::$shapes['09']['eyes'] = '';
+ self::$shapes['09']['top'] = '';
+
+ // Older
+ self::$shapes['10'] = [];
+ self::$shapes['10']['env'] = self::SVG_ELEMENT_ENV;
+ self::$shapes['10']['clo'] = '';
+ self::$shapes['10']['head'] = self::SVG_ELEMENT_HEAD;
+ self::$shapes['10']['mouth'] = '';
+ self::$shapes['10']['eyes'] = '';
+ self::$shapes['10']['top'] = '';
+
+ // Firehair
+ self::$shapes['11'] = [];
+ self::$shapes['11']['env'] = self::SVG_ELEMENT_ENV;
+ self::$shapes['11']['clo'] = '';
+ self::$shapes['11']['head'] = self::SVG_ELEMENT_HEAD;
+ self::$shapes['11']['mouth'] = '';
+ self::$shapes['11']['eyes'] = '';
+ self::$shapes['11']['top'] = '';
+
+ // Blond
+ self::$shapes['12'] = [];
+ self::$shapes['12']['env'] = self::SVG_ELEMENT_ENV;
+ self::$shapes['12']['clo'] = '';
+ self::$shapes['12']['head'] = self::SVG_ELEMENT_HEAD;
+ self::$shapes['12']['mouth'] = '';
+ self::$shapes['12']['eyes'] = '';
+ self::$shapes['12']['top'] = '';
+
+ // Ateam
+ self::$shapes['13'] = [];
+ self::$shapes['13']['env'] = self::SVG_ELEMENT_ENV;
+ self::$shapes['13']['clo'] = '';
+ self::$shapes['13']['head'] = self::SVG_ELEMENT_HEAD;
+ self::$shapes['13']['mouth'] = '';
+ self::$shapes['13']['eyes'] = '';
+ self::$shapes['13']['top'] = '';
+
+ // Rasta
+ self::$shapes['14'] = [];
+ self::$shapes['14']['env'] = self::SVG_ELEMENT_ENV;
+ self::$shapes['14']['clo'] = '';
+ self::$shapes['14']['head'] = self::SVG_ELEMENT_HEAD;
+ self::$shapes['14']['mouth'] = '';
+ self::$shapes['14']['eyes'] = '';
+ self::$shapes['14']['top'] = '';
+
+ // Meta
+ self::$shapes['15'] = [];
+ self::$shapes['15']['env'] = self::SVG_ELEMENT_ENV;
+ self::$shapes['15']['clo'] = '';
+ self::$shapes['15']['head'] = self::SVG_ELEMENT_HEAD;
+ self::$shapes['15']['mouth'] = '';
+ self::$shapes['15']['eyes'] = '';
+ self::$shapes['15']['top'] = '';
+
+ return self::$shapes;
+ }
+
+ /**
+ * @return array>>>
+ */
+ private static function themes(): array
+ {
+ if ([] !== self::$themes) {
+ return self::$themes;
+ }
+
+ // Robo
+ self::$themes['00']['A']['env'] = [ "#ff2f2b" ];
+ self::$themes['00']['A']['clo'] = ["#fff", "#000"];
+ self::$themes['00']['A']['head'] = ["#fff"];
+ self::$themes['00']['A']['mouth'] = ["#fff", "#000", "#000"];
+ self::$themes['00']['A']['eyes'] = ["#000", "none", "#00FFFF"];
+ self::$themes['00']['A']['top'] = ["#fff", "#fff"];
+
+ self::$themes['00']['B']['env'] = ["#ff1ec1"];
+ self::$themes['00']['B']['clo'] = ["#000", "#fff" ];
+ self::$themes['00']['B']['head'] = ["#ffc1c1"];
+ self::$themes['00']['B']['mouth'] = ["#fff", "#000", "#000"];
+ self::$themes['00']['B']['eyes'] = ["#FF2D00", "#fff", "none"];
+ self::$themes['00']['B']['top'] = ["#a21d00", "#fff"];
+
+ self::$themes['00']['C']['env'] = ["#0079b1"];
+ self::$themes['00']['C']['clo'] = ["#0e00b1", "#d1fffe"];
+ self::$themes['00']['C']['head'] = ["#f5aa77"];
+ self::$themes['00']['C']['mouth'] = ["#fff", "#000", "#000"];
+ self::$themes['00']['C']['eyes'] = ["#0c00de", "#fff", "none"];
+ self::$themes['00']['C']['top'] = ["#acfffd", "#acfffd"];
+
+ // Girl
+ self::$themes['01']['A']['env'] = ["#a50000"];
+ self::$themes['01']['A']['clo'] = ["#f06", "#8e0039"];
+ self::$themes['01']['A']['head'] = ["#85492C"];
+ self::$themes['01']['A']['mouth'] = ["#000"];
+ self::$themes['01']['A']['eyes'] = ["#000", "#ff9809"];
+ self::$themes['01']['A']['top'] = ["#ff9809", "#ff9809", "none", "none"];
+
+ self::$themes['01']['B']['env'] = ["#40E83B"];
+ self::$themes['01']['B']['clo'] = ["#00650b", "#62ce5a"];
+ self::$themes['01']['B']['head'] = ["#f7c1a6"];
+ self::$themes['01']['B']['mouth'] = ["#6e1c1c"];
+ self::$themes['01']['B']['eyes'] = ["#000", "#ff833b"];
+ self::$themes['01']['B']['top'] = ["#67FFCC", "none", "none", "#ecff3b"];
+
+ self::$themes['01']['C']['env'] = ["#ff2c2c"];
+ self::$themes['01']['C']['clo'] = ["#fff", "#000"];
+ self::$themes['01']['C']['head'] = ["#ffce8b"];
+ self::$themes['01']['C']['mouth'] = ["#000"];
+ self::$themes['01']['C']['eyes'] = ["#000", "#0072ff"];
+ self::$themes['01']['C']['top'] = ["#ff9809", "none", "#ffc809", "none"];
+
+ // Blonde
+ self::$themes['02']['A']['env'] = ["#ff7520"];
+ self::$themes['02']['A']['clo'] = ["#d12823"];
+ self::$themes['02']['A']['head'] = ["#fee3c5"];
+ self::$themes['02']['A']['mouth'] = ["#d12823"];
+ self::$themes['02']['A']['eyes'] = ["#000", "none"];
+ self::$themes['02']['A']['top'] = ["#000", "none", "none", "#FFCC00", "red"];
+
+ self::$themes['02']['B']['env'] = ["#ff9700"];
+ self::$themes['02']['B']['clo'] = ["#000"];
+ self::$themes['02']['B']['head'] = ["#d2ad6d"];
+ self::$themes['02']['B']['mouth'] = ["#000"];
+ self::$themes['02']['B']['eyes'] = ["#000", "#00ffdc"];
+ self::$themes['02']['B']['top'] = ["#fdff00", "#fdff00", "none", "none", "none"];
+
+ self::$themes['02']['C']['env'] = ["#26a7ff"];
+ self::$themes['02']['C']['clo'] = ["#d85cd7"];
+ self::$themes['02']['C']['head'] = ["#542e02"];
+ self::$themes['02']['C']['mouth'] = ["#f70014"];
+ self::$themes['02']['C']['eyes'] = ["#000", "magenta"];
+ self::$themes['02']['C']['top'] = ["#FFCC00", "#FFCC00", "#FFCC00", "#ff0000", "yellow"];
+
+ // Evilnormie
+ self::$themes['03']['A']['env'] = ["#6FC30E"];
+ self::$themes['03']['A']['clo'] = ["#b4e1fa", "#5b5d6e", "#515262", "#a0d2f0", "#a0d2f0"];
+ self::$themes['03']['A']['head'] = ["#fae3b9"];
+ self::$themes['03']['A']['mouth'] = ["#fff", "#000"];
+ self::$themes['03']['A']['eyes'] = ["#000"];
+ self::$themes['03']['A']['top'] = ["#8eff45", "#8eff45", "none", "none"];
+
+ self::$themes['03']['B']['env'] = ["#00a58c"];
+ self::$themes['03']['B']['clo'] = ["#000", "#5b00", "#5100", "#a000", "#a000"];
+ self::$themes['03']['B']['head'] = ["#FAD2B9"];
+ self::$themes['03']['B']['mouth'] = ["#fff", "#000"];
+ self::$themes['03']['B']['eyes'] = ["#000"];
+ self::$themes['03']['B']['top'] = ["#FFC600", "none", "#FFC600", "none"];
+
+ self::$themes['03']['C']['env'] = ["#ff501f"];
+ self::$themes['03']['C']['clo'] = ["#000", "#ff0000", "#ff0000", "#7d7d7d", "#7d7d7d"];
+ self::$themes['03']['C']['head'] = ["#fff3dc"];
+ self::$themes['03']['C']['mouth'] = ["#d2001b", "none"];
+ self::$themes['03']['C']['eyes'] = ["#000"];
+ self::$themes['03']['C']['top'] = ["#D2001B", "none", "none", "#D2001B"];
+
+ // Country
+ self::$themes['04']['A']['env'] = ["#fc0"];
+ self::$themes['04']['A']['clo'] = ["#901e0e", "#ffbe1e", "#ffbe1e", "#c55f54"];
+ self::$themes['04']['A']['head'] = ["#f8d9ad"];
+ self::$themes['04']['A']['mouth'] = ["#000", "none", "#000", "none"];
+ self::$themes['04']['A']['eyes'] = ["#000"];
+ self::$themes['04']['A']['top'] = ["#583D00", "#AF892E", "#462D00", "#a0a0a0"];
+
+ self::$themes['04']['B']['env'] = ["#386465"];
+ self::$themes['04']['B']['clo'] = ["#fff", "#333", "#333", "#333"];
+ self::$themes['04']['B']['head'] = ["#FFD79D"];
+ self::$themes['04']['B']['mouth'] = ["#000", "#000", "#000", "#000"];
+ self::$themes['04']['B']['eyes'] = ["#000"];
+ self::$themes['04']['B']['top'] = ["#27363C", "#5DCAD4", "#314652", "#333"];
+
+ self::$themes['04']['C']['env'] = ["#DFFF00"];
+ self::$themes['04']['C']['clo'] = ["#304267", "#aab0b1", "#aab0b1", "#aab0b1"];
+ self::$themes['04']['C']['head'] = ["#e6b876"];
+ self::$themes['04']['C']['mouth'] = ["#50230a", "#50230a", "#50230a", "#50230a"];
+ self::$themes['04']['C']['eyes'] = ["#000"];
+ self::$themes['04']['C']['top'] = ["#333", "#afafaf", "#222", "#6d3a1d"];
+
+ // Johnyold
+ self::$themes['05']['A']['env'] = ["#a09300"];
+ self::$themes['05']['A']['clo'] = ["#c7d4e2", "#435363", "#435363", "#141720", "#141720", "#e7ecf2", "#e7ecf2"];
+ self::$themes['05']['A']['head'] = ["#f5d4a6"];
+ self::$themes['05']['A']['mouth'] = ["#000", "#cf9f76"];
+ self::$themes['05']['A']['eyes'] = ["#000", "#000", "#000", "#000", "#000", "#000", "#000", "#000", "#fff", "#fff", "#fff", "#fff"];
+ self::$themes['05']['A']['top'] = ["none", "#fdff00"];
+
+ self::$themes['05']['B']['env'] = ["#b3003e"];
+ self::$themes['05']['B']['clo'] = ["#000", "#435363", "#435363", "#000", "none", "#e7ecf2", "#e7ecf2"];
+ self::$themes['05']['B']['head'] = ["#f5d4a6"];
+ self::$themes['05']['B']['mouth'] = ["#000", "#af9f94"];
+ self::$themes['05']['B']['eyes'] = ["#9ff3ffdb", "#000", "#9ff3ffdb", "#000", "#2f508a", "#000", "#000", "#000", "none", "none", "none", "none"];
+ self::$themes['05']['B']['top'] = ["#ff9a00", "#ff9a00"];
+
+ self::$themes['05']['C']['env'] = ["#884f00"];
+ self::$themes['05']['C']['clo'] = ["#ff0000", "#fff", "#fff", "#141720", "#141720", "#e7ecf2", "#e7ecf2"];
+ self::$themes['05']['C']['head'] = ["#c57b14"];
+ self::$themes['05']['C']['mouth'] = ["#000", "#cf9f76"];
+ self::$themes['05']['C']['eyes'] = ["none", "#000", "none", "#000", "#5a0000", "#000", "#000", "#000", "none", "none", "none", "none"];
+ self::$themes['05']['C']['top'] = ["#efefef", "none"];
+
+ // Asian
+ self::$themes['06']['A']['env'] = ["#8acf00"];
+ self::$themes['06']['A']['clo'] = ["#ee2829", "#ff0"];
+ self::$themes['06']['A']['head'] = ["#ffce73"];
+ self::$themes['06']['A']['mouth'] = ["#fff", "#000"];
+ self::$themes['06']['A']['eyes'] = ["#000"];
+ self::$themes['06']['A']['top'] = ["#000","#000","none", "#000", "#ff4e4e", "#000"];
+
+ self::$themes['06']['B']['env'] = ["#00d2a3"];
+ self::$themes['06']['B']['clo'] = ["#0D0046", "#ffce73"];
+ self::$themes['06']['B']['head'] = ["#ffce73"];
+ self::$themes['06']['B']['mouth'] = ["#000", "none"];
+ self::$themes['06']['B']['eyes'] = ["#000"];
+ self::$themes['06']['B']['top'] = ["#000","#000","#000", "none", "#ffb358", "#000", "none", "none"];
+
+ self::$themes['06']['C']['env'] = ["#ff184e"];
+ self::$themes['06']['C']['clo'] = ["#000", "none"];
+ self::$themes['06']['C']['head'] = ["#ffce73"];
+ self::$themes['06']['C']['mouth'] = ["#ff0000", "none"];
+ self::$themes['06']['C']['eyes'] = ["#000"];
+ self::$themes['06']['C']['top'] = ["none","none","none", "none", "none", "#ffc107", "none", "none"];
+
+ // Punk
+ self::$themes['07']['A']['env'] = ["#00deae"];
+ self::$themes['07']['A']['clo'] = ["#ff0000"];
+ self::$themes['07']['A']['head'] = ["#ffce94"];
+ self::$themes['07']['A']['mouth'] = ["#f73b6c", "#000"];
+ self::$themes['07']['A']['eyes'] = ["#e91e63", "#000", "#e91e63", "#000", "#000", "#000"];
+ self::$themes['07']['A']['top'] = ["#dd104f", "#dd104f", "#f73b6c", "#dd104f"];
+
+ self::$themes['07']['B']['env'] = ["#181284"];
+ self::$themes['07']['B']['clo'] = ["#491f49", "#ff9809", "#491f49"];
+ self::$themes['07']['B']['head'] = ["#f6ba97"];
+ self::$themes['07']['B']['mouth'] = ["#ff9809", "#000"];
+ self::$themes['07']['B']['eyes'] = ["#c4ffe4", "#000", "#c4ffe4", "#000", "#000", "#000"];
+ self::$themes['07']['B']['top'] = [ "none", "none", "#d6f740", "#516303"];
+
+ self::$themes['07']['C']['env'] = ["#bcf700"];
+ self::$themes['07']['C']['clo'] = ["#ff14e4", "#000", "#14fffd"];
+ self::$themes['07']['C']['head'] = ["#7b401e"];
+ self::$themes['07']['C']['mouth'] = ["#666", "#000"];
+ self::$themes['07']['C']['eyes'] = ["#00b5b4", "#000", "#00b5b4", "#000", "#000", "#000"];
+ self::$themes['07']['C']['top'] = ["#14fffd", "#14fffd", "#14fffd", "#0d3a62"];
+
+ // Afrohair
+ self::$themes['08']['A']['env'] = ["#0df"];
+ self::$themes['08']['A']['clo'] = ["#571e57", "#ff0"];
+ self::$themes['08']['A']['head'] = ["#f2c280"];
+ self::$themes['08']['A']['mouth'] = ["#ff0000"];
+ self::$themes['08']['A']['eyes'] = ["#795548", "#000"];
+ self::$themes['08']['A']['top'] = ["#de3b00", "none"];
+
+ self::$themes['08']['B']['env'] = ["#B400C2"];
+ self::$themes['08']['B']['clo'] = ["#0D204A", "#00ffdf"];
+ self::$themes['08']['B']['head'] = ["#ca8628"];
+ self::$themes['08']['B']['mouth'] = ["#1a1a1a"];
+ self::$themes['08']['B']['eyes'] = ["#cbbdaf", "#000"];
+ self::$themes['08']['B']['top'] = ["#000", "#000"];
+
+ self::$themes['08']['C']['env'] = ["#ffe926"];
+ self::$themes['08']['C']['clo'] = ["#00d6af", "#000"];
+ self::$themes['08']['C']['head'] = ["#8c5100"];
+ self::$themes['08']['C']['mouth'] = ["#7d0000"];
+ self::$themes['08']['C']['eyes'] = ["none", "#000"];
+ self::$themes['08']['C']['top'] = ["#f7f7f7", "none"];
+
+ // Normie female
+ self::$themes['09']['A']['env'] = ["#4aff0c"];
+ self::$themes['09']['A']['clo'] = ["#101010", "#fff", "#fff"];
+ self::$themes['09']['A']['head'] = ["#dbbc7f"];
+ self::$themes['09']['A']['mouth'] = ["#000"];
+ self::$themes['09']['A']['eyes'] = [ "#000", "none", "none"];
+ self::$themes['09']['A']['top'] = ["#531148", "#531148", "#531148", "none"];
+
+ self::$themes['09']['B']['env'] = ["#FFC107"];
+ self::$themes['09']['B']['clo'] = ["#033c58", "#fff", "#fff"];
+ self::$themes['09']['B']['head'] = ["#dbc97f"];
+ self::$themes['09']['B']['mouth'] = ["#000"];
+ self::$themes['09']['B']['eyes'] = ["none", "#000", "#fff"];
+ self::$themes['09']['B']['top'] = ["#FFEB3B", "#FFEB3B", "none", "#FFEB3B"];
+
+ self::$themes['09']['C']['env'] = ["#FF9800"];
+ self::$themes['09']['C']['clo'] = ["#b40000", "#fff", "#fff"];
+ self::$themes['09']['C']['head'] = ["#E2AF6B"];
+ self::$themes['09']['C']['mouth'] = ["#000"];
+ self::$themes['09']['C']['eyes'] = ["none", "#000", "#fff"];
+ self::$themes['09']['C']['top'] = ["#ec0000", "#ec0000", "none", "none"];
+
+ // Older
+ self::$themes['10']['A']['env'] = ["#104c8c"];
+ self::$themes['10']['A']['clo'] = ["#354B65", "#3D8EBB", "#89D0DA", "#00FFFD" ];
+ self::$themes['10']['A']['head'] = ["#cc9a5c"];
+ self::$themes['10']['A']['mouth'] = ["#222", "#fff"];
+ self::$themes['10']['A']['eyes'] = ["#000", "#000"];
+ self::$themes['10']['A']['top'] = ["#fff", "#fff", "none"];
+
+ self::$themes['10']['B']['env'] = ["#0DC15C"];
+ self::$themes['10']['B']['clo'] = ["#212121", "#fff", "#212121", "#fff", ];
+ self::$themes['10']['B']['head'] = ["#dca45f"];
+ self::$themes['10']['B']['mouth'] = ["#111", "#633b1d"];
+ self::$themes['10']['B']['eyes'] = ["#000", "#000"];
+ self::$themes['10']['B']['top'] = ["none", "#792B74", "#792B74"];
+
+ self::$themes['10']['C']['env'] = ["#ffe500"];
+ self::$themes['10']['C']['clo'] = ["#1e5e80", "#fff", "#1e5e80", "#fff"];
+ self::$themes['10']['C']['head'] = ["#e8bc86"];
+ self::$themes['10']['C']['mouth'] = ["#111", "none"];
+ self::$themes['10']['C']['eyes'] = ["#000", "#000"];
+ self::$themes['10']['C']['top'] = ["none", "none", "#633b1d"];
+
+ // Firehair
+ self::$themes['11']['A']['env'] = ["#4a3f73"];
+ self::$themes['11']['A']['clo'] = ["#e6e9ee", "#f1543f", "#ff7058", "#fff", "#fff"];
+ self::$themes['11']['A']['head'] = ["#b27e5b"];
+ self::$themes['11']['A']['mouth'] = ["#191919", "#191919"];
+ self::$themes['11']['A']['eyes'] = ["#000", "#000", "#57FFFD"];
+ self::$themes['11']['A']['top'] = ["#ffc", "#ffc", "#ffc"];
+
+ self::$themes['11']['B']['env'] = ["#00a08d"];
+ self::$themes['11']['B']['clo'] = ["#FFBA32", "#484848", "#4e4e4e", "#fff", "#fff"];
+ self::$themes['11']['B']['head'] = ["#ab5f2c"];
+ self::$themes['11']['B']['mouth'] = ["#191919", "#191919"];
+ self::$themes['11']['B']['eyes'] = ["#000", "#ff23fa63", "#000"];
+ self::$themes['11']['B']['top'] = ["#ff90f4", "#ff90f4", "#ff90f4"];
+
+ self::$themes['11']['C']['env'] = ["#22535d"];
+ self::$themes['11']['C']['clo'] = ["#000", "#ff2500", "#ff2500", "#fff", "#fff"];
+ self::$themes['11']['C']['head'] = ["#a76c44"];
+ self::$themes['11']['C']['mouth'] = ["#191919", "#191919"];
+ self::$themes['11']['C']['eyes'] = ["#000", "none", "#000"];
+ self::$themes['11']['C']['top'] = ["none", "#00efff", "none"];
+
+ // Blond
+ self::$themes['12']['A']['env'] = ["#2668DC"];
+ self::$themes['12']['A']['clo'] = ["#2385c6", "#b8d0e0", "#b8d0e0"];
+ self::$themes['12']['A']['head'] = ["#ad8a60"];
+ self::$themes['12']['A']['mouth'] = ["#000", "#4d4d4d"];
+ self::$themes['12']['A']['eyes'] = ["#7fb5a2", "#d1eddf", "#301e19"];
+ self::$themes['12']['A']['top'] = ["#fff510", "#fff510"];
+
+ self::$themes['12']['B']['env'] = ["#643869"];
+ self::$themes['12']['B']['clo'] = ["#D67D1B", "#b8d0e0", "#b8d0e0"];
+ self::$themes['12']['B']['head'] = ["#CC985A", "none0000"];
+ self::$themes['12']['B']['mouth'] = ["#000", "#ececec"];
+ self::$themes['12']['B']['eyes'] = ["#1f2644", "#9b97ce", "#301e19"];
+ self::$themes['12']['B']['top'] = ["#00eaff", "none"];
+
+ self::$themes['12']['C']['env'] = ["#F599FF"];
+ self::$themes['12']['C']['clo'] = ["#2823C6", "#b8d0e0", "#b8d0e0"];
+ self::$themes['12']['C']['head'] = ["#C7873A"];
+ self::$themes['12']['C']['mouth'] = ["#000", "#4d4d4d"];
+ self::$themes['12']['C']['eyes'] = ["#581b1b", "#FF8B8B", "#000"];
+ self::$themes['12']['C']['top'] = ["none", "#9c0092"];
+
+ // Ateam
+ self::$themes['13']['A']['env'] = ["#d10084"];
+ self::$themes['13']['A']['clo'] = ["#efedee", "#00a1e0", "#00a1e0", "#efedee", "#ffce1c"];
+ self::$themes['13']['A']['head'] = ["#b35f49"];
+ self::$themes['13']['A']['mouth'] = ["#3a484a", "#000"];
+ self::$themes['13']['A']['eyes'] = ["#000"];
+ self::$themes['13']['A']['top'] = ["#000", "none", "#000", "none"];
+
+ self::$themes['13']['B']['env'] = ["#E6C117"];
+ self::$themes['13']['B']['clo'] = ["#efedee", "#ec0033", "#ec0033", "#efedee", "#f2ff05"];
+ self::$themes['13']['B']['head'] = ["#ffc016"];
+ self::$themes['13']['B']['mouth'] = ["#4a3737", "#000"];
+ self::$themes['13']['B']['eyes'] = ["#000"];
+ self::$themes['13']['B']['top'] = ["#ffe900", "#ffe900", "none", "#ffe900"];
+
+ self::$themes['13']['C']['env'] = ["#1d8c00"];
+ self::$themes['13']['C']['clo'] = ["#e000cb", "#fff", "#fff", "#e000cb", "#ffce1c"];
+ self::$themes['13']['C']['head'] = ["#b96438"];
+ self::$themes['13']['C']['mouth'] = ["#000", "#000"];
+ self::$themes['13']['C']['eyes'] = ["#000"];
+ self::$themes['13']['C']['top'] = ["#53ffff", "#53ffff", "none", "none"];
+
+ // Rasta
+ self::$themes['14']['A']['env'] = ["#fc0065"];
+ self::$themes['14']['A']['clo'] = ["#708913", "#fdea14", "#708913", "#fdea14", "#708913"];
+ self::$themes['14']['A']['head'] = ["#DEA561"];
+ self::$themes['14']['A']['mouth'] = ["#444", "#000"];
+ self::$themes['14']['A']['eyes'] = ["#000"];
+ self::$themes['14']['A']['top'] = ["#32393f", "#32393f", "#32393f", "#32393f", "#32393f", "#32393f", "#32393f", "#32393f", "#32393f", "#32393f", "#32393f", "#32393f", "#32393f", "#32393f", "#32393f", "#32393f", "#32393f" ];
+
+ self::$themes['14']['B']['env'] = ["#81f72e"];
+ self::$themes['14']['B']['clo'] = ["#ff0000", "#ffc107", "#ff0000", "#ffc107", "#ff0000"];
+ self::$themes['14']['B']['head'] = ["#ef9831"];
+ self::$themes['14']['B']['mouth'] = ["#6b0000", "#000"];
+ self::$themes['14']['B']['eyes'] = ["#000"];
+ self::$themes['14']['B']['top'] = ["#FFFAAD", "#FFFAAD", "#FFFAAD", "#FFFAAD", "#FFFAAD", "#FFFAAD", "#FFFAAD", "#FFFAAD", "#FFFAAD", "#FFFAAD", "#FFFAAD", "#FFFAAD", "#FFFAAD", "none", "none", "none", "none"];
+
+ self::$themes['14']['C']['env'] = ["#00D872"];
+ self::$themes['14']['C']['clo'] = ["#590D00", "#FD1336", "#590D00", "#FD1336", "#590D00"];
+ self::$themes['14']['C']['head'] = ["#c36c00"];
+ self::$themes['14']['C']['mouth'] = ["#56442b", "#000"];
+ self::$themes['14']['C']['eyes'] = ["#000"];
+ self::$themes['14']['C']['top'] = ["#004E4C", "#004E4C", "#004E4C", "#004E4C", "#004E4C", "#004E4C", "#004E4C", "#004E4C", "#004E4C", "none", "none", "none", "none", "none", "none", "none", "none"];
+
+ // Meta
+ self::$themes['15']['A']['env'] = ["#111"];
+ self::$themes['15']['A']['clo'] = ["#000", "#00FFFF"];
+ self::$themes['15']['A']['head'] = ["#755227"];
+ self::$themes['15']['A']['mouth'] = ["#fff", "#000"];
+ self::$themes['15']['A']['eyes'] = ["black", "#008a", "aqua"];
+ self::$themes['15']['A']['top'] = ["#fff", "#fff", "#fff", "#fff", "#fff"];
+
+ self::$themes['15']['B']['env'] = ["#00D0D4"];
+ self::$themes['15']['B']['clo'] = ["#000", "#fff"];
+ self::$themes['15']['B']['head'] = ["#755227"];
+ self::$themes['15']['B']['mouth'] = ["#fff", "#000"];
+ self::$themes['15']['B']['eyes'] = ["black", "#1df7ffa3", "#fcff2c"];
+ self::$themes['15']['B']['top'] = ["#fff539", "none", "#fff539", "none", "#fff539"];
+
+ self::$themes['15']['C']['env'] = ["#DC75FF"];
+ self::$themes['15']['C']['clo'] = ["#000", "#FFBDEC"];
+ self::$themes['15']['C']['head'] = ["#997549"];
+ self::$themes['15']['C']['mouth'] = ["#fff", "#000"];
+ self::$themes['15']['C']['eyes'] = ["black", "black", "aqua"];
+ self::$themes['15']['C']['top'] = ["#00fffd", "none", "none", "none", "none"];
+
+ return self::$themes;
+ }
+}
diff --git a/src/MultiavatarTest.php b/src/MultiavatarTest.php
new file mode 100644
index 0000000..b499977
--- /dev/null
+++ b/src/MultiavatarTest.php
@@ -0,0 +1,164 @@
+multiavatar = new Multiavatar();
+ }
+
+ /** @test */
+ public function it_will_throw_if_the_ver_part_is_not_valid(): void
+ {
+ $this->expectException(InvalidArgumentException::class);
+ $this->expectExceptionMessage('The version part does not exists; expecting a value between `00` and `15`');
+
+ ($this->multiavatar)('foobar', ['ver' => ['part' => 16]]);
+ }
+
+ /** @test */
+ public function it_will_throw_if_the_ver_part_is_not_a_valid_type(): void
+ {
+ $this->expectException(InvalidArgumentException::class);
+ $this->expectExceptionMessage('The version part is expected to be a scalar; array was given.');
+
+ ($this->multiavatar)('foobar', ['ver' => ['part' => []]]);
+ }
+
+ /** @test */
+ public function it_will_throw_if_the_ver_theme_is_not_a_supported_type(): void
+ {
+ $this->expectException(InvalidArgumentException::class);
+ $this->expectExceptionMessage('The version theme is expected to be a string; object was given.');
+
+ ($this->multiavatar)('foobar', ['ver' => ['theme' => new \stdClass()]]);
+ }
+
+ /** @test */
+ public function it_will_throw_if_the_ver_theme_is_not_valid(): void
+ {
+ $this->expectException(InvalidArgumentException::class);
+ $this->expectExceptionMessage('The version theme does not exists; expecting a value between `A`, `B` and `C`.');
+
+ ($this->multiavatar)('foobar', ['ver' => ['theme' => 'D']]);
+ }
+
+ /** @test */
+ public function it_will_throw_if_the_avatar_type_is_not_valid(): void
+ {
+ $this->expectException(TypeError::class);
+ $this->expectExceptionMessage('Expected a scalar or a Stringable object; got: stdClass');
+
+ ($this->multiavatar)(new \stdClass());
+ }
+
+ /** @test */
+ public function it_will_return_the_same_svg_with_a_numeric_or_string_part(): void
+ {
+ $svgNumericPart = ($this->multiavatar)('foobar', ['ver' => ['part' => 5]]);
+ $svgNumericStringWithLeadingZeroPart = ($this->multiavatar)('foobar', ['ver' => ['part' => '0005']]);
+ $svgNumericStringPart = ($this->multiavatar)('foobar', ['ver' => ['part' => '5']]);
+
+ self::assertSame($svgNumericPart, $svgNumericStringWithLeadingZeroPart);
+ self::assertSame($svgNumericPart, $svgNumericStringPart);
+ }
+
+ /** @test */
+ public function it_will_return_the_same_svg_with_a_case_insensitive_theme(): void
+ {
+ $svgLowerTheme = ($this->multiavatar)('foobar', ['ver' => ['theme' => 'A']]);
+ $svgUpperTheme = ($this->multiavatar)('foobar', ['ver' => ['theme' => 'a']]);
+
+ self::assertSame($svgLowerTheme, $svgUpperTheme);
+ }
+
+ /** @test */
+ public function it_will_return_the_same_svg_if_the_ver_is_fully_setting_independently_of_the_avatar_id_value(): void
+ {
+ $options = ['ver' => ['theme' => 'A', 'part' => 3]];
+
+ $svgWithFixedVer1 = ($this->multiavatar)('first-avatar', $options);
+ $svgWithFixedVer2 = ($this->multiavatar)('second-avatar', $options);
+
+ self::assertSame($svgWithFixedVer1, $svgWithFixedVer2);
+ }
+
+ /** @test */
+ public function it_will_return_the_same_svg_with_sans_env_truthy_values(): void
+ {
+ $svgSansEnvTrueBoolean = ($this->multiavatar)('foobar', ['sansEnv' => true]);
+ $svgSansEnvTruthyNumeric = ($this->multiavatar)('foobar', ['sansEnv' => 1]);
+ $svgSansEnvTruthyString = ($this->multiavatar)('foobar', ['sansEnv' => 'yes']);
+
+ self::assertSame($svgSansEnvTrueBoolean, $svgSansEnvTruthyNumeric);
+ self::assertSame($svgSansEnvTrueBoolean, $svgSansEnvTruthyString);
+ }
+
+ /** @test */
+ public function it_will_return_the_same_svg_with_sans_env_falsy_values(): void
+ {
+ $svgSansEnvFalseBoolean = ($this->multiavatar)('foobar', ['sansEnv' => false]);
+ $svgSansEnvWrongValueIsFalse = ($this->multiavatar)('foobar', ['sansEnv' => 'fdsdf']);
+ $svgSansEnvNullValue = ($this->multiavatar)('foobar', ['sansEnv' => null]);
+
+ self::assertSame($svgSansEnvFalseBoolean, $svgSansEnvNullValue);
+ self::assertSame($svgSansEnvFalseBoolean, $svgSansEnvWrongValueIsFalse);
+ }
+
+ /** @test */
+ public function it_will_return_different_svg_with_sans_env_values(): void
+ {
+ $svgSansEnvFalse = ($this->multiavatar)('foobar', ['sansEnv' => false]);
+ $svgSansEnvTrue = ($this->multiavatar)('foobar', ['sansEnv' => true]);
+
+ self::assertNotSame($svgSansEnvFalse, $svgSansEnvTrue);
+ }
+
+ /** @test */
+ public function it_will_return_the_same_svg_with_avatar_id_numeric_or_string(): void
+ {
+ $svgAvatarIdIsString = ($this->multiavatar)('1234567890');
+ $svgAvatarIdIsNumeric = ($this->multiavatar)(1234567890);
+
+ self::assertSame($svgAvatarIdIsNumeric, $svgAvatarIdIsString);
+ }
+
+ /**
+ * @test
+ * @dataProvider getEmptySvgProvider
+ * @param object|string $avatarId
+ */
+ public function it_will_return_an_empty_svg($avatarId): void
+ {
+ self::assertSame('', ($this->multiavatar)($avatarId));
+ }
+
+ /**
+ * @return iterable
+ */
+ public function getEmptySvgProvider(): iterable
+ {
+ yield 'avatar is an empty string' => ['avatarId' => ''];
+ yield 'avatar is an empty string after being trimmed' => ['avatarId' => ' '];
+ yield 'avatar can be a stringable object' => [
+ 'avatarId' => new class {
+ public function __toString(): string {
+ return '';
+ }
+ },
+ ];
+ }
+}