├── .browserslistrc ├── .editorconfig ├── .eslintrc.js ├── .gitignore ├── LICENSE ├── README.md ├── babel.config.js ├── jest.config.js ├── package.json ├── postcss.config.js ├── public ├── _redirects ├── favicon.ico ├── img │ ├── 1x1.png │ ├── 8bits-coach.png │ ├── demo-cover.png │ └── icons │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── apple-touch-icon-120x120.png │ │ ├── apple-touch-icon-152x152.png │ │ ├── apple-touch-icon-180x180.png │ │ ├── apple-touch-icon-60x60.png │ │ ├── apple-touch-icon-76x76.png │ │ ├── apple-touch-icon.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── msapplication-icon-144x144.png │ │ ├── mstile-150x150.png │ │ └── safari-pinned-tab.svg ├── index.html ├── logos.json ├── manifest.json ├── pokemon.json ├── precache-sw.js └── robots.txt ├── src ├── AppShell.vue ├── assets │ └── scss │ │ ├── _variables.scss │ │ └── app.scss ├── buefy.js ├── components │ ├── FinishModal.vue │ ├── InformationsModal.vue │ ├── LevelSelect.vue │ ├── PokeCards │ │ ├── Card.vue │ │ ├── CardImage.vue │ │ └── Main.vue │ ├── Pokeball.vue │ ├── Shell │ │ ├── AlertDone.vue │ │ ├── AlertError.vue │ │ ├── Footer.vue │ │ ├── Header.vue │ │ └── index.js │ └── Timer.vue ├── main.js ├── registerServiceWorker.js ├── store │ ├── actions.js │ ├── getters.js │ ├── index.js │ ├── mutations.js │ ├── mutations.type.js │ ├── plugins-cards-actions.js │ └── state.js └── support │ ├── color.js │ ├── filters.js │ ├── ga.js │ ├── grid.js │ └── utils.js ├── tests └── unit │ ├── .eslintrc.js │ ├── components │ ├── __snapshots__ │ │ └── pokeball.spec.js.snap │ ├── pokeball.spec.js │ └── timer.spec.js │ └── helpers.js ├── vue.config.js └── yarn.lock /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not ie <= 8 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{js,jsx,ts,tsx,vue}] 2 | indent_style = space 3 | indent_size = 2 4 | trim_trailing_whitespace = true 5 | insert_final_newline = true 6 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | extends: [ 7 | 'plugin:vue/essential', 8 | '@vue/standard' 9 | ], 10 | rules: { 11 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 12 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' 13 | }, 14 | parserOptions: { 15 | parser: 'babel-eslint' 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | /coverage 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | 15 | # Editor directories and files 16 | .idea 17 | .vscode 18 | *.suo 19 | *.ntvs* 20 | *.njsproj 21 | *.sln 22 | *.sw* 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2019, Vinicius Reis 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pokémon - Memory Game 2 | 3 | A simple memory game using pokémon. 4 | 5 | [![Netlify Status](https://api.netlify.com/api/v1/badges/a55967e2-feb2-4ae4-bb35-d58e6c0d1321/deploy-status)](https://app.netlify.com/sites/vue-pokemon-memory-game/deploys) 6 | 7 | ![demo](public/img/demo-cover.png) 8 | 9 | ## Resources used 10 | 11 | - [Vue.js (PWA)](https://vuejs.org) 12 | - [Buefy](https://buefy.org/) 13 | - [Bulma CSS](https://bulma.io/) 14 | - [Material Design Icons](https://materialdesignicons.com/) 15 | 16 | ## Commands 17 | 18 | ```sh 19 | yarn install // install deps 20 | yarn run serve // serve app http://localhost:8080 21 | yarn run build // build app 22 | ``` 23 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/app' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleFileExtensions: [ 3 | 'js', 4 | 'jsx', 5 | 'json', 6 | 'vue' 7 | ], 8 | transform: { 9 | '^.+\\.vue$': 'vue-jest', 10 | '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub', 11 | '^.+\\.(jsx|js)$': 'babel-jest' 12 | }, 13 | moduleNameMapper: { 14 | '^lodash-es$': 'lodash', 15 | '^@/(.*)$': '/src/$1' 16 | }, 17 | snapshotSerializers: [ 18 | 'jest-serializer-vue' 19 | ], 20 | testMatch: [ 21 | '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)' 22 | ], 23 | testURL: 'http://localhost/', 24 | collectCoverageFrom: ['src/**/*.{js,vue}', '!**/node_modules/**'], 25 | coverageReporters: ['html', 'text-summary'] 26 | } 27 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-poke-memo", 3 | "version": "1.17.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build --modern", 8 | "lint": "vue-cli-service lint", 9 | "test:unit": "vue-cli-service test:unit", 10 | "test:covarage": "vue-cli-service test:unit --collectCoverage" 11 | }, 12 | "dependencies": { 13 | "buefy": "^0.7.10", 14 | "downloadjs": "^1.4.7", 15 | "geopattern": "^1.2.3", 16 | "html2canvas": "^1.0.0-rc.3", 17 | "lodash-es": "^4.17.15", 18 | "register-service-worker": "^1.7.1", 19 | "visibilityjs": "^2.0.2", 20 | "vue": "^2.6.11", 21 | "vuex": "^3.1.3" 22 | }, 23 | "devDependencies": { 24 | "@vue/cli-plugin-babel": "^4.2.3", 25 | "@vue/cli-plugin-eslint": "^4.2.3", 26 | "@vue/cli-plugin-pwa": "^4.2.3", 27 | "@vue/cli-plugin-unit-jest": "^4.2.3", 28 | "@vue/cli-service": "^4.2.3", 29 | "@vue/eslint-config-standard": "^5.1.2", 30 | "@vue/test-utils": "1.0.0-beta.32", 31 | "babel-core": "7.0.0-bridge.0", 32 | "babel-eslint": "^10.1.0", 33 | "babel-jest": "^25.1.0", 34 | "eslint": "^6.8.0", 35 | "eslint-plugin-import": "^2.20.1", 36 | "eslint-plugin-node": "^11.0.0", 37 | "eslint-plugin-promise": "^4.2.1", 38 | "eslint-plugin-standard": "^4.0.1", 39 | "eslint-plugin-vue": "^6.2.2", 40 | "node-sass": "^4.13.1", 41 | "sass-loader": "^8.0.2", 42 | "vue-cli-plugin-buefy": "^0.3.7", 43 | "vue-template-compiler": "^2.6.11" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | autoprefixer: {} 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /public/_redirects: -------------------------------------------------------------------------------- 1 | # Redirect default Netlify subdomain to primary domain 2 | https://vue-pokemon-memory-game.netlify.com/* https://vue-pokemon-memory-game.vinicius73.dev/:splat 301! 3 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinicius73/vue-pokemon-memory-game/50a9837d60013785c6631781c147db61b97d4545/public/favicon.ico -------------------------------------------------------------------------------- /public/img/1x1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinicius73/vue-pokemon-memory-game/50a9837d60013785c6631781c147db61b97d4545/public/img/1x1.png -------------------------------------------------------------------------------- /public/img/8bits-coach.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinicius73/vue-pokemon-memory-game/50a9837d60013785c6631781c147db61b97d4545/public/img/8bits-coach.png -------------------------------------------------------------------------------- /public/img/demo-cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinicius73/vue-pokemon-memory-game/50a9837d60013785c6631781c147db61b97d4545/public/img/demo-cover.png -------------------------------------------------------------------------------- /public/img/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinicius73/vue-pokemon-memory-game/50a9837d60013785c6631781c147db61b97d4545/public/img/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/img/icons/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinicius73/vue-pokemon-memory-game/50a9837d60013785c6631781c147db61b97d4545/public/img/icons/android-chrome-512x512.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinicius73/vue-pokemon-memory-game/50a9837d60013785c6631781c147db61b97d4545/public/img/icons/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinicius73/vue-pokemon-memory-game/50a9837d60013785c6631781c147db61b97d4545/public/img/icons/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinicius73/vue-pokemon-memory-game/50a9837d60013785c6631781c147db61b97d4545/public/img/icons/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinicius73/vue-pokemon-memory-game/50a9837d60013785c6631781c147db61b97d4545/public/img/icons/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinicius73/vue-pokemon-memory-game/50a9837d60013785c6631781c147db61b97d4545/public/img/icons/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinicius73/vue-pokemon-memory-game/50a9837d60013785c6631781c147db61b97d4545/public/img/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /public/img/icons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinicius73/vue-pokemon-memory-game/50a9837d60013785c6631781c147db61b97d4545/public/img/icons/favicon-16x16.png -------------------------------------------------------------------------------- /public/img/icons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinicius73/vue-pokemon-memory-game/50a9837d60013785c6631781c147db61b97d4545/public/img/icons/favicon-32x32.png -------------------------------------------------------------------------------- /public/img/icons/msapplication-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinicius73/vue-pokemon-memory-game/50a9837d60013785c6631781c147db61b97d4545/public/img/icons/msapplication-icon-144x144.png -------------------------------------------------------------------------------- /public/img/icons/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinicius73/vue-pokemon-memory-game/50a9837d60013785c6631781c147db61b97d4545/public/img/icons/mstile-150x150.png -------------------------------------------------------------------------------- /public/img/icons/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.11, written by Peter Selinger 2001-2013 9 | 10 | 12 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | Pokémon - Memory Game 22 | 23 | 24 | 27 |
28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /public/logos.json: -------------------------------------------------------------------------------- 1 | [150, 25, 245, 6, 384, 94, 257, 658, 445, 742, 718, 319, 202, 725, 242, 748, 39] 2 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Pokémon - Memory Game", 3 | "short_name": "Poke Memory Game", 4 | "icons": [ 5 | { 6 | "src": "./img/icons/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "./img/icons/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "start_url": "./index.html", 17 | "display": "standalone", 18 | "background_color": "#222224", 19 | "theme_color": "#ffffff" 20 | } 21 | -------------------------------------------------------------------------------- /public/pokemon.json: -------------------------------------------------------------------------------- 1 | [{"id":1,"identifier":"bulbasaur"},{"id":2,"identifier":"ivysaur"},{"id":3,"identifier":"venusaur"},{"id":4,"identifier":"charmander"},{"id":5,"identifier":"charmeleon"},{"id":6,"identifier":"charizard"},{"id":7,"identifier":"squirtle"},{"id":8,"identifier":"wartortle"},{"id":9,"identifier":"blastoise"},{"id":10,"identifier":"caterpie"},{"id":11,"identifier":"metapod"},{"id":12,"identifier":"butterfree"},{"id":13,"identifier":"weedle"},{"id":14,"identifier":"kakuna"},{"id":15,"identifier":"beedrill"},{"id":16,"identifier":"pidgey"},{"id":17,"identifier":"pidgeotto"},{"id":18,"identifier":"pidgeot"},{"id":19,"identifier":"rattata"},{"id":20,"identifier":"raticate"},{"id":21,"identifier":"spearow"},{"id":22,"identifier":"fearow"},{"id":23,"identifier":"ekans"},{"id":24,"identifier":"arbok"},{"id":25,"identifier":"pikachu"},{"id":26,"identifier":"raichu"},{"id":27,"identifier":"sandshrew"},{"id":28,"identifier":"sandslash"},{"id":29,"identifier":"nidoran-f"},{"id":30,"identifier":"nidorina"},{"id":31,"identifier":"nidoqueen"},{"id":32,"identifier":"nidoran-m"},{"id":33,"identifier":"nidorino"},{"id":34,"identifier":"nidoking"},{"id":35,"identifier":"clefairy"},{"id":36,"identifier":"clefable"},{"id":37,"identifier":"vulpix"},{"id":38,"identifier":"ninetales"},{"id":39,"identifier":"jigglypuff"},{"id":40,"identifier":"wigglytuff"},{"id":41,"identifier":"zubat"},{"id":42,"identifier":"golbat"},{"id":43,"identifier":"oddish"},{"id":44,"identifier":"gloom"},{"id":45,"identifier":"vileplume"},{"id":46,"identifier":"paras"},{"id":47,"identifier":"parasect"},{"id":48,"identifier":"venonat"},{"id":49,"identifier":"venomoth"},{"id":50,"identifier":"diglett"},{"id":51,"identifier":"dugtrio"},{"id":52,"identifier":"meowth"},{"id":53,"identifier":"persian"},{"id":54,"identifier":"psyduck"},{"id":55,"identifier":"golduck"},{"id":56,"identifier":"mankey"},{"id":57,"identifier":"primeape"},{"id":58,"identifier":"growlithe"},{"id":59,"identifier":"arcanine"},{"id":60,"identifier":"poliwag"},{"id":61,"identifier":"poliwhirl"},{"id":62,"identifier":"poliwrath"},{"id":63,"identifier":"abra"},{"id":64,"identifier":"kadabra"},{"id":65,"identifier":"alakazam"},{"id":66,"identifier":"machop"},{"id":67,"identifier":"machoke"},{"id":68,"identifier":"machamp"},{"id":69,"identifier":"bellsprout"},{"id":70,"identifier":"weepinbell"},{"id":71,"identifier":"victreebel"},{"id":72,"identifier":"tentacool"},{"id":73,"identifier":"tentacruel"},{"id":74,"identifier":"geodude"},{"id":75,"identifier":"graveler"},{"id":76,"identifier":"golem"},{"id":77,"identifier":"ponyta"},{"id":78,"identifier":"rapidash"},{"id":79,"identifier":"slowpoke"},{"id":80,"identifier":"slowbro"},{"id":81,"identifier":"magnemite"},{"id":82,"identifier":"magneton"},{"id":83,"identifier":"farfetchd"},{"id":84,"identifier":"doduo"},{"id":85,"identifier":"dodrio"},{"id":86,"identifier":"seel"},{"id":87,"identifier":"dewgong"},{"id":88,"identifier":"grimer"},{"id":89,"identifier":"muk"},{"id":90,"identifier":"shellder"},{"id":91,"identifier":"cloyster"},{"id":92,"identifier":"gastly"},{"id":93,"identifier":"haunter"},{"id":94,"identifier":"gengar"},{"id":95,"identifier":"onix"},{"id":96,"identifier":"drowzee"},{"id":97,"identifier":"hypno"},{"id":98,"identifier":"krabby"},{"id":99,"identifier":"kingler"},{"id":100,"identifier":"voltorb"},{"id":101,"identifier":"electrode"},{"id":102,"identifier":"exeggcute"},{"id":103,"identifier":"exeggutor"},{"id":104,"identifier":"cubone"},{"id":105,"identifier":"marowak"},{"id":106,"identifier":"hitmonlee"},{"id":107,"identifier":"hitmonchan"},{"id":108,"identifier":"lickitung"},{"id":109,"identifier":"koffing"},{"id":110,"identifier":"weezing"},{"id":111,"identifier":"rhyhorn"},{"id":112,"identifier":"rhydon"},{"id":113,"identifier":"chansey"},{"id":114,"identifier":"tangela"},{"id":115,"identifier":"kangaskhan"},{"id":116,"identifier":"horsea"},{"id":117,"identifier":"seadra"},{"id":118,"identifier":"goldeen"},{"id":119,"identifier":"seaking"},{"id":120,"identifier":"staryu"},{"id":121,"identifier":"starmie"},{"id":122,"identifier":"mr-mime"},{"id":123,"identifier":"scyther"},{"id":124,"identifier":"jynx"},{"id":125,"identifier":"electabuzz"},{"id":126,"identifier":"magmar"},{"id":127,"identifier":"pinsir"},{"id":128,"identifier":"tauros"},{"id":129,"identifier":"magikarp"},{"id":130,"identifier":"gyarados"},{"id":131,"identifier":"lapras"},{"id":132,"identifier":"ditto"},{"id":133,"identifier":"eevee"},{"id":134,"identifier":"vaporeon"},{"id":135,"identifier":"jolteon"},{"id":136,"identifier":"flareon"},{"id":137,"identifier":"porygon"},{"id":138,"identifier":"omanyte"},{"id":139,"identifier":"omastar"},{"id":140,"identifier":"kabuto"},{"id":141,"identifier":"kabutops"},{"id":142,"identifier":"aerodactyl"},{"id":143,"identifier":"snorlax"},{"id":144,"identifier":"articuno"},{"id":145,"identifier":"zapdos"},{"id":146,"identifier":"moltres"},{"id":147,"identifier":"dratini"},{"id":148,"identifier":"dragonair"},{"id":149,"identifier":"dragonite"},{"id":150,"identifier":"mewtwo"},{"id":151,"identifier":"mew"},{"id":152,"identifier":"chikorita"},{"id":153,"identifier":"bayleef"},{"id":154,"identifier":"meganium"},{"id":155,"identifier":"cyndaquil"},{"id":156,"identifier":"quilava"},{"id":157,"identifier":"typhlosion"},{"id":158,"identifier":"totodile"},{"id":159,"identifier":"croconaw"},{"id":160,"identifier":"feraligatr"},{"id":161,"identifier":"sentret"},{"id":162,"identifier":"furret"},{"id":163,"identifier":"hoothoot"},{"id":164,"identifier":"noctowl"},{"id":165,"identifier":"ledyba"},{"id":166,"identifier":"ledian"},{"id":167,"identifier":"spinarak"},{"id":168,"identifier":"ariados"},{"id":169,"identifier":"crobat"},{"id":170,"identifier":"chinchou"},{"id":171,"identifier":"lanturn"},{"id":172,"identifier":"pichu"},{"id":173,"identifier":"cleffa"},{"id":174,"identifier":"igglybuff"},{"id":175,"identifier":"togepi"},{"id":176,"identifier":"togetic"},{"id":177,"identifier":"natu"},{"id":178,"identifier":"xatu"},{"id":179,"identifier":"mareep"},{"id":180,"identifier":"flaaffy"},{"id":181,"identifier":"ampharos"},{"id":182,"identifier":"bellossom"},{"id":183,"identifier":"marill"},{"id":184,"identifier":"azumarill"},{"id":185,"identifier":"sudowoodo"},{"id":186,"identifier":"politoed"},{"id":187,"identifier":"hoppip"},{"id":188,"identifier":"skiploom"},{"id":189,"identifier":"jumpluff"},{"id":190,"identifier":"aipom"},{"id":191,"identifier":"sunkern"},{"id":192,"identifier":"sunflora"},{"id":193,"identifier":"yanma"},{"id":194,"identifier":"wooper"},{"id":195,"identifier":"quagsire"},{"id":196,"identifier":"espeon"},{"id":197,"identifier":"umbreon"},{"id":198,"identifier":"murkrow"},{"id":199,"identifier":"slowking"},{"id":200,"identifier":"misdreavus"},{"id":201,"identifier":"unown"},{"id":202,"identifier":"wobbuffet"},{"id":203,"identifier":"girafarig"},{"id":204,"identifier":"pineco"},{"id":205,"identifier":"forretress"},{"id":206,"identifier":"dunsparce"},{"id":207,"identifier":"gligar"},{"id":208,"identifier":"steelix"},{"id":209,"identifier":"snubbull"},{"id":210,"identifier":"granbull"},{"id":211,"identifier":"qwilfish"},{"id":212,"identifier":"scizor"},{"id":213,"identifier":"shuckle"},{"id":214,"identifier":"heracross"},{"id":215,"identifier":"sneasel"},{"id":216,"identifier":"teddiursa"},{"id":217,"identifier":"ursaring"},{"id":218,"identifier":"slugma"},{"id":219,"identifier":"magcargo"},{"id":220,"identifier":"swinub"},{"id":221,"identifier":"piloswine"},{"id":222,"identifier":"corsola"},{"id":223,"identifier":"remoraid"},{"id":224,"identifier":"octillery"},{"id":225,"identifier":"delibird"},{"id":226,"identifier":"mantine"},{"id":227,"identifier":"skarmory"},{"id":228,"identifier":"houndour"},{"id":229,"identifier":"houndoom"},{"id":230,"identifier":"kingdra"},{"id":231,"identifier":"phanpy"},{"id":232,"identifier":"donphan"},{"id":233,"identifier":"porygon2"},{"id":234,"identifier":"stantler"},{"id":235,"identifier":"smeargle"},{"id":236,"identifier":"tyrogue"},{"id":237,"identifier":"hitmontop"},{"id":238,"identifier":"smoochum"},{"id":239,"identifier":"elekid"},{"id":240,"identifier":"magby"},{"id":241,"identifier":"miltank"},{"id":242,"identifier":"blissey"},{"id":243,"identifier":"raikou"},{"id":244,"identifier":"entei"},{"id":245,"identifier":"suicune"},{"id":246,"identifier":"larvitar"},{"id":247,"identifier":"pupitar"},{"id":248,"identifier":"tyranitar"},{"id":249,"identifier":"lugia"},{"id":250,"identifier":"ho-oh"},{"id":251,"identifier":"celebi"},{"id":252,"identifier":"treecko"},{"id":253,"identifier":"grovyle"},{"id":254,"identifier":"sceptile"},{"id":255,"identifier":"torchic"},{"id":256,"identifier":"combusken"},{"id":257,"identifier":"blaziken"},{"id":258,"identifier":"mudkip"},{"id":259,"identifier":"marshtomp"},{"id":260,"identifier":"swampert"},{"id":261,"identifier":"poochyena"},{"id":262,"identifier":"mightyena"},{"id":263,"identifier":"zigzagoon"},{"id":264,"identifier":"linoone"},{"id":265,"identifier":"wurmple"},{"id":266,"identifier":"silcoon"},{"id":267,"identifier":"beautifly"},{"id":268,"identifier":"cascoon"},{"id":269,"identifier":"dustox"},{"id":270,"identifier":"lotad"},{"id":271,"identifier":"lombre"},{"id":272,"identifier":"ludicolo"},{"id":273,"identifier":"seedot"},{"id":274,"identifier":"nuzleaf"},{"id":275,"identifier":"shiftry"},{"id":276,"identifier":"taillow"},{"id":277,"identifier":"swellow"},{"id":278,"identifier":"wingull"},{"id":279,"identifier":"pelipper"},{"id":280,"identifier":"ralts"},{"id":281,"identifier":"kirlia"},{"id":282,"identifier":"gardevoir"},{"id":283,"identifier":"surskit"},{"id":284,"identifier":"masquerain"},{"id":285,"identifier":"shroomish"},{"id":286,"identifier":"breloom"},{"id":287,"identifier":"slakoth"},{"id":288,"identifier":"vigoroth"},{"id":289,"identifier":"slaking"},{"id":290,"identifier":"nincada"},{"id":291,"identifier":"ninjask"},{"id":292,"identifier":"shedinja"},{"id":293,"identifier":"whismur"},{"id":294,"identifier":"loudred"},{"id":295,"identifier":"exploud"},{"id":296,"identifier":"makuhita"},{"id":297,"identifier":"hariyama"},{"id":298,"identifier":"azurill"},{"id":299,"identifier":"nosepass"},{"id":300,"identifier":"skitty"},{"id":301,"identifier":"delcatty"},{"id":302,"identifier":"sableye"},{"id":303,"identifier":"mawile"},{"id":304,"identifier":"aron"},{"id":305,"identifier":"lairon"},{"id":306,"identifier":"aggron"},{"id":307,"identifier":"meditite"},{"id":308,"identifier":"medicham"},{"id":309,"identifier":"electrike"},{"id":310,"identifier":"manectric"},{"id":311,"identifier":"plusle"},{"id":312,"identifier":"minun"},{"id":313,"identifier":"volbeat"},{"id":314,"identifier":"illumise"},{"id":315,"identifier":"roselia"},{"id":316,"identifier":"gulpin"},{"id":317,"identifier":"swalot"},{"id":318,"identifier":"carvanha"},{"id":319,"identifier":"sharpedo"},{"id":320,"identifier":"wailmer"},{"id":321,"identifier":"wailord"},{"id":322,"identifier":"numel"},{"id":323,"identifier":"camerupt"},{"id":324,"identifier":"torkoal"},{"id":325,"identifier":"spoink"},{"id":326,"identifier":"grumpig"},{"id":327,"identifier":"spinda"},{"id":328,"identifier":"trapinch"},{"id":329,"identifier":"vibrava"},{"id":330,"identifier":"flygon"},{"id":331,"identifier":"cacnea"},{"id":332,"identifier":"cacturne"},{"id":333,"identifier":"swablu"},{"id":334,"identifier":"altaria"},{"id":335,"identifier":"zangoose"},{"id":336,"identifier":"seviper"},{"id":337,"identifier":"lunatone"},{"id":338,"identifier":"solrock"},{"id":339,"identifier":"barboach"},{"id":340,"identifier":"whiscash"},{"id":341,"identifier":"corphish"},{"id":342,"identifier":"crawdaunt"},{"id":343,"identifier":"baltoy"},{"id":344,"identifier":"claydol"},{"id":345,"identifier":"lileep"},{"id":346,"identifier":"cradily"},{"id":347,"identifier":"anorith"},{"id":348,"identifier":"armaldo"},{"id":349,"identifier":"feebas"},{"id":350,"identifier":"milotic"},{"id":351,"identifier":"castform"},{"id":352,"identifier":"kecleon"},{"id":353,"identifier":"shuppet"},{"id":354,"identifier":"banette"},{"id":355,"identifier":"duskull"},{"id":356,"identifier":"dusclops"},{"id":357,"identifier":"tropius"},{"id":358,"identifier":"chimecho"},{"id":359,"identifier":"absol"},{"id":360,"identifier":"wynaut"},{"id":361,"identifier":"snorunt"},{"id":362,"identifier":"glalie"},{"id":363,"identifier":"spheal"},{"id":364,"identifier":"sealeo"},{"id":365,"identifier":"walrein"},{"id":366,"identifier":"clamperl"},{"id":367,"identifier":"huntail"},{"id":368,"identifier":"gorebyss"},{"id":369,"identifier":"relicanth"},{"id":370,"identifier":"luvdisc"},{"id":371,"identifier":"bagon"},{"id":372,"identifier":"shelgon"},{"id":373,"identifier":"salamence"},{"id":374,"identifier":"beldum"},{"id":375,"identifier":"metang"},{"id":376,"identifier":"metagross"},{"id":377,"identifier":"regirock"},{"id":378,"identifier":"regice"},{"id":379,"identifier":"registeel"},{"id":380,"identifier":"latias"},{"id":381,"identifier":"latios"},{"id":382,"identifier":"kyogre"},{"id":383,"identifier":"groudon"},{"id":384,"identifier":"rayquaza"},{"id":385,"identifier":"jirachi"},{"id":386,"identifier":"deoxys-normal"},{"id":387,"identifier":"turtwig"},{"id":388,"identifier":"grotle"},{"id":389,"identifier":"torterra"},{"id":390,"identifier":"chimchar"},{"id":391,"identifier":"monferno"},{"id":392,"identifier":"infernape"},{"id":393,"identifier":"piplup"},{"id":394,"identifier":"prinplup"},{"id":395,"identifier":"empoleon"},{"id":396,"identifier":"starly"},{"id":397,"identifier":"staravia"},{"id":398,"identifier":"staraptor"},{"id":399,"identifier":"bidoof"},{"id":400,"identifier":"bibarel"},{"id":401,"identifier":"kricketot"},{"id":402,"identifier":"kricketune"},{"id":403,"identifier":"shinx"},{"id":404,"identifier":"luxio"},{"id":405,"identifier":"luxray"},{"id":406,"identifier":"budew"},{"id":407,"identifier":"roserade"},{"id":408,"identifier":"cranidos"},{"id":409,"identifier":"rampardos"},{"id":410,"identifier":"shieldon"},{"id":411,"identifier":"bastiodon"},{"id":412,"identifier":"burmy"},{"id":413,"identifier":"wormadam-plant"},{"id":414,"identifier":"mothim"},{"id":415,"identifier":"combee"},{"id":416,"identifier":"vespiquen"},{"id":417,"identifier":"pachirisu"},{"id":418,"identifier":"buizel"},{"id":419,"identifier":"floatzel"},{"id":420,"identifier":"cherubi"},{"id":421,"identifier":"cherrim"},{"id":422,"identifier":"shellos"},{"id":423,"identifier":"gastrodon"},{"id":424,"identifier":"ambipom"},{"id":425,"identifier":"drifloon"},{"id":426,"identifier":"drifblim"},{"id":427,"identifier":"buneary"},{"id":428,"identifier":"lopunny"},{"id":429,"identifier":"mismagius"},{"id":430,"identifier":"honchkrow"},{"id":431,"identifier":"glameow"},{"id":432,"identifier":"purugly"},{"id":433,"identifier":"chingling"},{"id":434,"identifier":"stunky"},{"id":435,"identifier":"skuntank"},{"id":436,"identifier":"bronzor"},{"id":437,"identifier":"bronzong"},{"id":438,"identifier":"bonsly"},{"id":439,"identifier":"mime-jr"},{"id":440,"identifier":"happiny"},{"id":441,"identifier":"chatot"},{"id":442,"identifier":"spiritomb"},{"id":443,"identifier":"gible"},{"id":444,"identifier":"gabite"},{"id":445,"identifier":"garchomp"},{"id":446,"identifier":"munchlax"},{"id":447,"identifier":"riolu"},{"id":448,"identifier":"lucario"},{"id":449,"identifier":"hippopotas"},{"id":450,"identifier":"hippowdon"},{"id":451,"identifier":"skorupi"},{"id":452,"identifier":"drapion"},{"id":453,"identifier":"croagunk"},{"id":454,"identifier":"toxicroak"},{"id":455,"identifier":"carnivine"},{"id":456,"identifier":"finneon"},{"id":457,"identifier":"lumineon"},{"id":458,"identifier":"mantyke"},{"id":459,"identifier":"snover"},{"id":460,"identifier":"abomasnow"},{"id":461,"identifier":"weavile"},{"id":462,"identifier":"magnezone"},{"id":463,"identifier":"lickilicky"},{"id":464,"identifier":"rhyperior"},{"id":465,"identifier":"tangrowth"},{"id":466,"identifier":"electivire"},{"id":467,"identifier":"magmortar"},{"id":468,"identifier":"togekiss"},{"id":469,"identifier":"yanmega"},{"id":470,"identifier":"leafeon"},{"id":471,"identifier":"glaceon"},{"id":472,"identifier":"gliscor"},{"id":473,"identifier":"mamoswine"},{"id":474,"identifier":"porygon-z"},{"id":475,"identifier":"gallade"},{"id":476,"identifier":"probopass"},{"id":477,"identifier":"dusknoir"},{"id":478,"identifier":"froslass"},{"id":479,"identifier":"rotom"},{"id":480,"identifier":"uxie"},{"id":481,"identifier":"mesprit"},{"id":482,"identifier":"azelf"},{"id":483,"identifier":"dialga"},{"id":484,"identifier":"palkia"},{"id":485,"identifier":"heatran"},{"id":486,"identifier":"regigigas"},{"id":487,"identifier":"giratina-altered"},{"id":488,"identifier":"cresselia"},{"id":489,"identifier":"phione"},{"id":490,"identifier":"manaphy"},{"id":491,"identifier":"darkrai"},{"id":492,"identifier":"shaymin-land"},{"id":493,"identifier":"arceus"},{"id":494,"identifier":"victini"},{"id":495,"identifier":"snivy"},{"id":496,"identifier":"servine"},{"id":497,"identifier":"serperior"},{"id":498,"identifier":"tepig"},{"id":499,"identifier":"pignite"},{"id":500,"identifier":"emboar"},{"id":501,"identifier":"oshawott"},{"id":502,"identifier":"dewott"},{"id":503,"identifier":"samurott"},{"id":504,"identifier":"patrat"},{"id":505,"identifier":"watchog"},{"id":506,"identifier":"lillipup"},{"id":507,"identifier":"herdier"},{"id":508,"identifier":"stoutland"},{"id":509,"identifier":"purrloin"},{"id":510,"identifier":"liepard"},{"id":511,"identifier":"pansage"},{"id":512,"identifier":"simisage"},{"id":513,"identifier":"pansear"},{"id":514,"identifier":"simisear"},{"id":515,"identifier":"panpour"},{"id":516,"identifier":"simipour"},{"id":517,"identifier":"munna"},{"id":518,"identifier":"musharna"},{"id":519,"identifier":"pidove"},{"id":520,"identifier":"tranquill"},{"id":521,"identifier":"unfezant"},{"id":522,"identifier":"blitzle"},{"id":523,"identifier":"zebstrika"},{"id":524,"identifier":"roggenrola"},{"id":525,"identifier":"boldore"},{"id":526,"identifier":"gigalith"},{"id":527,"identifier":"woobat"},{"id":528,"identifier":"swoobat"},{"id":529,"identifier":"drilbur"},{"id":530,"identifier":"excadrill"},{"id":531,"identifier":"audino"},{"id":532,"identifier":"timburr"},{"id":533,"identifier":"gurdurr"},{"id":534,"identifier":"conkeldurr"},{"id":535,"identifier":"tympole"},{"id":536,"identifier":"palpitoad"},{"id":537,"identifier":"seismitoad"},{"id":538,"identifier":"throh"},{"id":539,"identifier":"sawk"},{"id":540,"identifier":"sewaddle"},{"id":541,"identifier":"swadloon"},{"id":542,"identifier":"leavanny"},{"id":543,"identifier":"venipede"},{"id":544,"identifier":"whirlipede"},{"id":545,"identifier":"scolipede"},{"id":546,"identifier":"cottonee"},{"id":547,"identifier":"whimsicott"},{"id":548,"identifier":"petilil"},{"id":549,"identifier":"lilligant"},{"id":550,"identifier":"basculin-red-striped"},{"id":551,"identifier":"sandile"},{"id":552,"identifier":"krokorok"},{"id":553,"identifier":"krookodile"},{"id":554,"identifier":"darumaka"},{"id":555,"identifier":"darmanitan-standard"},{"id":556,"identifier":"maractus"},{"id":557,"identifier":"dwebble"},{"id":558,"identifier":"crustle"},{"id":559,"identifier":"scraggy"},{"id":560,"identifier":"scrafty"},{"id":561,"identifier":"sigilyph"},{"id":562,"identifier":"yamask"},{"id":563,"identifier":"cofagrigus"},{"id":564,"identifier":"tirtouga"},{"id":565,"identifier":"carracosta"},{"id":566,"identifier":"archen"},{"id":567,"identifier":"archeops"},{"id":568,"identifier":"trubbish"},{"id":569,"identifier":"garbodor"},{"id":570,"identifier":"zorua"},{"id":571,"identifier":"zoroark"},{"id":572,"identifier":"minccino"},{"id":573,"identifier":"cinccino"},{"id":574,"identifier":"gothita"},{"id":575,"identifier":"gothorita"},{"id":576,"identifier":"gothitelle"},{"id":577,"identifier":"solosis"},{"id":578,"identifier":"duosion"},{"id":579,"identifier":"reuniclus"},{"id":580,"identifier":"ducklett"},{"id":581,"identifier":"swanna"},{"id":582,"identifier":"vanillite"},{"id":583,"identifier":"vanillish"},{"id":584,"identifier":"vanilluxe"},{"id":585,"identifier":"deerling"},{"id":586,"identifier":"sawsbuck"},{"id":587,"identifier":"emolga"},{"id":588,"identifier":"karrablast"},{"id":589,"identifier":"escavalier"},{"id":590,"identifier":"foongus"},{"id":591,"identifier":"amoonguss"},{"id":592,"identifier":"frillish"},{"id":593,"identifier":"jellicent"},{"id":594,"identifier":"alomomola"},{"id":595,"identifier":"joltik"},{"id":596,"identifier":"galvantula"},{"id":597,"identifier":"ferroseed"},{"id":598,"identifier":"ferrothorn"},{"id":599,"identifier":"klink"},{"id":600,"identifier":"klang"},{"id":601,"identifier":"klinklang"},{"id":602,"identifier":"tynamo"},{"id":603,"identifier":"eelektrik"},{"id":604,"identifier":"eelektross"},{"id":605,"identifier":"elgyem"},{"id":606,"identifier":"beheeyem"},{"id":607,"identifier":"litwick"},{"id":608,"identifier":"lampent"},{"id":609,"identifier":"chandelure"},{"id":610,"identifier":"axew"},{"id":611,"identifier":"fraxure"},{"id":612,"identifier":"haxorus"},{"id":613,"identifier":"cubchoo"},{"id":614,"identifier":"beartic"},{"id":615,"identifier":"cryogonal"},{"id":616,"identifier":"shelmet"},{"id":617,"identifier":"accelgor"},{"id":618,"identifier":"stunfisk"},{"id":619,"identifier":"mienfoo"},{"id":620,"identifier":"mienshao"},{"id":621,"identifier":"druddigon"},{"id":622,"identifier":"golett"},{"id":623,"identifier":"golurk"},{"id":624,"identifier":"pawniard"},{"id":625,"identifier":"bisharp"},{"id":626,"identifier":"bouffalant"},{"id":627,"identifier":"rufflet"},{"id":628,"identifier":"braviary"},{"id":629,"identifier":"vullaby"},{"id":630,"identifier":"mandibuzz"},{"id":631,"identifier":"heatmor"},{"id":632,"identifier":"durant"},{"id":633,"identifier":"deino"},{"id":634,"identifier":"zweilous"},{"id":635,"identifier":"hydreigon"},{"id":636,"identifier":"larvesta"},{"id":637,"identifier":"volcarona"},{"id":638,"identifier":"cobalion"},{"id":639,"identifier":"terrakion"},{"id":640,"identifier":"virizion"},{"id":641,"identifier":"tornadus-incarnate"},{"id":642,"identifier":"thundurus-incarnate"},{"id":643,"identifier":"reshiram"},{"id":644,"identifier":"zekrom"},{"id":645,"identifier":"landorus-incarnate"},{"id":646,"identifier":"kyurem"},{"id":647,"identifier":"keldeo-ordinary"},{"id":648,"identifier":"meloetta-aria"},{"id":649,"identifier":"genesect"},{"id":650,"identifier":"chespin"},{"id":651,"identifier":"quilladin"},{"id":652,"identifier":"chesnaught"},{"id":653,"identifier":"fennekin"},{"id":654,"identifier":"braixen"},{"id":655,"identifier":"delphox"},{"id":656,"identifier":"froakie"},{"id":657,"identifier":"frogadier"},{"id":658,"identifier":"greninja"},{"id":659,"identifier":"bunnelby"},{"id":660,"identifier":"diggersby"},{"id":661,"identifier":"fletchling"},{"id":662,"identifier":"fletchinder"},{"id":663,"identifier":"talonflame"},{"id":664,"identifier":"scatterbug"},{"id":665,"identifier":"spewpa"},{"id":666,"identifier":"vivillon"},{"id":667,"identifier":"litleo"},{"id":668,"identifier":"pyroar"},{"id":669,"identifier":"flabebe"},{"id":670,"identifier":"floette"},{"id":671,"identifier":"florges"},{"id":672,"identifier":"skiddo"},{"id":673,"identifier":"gogoat"},{"id":674,"identifier":"pancham"},{"id":675,"identifier":"pangoro"},{"id":676,"identifier":"furfrou"},{"id":677,"identifier":"espurr"},{"id":678,"identifier":"meowstic-male"},{"id":679,"identifier":"honedge"},{"id":680,"identifier":"doublade"},{"id":681,"identifier":"aegislash-shield"},{"id":682,"identifier":"spritzee"},{"id":683,"identifier":"aromatisse"},{"id":684,"identifier":"swirlix"},{"id":685,"identifier":"slurpuff"},{"id":686,"identifier":"inkay"},{"id":687,"identifier":"malamar"},{"id":688,"identifier":"binacle"},{"id":689,"identifier":"barbaracle"},{"id":690,"identifier":"skrelp"},{"id":691,"identifier":"dragalge"},{"id":692,"identifier":"clauncher"},{"id":693,"identifier":"clawitzer"},{"id":694,"identifier":"helioptile"},{"id":695,"identifier":"heliolisk"},{"id":696,"identifier":"tyrunt"},{"id":697,"identifier":"tyrantrum"},{"id":698,"identifier":"amaura"},{"id":699,"identifier":"aurorus"},{"id":700,"identifier":"sylveon"},{"id":701,"identifier":"hawlucha"},{"id":702,"identifier":"dedenne"},{"id":703,"identifier":"carbink"},{"id":704,"identifier":"goomy"},{"id":705,"identifier":"sliggoo"},{"id":706,"identifier":"goodra"},{"id":707,"identifier":"klefki"},{"id":708,"identifier":"phantump"},{"id":709,"identifier":"trevenant"},{"id":710,"identifier":"pumpkaboo-average"},{"id":711,"identifier":"gourgeist-average"},{"id":712,"identifier":"bergmite"},{"id":713,"identifier":"avalugg"},{"id":714,"identifier":"noibat"},{"id":715,"identifier":"noivern"},{"id":716,"identifier":"xerneas"},{"id":717,"identifier":"yveltal"},{"id":718,"identifier":"zygarde"},{"id":719,"identifier":"diancie"},{"id":720,"identifier":"hoopa"},{"id":721,"identifier":"volcanion"},{"id":722,"identifier":"rowlet"},{"id":723,"identifier":"dartrix"},{"id":724,"identifier":"decidueye"},{"id":725,"identifier":"litten"},{"id":726,"identifier":"torracat"},{"id":727,"identifier":"incineroar"},{"id":728,"identifier":"popplio"},{"id":729,"identifier":"brionne"},{"id":730,"identifier":"primarina"},{"id":731,"identifier":"pikipek"},{"id":732,"identifier":"trumbeak"},{"id":733,"identifier":"toucannon"},{"id":734,"identifier":"yungoos"},{"id":735,"identifier":"gumshoos"},{"id":736,"identifier":"grubbin"},{"id":737,"identifier":"charjabug"},{"id":738,"identifier":"vikavolt"},{"id":739,"identifier":"crabrawler"},{"id":740,"identifier":"crabominable"},{"id":741,"identifier":"oricorio-baile"},{"id":742,"identifier":"cutiefly"},{"id":743,"identifier":"ribombee"},{"id":744,"identifier":"rockruff"},{"id":745,"identifier":"lycanroc-midday"},{"id":746,"identifier":"wishiwashi-solo"},{"id":747,"identifier":"mareanie"},{"id":748,"identifier":"toxapex"},{"id":749,"identifier":"mudbray"},{"id":750,"identifier":"mudsdale"},{"id":751,"identifier":"dewpider"},{"id":752,"identifier":"araquanid"},{"id":753,"identifier":"fomantis"},{"id":754,"identifier":"lurantis"},{"id":755,"identifier":"morelull"},{"id":756,"identifier":"shiinotic"},{"id":757,"identifier":"salandit"},{"id":758,"identifier":"salazzle"},{"id":759,"identifier":"stufful"},{"id":760,"identifier":"bewear"},{"id":761,"identifier":"bounsweet"},{"id":762,"identifier":"steenee"},{"id":763,"identifier":"tsareena"},{"id":764,"identifier":"comfey"},{"id":765,"identifier":"oranguru"},{"id":766,"identifier":"passimian"},{"id":767,"identifier":"wimpod"},{"id":768,"identifier":"golisopod"},{"id":769,"identifier":"sandygast"},{"id":770,"identifier":"palossand"},{"id":771,"identifier":"pyukumuku"},{"id":772,"identifier":"type-null"},{"id":773,"identifier":"silvally"},{"id":774,"identifier":"minior-red-meteor"},{"id":775,"identifier":"komala"},{"id":776,"identifier":"turtonator"},{"id":777,"identifier":"togedemaru"},{"id":778,"identifier":"mimikyu-disguised"},{"id":779,"identifier":"bruxish"},{"id":780,"identifier":"drampa"},{"id":781,"identifier":"dhelmise"},{"id":782,"identifier":"jangmo-o"},{"id":783,"identifier":"hakamo-o"},{"id":784,"identifier":"kommo-o"},{"id":785,"identifier":"tapu-koko"},{"id":786,"identifier":"tapu-lele"},{"id":787,"identifier":"tapu-bulu"},{"id":788,"identifier":"tapu-fini"},{"id":789,"identifier":"cosmog"},{"id":790,"identifier":"cosmoem"},{"id":791,"identifier":"solgaleo"},{"id":792,"identifier":"lunala"},{"id":793,"identifier":"nihilego"},{"id":794,"identifier":"buzzwole"},{"id":795,"identifier":"pheromosa"},{"id":796,"identifier":"xurkitree"},{"id":797,"identifier":"celesteela"},{"id":798,"identifier":"kartana"},{"id":799,"identifier":"guzzlord"},{"id":800,"identifier":"necrozma"},{"id":801,"identifier":"magearna"},{"id":802,"identifier":"marshadow"},{"id":803,"identifier":"poipole"},{"id":804,"identifier":"naganadel"},{"id":805,"identifier":"stakataka"},{"id":806,"identifier":"blacephalon"},{"id":807,"identifier":"zeraora"},{"id":10001,"identifier":"deoxys-attack"},{"id":10002,"identifier":"deoxys-defense"},{"id":10003,"identifier":"deoxys-speed"},{"id":10004,"identifier":"wormadam-sandy"},{"id":10005,"identifier":"wormadam-trash"},{"id":10006,"identifier":"shaymin-sky"},{"id":10007,"identifier":"giratina-origin"},{"id":10008,"identifier":"rotom-heat"},{"id":10009,"identifier":"rotom-wash"},{"id":10010,"identifier":"rotom-frost"},{"id":10011,"identifier":"rotom-fan"},{"id":10012,"identifier":"rotom-mow"},{"id":10013,"identifier":"castform-sunny"},{"id":10014,"identifier":"castform-rainy"},{"id":10015,"identifier":"castform-snowy"},{"id":10016,"identifier":"basculin-blue-striped"},{"id":10017,"identifier":"darmanitan-zen"},{"id":10018,"identifier":"meloetta-pirouette"},{"id":10019,"identifier":"tornadus-therian"},{"id":10020,"identifier":"thundurus-therian"},{"id":10021,"identifier":"landorus-therian"},{"id":10022,"identifier":"kyurem-black"},{"id":10023,"identifier":"kyurem-white"},{"id":10024,"identifier":"keldeo-resolute"},{"id":10025,"identifier":"meowstic-female"},{"id":10026,"identifier":"aegislash-blade"},{"id":10027,"identifier":"pumpkaboo-small"},{"id":10028,"identifier":"pumpkaboo-large"},{"id":10029,"identifier":"pumpkaboo-super"},{"id":10030,"identifier":"gourgeist-small"},{"id":10031,"identifier":"gourgeist-large"},{"id":10032,"identifier":"gourgeist-super"},{"id":10033,"identifier":"venusaur-mega"},{"id":10034,"identifier":"charizard-mega-x"},{"id":10035,"identifier":"charizard-mega-y"},{"id":10036,"identifier":"blastoise-mega"},{"id":10037,"identifier":"alakazam-mega"},{"id":10038,"identifier":"gengar-mega"},{"id":10039,"identifier":"kangaskhan-mega"},{"id":10040,"identifier":"pinsir-mega"},{"id":10041,"identifier":"gyarados-mega"},{"id":10042,"identifier":"aerodactyl-mega"},{"id":10043,"identifier":"mewtwo-mega-x"},{"id":10044,"identifier":"mewtwo-mega-y"},{"id":10045,"identifier":"ampharos-mega"},{"id":10046,"identifier":"scizor-mega"},{"id":10047,"identifier":"heracross-mega"},{"id":10048,"identifier":"houndoom-mega"},{"id":10049,"identifier":"tyranitar-mega"},{"id":10050,"identifier":"blaziken-mega"},{"id":10051,"identifier":"gardevoir-mega"},{"id":10052,"identifier":"mawile-mega"},{"id":10053,"identifier":"aggron-mega"},{"id":10054,"identifier":"medicham-mega"},{"id":10055,"identifier":"manectric-mega"},{"id":10056,"identifier":"banette-mega"},{"id":10057,"identifier":"absol-mega"},{"id":10058,"identifier":"garchomp-mega"},{"id":10059,"identifier":"lucario-mega"},{"id":10060,"identifier":"abomasnow-mega"},{"id":10061,"identifier":"floette-eternal"},{"id":10062,"identifier":"latias-mega"},{"id":10063,"identifier":"latios-mega"},{"id":10064,"identifier":"swampert-mega"},{"id":10065,"identifier":"sceptile-mega"},{"id":10066,"identifier":"sableye-mega"},{"id":10067,"identifier":"altaria-mega"},{"id":10068,"identifier":"gallade-mega"},{"id":10069,"identifier":"audino-mega"},{"id":10070,"identifier":"sharpedo-mega"},{"id":10071,"identifier":"slowbro-mega"},{"id":10072,"identifier":"steelix-mega"},{"id":10073,"identifier":"pidgeot-mega"},{"id":10074,"identifier":"glalie-mega"},{"id":10075,"identifier":"diancie-mega"},{"id":10076,"identifier":"metagross-mega"},{"id":10077,"identifier":"kyogre-primal"},{"id":10078,"identifier":"groudon-primal"},{"id":10079,"identifier":"rayquaza-mega"},{"id":10080,"identifier":"pikachu-rock-star"},{"id":10081,"identifier":"pikachu-belle"},{"id":10082,"identifier":"pikachu-pop-star"},{"id":10083,"identifier":"pikachu-phd"},{"id":10084,"identifier":"pikachu-libre"},{"id":10085,"identifier":"pikachu-cosplay"},{"id":10086,"identifier":"hoopa-unbound"},{"id":10087,"identifier":"camerupt-mega"},{"id":10088,"identifier":"lopunny-mega"},{"id":10089,"identifier":"salamence-mega"},{"id":10090,"identifier":"beedrill-mega"},{"id":10091,"identifier":"rattata-alola"},{"id":10092,"identifier":"raticate-alola"},{"id":10093,"identifier":"raticate-totem-alola"},{"id":10094,"identifier":"pikachu-original-cap"},{"id":10095,"identifier":"pikachu-hoenn-cap"},{"id":10096,"identifier":"pikachu-sinnoh-cap"},{"id":10097,"identifier":"pikachu-unova-cap"},{"id":10098,"identifier":"pikachu-kalos-cap"},{"id":10099,"identifier":"pikachu-alola-cap"},{"id":10100,"identifier":"raichu-alola"},{"id":10101,"identifier":"sandshrew-alola"},{"id":10102,"identifier":"sandslash-alola"},{"id":10103,"identifier":"vulpix-alola"},{"id":10104,"identifier":"ninetales-alola"},{"id":10105,"identifier":"diglett-alola"},{"id":10106,"identifier":"dugtrio-alola"},{"id":10107,"identifier":"meowth-alola"},{"id":10108,"identifier":"persian-alola"},{"id":10109,"identifier":"geodude-alola"},{"id":10110,"identifier":"graveler-alola"},{"id":10111,"identifier":"golem-alola"},{"id":10112,"identifier":"grimer-alola"},{"id":10113,"identifier":"muk-alola"},{"id":10114,"identifier":"exeggutor-alola"},{"id":10115,"identifier":"marowak-alola"},{"id":10116,"identifier":"greninja-battle-bond"},{"id":10117,"identifier":"greninja-ash"},{"id":10118,"identifier":"zygarde-10"},{"id":10119,"identifier":"zygarde-50"},{"id":10120,"identifier":"zygarde-complete"},{"id":10121,"identifier":"gumshoos-totem"},{"id":10122,"identifier":"vikavolt-totem"},{"id":10123,"identifier":"oricorio-pom-pom"},{"id":10124,"identifier":"oricorio-pau"},{"id":10125,"identifier":"oricorio-sensu"},{"id":10126,"identifier":"lycanroc-midnight"},{"id":10127,"identifier":"wishiwashi-school"},{"id":10128,"identifier":"lurantis-totem"},{"id":10129,"identifier":"salazzle-totem"},{"id":10130,"identifier":"minior-orange-meteor"},{"id":10131,"identifier":"minior-yellow-meteor"},{"id":10132,"identifier":"minior-green-meteor"},{"id":10133,"identifier":"minior-blue-meteor"},{"id":10134,"identifier":"minior-indigo-meteor"},{"id":10135,"identifier":"minior-violet-meteor"},{"id":10136,"identifier":"minior-red"},{"id":10137,"identifier":"minior-orange"},{"id":10138,"identifier":"minior-yellow"},{"id":10139,"identifier":"minior-green"},{"id":10140,"identifier":"minior-blue"},{"id":10141,"identifier":"minior-indigo"},{"id":10142,"identifier":"minior-violet"},{"id":10143,"identifier":"mimikyu-busted"},{"id":10144,"identifier":"mimikyu-totem-disguised"},{"id":10145,"identifier":"mimikyu-totem-busted"},{"id":10146,"identifier":"kommo-o-totem"},{"id":10147,"identifier":"magearna-original"},{"id":10148,"identifier":"pikachu-partner-cap"},{"id":10149,"identifier":"marowak-totem"},{"id":10150,"identifier":"ribombee-totem"},{"id":10151,"identifier":"rockruff-own-tempo"},{"id":10152,"identifier":"lycanroc-dusk"},{"id":10153,"identifier":"araquanid-totem"},{"id":10154,"identifier":"togedemaru-totem"},{"id":10155,"identifier":"necrozma-dusk"},{"id":10156,"identifier":"necrozma-dawn"},{"id":10157,"identifier":"necrozma-ultra"}] -------------------------------------------------------------------------------- /public/precache-sw.js: -------------------------------------------------------------------------------- 1 | self.workbox.precaching.precache([ 2 | 'https://cdn.materialdesignicons.com/3.5.95/css/materialdesignicons.min.css', 3 | 'https://cdn.materialdesignicons.com/3.5.95/fonts/materialdesignicons-webfont.eot?v=3.5.95' 4 | ]) 5 | 6 | const imgRgx = new RegExp(/(https?:\/\/.*\.(?:png|jpg))/i) 7 | 8 | const handler = new self.workbox.strategies.CacheFirst({ 9 | plugins: [ 10 | new self.workbox.cacheableResponse.Plugin({ 11 | statuses: [0, 200, 304] 12 | }) 13 | ], 14 | cacheName: 'images' 15 | }) 16 | 17 | const matchFunction = ({ url }) => { 18 | return imgRgx.test(url.href) 19 | } 20 | 21 | self.workbox.routing.registerRoute( 22 | matchFunction, 23 | handler 24 | ) 25 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /src/AppShell.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 73 | -------------------------------------------------------------------------------- /src/assets/scss/_variables.scss: -------------------------------------------------------------------------------- 1 | // Included below are all the defined variables from Bulma 2 | // Modify as needed, removing the !default attribute. 3 | 4 | // Colors 5 | 6 | $black: hsl(0, 0%, 4%) !default; 7 | $black-bis: hsl(0, 0%, 7%) !default; 8 | $black-ter: hsl(0, 0%, 14%) !default; 9 | 10 | $grey-darker: hsl(0, 0%, 21%) !default; 11 | $grey-dark: hsl(0, 0%, 29%) !default; 12 | $grey: hsl(0, 0%, 48%) !default; 13 | $grey-light: hsl(0, 0%, 71%) !default; 14 | $grey-lighter: hsl(0, 0%, 86%) !default; 15 | 16 | $white-ter: hsl(0, 0%, 96%) !default; 17 | $white-bis: hsl(0, 0%, 98%) !default; 18 | $white: hsl(0, 0%, 100%) !default; 19 | 20 | $orange: hsl(14, 100%, 53%) !default; 21 | $yellow: hsl(48, 100%, 67%) !default; 22 | $green: hsl(141, 71%, 48%) !default; 23 | $turquoise: hsl(171, 100%, 41%) !default; 24 | $cyan: hsl(204, 86%, 53%) !default; 25 | $blue: hsl(217, 71%, 53%) !default; 26 | $purple: hsl(271, 100%, 71%) !default; 27 | $red: hsl(348, 100%, 61%) !default; 28 | 29 | // Typography 30 | 31 | $family-sans-serif: BlinkMacSystemFont, -apple-system, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Helvetica", "Arial", sans-serif !default; 32 | $family-monospace: monospace !default; 33 | $render-mode: optimizeLegibility !default; 34 | 35 | $size-1: 3rem !default; 36 | $size-2: 2.5rem !default; 37 | $size-3: 2rem !default; 38 | $size-4: 1.5rem !default; 39 | $size-5: 1.25rem !default; 40 | $size-6: 1rem !default; 41 | $size-7: 0.75rem !default; 42 | 43 | $weight-light: 300 !default; 44 | $weight-normal: 400 !default; 45 | $weight-medium: 500 !default; 46 | $weight-semibold: 600 !default; 47 | $weight-bold: 700 !default; 48 | 49 | // Responsiveness 50 | 51 | // The container horizontal gap, which acts as the offset for breakpoints 52 | $gap: 32px !default; 53 | // 960, 1152, and 1344 have been chosen because they are divisible by both 12 and 16 54 | $tablet: 769px !default; 55 | // 960px container + 4rem 56 | $desktop: 960px + (2 * $gap) !default; 57 | // 1152px container + 4rem 58 | $widescreen: 1152px + (2 * $gap) !default; 59 | // 1344px container + 4rem; 60 | $fullhd: 1344px + (2 * $gap) !default; 61 | 62 | // Miscellaneous 63 | 64 | $easing: ease-out !default; 65 | $radius-small: 2px !default; 66 | $radius: 3px !default; 67 | $radius-large: 5px !default; 68 | $radius-rounded: 290486px !default; 69 | $speed: 86ms !default; 70 | 71 | // Flags 72 | 73 | $variable-columns: true !default; 74 | 75 | 76 | // The default Bulma derived variables are declared below 77 | 78 | $primary: $turquoise !default; 79 | 80 | $info: $cyan !default; 81 | $success: $green !default; 82 | $warning: $yellow !default; 83 | $danger: $red !default; 84 | 85 | $light: $white-ter !default; 86 | $dark: $grey-darker !default; 87 | 88 | // Invert colors 89 | 90 | $orange-invert: findColorInvert($orange) !default; 91 | $yellow-invert: findColorInvert($yellow) !default; 92 | $green-invert: findColorInvert($green) !default; 93 | $turquoise-invert: findColorInvert($turquoise) !default; 94 | $cyan-invert: findColorInvert($cyan) !default; 95 | $blue-invert: findColorInvert($blue) !default; 96 | $purple-invert: findColorInvert($purple) !default; 97 | $red-invert: findColorInvert($red) !default; 98 | 99 | $primary-invert: $turquoise-invert !default; 100 | $info-invert: $cyan-invert !default; 101 | $success-invert: $green-invert !default; 102 | $warning-invert: $yellow-invert !default; 103 | $danger-invert: $red-invert !default; 104 | $light-invert: $dark !default; 105 | $dark-invert: $light !default; 106 | 107 | // General colors 108 | 109 | $background: $white-ter !default; 110 | 111 | $border: $grey-lighter !default; 112 | $border-hover: $grey-light !default; 113 | 114 | // Text colors 115 | 116 | $text: $grey-dark !default; 117 | $text-invert: findColorInvert($text) !default; 118 | $text-light: $grey !default; 119 | $text-strong: $grey-darker !default; 120 | 121 | // Code colors 122 | 123 | $code: $red !default; 124 | $code-background: $background !default; 125 | 126 | $pre: $text !default; 127 | $pre-background: $background !default; 128 | 129 | // Link colors 130 | 131 | $link: $blue !default; 132 | $link-invert: $blue-invert !default; 133 | $link-visited: $purple !default; 134 | 135 | $link-hover: $grey-darker !default; 136 | $link-hover-border: $grey-light !default; 137 | 138 | $link-focus: $grey-darker !default; 139 | $link-focus-border: $blue !default; 140 | 141 | $link-active: $grey-darker !default; 142 | $link-active-border: $grey-dark !default; 143 | 144 | // Typography 145 | 146 | $family-primary: $family-sans-serif !default; 147 | $family-code: $family-monospace !default; 148 | 149 | $size-small: $size-7 !default; 150 | $size-normal: $size-6 !default; 151 | $size-medium: $size-5 !default; 152 | $size-large: $size-4 !default; 153 | -------------------------------------------------------------------------------- /src/assets/scss/app.scss: -------------------------------------------------------------------------------- 1 | @import "~bulma/sass/utilities/initial-variables"; 2 | @import "~bulma/sass/utilities/functions"; 3 | // 1. Set your own initial variables and derived 4 | // variables in _variables.scss 5 | @import "variables"; 6 | 7 | // 2. Setup your Custom Colors 8 | @import "~bulma/sass/utilities/derived-variables"; 9 | 10 | // 3. Add new color variables to the color map. 11 | // 12 | 13 | 14 | @import "~bulma"; 15 | @import "~buefy/src/scss/buefy"; 16 | 17 | // 4. Provide custom buefy overrides and site styles here 18 | 19 | .card.is-spotlight { 20 | box-shadow: 0 2px 3px rgba($blue, 0.3), 0 0 0 1px rgba($blue, 0.3) 21 | } 22 | 23 | .column { 24 | padding-top: 0; 25 | } 26 | 27 | 28 | @keyframes fadeIn { 29 | from { 30 | opacity: 0; 31 | } 32 | 33 | to { 34 | opacity: 1; 35 | } 36 | } 37 | 38 | .fade-in { 39 | animation: fadeIn 1s ease-in-out; 40 | } 41 | -------------------------------------------------------------------------------- /src/buefy.js: -------------------------------------------------------------------------------- 1 | import { Notification } from 'buefy/dist/components/notification' 2 | import { Icon } from 'buefy/dist/components/icon' 3 | import { Loading } from 'buefy/dist/components/loading' 4 | import { Switch } from 'buefy/dist/components/switch' 5 | 6 | export function install (Vue) { 7 | Vue.component('b-notification', Notification) 8 | Vue.component('b-icon', Icon) 9 | Vue.component('b-loading', Loading) 10 | Vue.component('b-switch', Switch) 11 | } 12 | -------------------------------------------------------------------------------- /src/components/FinishModal.vue: -------------------------------------------------------------------------------- 1 | 71 | 72 | 191 | 192 | 226 | -------------------------------------------------------------------------------- /src/components/InformationsModal.vue: -------------------------------------------------------------------------------- 1 | 56 | 57 | 81 | 82 | 84 | -------------------------------------------------------------------------------- /src/components/LevelSelect.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 45 | -------------------------------------------------------------------------------- /src/components/PokeCards/Card.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 57 | -------------------------------------------------------------------------------- /src/components/PokeCards/CardImage.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 85 | 86 | 125 | -------------------------------------------------------------------------------- /src/components/PokeCards/Main.vue: -------------------------------------------------------------------------------- 1 | 55 | 56 | 151 | 152 | 171 | -------------------------------------------------------------------------------- /src/components/Pokeball.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 19 | 20 | 95 | -------------------------------------------------------------------------------- /src/components/Shell/AlertDone.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 22 | -------------------------------------------------------------------------------- /src/components/Shell/AlertError.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 24 | -------------------------------------------------------------------------------- /src/components/Shell/Footer.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 29 | 30 | 39 | -------------------------------------------------------------------------------- /src/components/Shell/Header.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 83 | 84 | 93 | -------------------------------------------------------------------------------- /src/components/Shell/index.js: -------------------------------------------------------------------------------- 1 | const ShellHeader = () => import(/* webpackChunkName: "app-shell-fragment" */'./Header.vue') 2 | const ShellFooter = () => import(/* webpackChunkName: "app-shell-fragment" */'./Footer.vue') 3 | const ShellAlertDone = () => import(/* webpackChunkName: "app-shell-fragment" */'./AlertDone.vue') 4 | const ShellAlertError = () => import(/* webpackChunkName: "app-shell-fragment" */'./AlertError.vue') 5 | 6 | export default { 7 | ShellHeader, 8 | ShellFooter, 9 | ShellAlertDone, 10 | ShellAlertError 11 | } 12 | -------------------------------------------------------------------------------- /src/components/Timer.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 61 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import store from './store' 3 | import { install as Filters } from './support/filters' 4 | import { install as Ga } from './support/ga' 5 | import { install as Buefy } from './buefy' 6 | import './registerServiceWorker' 7 | import './assets/scss/app.scss' 8 | 9 | Vue.use(Ga) 10 | Vue.use(Buefy) 11 | Vue.use(Filters) 12 | 13 | Vue.config.productionTip = false 14 | 15 | const App = () => import(/* webpackChunkName: "app-shell" */ './AppShell.vue') 16 | 17 | new Vue({ 18 | store, 19 | render: h => h(App) 20 | }).$mount('#app') 21 | -------------------------------------------------------------------------------- /src/registerServiceWorker.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { register } from 'register-service-worker' 4 | 5 | const dispatchEvent = (name, meta, timeout = 8000) => { 6 | setTimeout(() => { 7 | const event = new Event(name) 8 | 9 | if (meta) { 10 | event.meta = meta 11 | } 12 | 13 | document.dispatchEvent(event) 14 | }, timeout) 15 | } 16 | 17 | if (process.env.NODE_ENV === 'production') { 18 | register(`${process.env.BASE_URL}service-worker.js`, { 19 | ready () { 20 | // console.log( 21 | // 'App is being served from cache by a service worker.\n' + 22 | // 'For more details, visit https://goo.gl/AFskqB' 23 | // ) 24 | }, 25 | registered (registration) { 26 | registration.update() 27 | }, 28 | cached () { 29 | // console.log('Content has been cached for offline use.') 30 | }, 31 | updatefound () { 32 | console.log('New content is downloading.') 33 | }, 34 | updated () { 35 | dispatchEvent('sw:update') 36 | dispatchEvent('sw:update', undefined, 8000 * 5) 37 | }, 38 | offline () { 39 | // console.log('No internet connection found. App is running in offline mode.') 40 | }, 41 | error (error) { 42 | console.error('Error during service worker registration:', error) 43 | } 44 | }) 45 | } 46 | -------------------------------------------------------------------------------- /src/store/actions.js: -------------------------------------------------------------------------------- 1 | import * as mutations from './mutations.type' 2 | import { includes } from 'lodash-es' 3 | 4 | const loadPokemon = ({ commit }) => { 5 | commit(mutations.setIsLoading, true) 6 | commit(mutations.setIsRunning, false) 7 | commit(mutations.resetSelecteds) 8 | commit(mutations.resetFound) 9 | commit(mutations.resetFailures) 10 | commit(mutations.resetScore) 11 | 12 | return fetch('/pokemon.json') 13 | .then(response => response.json()) 14 | .then(data => { 15 | commit(mutations.setError, '') 16 | commit(mutations.setPokemonRawList, [...data]) 17 | return new Promise(resolve => { 18 | setTimeout(() => { 19 | commit(mutations.setIsRunning, true) 20 | commit(mutations.setIsLoading, false) 21 | }, 500) 22 | }) 23 | }) 24 | .catch(err => { 25 | commit(mutations.setIsLoading, false) 26 | commit(mutations.setError, err.message) 27 | }) 28 | } 29 | 30 | const selectPokeCard = ({ commit, state }, pokemon) => { 31 | const { found, selecteds } = state 32 | 33 | if (includes(found, pokemon.id) || includes(selecteds, pokemon.index)) { 34 | return 35 | } 36 | 37 | commit(mutations.addSelected, pokemon.index) 38 | } 39 | 40 | const setLevel = ({ commit, dispatch }, level) => { 41 | commit(mutations.setLevel, level) 42 | 43 | return dispatch('loadPokemon') 44 | } 45 | 46 | const setIsEasyMode = ({ commit, dispatch }, value) => { 47 | commit(mutations.setIsEasyMode, value) 48 | 49 | return dispatch('loadPokemon') 50 | } 51 | 52 | const setIsRouletteMode = ({ commit, dispatch }, value) => { 53 | commit(mutations.setIsRouletteMode, value) 54 | 55 | return dispatch('loadPokemon') 56 | } 57 | 58 | const addFound = ({ commit, state, getters }, id) => { 59 | const { nextScoreIncrement } = getters 60 | 61 | commit(mutations.addFound, id) 62 | commit(mutations.addScore, nextScoreIncrement) 63 | commit(mutations.resetFailures) 64 | } 65 | 66 | export default { loadPokemon, selectPokeCard, setLevel, addFound, setIsEasyMode, setIsRouletteMode } 67 | -------------------------------------------------------------------------------- /src/store/getters.js: -------------------------------------------------------------------------------- 1 | import { size, map, chunk, shuffle, find } from 'lodash-es' 2 | import { randomIntList, makeLevels } from '../support/utils' 3 | import { getColsNumber, getColsMobileNumber } from '../support/grid' 4 | 5 | export default { 6 | // count all pokemon 7 | pokemonRawCount: ({ pokemonRawList }) => size(pokemonRawList), 8 | // number of cards 9 | levelCount: ({ level }) => level * 2, 10 | // number of pokemon found 11 | foundCount: ({ found }) => size(found), 12 | levels: ({ isMobile }) => { 13 | return makeLevels(6, isMobile ? 4 : 10) 14 | }, 15 | timerStatus: ({ isRunning }, { isDone }) => { 16 | return isRunning && !isDone 17 | }, 18 | // random pokemon pokemon list 19 | pokemon: ({ level, pokemonRawList }, { pokemonRawCount }) => { 20 | if (pokemonRawCount <= 0) { 21 | return [] 22 | } 23 | 24 | const indexes = randomIntList(level, pokemonRawCount - 1, 0) 25 | return map(indexes, index => pokemonRawList[index]) 26 | }, 27 | // list of pokecards 28 | pokeCards: ({ shuffleCount }, { pokemon }) => { 29 | const list = shuffle([...pokemon, ...pokemon]) 30 | 31 | return map(list, (row, index) => { 32 | return { 33 | ...row, 34 | shuffleCount, // only to force update of the list. 35 | index 36 | } 37 | }) 38 | }, 39 | // lists of pokemon list 40 | pokeCardsLists: ({ isMobile }, { pokeCards }) => { 41 | const len = size(pokeCards) 42 | return chunk( 43 | pokeCards, 44 | isMobile ? getColsMobileNumber(len) : getColsNumber(len) 45 | ) 46 | }, 47 | // poke cards selected 48 | selectedCards: ({ selecteds }, { pokeCards }) => { 49 | return map(selecteds, index => { 50 | return find(pokeCards, card => card.index === index) 51 | }) 52 | }, 53 | // all pokemon has find 54 | isDone: ({ level }, { foundCount }) => { 55 | if (foundCount === 0) { 56 | return false 57 | } 58 | 59 | return level === foundCount 60 | }, 61 | // cards selected is math 62 | isMath: (state, { selectedCards }) => { 63 | if (size(selectedCards) === 2) { 64 | const [a, b] = selectedCards 65 | return a.id === b.id 66 | } 67 | 68 | return false 69 | }, 70 | baseScore: ({ level, isEasyMode, isRouletteMode }) => { 71 | const factor = isRouletteMode ? 3 : 2 72 | const base = Math.pow(level, factor) 73 | 74 | return isEasyMode 75 | ? Math.floor(base * (isRouletteMode ? 0.25 : 0.50)) 76 | : base 77 | }, 78 | nextScoreIncrement: ({ level, failures }, { baseScore }) => { 79 | if (failures === 0) { 80 | return baseScore 81 | } 82 | 83 | // max factor 84 | const factor = failures < 10 ? (failures / 10) : 0.9 85 | const value = baseScore - (baseScore * factor) 86 | 87 | return Math.floor(value) 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex, { Store } from 'vuex' 3 | import state from './state' 4 | import mutations from './mutations' 5 | import actions from './actions' 6 | import getters from './getters' 7 | import cardsActions from './plugins-cards-actions' 8 | 9 | Vue.use(Vuex) 10 | 11 | export default new Store({ 12 | mutations, 13 | actions, 14 | getters, 15 | state, 16 | strict: process.env.NODE_ENV !== 'production', 17 | plugins: [cardsActions] 18 | }) 19 | -------------------------------------------------------------------------------- /src/store/mutations.js: -------------------------------------------------------------------------------- 1 | import { size, uniq, toSafeInteger } from 'lodash-es' 2 | import * as types from './mutations.type' 3 | 4 | const isSet = action => action === 'set' 5 | const makeMutation = prop => (state, value) => { 6 | state[prop] = value 7 | } 8 | 9 | const mutations = Object.entries(types) 10 | .reduce((acc, [key, value]) => { 11 | const [action, prop] = value.split('/') 12 | 13 | if (isSet(action)) { 14 | acc[value] = makeMutation(prop) 15 | } 16 | 17 | return acc 18 | }, {}) 19 | 20 | export default { 21 | ...mutations, 22 | // reset 23 | [types.resetFound]: state => { 24 | state.found = [] 25 | }, 26 | [types.resetSelecteds]: state => { 27 | state.selecteds = [] 28 | }, 29 | [types.resetFailures]: state => { 30 | state.failures = 0 31 | }, 32 | [types.resetScore]: (state, value) => { 33 | state.score = 0 34 | }, 35 | // add 36 | [types.addScore]: (state, value) => { 37 | state.score = state.score + toSafeInteger(value) 38 | }, 39 | [types.addFailure]: state => { 40 | state.failures = state.failures + 1 41 | }, 42 | [types.addFound]: (state, id) => { 43 | state.found = uniq([...state.found, id]) 44 | }, 45 | [types.addSelected]: (state, id) => { 46 | if (size(state.selecteds) < 2) { 47 | state.selecteds = uniq([...state.selecteds, id]) 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/store/mutations.type.js: -------------------------------------------------------------------------------- 1 | export const setError = 'set/error' 2 | export const setLevel = 'set/level' 3 | export const setTimer = 'set/timer' 4 | export const setShuffleCount = 'set/shuffleCount' 5 | export const setIsRouletteMode = 'set/isRouletteMode' 6 | export const setIsEasyMode = 'set/isEasyMode' 7 | export const setIsRunning = 'set/isRunning' 8 | export const setIsLoading = 'set/isLoading' 9 | export const setPokemonRawList = 'set/pokemonRawList' 10 | 11 | export const addFound = 'add/found' 12 | export const addSelected = 'add/selected' 13 | export const addFailure = 'add/failure' 14 | export const addScore = 'add/score' 15 | 16 | export const resetScore = 'reset/score' 17 | export const resetFailures = 'reset/failures' 18 | export const resetFound = 'reset/found' 19 | export const resetSelecteds = 'reset/selecteds' 20 | -------------------------------------------------------------------------------- /src/store/plugins-cards-actions.js: -------------------------------------------------------------------------------- 1 | import { Snackbar } from 'buefy/dist/components/snackbar' 2 | import { Toast } from 'buefy/dist/components/toast' 3 | import { size, head, toUpper } from 'lodash-es' 4 | import * as mutations from './mutations.type' 5 | 6 | const cathAlert = identifier => { 7 | Snackbar.open({ 8 | position: 'is-top', 9 | message: `You find ${toUpper(identifier)}!`, 10 | queue: false, 11 | duration: 1000 12 | }) 13 | } 14 | 15 | const cardsActionsPlugin = store => { 16 | const resetSelecteds = () => { 17 | setTimeout(() => { 18 | store.commit(mutations.resetSelecteds) 19 | }, 400) 20 | } 21 | 22 | const addFound = ({ id, identifier }) => { 23 | cathAlert(identifier) 24 | store.dispatch('addFound', id) 25 | } 26 | 27 | store.watch( 28 | ({ pokemonRawList, isMobile, shuffleCount }) => ({ pokemonRawList, isMobile, shuffleCount }), 29 | ({ isMobile }) => { 30 | if (isMobile) { 31 | setTimeout(() => { 32 | const el = document.querySelector('#main') 33 | if (el) { 34 | el.scrollIntoView() 35 | } 36 | }) 37 | } 38 | } 39 | ) 40 | 41 | // roulette mode 42 | store.watch( 43 | ({ level, isRouletteMode }, { foundCount }) => ({ level, foundCount, isRouletteMode }), 44 | ({ level, foundCount, isRouletteMode }) => { 45 | // skip 46 | if (foundCount <= 1 || !isRouletteMode || level === foundCount) { 47 | return 48 | } 49 | 50 | if ((foundCount % (level / 3)) === 0) { 51 | store.commit(mutations.setIsLoading, true) 52 | 53 | setTimeout(() => { 54 | store.commit(mutations.setShuffleCount, Math.random() * 100) 55 | store.commit(mutations.setIsLoading, false) 56 | }, 500) 57 | } 58 | } 59 | ) 60 | 61 | // watch Easy Mode 62 | store.watch( 63 | ({ isEasyMode }) => isEasyMode, 64 | val => { 65 | val 66 | ? Toast.open({ 67 | type: 'is-warning', 68 | message: 'Easy Mode is On. Your score will be lower than normal.' 69 | }) 70 | : Toast.open({ 71 | message: 'Easy Mode is Off, Your score returns to normal.' 72 | }) 73 | } 74 | ) 75 | 76 | // watch cards selections 77 | store.watch( 78 | // get data 79 | (state, { isMath, selectedCards }) => ({ selectedCards, isMath }), 80 | // handler 81 | ({ selectedCards, isMath }) => { 82 | if (isMath) { 83 | addFound( 84 | head(selectedCards) 85 | ) 86 | } 87 | 88 | // need reset 89 | if (size(selectedCards) === 2) { 90 | resetSelecteds() 91 | 92 | if (!isMath) { 93 | store.commit(mutations.addFailure) 94 | } 95 | } 96 | } 97 | ) 98 | } 99 | 100 | export default cardsActionsPlugin 101 | -------------------------------------------------------------------------------- /src/store/state.js: -------------------------------------------------------------------------------- 1 | import { isMobile } from '../support/utils' 2 | 3 | export default { 4 | level: 6, 5 | score: 0, 6 | timer: 0, 7 | failures: 0, 8 | shuffleCount: 0, 9 | error: '', 10 | isRunning: false, 11 | isEasyMode: false, 12 | isRouletteMode: false, 13 | isLoading: false, 14 | isMobile: isMobile(), 15 | found: [], 16 | selecteds: [], 17 | pokemonRawList: [] 18 | } 19 | -------------------------------------------------------------------------------- /src/support/color.js: -------------------------------------------------------------------------------- 1 | import { memoize } from 'lodash-es' 2 | import GeoPattern from 'geopattern' 3 | 4 | /** 5 | * @param {String} val 6 | * @returns {String} 7 | */ 8 | const getPattern = memoize(val => { 9 | return GeoPattern.generate(val, { generator: 'squares' }) 10 | .toDataUrl() 11 | }) 12 | 13 | export { getPattern } 14 | -------------------------------------------------------------------------------- /src/support/filters.js: -------------------------------------------------------------------------------- 1 | import { padStart, toInteger, toSafeInteger } from 'lodash-es' 2 | const padHour = (value) => padStart(value, 2, 0) 3 | 4 | const secToTimeStr = (val, showHour = true) => { 5 | const seconds = toInteger(val) 6 | const result = [] 7 | 8 | if (showHour) { 9 | result.push(padHour(Math.floor(seconds / 3600))) // hours 10 | result.push(padHour(Math.floor(seconds / 60) % 60)) // minutes 11 | } else { 12 | result.push(padHour(Math.floor(seconds / 60))) // hours | minutes 13 | } 14 | 15 | result.push(padHour(seconds % 60)) 16 | 17 | return result.join(':') 18 | } 19 | 20 | const getNavigatorLanguage = () => { 21 | if (navigator.languages && navigator.languages.length) { 22 | return navigator.languages[0] 23 | } 24 | return navigator.userLanguage || navigator.language || navigator.browserLanguage || 'en' 25 | } 26 | 27 | const defLanguage = getNavigatorLanguage() 28 | 29 | const numberFormat = (value, options = {}) => { 30 | return toSafeInteger(value).toLocaleString(defLanguage, options) 31 | } 32 | 33 | export function install (Vue) { 34 | Vue.filter('secToTimeStr', secToTimeStr) 35 | Vue.filter('number', numberFormat) 36 | } 37 | -------------------------------------------------------------------------------- /src/support/ga.js: -------------------------------------------------------------------------------- 1 | function call (...args) { 2 | if (!window.ga) { 3 | return 4 | } 5 | 6 | window.ga(...args) 7 | } 8 | 9 | const send = (...args) => { 10 | call('send', ...args) 11 | } 12 | 13 | const set = (...args) => { 14 | call('set', ...args) 15 | } 16 | 17 | call.send = send 18 | call.set = set 19 | 20 | const install = Vue => { 21 | Object.defineProperty(Vue.prototype, '$ga', { 22 | get: () => call 23 | }) 24 | } 25 | 26 | export { send, set, install } 27 | export default install 28 | -------------------------------------------------------------------------------- /src/support/grid.js: -------------------------------------------------------------------------------- 1 | import { cond, stubTrue, curry, constant, gte } from 'lodash-es' 2 | 3 | const isDivisible = curry((a, b) => { 4 | return (b % a) === 0 5 | }) 6 | 7 | const getLargeCols = cond([ 8 | [isDivisible(10), constant(10)], 9 | [isDivisible(12), constant(12)], 10 | [stubTrue, constant(16)] 11 | ]) 12 | 13 | const getColsNumber = cond([ 14 | [val => gte(val, 60), getLargeCols], 15 | [isDivisible(7), constant(7)], 16 | [isDivisible(9), constant(9)], 17 | [isDivisible(8), constant(8)], 18 | [stubTrue, constant(6)] 19 | ]) 20 | 21 | const getColsMobileNumber = cond([ 22 | [val => gte(val, 24), constant(4)], 23 | [stubTrue, constant(3)] 24 | ]) 25 | 26 | export { getColsNumber, getColsMobileNumber } 27 | -------------------------------------------------------------------------------- /src/support/utils.js: -------------------------------------------------------------------------------- 1 | import { random, uniq, size } from 'lodash-es' 2 | 3 | const nextUniq = (length, min, max, original = []) => { 4 | const cleaned = uniq(original) 5 | 6 | if (size(cleaned) === length) { 7 | return cleaned 8 | } 9 | 10 | return nextUniq(length, min, max, [...cleaned, random(min, max)]) 11 | } 12 | 13 | const randomIntList = (length, max, min = 0) => { 14 | return nextUniq(length, max, min) 15 | } 16 | 17 | const pokeDBSprite = key => { 18 | return `https://images.weserv.nl/?url=img.pokemondb.net/artwork/${key}.jpg` 19 | } 20 | 21 | const pokeApiSprite = id => { 22 | return `https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${id}.png` 23 | } 24 | 25 | const isMobile = () => window.screen.width <= 699 26 | 27 | const makeLevels = (base, length) => Array.from({ length }).map((_, index) => { 28 | return base * (index + 1) 29 | }) 30 | 31 | export { randomIntList, pokeDBSprite, pokeApiSprite, isMobile, makeLevels } 32 | -------------------------------------------------------------------------------- /tests/unit/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | jest: true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /tests/unit/components/__snapshots__/pokeball.spec.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Pokeball.vue renders component 1`] = ` 4 |
7 |
10 |
13 |
16 |
17 |
18 |
19 | `; 20 | -------------------------------------------------------------------------------- /tests/unit/components/pokeball.spec.js: -------------------------------------------------------------------------------- 1 | import { shallowMount } from '@vue/test-utils' 2 | import Pokeball from '@/components/Pokeball.vue' 3 | 4 | describe('Pokeball.vue', () => { 5 | it('renders component', () => { 6 | const wrapper = shallowMount(Pokeball) 7 | expect(wrapper.element).toMatchSnapshot() 8 | }) 9 | }) 10 | -------------------------------------------------------------------------------- /tests/unit/components/timer.spec.js: -------------------------------------------------------------------------------- 1 | import Timer from '@/components/Timer.vue' 2 | import { shallowMount } from '@vue/test-utils' 3 | import { factoryVue } from '../helpers' 4 | import Vuex from 'vuex' 5 | 6 | const localVue = factoryVue() 7 | 8 | jest.useFakeTimers() 9 | 10 | describe('Timer.vue', () => { 11 | let hidden = false 12 | 13 | Object.defineProperty(document, 'hidden', { 14 | configurable: true, 15 | get () { return hidden }, 16 | set (bool) { hidden = Boolean(bool) } 17 | }) 18 | 19 | let actions 20 | let mutations 21 | let getters 22 | let state 23 | let store 24 | 25 | beforeEach(() => { 26 | actions = { 27 | loadPokemon: jest.fn() 28 | } 29 | mutations = { 30 | 'set/timer': jest.fn((state, val) => { 31 | state.timer = val 32 | }) 33 | } 34 | getters = { 35 | timerStatus: ({ timerStatus }) => timerStatus 36 | } 37 | state = { 38 | timer: 0, 39 | timerStatus: true, // for getter 40 | isRunning: true, 41 | score: 99, 42 | isMobile: false 43 | } 44 | store = new Vuex.Store({ 45 | actions, 46 | state, 47 | getters, 48 | mutations 49 | }) 50 | }) 51 | 52 | it('call "setTimer"', () => { 53 | shallowMount(Timer, { store, localVue }) 54 | 55 | jest.advanceTimersByTime(2000) 56 | 57 | expect(mutations['set/timer']).toHaveBeenCalledTimes(3) 58 | expect(state.timer).toBe(2) 59 | }) 60 | 61 | it('stop on visibilitychange', () => { 62 | shallowMount(Timer, { store, localVue }) 63 | 64 | expect(state.timer).toBe(0) 65 | 66 | jest.advanceTimersByTime(3000) 67 | 68 | hidden = true 69 | document.dispatchEvent(new Event('visibilitychange')) 70 | 71 | jest.advanceTimersByTime(5000) 72 | 73 | expect(mutations['set/timer']).toHaveBeenCalledTimes(4) 74 | expect(state.timer).toBe(3) 75 | 76 | hidden = false 77 | document.dispatchEvent(new Event('visibilitychange')) 78 | 79 | jest.advanceTimersByTime(5000) 80 | 81 | expect(mutations['set/timer']).toHaveBeenCalledTimes(9) 82 | expect(state.timer).toBe(8) 83 | }) 84 | 85 | it('call "loadPokemon"', () => { 86 | const wrapper = shallowMount(Timer, { store, localVue }) 87 | 88 | const btn = wrapper.find('a.--btn-reload') 89 | 90 | btn.trigger('click') 91 | 92 | expect(actions.loadPokemon).toHaveBeenCalledTimes(1) 93 | }) 94 | 95 | it('mobile version', () => { 96 | state.isMobile = true 97 | const wrapper = shallowMount(Timer, { store, localVue }) 98 | 99 | ;(['a.--btn-reload', '.--icon-clock', '.--icon-counter']) 100 | .forEach(selector => { 101 | expect(wrapper.find(selector).exists()).toBe(false) 102 | }) 103 | }) 104 | 105 | it('beforeDestroy', () => { 106 | const wrapper = shallowMount(Timer, { store, localVue }) 107 | const stopTimer = wrapper.vm.stopTimer.bind(wrapper) 108 | const stopTimerMock = jest.fn(() => { 109 | stopTimer() 110 | }) 111 | 112 | wrapper.setMethods({ stopTimer: stopTimerMock }) 113 | 114 | wrapper.destroy() 115 | 116 | expect(stopTimerMock).toHaveBeenCalledTimes(1) 117 | }) 118 | 119 | it('timerStatus', () => { 120 | const wrapper = shallowMount(Timer, { store, localVue }) 121 | 122 | // original 123 | const stopTimer = wrapper.vm.stopTimer.bind(wrapper) 124 | const startTimer = wrapper.vm.startTimer.bind(wrapper) 125 | 126 | // mock 127 | const stopTimerMock = jest.fn(() => { 128 | stopTimer() 129 | }) 130 | const startTimerMock = jest.fn(() => { 131 | startTimer() 132 | }) 133 | 134 | wrapper.setMethods({ stopTimer: stopTimerMock, startTimer: startTimerMock }) 135 | jest.advanceTimersByTime(2000) 136 | 137 | state.timerStatus = false 138 | state.timerStatus = true 139 | state.timerStatus = false 140 | 141 | expect(stopTimerMock).toHaveBeenCalledTimes(2) 142 | expect(startTimerMock).toHaveBeenCalledTimes(1) 143 | }) 144 | }) 145 | -------------------------------------------------------------------------------- /tests/unit/helpers.js: -------------------------------------------------------------------------------- 1 | import { install as Buefy } from '@/buefy' 2 | import { install as filters } from '@/support/filters' 3 | import { createLocalVue } from '@vue/test-utils' 4 | import Vuex from 'vuex' 5 | 6 | const factoryVue = () => { 7 | const localVue = createLocalVue() 8 | 9 | localVue.use(Vuex) 10 | localVue.use(filters) 11 | localVue.use(Buefy) 12 | 13 | return localVue 14 | } 15 | 16 | export { factoryVue } 17 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | const version = require('./package.json').version 2 | const now = Math.round(Date.now() / 6000).toString(36) 3 | 4 | process.env.VUE_APP_VERSION = `${version}-${now}` 5 | 6 | module.exports = { 7 | configureWebpack: { 8 | node: { Buffer: false }, 9 | optimization: { 10 | splitChunks: { 11 | cacheGroups: { 12 | html2canvas: { 13 | priority: 9, 14 | test: /\/html2canvas/, 15 | name: 'html2canvas', 16 | chunks: 'all' 17 | }, 18 | downloadjs: { 19 | priority: 8, 20 | test: /\/downloadjs/, 21 | name: 'buefy', 22 | chunks: 'all' 23 | }, 24 | buefy: { 25 | priority: 7, 26 | test: /\/buefy/, 27 | name: 'buefy', 28 | chunks: 'all' 29 | }, 30 | 'lodash-es': { 31 | priority: 6, 32 | test: /\/lodash-es/, 33 | name: 'lodash-es', 34 | chunks: 'all' 35 | } 36 | } 37 | } 38 | } 39 | }, 40 | pwa: { 41 | name: 'Pokémon - Memory Game', 42 | appleMobileWebAppCapable: 'yes', 43 | appleMobileWebAppStatusBarStyle: 'black', 44 | workboxOptions: { 45 | importScripts: ['/precache-sw.js'], 46 | skipWaiting: true 47 | } 48 | } 49 | } 50 | --------------------------------------------------------------------------------