From b62ec108a3afa76e95d774694d7f09cfec1ac70f Mon Sep 17 00:00:00 2001 From: Dale Lane Date: Sun, 1 Nov 2020 00:13:04 +0000 Subject: [PATCH] feat: Explain how text ML models are trained (#343) This PR adds an interactive visualization of a neural network, customized based on the characteristics of a student's project. For more details, see https://dalelane.co.uk/blog/?p=4182 Signed-off-by: Dale Lane --- custom_typings/compromise/index.d.ts | 1 + custom_typings/emoticon/index.d.ts | 1 + package-lock.json | 1614 ++++++++++++++--- package.json | 21 +- public/app.js | 9 + .../describemodel/describemodel.controller.js | 4 +- .../describemodel/describemodel.html | 1 - .../describemodel.controller.js | 1227 +++++++++++++ .../describetextmodel/describemodel.css | 154 ++ .../describetextmodel/describemodel.html | 244 +++ .../describetextmodel/fcnn.service.js | 800 ++++++++ .../components/describetextmodel/scratch.txt | 28 + public/components/logger/logger.service.js | 9 +- public/components/models/models.controller.js | 1 + public/components/models/models.html | 4 +- .../training/training.controller.js | 9 + public/languages/ar.json | 159 ++ public/languages/cs.json | 159 ++ public/languages/cy.json | 159 ++ public/languages/de.json | 159 ++ public/languages/el.json | 159 ++ public/languages/en.json | 159 ++ public/languages/es.json | 159 ++ public/languages/fr.json | 159 ++ public/languages/hr.json | 159 ++ public/languages/it.json | 159 ++ public/languages/ja.json | 159 ++ public/languages/ko.json | 159 ++ public/languages/nl-be.json | 159 ++ public/languages/pl.json | 159 ++ public/languages/pt-br.json | 159 ++ public/languages/ru.json | 159 ++ public/languages/si-lk.json | 159 ++ public/languages/sv-se.json | 159 ++ public/languages/tr.json | 159 ++ public/languages/zh-cn.json | 159 ++ public/languages/zh-tw.json | 159 ++ src/lib/restapi/config.ts | 1 + src/lib/restapi/models.ts | 31 +- src/lib/training/describetext.ts | 175 ++ src/lib/utils/bagofwords.ts | 143 ++ src/lib/utils/emoticons.ts | 25 + src/lib/utils/random.ts | 26 + src/tests/utils/bagofwords.ts | 98 + src/tests/utils/emoticons.ts | 27 + src/tests/utils/random.ts | 41 + 46 files changed, 7737 insertions(+), 296 deletions(-) create mode 100644 custom_typings/compromise/index.d.ts create mode 100644 custom_typings/emoticon/index.d.ts create mode 100644 public/components/describetextmodel/describemodel.controller.js create mode 100644 public/components/describetextmodel/describemodel.css create mode 100644 public/components/describetextmodel/describemodel.html create mode 100644 public/components/describetextmodel/fcnn.service.js create mode 100644 public/components/describetextmodel/scratch.txt create mode 100644 src/lib/training/describetext.ts create mode 100644 src/lib/utils/bagofwords.ts create mode 100644 src/lib/utils/emoticons.ts create mode 100644 src/tests/utils/bagofwords.ts create mode 100644 src/tests/utils/emoticons.ts create mode 100644 src/tests/utils/random.ts diff --git a/custom_typings/compromise/index.d.ts b/custom_typings/compromise/index.d.ts new file mode 100644 index 000000000..ab9022fb0 --- /dev/null +++ b/custom_typings/compromise/index.d.ts @@ -0,0 +1 @@ +declare module 'compromise'; diff --git a/custom_typings/emoticon/index.d.ts b/custom_typings/emoticon/index.d.ts new file mode 100644 index 000000000..9676a0818 --- /dev/null +++ b/custom_typings/emoticon/index.d.ts @@ -0,0 +1 @@ +declare module 'emoticon'; diff --git a/package-lock.json b/package-lock.json index f2b5e35f9..3a87535fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -268,9 +268,9 @@ } }, "@eslint/eslintrc": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.1.3.tgz", - "integrity": "sha512-4YVwPkANLeNtRjMekzux1ci8hIaH5eGKktGqR0d3LWsKNn5B2X/1Z6Trxy7jQXl9EBGE6Yj02O+t09FMeRllaA==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.1.tgz", + "integrity": "sha512-XRUeBZ5zBWLYgSANMpThFddrZZkEbGHgUdt5UJjZfnlN9BGCiUBrf+nvbRupSjMvqzwnQN0qwCmOxITt1cfywA==", "dev": true, "requires": { "ajv": "^6.12.4", @@ -720,9 +720,9 @@ "dev": true }, "@types/lodash": { - "version": "4.14.162", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.162.tgz", - "integrity": "sha512-alvcho1kRUnnD1Gcl4J+hK0eencvzq9rmzvFPRmP5rPHx9VVsJj6bKLTATPVf9ktgv4ujzh7T+XWKp+jhuODig==", + "version": "4.14.164", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.164.tgz", + "integrity": "sha512-fXCEmONnrtbYUc5014avwBeMdhHHO8YJCkOBflUL9EoJBSKZ1dei+VO74fA7JkTHZ1GvZack2TyIw5U+1lT8jg==", "dev": true }, "@types/mime": { @@ -757,6 +757,15 @@ "integrity": "sha512-wH6Tu9mbiOt0n5EvdoWy0VGQaJMHfLIxY/6wS0xLC7CV1taM6gESEzcYy0ZlWvxxiiljYvfDIvz4hHbUUDRlhw==", "dev": true }, + "@types/natural": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/natural/-/natural-2.1.0.tgz", + "integrity": "sha512-R/HWzH71wilqo3idmqIAmeJ4dvDnvcOl7z7dV/d/6c+Wz5QB6wdBSLcpQYClkQa2vhxbdZp8uPkYN4Z+ByIjhQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/node": { "version": "12.12.64", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.64.tgz", @@ -907,6 +916,12 @@ "@types/superagent": "*" } }, + "@types/syllable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@types/syllable/-/syllable-4.1.0.tgz", + "integrity": "sha512-a54p2YlgEZfWFtvDWqPfMF5ag9cjQVDIAfAt9rE6DuuQvAvtjr20o0hiALAHm7SBBzV5ypFWxNBc7zn2fMAvEA==", + "dev": true + }, "@types/tmp": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.2.0.tgz", @@ -949,6 +964,173 @@ "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", + "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==" + }, + "@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==" + }, + "@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==" + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", + "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", + "requires": { + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", + "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==" + }, + "@webassemblyjs/helper-module-context": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", + "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", + "requires": { + "@webassemblyjs/ast": "1.9.0" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==" + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==" + }, + "@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", + "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -976,10 +1158,15 @@ "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", "dev": true }, + "afinn-165": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/afinn-165/-/afinn-165-1.0.4.tgz", + "integrity": "sha512-7+Wlx3BImrK0HiG6y3lU4xX7SpBPSSu8T9iguPMlaueRFxjbYwAQrp9lqZUuFikqKbd/en8lVREILvP2J80uJA==" + }, "agent-base": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.1.tgz", - "integrity": "sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "requires": { "debug": "4" }, @@ -1020,6 +1207,16 @@ "uri-js": "^4.2.2" } }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==" + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" + }, "alter": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/alter/-/alter-0.2.0.tgz", @@ -1092,7 +1289,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, "requires": { "micromatch": "^3.1.4", "normalize-path": "^2.1.1" @@ -1102,7 +1298,6 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, "requires": { "arr-flatten": "^1.1.0", "array-unique": "^0.3.2", @@ -1120,7 +1315,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -1131,7 +1325,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, "requires": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", @@ -1143,7 +1336,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -1154,7 +1346,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -1163,7 +1354,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -1174,7 +1364,6 @@ "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, "requires": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", @@ -1195,7 +1384,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, "requires": { "remove-trailing-separator": "^1.0.1" } @@ -1204,7 +1392,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, "requires": { "is-number": "^3.0.0", "repeat-string": "^1.6.1" @@ -1212,6 +1399,14 @@ } } }, + "apparatus": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/apparatus/-/apparatus-0.0.10.tgz", + "integrity": "sha512-KLy/ugo33KZA7nugtQ7O0E1c8kQ52N3IvD/XgIh4w/Nr28ypfkwDfA67F1ev4N1m5D+BOk1+b2dEJDfpj/VvZg==", + "requires": { + "sylvester": ">= 0.0.8" + } + }, "append-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", @@ -1336,8 +1531,7 @@ "arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" }, "arr-filter": { "version": "1.1.2", @@ -1351,8 +1545,7 @@ "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" }, "arr-map": { "version": "2.0.2", @@ -1366,8 +1559,7 @@ "arr-union": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" }, "array-each": { "version": "1.0.1", @@ -1454,8 +1646,7 @@ "array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" }, "asn1": { "version": "0.2.4", @@ -1483,6 +1674,30 @@ } } }, + "assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "requires": { + "inherits": "2.0.1" + } + } + } + }, "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", @@ -1491,8 +1706,7 @@ "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" }, "astral-regex": { "version": "1.0.0", @@ -1523,8 +1737,7 @@ "async-each": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==" }, "async-settle": { "version": "1.0.0", @@ -1543,8 +1756,7 @@ "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" }, "autoprefixer": { "version": "9.8.6", @@ -1815,7 +2027,6 @@ "version": "0.11.2", "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, "requires": { "cache-base": "^1.0.1", "class-utils": "^0.3.5", @@ -1830,7 +2041,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, "requires": { "is-descriptor": "^1.0.0" } @@ -1839,7 +2049,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -1848,7 +2057,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -1857,7 +2065,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", @@ -1885,6 +2092,11 @@ "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==", "dev": true }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" + }, "binary": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", @@ -1898,14 +2110,12 @@ "binary-extensions": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==" }, "bindings": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, "optional": true, "requires": { "file-uri-to-path": "1.0.0" @@ -1977,7 +2187,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, "requires": { "fill-range": "^7.0.1" } @@ -2066,6 +2275,14 @@ } } }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "requires": { + "pako": "~1.0.5" + } + }, "browserslist": { "version": "4.14.5", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.5.tgz", @@ -2162,6 +2379,11 @@ "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", "dev": true }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" + }, "bunyan": { "version": "1.8.14", "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.14.tgz", @@ -2219,11 +2441,55 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" }, + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "requires": { + "glob": "^7.1.3" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + } + } + }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, "requires": { "collection-visit": "^1.0.0", "component-emitter": "^1.2.1", @@ -2351,7 +2617,6 @@ "version": "2.1.8", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "dev": true, "requires": { "anymatch": "^2.0.0", "async-each": "^1.0.1", @@ -2371,7 +2636,6 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, "requires": { "arr-flatten": "^1.1.0", "array-unique": "^0.3.2", @@ -2389,7 +2653,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -2398,7 +2661,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, "requires": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", @@ -2410,7 +2672,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, "requires": { "is-glob": "^3.1.0", "path-dirname": "^1.0.0" @@ -2420,7 +2681,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, "requires": { "is-extglob": "^2.1.0" } @@ -2431,7 +2691,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, "requires": { "kind-of": "^3.0.2" } @@ -2440,7 +2699,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -2449,7 +2707,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, "requires": { "is-number": "^3.0.0", "repeat-string": "^1.6.1" @@ -2462,6 +2719,14 @@ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, + "chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "requires": { + "tslib": "^1.9.0" + } + }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -2475,7 +2740,6 @@ "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, "requires": { "arr-union": "^3.1.0", "define-property": "^0.2.5", @@ -2487,7 +2751,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -2643,7 +2906,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, "requires": { "map-visit": "^1.0.0", "object-visit": "^1.0.0" @@ -2709,20 +2971,17 @@ "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" }, "component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" }, "compress-commons": { "version": "4.0.1", @@ -2772,6 +3031,19 @@ } } }, + "compromise": { + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/compromise/-/compromise-13.7.0.tgz", + "integrity": "sha512-RGCUJQs906TCU04rN0Fb2xwrzL9/xyr6MTggTytrlI+VEaBVqeO0ccOtTLEnlI4BVB6hoCic5Nmbp3nRdNKpJA==", + "requires": { + "efrt-unpack": "2.2.0" + } + }, + "compromise-numbers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/compromise-numbers/-/compromise-numbers-1.0.0.tgz", + "integrity": "sha512-+D9mfomLiPkJ2Sx+aDhz1CrTBCNpnnti93bI0rOKf3adjrnRcS2yU0Tpb1z7dz4aU/OpKD0d0QjXPCiOgu8ekw==" + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2836,11 +3108,21 @@ } } }, + "console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==" + }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" + }, "content-disposition": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", @@ -2884,11 +3166,33 @@ "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", "dev": true }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "requires": { + "glob": "^7.1.3" + } + } + } + }, "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" }, "copy-props": { "version": "2.0.4", @@ -3051,6 +3355,11 @@ } } }, + "cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=" + }, "d": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", @@ -3109,8 +3418,7 @@ "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" }, "decompress-response": { "version": "4.2.1", @@ -3181,7 +3489,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, "requires": { "is-descriptor": "^1.0.2", "isobject": "^3.0.1" @@ -3191,7 +3498,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -3200,7 +3506,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -3209,7 +3514,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", @@ -3373,6 +3677,11 @@ "esutils": "^2.0.2" } }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" + }, "dtrace-provider": { "version": "0.8.8", "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.8.tgz", @@ -3418,7 +3727,6 @@ "version": "3.7.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, "requires": { "end-of-stream": "^1.0.0", "inherits": "^2.0.1", @@ -3430,7 +3738,6 @@ "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -3475,6 +3782,11 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, + "efrt-unpack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/efrt-unpack/-/efrt-unpack-2.2.0.tgz", + "integrity": "sha512-9xUSSj7qcUxz+0r4X3+bwUNttEfGfK5AH+LVa1aTpqdAfrN5VhROYCfcF+up4hp5OL7IUKcZJJrzAGipQRDoiQ==" + }, "electron-to-chromium": { "version": "1.3.577", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.577.tgz", @@ -3508,6 +3820,16 @@ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" + }, + "emoticon": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/emoticon/-/emoticon-3.2.0.tgz", + "integrity": "sha512-SNujglcLTTg+lDAcApPNgEdudaqQFiAbJCqzjNxJkvN9vAwCGi0uu8IUVvx+f16h+V44KCY6Y2yboroc9pilHg==" + }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -3521,6 +3843,41 @@ "once": "^1.4.0" } }, + "enhanced-resolve": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz", + "integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==", + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + } + } + }, "enquirer": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", @@ -3530,6 +3887,14 @@ "ansi-colors": "^4.1.1" } }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "requires": { + "prr": "~1.0.1" + } + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -3660,13 +4025,13 @@ "dev": true }, "eslint": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.11.0.tgz", - "integrity": "sha512-G9+qtYVCHaDi1ZuWzBsOWo2wSwd70TXnU6UHA3cTYHp7gCTXZcpggWFoUVAMRarg68qtPoNfFbzPh+VdOgmwmw==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.12.1.tgz", + "integrity": "sha512-HlMTEdr/LicJfN08LB3nM1rRYliDXOmfoO4vj39xN6BLpFzF00hbwBoqHk8UcJ2M/3nlARZWy/mslvGEuZFvsg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@eslint/eslintrc": "^0.1.3", + "@eslint/eslintrc": "^0.2.1", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -3854,7 +4219,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, "requires": { "estraverse": "^5.2.0" }, @@ -3862,16 +4226,14 @@ "estraverse": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==" } } }, "estraverse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" }, "esutils": { "version": "2.0.3", @@ -3900,6 +4262,11 @@ "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", "dev": true }, + "events": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", + "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==" + }, "evp_bytestokey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", @@ -3971,7 +4338,6 @@ "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, "requires": { "debug": "^2.3.3", "define-property": "^0.2.5", @@ -3986,7 +4352,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "requires": { "ms": "2.0.0" } @@ -3995,7 +4360,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -4004,7 +4368,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -4121,7 +4484,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, "requires": { "assign-symbols": "^1.0.0", "is-extendable": "^1.0.1" @@ -4131,7 +4493,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, "requires": { "is-plain-object": "^2.0.4" } @@ -4169,7 +4530,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, "requires": { "array-unique": "^0.3.2", "define-property": "^1.0.0", @@ -4185,7 +4545,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, "requires": { "is-descriptor": "^1.0.0" } @@ -4194,7 +4553,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -4203,7 +4561,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -4212,7 +4569,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -4221,7 +4577,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", @@ -4292,6 +4647,11 @@ "reusify": "^1.0.4" } }, + "figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==" + }, "figures": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", @@ -4332,7 +4692,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, "optional": true }, "filecompare": { @@ -4373,7 +4732,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, "requires": { "to-regex-range": "^5.0.1" } @@ -4406,7 +4764,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, "requires": { "commondir": "^1.0.1", "make-dir": "^2.0.0", @@ -4417,7 +4774,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, "requires": { "locate-path": "^3.0.0" } @@ -4514,7 +4870,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, "requires": { "inherits": "^2.0.3", "readable-stream": "^2.3.6" @@ -4524,7 +4879,6 @@ "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -4548,8 +4902,7 @@ "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" }, "for-own": { "version": "1.0.0", @@ -4627,7 +4980,6 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, "requires": { "map-cache": "^0.2.2" } @@ -4637,6 +4989,31 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + } + } + }, "fromentries": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.2.1.tgz", @@ -4658,6 +5035,33 @@ "through2": "^2.0.3" } }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + } + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -4667,7 +5071,6 @@ "version": "1.2.13", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "dev": true, "optional": true, "requires": { "bindings": "^1.5.0", @@ -4743,8 +5146,7 @@ "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" }, "getobject": { "version": "0.1.0", @@ -4782,7 +5184,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dev": true, "requires": { "is-glob": "^4.0.1" } @@ -6823,7 +7224,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, "requires": { "get-value": "^2.0.6", "has-values": "^1.0.0", @@ -6834,7 +7234,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, "requires": { "is-number": "^3.0.0", "kind-of": "^4.0.0" @@ -6844,7 +7243,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -6853,7 +7251,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -6864,7 +7261,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -7018,6 +7414,11 @@ "resolved": "https://registry.npmjs.org/http-status/-/http-status-1.4.2.tgz", "integrity": "sha512-mBnIohUwRw9NyXMEMMv8/GANnzEYUj0Y8d3uL01zDWFkxUjYyZ6rgCaAI2zZ1Wb34Oqtbx/nFZolPRDc8Xlm5A==" }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" + }, "https-proxy-agent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", @@ -7043,9 +7444,9 @@ } }, "ibm-cos-sdk": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/ibm-cos-sdk/-/ibm-cos-sdk-1.7.0.tgz", - "integrity": "sha512-81gtWKRctZeKK+kwDIcpwzcAkyhP/KWFfRZetU3lzDrtWKZd0A1+Mn25UnTVVHYK3zy4mselKXTOIVqnpQEYbg==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/ibm-cos-sdk/-/ibm-cos-sdk-1.8.0.tgz", + "integrity": "sha512-1RTs4iuOiJ0zGDG7jiizzH8CJzLXsHimW5sITFIGDKBQJ2L0O850dWUR0NiMX4qJe97hLSMULinG/2Uf5U05bw==", "requires": { "buffer": "^4.9.1", "crypto-browserify": "^3.12.0", @@ -7087,6 +7488,11 @@ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" + }, "ignore": { "version": "5.1.8", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", @@ -7111,8 +7517,7 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, "indent-string": { "version": "4.0.0", @@ -7120,6 +7525,11 @@ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==" + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -7272,7 +7682,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -7281,7 +7690,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -7297,7 +7705,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, "requires": { "binary-extensions": "^1.0.0" } @@ -7305,8 +7712,7 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "is-callable": { "version": "1.2.2", @@ -7318,7 +7724,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -7327,7 +7732,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -7344,7 +7748,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, "requires": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", @@ -7354,22 +7757,19 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" } } }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-finite": { "version": "1.1.0", @@ -7389,7 +7789,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, "requires": { "is-extglob": "^2.1.1" } @@ -7409,8 +7808,7 @@ "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, "is-object": { "version": "1.0.1", @@ -7440,7 +7838,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, "requires": { "isobject": "^3.0.1" } @@ -7513,8 +7910,12 @@ "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" }, "isarray": { "version": "1.0.0", @@ -7530,8 +7931,7 @@ "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" }, "isstream": { "version": "0.1.2", @@ -7935,8 +8335,7 @@ "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" }, "json-schema": { "version": "0.2.3", @@ -7948,6 +8347,14 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "requires": { + "jsonify": "~0.0.0" + } + }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", @@ -7968,6 +8375,11 @@ "minimist": "^1.2.5" } }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + }, "jsonwebtoken": { "version": "8.5.1", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", @@ -8053,9 +8465,9 @@ } }, "jwks-rsa": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-1.10.1.tgz", - "integrity": "sha512-UmjOsATVu7eQr17wbBCS+BSoz5LFtl57PtNXHbHFeT1WKomHykCHtn7c8inWVI7tpnsy6CZ1KOMJTgipFwXPig==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-1.11.0.tgz", + "integrity": "sha512-G7ZgXZ3dlGbOUBQwgF+U/SVzOlI9KxJ9Uzp61bue2S5TV0h7c+kJRCl3bEPkC5PVmeu7/h82B3uQALVJMjzt/Q==", "requires": { "@types/express-jwt": "0.0.42", "axios": "^0.19.2", @@ -8065,7 +8477,8 @@ "jsonwebtoken": "^8.5.1", "limiter": "^1.1.5", "lru-memoizer": "^2.1.2", - "ms": "^2.1.2" + "ms": "^2.1.2", + "proxy-from-env": "^1.1.0" }, "dependencies": { "debug": { @@ -8106,8 +8519,7 @@ "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" }, "last-run": { "version": "1.1.1", @@ -8373,11 +8785,35 @@ } } }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==" + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "requires": { + "minimist": "^1.2.0" + } + } + } + }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, "requires": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" @@ -8535,7 +8971,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, "requires": { "pify": "^4.0.1", "semver": "^5.6.0" @@ -8568,8 +9003,7 @@ "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" }, "map-stream": { "version": "0.0.7", @@ -8581,7 +9015,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, "requires": { "object-visit": "^1.0.0" } @@ -8794,6 +9227,31 @@ "timers-ext": "^0.1.5" } }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + } + } + }, "merge": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz", @@ -8917,11 +9375,27 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, "mixin-deep": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, "requires": { "for-in": "^1.0.2", "is-extendable": "^1.0.1" @@ -8931,7 +9405,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, "requires": { "is-plain-object": "^2.0.4" } @@ -9195,6 +9668,29 @@ "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", "optional": true }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "requires": { + "glob": "^7.1.3" + } + } + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -9259,7 +9755,6 @@ "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, "requires": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", @@ -9279,6 +9774,20 @@ "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" }, + "natural": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/natural/-/natural-2.1.5.tgz", + "integrity": "sha512-z5ljUGW3Nqgu+e1m0/sN0b7GSsbGyGCTCgQJ6hv0sxOe2+8FaIlkdHIGkP0y1zCxO0vYawukOEUTryY9NKix7w==", + "requires": { + "afinn-165": "^1.0.2", + "apparatus": "^0.0.10", + "json-stable-stringify": "^1.0.1", + "sylvester": "^0.0.12", + "underscore": "^1.9.1", + "webpack": "^4.29.0", + "wordnet-db": "^3.1.11" + } + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -9299,8 +9808,7 @@ "neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, "nested-error-stacks": { "version": "2.1.0", @@ -9406,6 +9914,83 @@ "semver": "^5.7.0" } }, + "node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + }, + "dependencies": { + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + } + } + } + } + }, "node-preload": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", @@ -9463,6 +10048,11 @@ "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", "dev": true }, + "normalize-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/normalize-strings/-/normalize-strings-1.1.0.tgz", + "integrity": "sha1-skp17UgXY5RAT3Rkm1y4BA6JmnU=" + }, "now-and-later": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", @@ -9966,7 +10556,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, "requires": { "copy-descriptor": "^0.1.0", "define-property": "^0.2.5", @@ -9977,7 +10566,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -9986,7 +10574,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -10009,7 +10596,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, "requires": { "isobject": "^3.0.0" } @@ -10083,7 +10669,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, "requires": { "isobject": "^3.0.1" } @@ -10210,6 +10795,11 @@ } } }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" + }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", @@ -10250,7 +10840,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "requires": { "p-try": "^2.0.0" } @@ -10259,7 +10848,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, "requires": { "p-limit": "^2.0.0" } @@ -10300,6 +10888,32 @@ "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + } + } + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -10362,20 +10976,22 @@ "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==" }, "path-dirname": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" }, "path-is-absolute": { "version": "1.0.1", @@ -10449,14 +11065,14 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, "pg": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.4.1.tgz", - "integrity": "sha512-NRsH0aGMXmX1z8Dd0iaPCxWUw4ffu+lIAmGm+sTCwuDDWkpEgRCAHZYDwqaNhC5hG5DRMOjSUFasMWhvcmLN1A==", + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.4.2.tgz", + "integrity": "sha512-E9FlUrrc7w3+sbRmL1CSw99vifACzB2TjhMM9J5w9D1LIg+6un0jKkpHS1EQf2CWhKhec2bhrBLVMmUBDbjPRQ==", "requires": { "buffer-writer": "2.0.0", "packet-reader": "1.0.0", "pg-connection-string": "^2.4.0", - "pg-pool": "^3.2.1", + "pg-pool": "^3.2.2", "pg-protocol": "^1.3.0", "pg-types": "^2.1.0", "pgpass": "1.x" @@ -10473,9 +11089,9 @@ "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" }, "pg-pool": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.2.1.tgz", - "integrity": "sha512-BQDPWUeKenVrMMDN9opfns/kZo4lxmSWhIqo+cSAF7+lfi9ZclQbr9vfnlNaPr8wYF3UYjm5X0yPAhbcgqNOdA==" + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.2.2.tgz", + "integrity": "sha512-ORJoFxAlmmros8igi608iVEbQNNZlp89diFVx6yV5v+ehmpMY9sK6QgpmgoXbmkNaBAx8cOOZh9g80kJv1ooyA==" }, "pg-protocol": { "version": "1.3.0", @@ -10495,18 +11111,17 @@ } }, "pgpass": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", - "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.4.tgz", + "integrity": "sha512-YmuA56alyBq7M59vxVBfPJrGSozru8QAdoNlWuW3cz8l+UX3cWge0vTvjKhsSHSJpo3Bom8/Mm6hf0TR5GY0+w==", "requires": { - "split": "^1.0.0" + "split2": "^3.1.1" } }, "picomatch": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" }, "pify": { "version": "4.0.1", @@ -10532,7 +11147,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, "requires": { "find-up": "^3.0.0" } @@ -10560,6 +11174,11 @@ } } }, + "pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==" + }, "ports": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/ports/-/ports-1.1.0.tgz", @@ -10568,8 +11187,7 @@ "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" }, "postcss": { "version": "8.1.2", @@ -10687,6 +11305,11 @@ "stream-parser": "~0.3.1" } }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -10707,7 +11330,12 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, - "proxy-addr": { + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" + }, + "proxy-addr": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", @@ -10716,6 +11344,11 @@ "ipaddr.js": "1.9.1" } }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "proxyquire": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-2.1.3.tgz", @@ -10727,6 +11360,11 @@ "resolve": "^1.11.1" } }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -10770,7 +11408,6 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, "requires": { "duplexify": "^3.6.0", "inherits": "^2.0.3", @@ -10781,7 +11418,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -10804,6 +11440,11 @@ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -10930,7 +11571,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, "requires": { "graceful-fs": "^4.1.11", "micromatch": "^3.1.10", @@ -10941,7 +11581,6 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, "requires": { "arr-flatten": "^1.1.0", "array-unique": "^0.3.2", @@ -10959,7 +11598,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -10970,7 +11608,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, "requires": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", @@ -10982,7 +11619,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -10993,7 +11629,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -11002,7 +11637,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -11013,7 +11647,6 @@ "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, "requires": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", @@ -11034,7 +11667,6 @@ "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -11049,7 +11681,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, "requires": { "is-number": "^3.0.0", "repeat-string": "^1.6.1" @@ -11095,7 +11726,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, "requires": { "extend-shallow": "^3.0.2", "safe-regex": "^1.1.0" @@ -11140,20 +11770,17 @@ "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" }, "repeat-element": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" }, "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" }, "repeating": { "version": "2.0.1", @@ -11288,8 +11915,7 @@ "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" }, "restore-cursor": { "version": "2.0.0", @@ -11304,8 +11930,7 @@ "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" }, "reusify": { "version": "1.0.4", @@ -11356,6 +11981,14 @@ "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", "dev": true }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "requires": { + "aproba": "^1.1.1" + } + }, "rx-lite": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", @@ -11386,7 +12019,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, "requires": { "ret": "~0.1.10" } @@ -11401,6 +12033,16 @@ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -11491,7 +12133,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, "requires": { "extend-shallow": "^2.0.1", "is-extendable": "^0.1.1", @@ -11503,7 +12144,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -11513,8 +12153,7 @@ "setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" }, "setprototypeof": { "version": "1.1.1", @@ -11657,9 +12296,9 @@ } }, "sinon": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.0.tgz", - "integrity": "sha512-eSNXz1XMcGEMHw08NJXSyTHIu6qTCOiN8x9ODACmZpNQpr0aXTBXBnI4xTzQzR+TEpOmLiKowGf9flCuKIzsbw==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.1.tgz", + "integrity": "sha512-naPfsamB5KEE1aiioaoqJ6MEhdUs/2vtI5w1hPAXX/UwvoPjXcwh1m5HiKx0HGgKR8lQSoFIgY5jM6KK8VrS9w==", "dev": true, "requires": { "@sinonjs/commons": "^1.8.1", @@ -11729,7 +12368,6 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, "requires": { "base": "^0.11.1", "debug": "^2.2.0", @@ -11745,7 +12383,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "requires": { "ms": "2.0.0" } @@ -11754,7 +12391,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -11763,7 +12399,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -11774,7 +12409,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, "requires": { "define-property": "^1.0.0", "isobject": "^3.0.0", @@ -11785,7 +12419,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, "requires": { "is-descriptor": "^1.0.0" } @@ -11794,7 +12427,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -11803,7 +12435,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -11812,7 +12443,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", @@ -11825,7 +12455,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, "requires": { "kind-of": "^3.2.0" }, @@ -11834,24 +12463,26 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } } } }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" }, "source-map-resolve": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, "requires": { "atob": "^2.1.2", "decode-uri-component": "^0.2.0", @@ -11860,11 +12491,26 @@ "urix": "^0.1.0" } }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, "source-map-url": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" }, "sparkles": { "version": "1.0.1", @@ -11938,23 +12584,22 @@ "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==", "dev": true }, - "split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "requires": { - "through": "2" - } - }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, "requires": { "extend-shallow": "^3.0.0" } }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + } + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -11976,6 +12621,14 @@ "tweetnacl": "~0.14.0" } }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "requires": { + "figgy-pudding": "^3.5.1" + } + }, "stable": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", @@ -11992,7 +12645,6 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, "requires": { "define-property": "^0.2.5", "object-copy": "^0.1.0" @@ -12002,7 +12654,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -12019,12 +12670,74 @@ "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + } + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, "stream-exhaust": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", "dev": true }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + } + } + }, "stream-parser": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/stream-parser/-/stream-parser-0.3.1.tgz", @@ -12046,8 +12759,7 @@ "stream-shift": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" }, "streamsearch": { "version": "0.1.2", @@ -12281,6 +12993,20 @@ "es6-symbol": "^3.1.1" } }, + "syllable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/syllable/-/syllable-4.1.0.tgz", + "integrity": "sha512-KUiIxtFxV17EEKqLYCHDcwaYxudDTRhX34mfTVYWkWFDsmiNRz1ZumpP3v0lTqsVQs78y3dqlSxkEMRk/SCVYQ==", + "requires": { + "normalize-strings": "^1.1.0", + "pluralize": "^8.0.0" + } + }, + "sylvester": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/sylvester/-/sylvester-0.0.12.tgz", + "integrity": "sha1-WohEFc0tACxX56OqyZRip1zp/bQ=" + }, "table": { "version": "5.4.6", "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", @@ -12327,6 +13053,11 @@ } } }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" + }, "tar-fs": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.0.tgz", @@ -12350,6 +13081,54 @@ "readable-stream": "^3.1.1" } }, + "terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "requires": { + "randombytes": "^2.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, "test-exclude": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", @@ -12371,13 +13150,13 @@ "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, "requires": { "readable-stream": "~2.3.6", "xtend": "~4.0.1" @@ -12387,7 +13166,6 @@ "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -12416,6 +13194,14 @@ "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", "dev": true }, + "timers-browserify": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz", + "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==", + "requires": { + "setimmediate": "^1.0.4" + } + }, "timers-ext": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", @@ -12454,6 +13240,11 @@ "is-negated-glob": "^1.0.0" } }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" + }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -12464,7 +13255,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -12473,7 +13263,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -12484,7 +13273,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, "requires": { "define-property": "^2.0.2", "extend-shallow": "^3.0.2", @@ -12496,7 +13284,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "requires": { "is-number": "^7.0.0" } @@ -12554,8 +13341,7 @@ "tslib": { "version": "1.14.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.0.tgz", - "integrity": "sha512-+Zw5lu0D9tvBMjGP8LpvMb0u2WW2QV3y+D8mO6J+cNzCYIN4sVy43Bf9vl92nqFahutN0I8zHa7cc4vihIshnw==", - "dev": true + "integrity": "sha512-+Zw5lu0D9tvBMjGP8LpvMb0u2WW2QV3y+D8mO6J+cNzCYIN4sVy43Bf9vl92nqFahutN0I8zHa7cc4vihIshnw==" }, "tslint": { "version": "6.1.3", @@ -12656,6 +13442,11 @@ "tslib": "^1.8.1" } }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=" + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -12719,9 +13510,9 @@ } }, "typescript": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.3.tgz", - "integrity": "sha512-tEu6DGxGgRJPb/mVPIZ48e69xCn2yRmCgYmDugAVwmJ6o+0u1RI18eO7E7WBTLYLaEVVOhwQmcdhQHweux/WPg==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.5.tgz", + "integrity": "sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==", "dev": true }, "typescript-require": { @@ -12811,7 +13602,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, "requires": { "arr-union": "^3.1.0", "get-value": "^2.0.6", @@ -12819,6 +13609,22 @@ "set-value": "^2.0.1" } }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "requires": { + "imurmurhash": "^0.1.4" + } + }, "unique-stream": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", @@ -12838,7 +13644,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, "requires": { "has-value": "^0.3.1", "isobject": "^3.0.0" @@ -12848,7 +13653,6 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, "requires": { "get-value": "^2.0.3", "has-values": "^0.1.4", @@ -12859,7 +13663,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, "requires": { "isarray": "1.0.0" } @@ -12869,8 +13672,7 @@ "has-values": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" } } }, @@ -12918,8 +13720,7 @@ "upath": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" }, "uri-js": { "version": "4.4.0", @@ -12932,8 +13733,7 @@ "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" }, "url": { "version": "0.10.3", @@ -12954,8 +13754,22 @@ "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "requires": { + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + } + } }, "util-deprecate": { "version": "1.0.2", @@ -12973,9 +13787,9 @@ "integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==" }, "v8-compile-cache": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", - "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", + "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", "dev": true }, "v8flags": { @@ -13109,6 +13923,11 @@ "source-map": "^0.5.1" } }, + "vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" + }, "walk": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/walk/-/walk-2.3.3.tgz", @@ -13118,6 +13937,241 @@ "foreachasync": "3.x" } }, + "watchpack": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.4.tgz", + "integrity": "sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg==", + "requires": { + "chokidar": "^3.4.1", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.0" + }, + "dependencies": { + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "optional": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "optional": true + }, + "chokidar": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", + "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", + "optional": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + } + }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "optional": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "optional": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "optional": true, + "requires": { + "picomatch": "^2.2.1" + } + } + } + }, + "watchpack-chokidar2": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz", + "integrity": "sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA==", + "optional": true, + "requires": { + "chokidar": "^2.1.8" + } + }, + "webpack": { + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.2.tgz", + "integrity": "sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.3.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -13162,12 +14216,25 @@ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true }, + "wordnet-db": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/wordnet-db/-/wordnet-db-3.1.14.tgz", + "integrity": "sha512-zVyFsvE+mq9MCmwXUWHIcpfbrHHClZWZiVOzKSxNJruIcFn2RbY55zkhiAMMxM8zCVSmtNiViq8FsAZSFpMYag==" + }, "wordwrap": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", "dev": true }, + "worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "requires": { + "errno": "~0.1.7" + } + }, "workerpool": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.2.tgz", @@ -13273,8 +14340,7 @@ "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" }, "yallist": { "version": "2.1.2", diff --git a/package.json b/package.json index f9dd4708f..0114fea6b 100644 --- a/package.json +++ b/package.json @@ -26,10 +26,11 @@ "@types/jsonwebtoken": "8.5.0", "@types/jszip": "3.4.1", "@types/jwt-decode": "2.2.1", - "@types/lodash": "4.14.162", + "@types/lodash": "4.14.164", "@types/mocha": "8.0.3", "@types/multer": "1.4.4", "@types/mustache": "4.0.1", + "@types/natural": "^2.1.0", "@types/node": "12.x", "@types/nodemailer": "6.4.0", "@types/pg": "7.14.5", @@ -40,6 +41,7 @@ "@types/sharp": "0.26.0", "@types/sinon-express-mock": "1.3.9", "@types/supertest": "2.0.10", + "@types/syllable": "^4.1.0", "@types/tmp": "0.2.0", "@types/unzip": "0.1.1", "@types/unzipper": "0.10.3", @@ -47,7 +49,7 @@ "autoprefixer": "9.8.6", "clone": "2.1.2", "del": "6.0.0", - "eslint": "7.11.0", + "eslint": "7.12.1", "eslint-plugin-node": "11.1.0", "filecompare": "1.0.4", "grunt": "1.3.0", @@ -80,12 +82,12 @@ "nyc": "15.1.0", "postcss": "8.1.2", "proxyquire": "2.1.3", - "sinon": "9.2.0", + "sinon": "9.2.1", "sinon-express-mock": "2.2.1", "supertest": "5.0.0", "tslint": "6.1.3", "tslint-eslint-rules": "5.4.0", - "typescript": "4.0.3", + "typescript": "4.0.5", "typescript-require": "0.3.0", "unzipper": "0.10.11" }, @@ -98,8 +100,11 @@ "bunyan-slack": "0.0.10", "cfenv": "1.2.3", "compression": "1.7.4", + "compromise": "13.7.0", + "compromise-numbers": "1.0.0", "connect-query": "1.0.0", "content-range": "1.1.0", + "emoticon": "3.2.0", "express": "4.17.1", "express-jwt": "6.0.0", "file-type": "16.0.0", @@ -107,23 +112,25 @@ "helmet": "4.1.1", "http-range-parse": "1.0.0", "http-status": "1.4.2", - "ibm-cos-sdk": "1.7.0", + "ibm-cos-sdk": "1.8.0", "jsonwebtoken": "8.5.1", "jszip": "3.5.0", - "jwks-rsa": "1.10.1", + "jwks-rsa": "1.11.0", "jwt-decode": "3.0.0", "lodash": "4.17.20", "lru": "3.1.0", "multer": "1.4.2", "mustache": "4.0.1", + "natural": "2.1.5", "nodemailer": "6.4.14", - "pg": "8.4.1", + "pg": "8.4.2", "probe-image-size": "5.0.0", "randomstring": "1.1.5", "read-chunk": "3.2.0", "request": "2.88.2", "request-promise": "4.2.6", "sharp": "0.26.2", + "syllable": "^4.1.0", "tmp": "0.2.1", "uuid": "8.3.1" } diff --git a/public/app.js b/public/app.js index 333cc9408..d24ac9ef8 100644 --- a/public/app.js +++ b/public/app.js @@ -174,6 +174,15 @@ VERSION : <%= VERSION %> } }) + .state('mlproject_text_model_describe', { + url: '/mlproject/:userId/:projectId/models/text/:modelId', + controller: 'ModelTextDescribeController', + templateUrl: 'static/components-<%= VERSION %>/describetextmodel/describemodel.html', + controllerAs: 'vm', + params: { + VERSION : <%= VERSION %> + } + }) .state('mlproject_makes', { url: '/mlproject/:userId/:projectId/makes', controller: 'MakesController', diff --git a/public/components/describemodel/describemodel.controller.js b/public/components/describemodel/describemodel.controller.js index 1328ba737..4048fdbde 100644 --- a/public/components/describemodel/describemodel.controller.js +++ b/public/components/describemodel/describemodel.controller.js @@ -6,10 +6,10 @@ ModelDescribeController.$inject = [ 'authService', 'projectsService', 'trainingService', 'loggerService', - '$stateParams', '$scope', '$timeout', '$interval', '$document', 'loggerService' + '$stateParams', '$scope', '$timeout', '$interval', '$document' ]; - function ModelDescribeController(authService, projectsService, trainingService, loggerService, $stateParams, $scope, $timeout, $interval, $document, loggerService) { + function ModelDescribeController(authService, projectsService, trainingService, loggerService, $stateParams, $scope, $timeout, $interval, $document) { var vm = this; vm.authService = authService; diff --git a/public/components/describemodel/describemodel.html b/public/components/describemodel/describemodel.html index 44d8d18e4..aa9c08c34 100644 --- a/public/components/describemodel/describemodel.html +++ b/public/components/describemodel/describemodel.html @@ -22,7 +22,6 @@

ng-click="vm.dismissAlert('errors', $index)" id="errors{{error.alertid}}"> - Sorry! This is a new page and I still have some bits left to fix...

{{ error.message }}
diff --git a/public/components/describetextmodel/describemodel.controller.js b/public/components/describetextmodel/describemodel.controller.js new file mode 100644 index 000000000..fcacb8cf4 --- /dev/null +++ b/public/components/describetextmodel/describemodel.controller.js @@ -0,0 +1,1227 @@ +(function () { + + angular + .module('app') + .controller('ModelTextDescribeController', ModelTextDescribeController); + + ModelTextDescribeController.$inject = [ + 'authService', 'projectsService', 'trainingService', 'fcnnVisualisationService', 'loggerService', 'utilService', + '$stateParams', '$scope', '$timeout', '$interval', '$document', '$rootScope' + ]; + + function ModelTextDescribeController(authService, projectsService, trainingService, fcnnVisualisationService, loggerService, utilService, $stateParams, $scope, $timeout, $interval, $document, $rootScope) { + var vm = this; + vm.authService = authService; + + + $scope.loading = true; + + $scope.projectId = $stateParams.projectId; + $scope.userId = $stateParams.userId; + $scope.modelId = $stateParams.modelId; + + $scope.modelinfo = undefined; + $scope.currentExample = undefined; + + var alertId = 1; + vm.errors = []; + vm.warnings = []; + vm.dismissAlert = function (type, errIdx) { + vm[type].splice(errIdx, 1); + }; + function displayAlert(type, status, errObj) { + if (!errObj) { + errObj = {}; + } + + // create alert and display it + var newId = alertId++; + var newAlert = { + code : errObj.code, + alertid : newId, + message : errObj.message || errObj.error || 'Unknown error', + status : status + }; + vm[type].push(newAlert); + + return newId; + } + + function scrollToNewItem(itemId) { + $timeout(function () { + var newItem = document.getElementById(itemId); + $document.duScrollToElementAnimated(angular.element(newItem)); + }, 0); + } + + utilService.loadScript('https://d3js.org/d3.v5.min.js') + .then(function () { + return authService.getProfileDeferred(); + }) + .then(function (profile) { + vm.profile = profile; + + loggerService.debug('[ml4kdesc] Getting project info'); + return projectsService.getProject($scope.projectId, $scope.userId, profile.tenant); + }) + .then(function (project) { + loggerService.debug('[ml4kdesc] project', project); + $scope.project = project; + loggerService.debug('[ml4kdesc] getting ML models'); + return trainingService.getModels($scope.projectId, $scope.userId, vm.profile.tenant); + }) + .then(function (models) { + loggerService.debug('[ml4kdesc] models', models); + if (models && models.length > 0 && (models[0].status === 'Available') || (models[0].status === 'Training')) { + return trainingService.getModel($scope.project.id, $scope.userId, vm.profile.tenant, $scope.modelId, models[0].updated); + } + else { + var errId = displayAlert('errors', 400, { message : 'Model not ready to be described' }); + scrollToNewItem('errors' + errId); + $scope.loading = false; + } + }) + .then(function (modelinfo) { + loggerService.debug('[ml4kdesc] model info', modelinfo); + + $scope.loading = false; + $scope.modelinfo = modelinfo; + initializeVisualisation(); + }) + .catch(function (err) { + var errId = displayAlert('errors', err.status, err.data); + scrollToNewItem('errors' + errId); + $scope.loading = false; + }); + + + //------------------------------------------------------------------------------- + // Adding the model graphic to the page + //------------------------------------------------------------------------------- + + function initializeVisualisation() { + loggerService.debug('[ml4kdesc] initializing visualization'); + + initializeModelValues(); + + $timeout(function () { + fcnnVisualisationService.init('mlforkidsmodelvizimg'); + redrawNeuralNetworkDiagram(ARCHITECTURES.INITIAL); + }, 0); + } + + + //------------------------------------------------------------------------------- + // Defining the models + //------------------------------------------------------------------------------- + + var modelInfo = { + architecture : [], + spacing : [] + }; + + var WEIGHTS = {}; + var BIAS = {}; + var VALUES = {}; + + function initializeModelValues() { + loggerService.debug('[ml4kdesc] initializing weights and bias values'); + + for (var startLayer = 1; startLayer < 8; startLayer++) { + var endLayer = startLayer + 1; + + for (var startNode = 0; startNode < 10; startNode++) { + var startNodeId = startLayer + '_' + startNode; + + BIAS[startNodeId] = (5 - (startNode % 5)); + VALUES[startNodeId] = 0; + WEIGHTS[startNodeId] = {}; + + for (var endNode = 0; endNode < 10; endNode++) { + var endNodeId = endLayer + '_' + endNode; + + WEIGHTS[startNodeId][endNodeId] = getRandomInt(1, 5); + } + } + } + } + + // randomly increase or decrease by 1 + function adjust(val) { + return val + (Math.random() > 0.5 ? 1 : -1); + } + + var ARCHITECTURES = { + // represents a large complex model displayed when the wizard starts + INITIAL : 'initial', + // represents the model used for the full walkthrough + CUSTOM : 'custom', + // represents a model with a medium size input layer, used to illustrate custom features + FEATURE_SELECTION : 'feature', + // represents a model with a large input layer, used to illustrate bag-of-words + BAG_OF_WORDS : 'bag-of-words', + }; + + function setModelInfo(modeltype) { + if (modeltype === ARCHITECTURES.INITIAL) { + modelInfo.architecture = [ 9, 7, 9, 5, 7, 1 ]; + modelInfo.spacing = [ 20, 20, 20, 20, 20, 20 ]; + } + else if (modeltype === ARCHITECTURES.CUSTOM) { + modelInfo.architecture = [ 1, 7, 5, 8, $scope.project.labels.length ]; + modelInfo.spacing = [ 0, 20, 20, 20, 100 ]; + } + else if (modeltype === ARCHITECTURES.BAG_OF_WORDS) { + modelInfo.architecture = [ 1, 10, 5, 8, $scope.project.labels.length ]; + modelInfo.spacing = [ 0, 20, 20, 20, 100 ]; + } + else if (modeltype === ARCHITECTURES.FEATURE_SELECTION) { + modelInfo.architecture = [ 1, 9, 6, 7, $scope.project.labels.length ]; + modelInfo.spacing = [ 0, 20, 20, 20, 100 ]; + } + } + // returns the number of nodes in layer 1 + function getInputLayerSize() { + return modelInfo.architecture[1]; + } + + + + //------------------------------------------------------------------------------- + // Stepping through the wizard + //------------------------------------------------------------------------------- + + var FIRST_PAGE = 1; + var LAST_PAGE = 29; + + vm.wizardPage = FIRST_PAGE; + + vm.wizardBusy = false; + + function wizardStepComplete() { + vm.wizardBusy = false; + } + + vm.searchBoxLinks = [ + // 0 : + '', + // 1 : + 'https://duckduckgo.com/?q=neural+networks', + // 2 : + 'https://duckduckgo.com/?q=deep+learning', + // 3 : + 'https://duckduckgo.com/?q=input+layer+neural+network', + // 4 : + 'https://duckduckgo.com/?q=encoding+text+classification', + // 5 : + 'https://duckduckgo.com/?q=bag+of+words+machine+learning', + // 6 : + 'https://duckduckgo.com/?q=feature+extraction+text+classification', + // 7 : + 'https://duckduckgo.com/?q=word+embedding+neural+network', + // 8 : + 'https://duckduckgo.com/?q=hidden+layer+neural+network', + // 9 : + 'https://duckduckgo.com/?q=activation+function+neural+network', + // 10 : + 'https://duckduckgo.com/?q=weight+bias+neural+network', + // 11 : + 'https://duckduckgo.com/?q=weight+bias+neural+network', + // 12 : + 'https://duckduckgo.com/?q=activation+function+neural+network', + // 13 : + 'https://duckduckgo.com/?q=activation+function+neural+network', + // 14 : + 'https://duckduckgo.com/?q=hidden+layer+neural+network', + // 15 : + 'https://duckduckgo.com/?q=hidden+layer+neural+network', + // 16 : + 'https://duckduckgo.com/?q=output+layer+neural+network', + // 17 : + 'https://duckduckgo.com/?q=loss+function+neural+networks+artificial+intelligence', + // 18 : + 'https://duckduckgo.com/?q=back+propagation+neural+network', + // 19 : + 'https://duckduckgo.com/?q=neural+networks', + // 20: + 'https://duckduckgo.com/?q=encoding+text+classification', + // 21 : + 'https://duckduckgo.com/?q=hidden+layer+neural+network', + // 22 : + 'https://duckduckgo.com/?q=activation+function+neural+network', + // 23 : + 'https://duckduckgo.com/?q=activation+function+neural+network', + // 24 : + 'https://duckduckgo.com/?q=hidden+layer+neural+network', + // 25 : + 'https://duckduckgo.com/?q=output+layer+neural+network', + // 26 : + 'https://duckduckgo.com/?q=loss+function+neural+networks+artificial+intelligence', + // 27 : + 'https://duckduckgo.com/?q=back+propagation+neural+network', + // 28 : + 'https://duckduckgo.com/?q=epochs+neural+network', + // 29 : + 'https://duckduckgo.com/?q=neural+networks' + ]; + + var runningAnimations = []; + + vm.previousPage = function () { + loggerService.debug('[ml4kdesc] previousPage'); + vm.wizardBusy = true; + + if (vm.wizardPage > FIRST_PAGE) { + vm.wizardPage = vm.wizardPage - 1; + } + if (vm.wizardPage === 2) { + redrawNeuralNetworkDiagram(ARCHITECTURES.INITIAL); + } + if (vm.wizardPage === 3) { + fcnnVisualisationService.clearInputLabels(); + } + if (vm.wizardPage === 4) { + redrawNeuralNetworkDiagram(ARCHITECTURES.CUSTOM); + displayTrainingExampleInput(); + } + if (vm.wizardPage === 5) { + redrawNeuralNetworkDiagram(ARCHITECTURES.BAG_OF_WORDS); + displayTrainingExampleInput(); + } + if (vm.wizardPage === 8) { + fcnnVisualisationService.hideAnnotation('2_0'); + } + if (vm.wizardPage === 10) { + clearBias(2, 0); + } + if (vm.wizardPage === 11) { + populateHiddenLayerNodeWithPlaceholder(2, 0); + } + if (vm.wizardPage === 12) { + clearBias(2, 1); + populateHiddenLayerNodeWithPlaceholder(2, 1); + fcnnVisualisationService.hideAnnotation('2_1'); + } + if (vm.wizardPage === 13) { + clearBias(2, 2); + populateHiddenLayerNodeWithPlaceholder(2, 2); + fcnnVisualisationService.hideAnnotation('2_2'); + } + if (vm.wizardPage === 14 || vm.wizardPage === 15) { + populateHiddenLayerNodeWithPlaceholder(2, 3); + populateHiddenLayerNodeWithPlaceholder(2, 4); + clearHiddenLayerNodeValues(3); + } + if (vm.wizardPage === 15) { + hideOutputValues(); + clearOutputLayerNodeValues(); + } + if (vm.wizardPage === 19) { + fcnnVisualisationService.clearInputLabels(); + } + if (vm.wizardPage === 20) { + populateHiddenLayerNodeWithPlaceholder(2, 0); + fcnnVisualisationService.hideAnnotation('2_0'); + } + if (vm.wizardPage === 21) { + populateHiddenLayerNodeWithPlaceholder(2, 1); + fcnnVisualisationService.hideAnnotation('2_1'); + } + if (vm.wizardPage === 22) { + populateHiddenLayerNodeWithPlaceholder(2, 2); + fcnnVisualisationService.hideAnnotation('2_2'); + } + if (vm.wizardPage === 23 || vm.wizardPage === 24) { + populateHiddenLayerNodeWithPlaceholder(2, 3); + populateHiddenLayerNodeWithPlaceholder(2, 4); + clearHiddenLayerNodeValues(3); + } + if (vm.wizardPage === 24) { + hideOutputValues(); + clearOutputLayerNodeValues(); + } + + + displayPage(); + }; + + vm.nextPage = function () { + loggerService.debug('[ml4kdesc] nextPage'); + vm.wizardBusy = true; + + if (vm.wizardPage < LAST_PAGE) { + vm.wizardPage = vm.wizardPage + 1; + } + if (vm.wizardPage === 3) { + redrawNeuralNetworkDiagram(ARCHITECTURES.CUSTOM); + } + if (vm.wizardPage === 5) { + redrawNeuralNetworkDiagram(ARCHITECTURES.BAG_OF_WORDS); + displayTrainingExampleInput(); + } + if (vm.wizardPage === 6) { + redrawNeuralNetworkDiagram(ARCHITECTURES.FEATURE_SELECTION); + displayTrainingExampleInput(); + } + if (vm.wizardPage === 7) { + redrawNeuralNetworkDiagram(ARCHITECTURES.CUSTOM); + displayTrainingExampleInput(); + } + if (vm.wizardPage === 13) { + fcnnVisualisationService.hideAnnotation('2_0'); + } + if (vm.wizardPage === 14) { + fcnnVisualisationService.hideAnnotation('2_1'); + } + if (vm.wizardPage === 15) { + fcnnVisualisationService.hideAnnotation('2_2'); + } + if (vm.wizardPage === 22) { + fcnnVisualisationService.hideAnnotation('2_0'); + } + if (vm.wizardPage === 23) { + fcnnVisualisationService.hideAnnotation('2_1'); + } + if (vm.wizardPage === 24) { + fcnnVisualisationService.hideAnnotation('2_2'); + } + + displayPage(); + }; + + function displayPage() { + loggerService.debug('[ml4kdesc] displaying wizard page', vm.wizardPage); + + cancelRunningAnimations(); + + switch (vm.wizardPage) { + case 1: + wizardStepComplete(); + break; + case 2: + highlightNetworkLayersInSequence(); + wizardStepComplete(); + break; + case 3: + $scope.currentExample = $scope.modelinfo.examples[0]; + displayTrainingExampleInput(wizardStepComplete); + break; + case 4: + populateInputLayer($scope.currentExample.random, FAST, wizardStepComplete); + break; + case 5: + populateInputLayer($scope.currentExample.bagofwords, SLOW, wizardStepComplete); + break; + case 6: + populateInputLayer($scope.currentExample.customfeatures, SLOW, wizardStepComplete); + break; + case 7: + populateInputLayer($scope.currentExample.random, FAST, wizardStepComplete); + break; + case 8: + populateHiddenLayerWithPlaceholders(2, wizardStepComplete); + break; + case 9: + displayHiddenLayerValueWithWorking(2, 0, { }); + wizardStepComplete(); + break; + case 10: + displayHiddenLayerValueWithWorking(2, 0, { weight : true }); + wizardStepComplete(); + break; + case 11: + displayHiddenLayerValueWithWorking(2, 0, { weight : true, bias : true }); + wizardStepComplete(); + break; + case 12: + displayHiddenLayerValueWithWorking(2, 0, { weight : true, bias : true, finalvalue : true }); + wizardStepComplete(); + break; + case 13: + displayHiddenLayerValueWithWorking(2, 1, { weight : true, bias : true, finalvalue : true }); + wizardStepComplete(); + break; + case 14: + displayHiddenLayerValueWithWorking(2, 2, { weight : true, bias : true, finalvalue : true }); + wizardStepComplete(); + break; + case 15: + displayAllHiddenLayerValues(VERY_SLOW, wizardStepComplete); + break; + case 16: + displayOutputValues(wizardStepComplete); + break; + case 17: + displayOutputErrorRate(wizardStepComplete); + break; + case 18: + displayBackPropagation(SLOW, wizardStepComplete); + break; + case 19: + hideOutputValues(); + $scope.currentExample = $scope.modelinfo.examples[1]; + displayTrainingExampleInput(wizardStepComplete); + break; + case 20: + populateInputLayer($scope.currentExample.random, FAST, wizardStepComplete); + break; + case 21: + displayHiddenLayerValueWithWorking(2, 0, { weight : true, bias : true, finalvalue : true }); + wizardStepComplete(); + break; + case 22: + displayHiddenLayerValueWithWorking(2, 1, { weight : true, bias : true, finalvalue : true }); + wizardStepComplete(); + break; + case 23: + displayHiddenLayerValueWithWorking(2, 2, { weight : true, bias : true, finalvalue : true }); + wizardStepComplete(); + break; + case 24: + displayAllHiddenLayerValues(FAST, wizardStepComplete); + break; + case 25: + displayOutputValues(wizardStepComplete); + break; + case 26: + displayOutputErrorRate(wizardStepComplete); + break; + case 27: + displayBackPropagation(FAST, wizardStepComplete); + break; + case 28: + animateEpoch(wizardStepComplete); + break; + case 29: + redrawNeuralNetworkDiagram(ARCHITECTURES.INITIAL); + break; + } + } + + //------------------------------------------------------------------------------- + // Update the model graphic + //------------------------------------------------------------------------------- + + var LOWEST_SPEED = 800; + var VERY_SLOW = 600; + var SLOW = 400; + var FAST = 200; + var FASTEST_SPEED = 150; + + function redrawNeuralNetworkDiagram(modeltype) { + loggerService.debug('[ml4kdesc] redrawing the model network diagram', modeltype); + + setModelInfo(modeltype); + fcnnVisualisationService.create(modelInfo.architecture, modelInfo.spacing); + } + + function cancelRunningAnimations() { + loggerService.debug('[ml4kdesc] stopping previous animations'); + + for (var i = 0; i < runningAnimations.length; i++) { + $interval.cancel(runningAnimations[i]); + } + runningAnimations = []; + fcnnVisualisationService.remove_focus(); + } + + $rootScope.$on('$locationChangeStart', function () { + cancelRunningAnimations(); + }); + + function highlightNetworkLayersInSequence() { + loggerService.debug('[ml4kdesc] animating network layers'); + + var highlightedLayer = 0; + + fcnnVisualisationService.toggleLayerHighlight(highlightedLayer); + runningAnimations.push($interval(function () { + fcnnVisualisationService.toggleLayerHighlight(highlightedLayer); + highlightedLayer += 1; + fcnnVisualisationService.toggleLayerHighlight(highlightedLayer); + }, SLOW, 100)); + } + + function displayTrainingExampleInput(onComplete) { + loggerService.debug('[ml4kdesc] displaying training example in diagram'); + + fcnnVisualisationService.updateInputText($scope.currentExample.text); + fcnnVisualisationService.highlightInputText(); + + if (onComplete) { + onComplete(); + } + } + + function populateInputLayer(examples, speed, onComplete) { + loggerService.debug('[ml4kdesc] populating input layer'); + + fcnnVisualisationService.clearInputLabels(); + + var nodeIdx = 0; + var values = {}; + var iterations = getInputLayerSize(); + runningAnimations.push($interval(function () { + var example = examples[nodeIdx]; + + var nodeid = '1_' + nodeIdx; + values[nodeid] = { value : example.value }; + fcnnVisualisationService.updateLabels(values); + + if (example.annotation) { + fcnnVisualisationService.showAnnotation(nodeid, example.annotation); + } + + nodeIdx += 1; + + if (onComplete && nodeIdx === iterations) { + onComplete(); + } + }, speed, iterations)); + } + + + function calculateHiddenLayerValue(layerId, nodeIdx) { + loggerService.debug('[ml4kdesc] calculating hidden layer value', layerId, nodeIdx); + + var value = 0; + + var endLayerId = layerId; + var endNodeId = layerId + '_' + nodeIdx; + + var numNodes = getInputLayerSize(); + + var startLayerId = endLayerId - 1; + for (var startNodeIdx = 0; startNodeIdx < numNodes; startNodeIdx++) { + var startNodeId = startLayerId + '_' + startNodeIdx; + + value += ($scope.currentExample.random[startNodeIdx].value * WEIGHTS[startNodeId][endNodeId]); + } + + value += BIAS[endNodeId]; + + VALUES[endNodeId] = value; + + return value; + } + + function clearBias(layerId, nodeIdx) { + var nodeid = layerId + '_' + nodeIdx; + var values = {}; + values[nodeid] = { bias : undefined }; + fcnnVisualisationService.updateLabels(values); + } + + function populateHiddenLayerNodeWithPlaceholder(layerId, nodeIdx) { + var nodeid = layerId + '_' + nodeIdx; + var values = {}; + values[nodeid] = { value : '?' }; + fcnnVisualisationService.updateLabels(values); + } + + function clearHiddenLayerNodeValues(layerId) { + for (var nodeId = 0; nodeId < modelInfo.architecture[layerId]; nodeId++) { + populateHiddenLayerNodeWithPlaceholder(layerId, nodeId); + } + } + + + function populateHiddenLayerWithPlaceholders(layerId, onComplete) { + loggerService.debug('[ml4kdesc] populating hidden layer with placeholders', layerId); + + var nodeIdx = 0; + var iterations = modelInfo.architecture[layerId]; + runningAnimations.push($interval(function () { + populateHiddenLayerNodeWithPlaceholder(layerId, nodeIdx); + + nodeIdx += 1; + + if (onComplete && nodeIdx === iterations) { + onComplete(); + } + }, FAST, iterations)); + } + + + function displayHiddenLayerValueWithWorking(layerId, nodeId, includes) { + loggerService.debug('[ml4kdesc] displaying hidden layer values', layerId, nodeId, includes); + + fcnnVisualisationService.highlightHiddenLayerNode(layerId, nodeId); + + var inputLayer = layerId - 1; + var numInputNodes = modelInfo.architecture[inputLayer]; + var lastInputNodeIdx = numInputNodes - 1; + + var targetId = layerId + '_' + nodeId; + + if (includes.weight) { + var weightsToDisplay = []; + for (var inputNodeId = 0; inputNodeId < numInputNodes; inputNodeId++) { + weightsToDisplay.push('w = ' + WEIGHTS[inputLayer + '_' + inputNodeId][targetId]); + } + fcnnVisualisationService.displayWeights(layerId, nodeId, weightsToDisplay, {}); + } + + var values = {}; + if (includes.bias || includes.value) { + values[targetId] = {}; + if (includes.bias) { + values[targetId].bias = BIAS[targetId]; + } + if (includes.finalvalue) { + values[targetId].value = calculateHiddenLayerValue(layerId, nodeId); + } + fcnnVisualisationService.updateLabels(values); + } + + var working = ""; + if (includes.bias) { + working += (""); + working += (""); + } + for (var i = 0; i < numInputNodes; i++) { + var tablerow = ""; + tablerow += ""; + if (includes.weight) { + tablerow += "" + + ""; + } + tablerow += ""; + tablerow += ""; + + working += tablerow; + } + if (includes.finalvalue) { + working += (""); + working += (""); + } + working += "
" + BIAS[targetId] + "+
 
" + $scope.currentExample.random[i].value + "x" + WEIGHTS[inputLayer + '_' + i][targetId] + "" + (i === lastInputNodeIdx ? "" : "+") + "
 
= " + values[targetId].value + "
"; + + fcnnVisualisationService.showAnnotation(targetId, working); + } + + function displayAllHiddenLayerValues(speed, onComplete) { + loggerService.debug('[ml4kdesc] display hidden layer values', speed); + + var values = {}; + + var remainingNodes = [ + [ 2, 3 ], + [ 2, 4 ], + [ 3, 0 ], + [ 3, 1 ], + [ 3, 2 ], + [ 3, 3 ], + [ 3, 4 ], + [ 3, 5 ], + [ 3, 6 ], + [ 3, 7 ] + ]; + + for (var i = 0; i < remainingNodes.length; i++) { + var remainingNode = remainingNodes[i]; + var remainingNodeId = remainingNode[0] + '_' + remainingNode[1]; + values[remainingNodeId] = { bias : BIAS[remainingNodeId] }; + } + fcnnVisualisationService.updateLabels(values); + + var nodeIdx = -1; + var iterations = remainingNodes.length; + runningAnimations.push($interval(function () { + if (nodeIdx >= 0) { + var remainingNode = remainingNodes[nodeIdx]; + var nodeid = remainingNode[0] + '_' + remainingNode[1]; + values[nodeid].value = calculateHiddenLayerValue(remainingNode[0], remainingNode[1]); + fcnnVisualisationService.updateLabels(values); + } + + nodeIdx += 1; + + if (onComplete && nodeIdx === iterations) { + onComplete(); + } + }, speed, iterations + 1)); + } + + function hideOutputValues() { + fcnnVisualisationService.updateOutputHtml(); + } + + function displayOutputValues(onComplete) { + loggerService.debug('[ml4kdesc] display output values'); + displayOutputLayerNodeValues(); + + $timeout(function () { + displayOutputInfoTable({}); + onComplete(); + }, VERY_SLOW); + } + + function clearOutputLayerNodeValues() { + var layerId = modelInfo.architecture.length - 1; + var values = {}; + for (var nodeIdx = 0; nodeIdx < $scope.project.labels.length; nodeIdx++) { + values[layerId + '_' + nodeIdx] = { value : '' }; + } + fcnnVisualisationService.updateLabels(values); + } + + function displayOutputLayerNodeValues() { + loggerService.debug('[ml4kdesc] adding output layer node values'); + var layerId = modelInfo.architecture.length - 1; + var values = {}; + for (var nodeIdx = 0; nodeIdx < $scope.project.labels.length; nodeIdx++) { + var label = $scope.project.labels[nodeIdx]; + values[layerId + '_' + nodeIdx] = { value : $scope.currentExample.output[label] }; + } + fcnnVisualisationService.updateLabels(values); + } + + function displayOutputErrorRate(onComplete) { + loggerService.debug('[ml4kdesc] displaying output error rate'); + + displayOutputInfoTable({ training : true }); + + $timeout(function () { + displayOutputInfoTable({ training : true, error : true }); + onComplete(); + }, LOWEST_SPEED); + } + + function displayOutputInfoTable(includes) { + loggerService.debug('[ml4kdesc] generating output info table', includes); + + var output = ""; + output += ""; + if (includes.training) { + output += ""; + + if (includes.error) { + output += ""; + } + } + output += ""; + + for (var i = 0; i < $scope.project.labels.length; i++) { + var label = $scope.project.labels[i]; + + output += ""; + output += ""; + + if (includes.training) { + var trainingvalue = (label === $scope.currentExample.label) ? 100 : 0; + output += ""; + + if (includes.error) { + var errorrate = $scope.currentExample.output[label] - trainingvalue; + if (errorrate > 0) { + errorrate = "+" + errorrate; + } + + output += (""); + } + } + + output += ""; + } + output += "
labeloutputtrainingerror
" + label + "" + $scope.currentExample.output[label] + "" + trainingvalue + "" + + (includes.errorhighlight ? "" : "") + + errorrate + + (includes.errorhighlight ? "" : "") + + "
"; + + fcnnVisualisationService.updateOutputHtml(output); + } + + + function displayLinkWeights(layerId, includes) { + loggerService.debug('[ml4kdesc] displaying link weights', layerId, includes); + + var previousLayer = layerId - 1; + var previousLayerNumNodes = modelInfo.architecture[previousLayer]; + + var numNodes = modelInfo.architecture[layerId]; + for (var i = 0; i < numNodes; i++) { + var targetId = layerId + '_' + i; + var weights = []; + for (var j = 0; j < previousLayerNumNodes; j++) { + if (includes.hide) { + weights.push(''); + } + else { + if (includes.adjustment) { + WEIGHTS[previousLayer + '_' + j][targetId] = adjust(WEIGHTS[previousLayer + '_' + j][targetId]); + } + weights.push(WEIGHTS[previousLayer + '_' + j][targetId]); + } + } + fcnnVisualisationService.displayWeights(layerId, i, weights, { label : includes.highlight }); + } + } + + + function displayBackPropagation(speed, onComplete) { + loggerService.debug('[ml4kdesc] running backprop animation'); + + fcnnVisualisationService.removeValues(); + + displayOutputInfoTable({ training : true, error : true, errorhighlight : true }); + + var steps = []; + for (var layerId = modelInfo.architecture.length - 1; layerId > 1; layerId--) { + for (var nodeId = 0; nodeId < modelInfo.architecture[layerId]; nodeId++) { + if (layerId != (modelInfo.architecture.length - 1)) { + steps.push({ layer : layerId, type : 'bias', node : nodeId, action : 'adjust' }); + steps.push({ layer : layerId, type : 'bias', node : nodeId, action : 'current' }); + } + } + for (var nodeId = 0; nodeId < modelInfo.architecture[layerId]; nodeId++) { + steps.push({ layer : layerId, type : 'weights', node : nodeId, action : 'current' }); + steps.push({ layer : layerId, type : 'weights', node : nodeId, action : 'adjust' }); + steps.push({ layer : layerId, type : 'weights', node : nodeId, action : 'hide' }); + } + } + + var stepId = 0; + runningAnimations.push($interval(function () { + var step = steps[stepId]; + + var targetId = step.layer + '_' + step.node; + + if (step.type === 'weights') { + var inputLayer = step.layer - 1; + var numInputNodes = modelInfo.architecture[inputLayer]; + + var highlights = { + label : step.action === 'adjust', + path : step.action !== 'hide' + }; + + var weightsToDisplay = []; + + if (step.action === 'adjust') { + for (var inputNodeId = 0; inputNodeId < numInputNodes; inputNodeId++) { + WEIGHTS[inputLayer + '_' + inputNodeId][targetId] = adjust(WEIGHTS[inputLayer + '_' + inputNodeId][targetId]); + } + } + if (step.action === 'current' || step.action === 'adjust') { + for (var inputNodeId = 0; inputNodeId < numInputNodes; inputNodeId++) { + weightsToDisplay.push('w = ' + WEIGHTS[inputLayer + '_' + inputNodeId][targetId]); + } + } + if (step.action === 'hide') { + for (var inputNodeId = 0; inputNodeId < numInputNodes; inputNodeId++) { + weightsToDisplay.push(''); + } + } + + fcnnVisualisationService.displayWeights(step.layer, step.node, weightsToDisplay, highlights); + } + if (step.type === 'bias') { + if (step.action === 'adjust') { + BIAS[targetId] = adjust(BIAS[targetId]); + } + + var values = {}; + values[targetId] = { bias : BIAS[targetId] }; + fcnnVisualisationService.updateLabels(values, step.action === 'adjust'); + } + + stepId += 1; + if (onComplete && stepId === steps.length) { + onComplete(); + } + }, speed, steps.length)); + } + + + + function animateEpoch(onComplete) { + loggerService.debug('[ml4kdesc] animating network layers with real examples'); + + var numInputNodes = getInputLayerSize(); + + var exampleIdx = 1; + + var steps = []; + steps.push({ action : 'next-example', node : [ 0, 0 ] }); + steps.push({ action : 'highlight-example', node : [ 0, 0 ] }); + for (var i = 0; i < numInputNodes; i++) { + steps.push({ action : 'input-layer', node : [ 1, i ] }); + } + steps.push({ action : 'remove-focus', node : [ 0, 0 ] }); + for (var hiddenLayer = 2; hiddenLayer < (modelInfo.architecture.length - 1); hiddenLayer++) { + for (var hiddenLayerNodeIdx = 0; hiddenLayerNodeIdx < modelInfo.architecture[hiddenLayer]; hiddenLayerNodeIdx++) { + steps.push({ action : 'hidden-nodes', node : [ hiddenLayer, hiddenLayerNodeIdx ] }); + } + } + + steps.push({ action : 'remove-focus', node : [ 0, 0 ] }); + for (var k = 0; k < $scope.project.labels.length; k++) { + steps.push({ action : 'output-layer', node : [ 4, k ] }); + } + steps.push({ action : 'output-info', node : [ 4, 0 ] }); + steps.push({ action : 'error-rate', node : [ 4, 0 ] }); + steps.push({ action : 'hide-example', node : [ 0, 0 ] }); + + for (var stepLayer = 4; stepLayer >= 2; stepLayer--) { + if (stepLayer < 4) { + for (var x = 0; x < modelInfo.architecture[stepLayer]; x++) { + steps.push({ action : 'highlight-bias', node : [ stepLayer, x ] }); + steps.push({ action : 'adjust-bias', node : [ stepLayer, x ] }); + } + steps.push({ action : 'remove-bias-highlights', node : [ stepLayer, 0 ] }); + } + + steps.push({ action : 'display-weights', node : [ stepLayer, 0 ] }); + steps.push({ action : 'highlight-weights', node : [ stepLayer, 0 ] }); + steps.push({ action : 'adjust-weights', node : [ stepLayer, 0 ] }); + steps.push({ action : 'display-weights', node : [ stepLayer, 0 ] }); + steps.push({ action : 'hide-weights', node : [ stepLayer, 0 ] }); + } + + + var stepId = 0; + + runningAnimations.push($interval(function () { + var step = steps[stepId]; + var action = step.action; + + var node = step.node; + var layerId = node[0]; + var nodeIdx = node[1]; + + var nodeid = layerId + '_' + nodeIdx; + + var values = {}; + + loggerService.debug('[ml4kdesc] animation', action, node); + + if (action === 'next-example') { + fcnnVisualisationService.remove_focus(); + fcnnVisualisationService.updateOutputHtml(); + + $scope.currentExample = $scope.modelinfo.examples[exampleIdx]; + fcnnVisualisationService.updateInputText($scope.currentExample.text); + + exampleIdx = (exampleIdx + 1) % $scope.modelinfo.examples.length; + } + else if (action === 'highlight-example') { + fcnnVisualisationService.highlightInputText(); + } + else if (action === 'input-layer') { + var example = $scope.currentExample.random[nodeIdx]; + + values[nodeid] = { value : example.value }; + fcnnVisualisationService.updateLabels(values); + } + else if (action === 'hidden-nodes') { + values[nodeid] = { value : calculateHiddenLayerValue(layerId, nodeIdx) }; + fcnnVisualisationService.updateLabels(values); + } + else if (action === 'output-layer') { + displayOutputLayerNodeValues(); + } + else if (action === 'output-info') { + displayOutputInfoTable({}); + } + else if (action === 'error-rate') { + fcnnVisualisationService.remove_focus(); + displayOutputInfoTable({ training : true }); + } + else if (action === 'hide-example') { + fcnnVisualisationService.removeValues(); + displayOutputInfoTable({ training : true, error : true, errorhighlight : true }); + } + else if (action === 'display-weights') { + displayLinkWeights(layerId, {}); + } + else if (action === 'hide-weights') { + fcnnVisualisationService.removeValues(); + displayLinkWeights(layerId, { hide : true }); + } + else if (action === 'highlight-weights') { + displayLinkWeights(layerId, { highlight : true }); + } + else if (action === 'adjust-weights') { + displayLinkWeights(layerId, { highlight : true, adjustment : true }); + } + else if (action === 'highlight-bias') { + values[nodeid] = { bias : BIAS[nodeid] }; + fcnnVisualisationService.updateLabels(values, true); + } + else if (action === 'adjust-bias') { + BIAS[nodeid] = adjust(BIAS[nodeid]); + + values[nodeid] = { bias : BIAS[nodeid] }; + fcnnVisualisationService.updateLabels(values, true); + } + else if (action === 'remove-bias-highlights') { + var numNodes = modelInfo.architecture[layerId]; + for (var i = 0; i < numNodes; i++) { + var targetId = layerId + '_' + i; + values[targetId] = { bias : BIAS[targetId] }; + } + fcnnVisualisationService.updateLabels(values); + } + else if (action === 'remove-focus') { + fcnnVisualisationService.remove_focus(); + } + + + stepId = (stepId + 1) % steps.length; + }, FASTEST_SPEED, 1500)); + + onComplete(); + } + + + //------------------------------------------------------------------------------- + // Moving the model graphic around + //------------------------------------------------------------------------------- + + var operation; + + vm.stop = function() { + if (operation) { + $interval.cancel(operation); + clearInterval(operation); + operation = undefined; + } + }; + + var REPEAT_INTERVAL = 50; + var SCROLL_PIXELS = 20; + var scale = 100; + + + vm.grow = function() { + vm.stop(); + var image = document.getElementById("mlforkidsmodelvizimg"); + operation = $interval(function () { + scale += 10; + image.style["width"] = scale + "%"; + }, REPEAT_INTERVAL); + }; + + vm.shrink = function() { + vm.stop(); + var image = document.getElementById("mlforkidsmodelvizimg"); + operation = $interval(function () { + if (scale > 100) { + scale -= 10; + image.style["width"] = scale + "%"; + } + }, REPEAT_INTERVAL); + }; + + vm.goleft = function() { + vm.stop(); + var container = document.getElementById("mlforkidsmodelvizimghost"); + operation = $interval(function () { + container.scrollLeft += SCROLL_PIXELS; + console.log('left : ' + container.scrollLeft); + }, REPEAT_INTERVAL); + }; + vm.goright = function() { + vm.stop(); + var container = document.getElementById("mlforkidsmodelvizimghost"); + operation = $interval(function () { + container.scrollLeft -= SCROLL_PIXELS; + console.log('left : ' + container.scrollLeft); + }, REPEAT_INTERVAL); + }; + vm.goup = function() { + vm.stop(); + var container = document.getElementById("mlforkidsmodelvizimghost"); + operation = $interval(function () { + container.scrollTop -= SCROLL_PIXELS; + console.log('top : ' + container.scrollTop); + }, REPEAT_INTERVAL); + }; + vm.godown = function() { + vm.stop(); + var container = document.getElementById("mlforkidsmodelvizimghost"); + operation = $interval(function () { + container.scrollTop += SCROLL_PIXELS; + console.log('top : ' + container.scrollTop); + }, REPEAT_INTERVAL); + }; + + // function zoomToElement(elementId) { + // var image = document.getElementById("mlforkidsmodelvizimg"); + + // var currentWidth = image.style["width"] || "100%"; + // var percentIdx = currentWidth.indexOf("%"); + // if (percentIdx > 0) { + // currentWidth = currentWidth.substr(0, percentIdx); + // } + // var zoomScaleStep = 20; + + // var currentZoomLevel = parseInt(currentWidth, 10); + // console.log('zoom level is ' + currentZoomLevel); + + // currentZoomLevel = currentZoomLevel - (currentZoomLevel % zoomScaleStep); + + // var targetZoomLevel = 200; + + // if (currentZoomLevel > targetZoomLevel) { + // var steps = (currentZoomLevel - targetZoomLevel) / zoomScaleStep; + // $interval(function () { + // currentZoomLevel -= zoomScaleStep; + // console.log('setting zoom to ' + currentZoomLevel); + // image.style["width"] = currentZoomLevel + "%"; + // }, FASTEST_SPEED, steps); + // } + // else if (currentZoomLevel < targetZoomLevel) { + // var steps = (targetZoomLevel - currentZoomLevel) / zoomScaleStep; + // $interval(function () { + // currentZoomLevel += zoomScaleStep; + // console.log('setting zoom to ' + currentZoomLevel); + // image.style["width"] = currentZoomLevel + "%"; + // }, FASTEST_SPEED, steps); + // } + + + // var target = getElementById(elementId); + // var location = target.getBoundingClientRect(); + // var xLocation = location.x - (location.x % 50); + + // var container = document.getElementById("mlforkidsmodelvizimghost"); + // container.scrollLeft = xLocation; + // } + // function resetZoom() { + // var image = document.getElementById("mlforkidsmodelvizimg"); + // var currentWidth = image.style["width"] || "100%"; + // var percentIdx = currentWidth.indexOf("%"); + // if (percentIdx > 0) { + // currentWidth = currentWidth.substr(0, percentIdx); + // } + // var zoomScaleStep = 20; + + // var currentZoomLevel = parseInt(currentWidth, 10); + // console.log('zoom level is ' + currentZoomLevel); + + // currentZoomLevel = currentZoomLevel - (currentZoomLevel % zoomScaleStep); + + // if (currentZoomLevel > 100) { + // var steps = (currentZoomLevel - 100) / zoomScaleStep; + // $interval(function () { + // currentZoomLevel -= zoomScaleStep; + // console.log('setting zoom to ' + currentZoomLevel); + // image.style["width"] = currentZoomLevel + "%"; + // }, FASTEST_SPEED, steps); + // } + // } + + + + //------------------------------------------------------------------------------- + + function getRandomInt(min, max) { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(Math.random() * (max - min + 1)) + min; + } + } +}()); diff --git a/public/components/describetextmodel/describemodel.css b/public/components/describetextmodel/describemodel.css new file mode 100644 index 000000000..3cf90a7bd --- /dev/null +++ b/public/components/describetextmodel/describemodel.css @@ -0,0 +1,154 @@ +.describemlmodel .describeintro .nnexplanation { + flex-grow: 3; + min-height: 140px; +} + +.describemlmodel .nnexplanation .bodytext { + margin-bottom: 1em; +} + +.describemlmodel .nnexplanation .bodytext em { + font-style: italic; + font-weight: bold; + color: #41515f; +} + +.describemlmodel .nnwizardaction { + text-align: center; +} + +.describemlmodel .nnsearchbox { + margin-right: 0; + margin-left: 15px; + background-color: #eeeeee; + border-radius: 2em; + padding: 1em; + flex-grow: 1; + position: relative; + min-width: 225px; +} + +.describemlmodel .nnsearchbox .nnsearchprompt { + font-size: 0.7em; +} +.describemlmodel .nnsearchbox .nnsearchterm { + font-size: 2em; + font-weight: bold; + padding-left: 0.3em; +} +.describemlmodel .nnsearchbox .nnsearchgraphic { + position: absolute; + bottom: 0; + right: 0; + padding: 1em; +} +.describemlmodel .nnsearchbox .nnsearchgraphic svg { + opacity: 0.1; +} + +.describemlmodel .nnwizardaction button.btn-primary { + width: 180px; +} +.describemlmodel .nnwizardaction button.btn-default { + width: 120px; +} + +.describemlmodel .nnwizardaction button { + width: 180px; + margin-top: 1em; + margin-bottom: 1em; +} + + +.describemlmodel .visualisationimagehost .inputdata { + font-size: 13px; + text-align: center; + background-color: white; + border: thin grey solid; + padding: 2px; +} + + + + +.describemlmodel .visualisationimagehost .nodedata { + font-size: 12px; +} +.describemlmodel .visualisationimagehost .nodevalue { + font-size: 17px; +} +.describemlmodel .visualisationimagehost .nodeseparator { + stroke-width: 0.5; + stroke-opacity: 1; + stroke: rgb(80, 80, 80); +} +.describemlmodel .visualisationimagehost .nodeweight { + font-size: 10px; +} +.describemlmodel .visualisationimagehost .nodeweight.highlighted { + font-weight: 900; + color: #1864ab; +} + +.describemlmodel .visualisationimagehost .link.highlighted { + stroke-width: 1.2 !important; + stroke: #1864ab !important; +} + + +.describemlmodel .visualisationimagehost .inputannotation { + background-color: #f1feff; + border: thin #1864ab solid; + font-size: 12px; + padding: 3px; +} + +.describemlmodel .visualisationimagehost .hiddenlayerfunction { + background-color: #f0f0ff; + font-family: 'Courier New', Courier, monospace; + font-size: 10px; + padding: 8px; + text-align: right; + border: thin #1864ab solid; +} + +.describemlmodel .visualisationimagehost .outputlayerdetail table { + background-color: white; +} + +.describemlmodel .visualisationimagehost .outputlayerdetail { + background-color: white; + font-size: 10px; + padding: 9px; + border: thin #1864ab solid; +} + +.describemlmodel .visualisationimagehost .outputlayerdetail th { + border-bottom: thin black solid; + padding-left: 8px; + padding-right: 8px; +} +.describemlmodel .visualisationimagehost .outputlayerdetail td { + padding: 8px 16px 8px 8px; + font-family: 'Courier New', Courier, monospace; +} + +.describemlmodel .visualisationimagehost .hiddenlayerfunction td { + padding-left: 5px; + padding-right: 5px; +} + +.describemlmodel .visualisationimagehost .hiddendiagramelement { + visibility: hidden; +} + + +.describemlmodel .visualisationimagehost .highlightedlayer { + fill: #84cbcc !important; + background-color: #84cbcc; + + stroke: #1864ab !important; + color: #1864ab; + + font-weight: bold; +} diff --git a/public/components/describetextmodel/describemodel.html b/public/components/describetextmodel/describemodel.html new file mode 100644 index 000000000..e5d26f0d3 --- /dev/null +++ b/public/components/describetextmodel/describemodel.html @@ -0,0 +1,244 @@ +
+
+ +
+
+ +
+
+
+ +
+
+
+

{{ 'DESCRIBEMODEL.TITLE' | translate }} beta

+
+
+ +
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ 'DESCRIBETEXTMODEL.PAGE14.TEXT2' | translate }} +
    +
  • +
  • +
  • +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + +
+ +
+ +
+
+
+
+ +
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ diff --git a/public/components/describetextmodel/fcnn.service.js b/public/components/describetextmodel/fcnn.service.js new file mode 100644 index 000000000..2271952b1 --- /dev/null +++ b/public/components/describetextmodel/fcnn.service.js @@ -0,0 +1,800 @@ + +(function () { + // angular-ized service implementation of https://github.com/alexlenail/NN-SVG + // with some additional functions to add extra annotations and text to the NN visualisation + + + // MIT License + // from https://github.com/alexlenail/NN-SVG/blob/master/LICENSE + // + // Copyright (c) 2018 Alexander Lenail + // + // Permission is hereby granted, free of charge, to any person obtaining a copy + // of this software and associated documentation files (the "Software"), to deal + // in the Software without restriction, including without limitation the rights + // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + // copies of the Software, and to permit persons to whom the Software is + // furnished to do so, subject to the following conditions: + // + // The above copyright notice and this permission notice shall be included in all + // copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + // SOFTWARE. + + angular + .module('app') + .service('fcnnVisualisationService', fcnnVisualisationService); + + fcnnVisualisationService.$inject = [ + 'loggerService' + ]; + + function fcnnVisualisationService(loggerService) { + + var ID_PREFIX = 'ml4kids_nn_'; + + var NS_SVG = 'http://www.w3.org/2000/svg'; + var NS_HTML = 'http://www.w3.org/1999/xhtml'; + + + //------------------------------------------------------------------------- + // utility functions + // adapted from https://github.com/alexlenail/NN-SVG/blob/master/util.js + //------------------------------------------------------------------------- + + function nWise(n, array) { + var iterators = Array(n).fill().map(function () { + return array[Symbol.iterator](); + }); + iterators.forEach(function (it, index) { + Array(index).fill().forEach(function () { + return it.next(); + }); + }); + return Array(array.length - n + 1).fill().map(function () { + return iterators.map(function (it) { + return it.next().value; + }); + }); + } + + function pairWise(array) { + return nWise(2, array); + } + + function range(n) { + return Array(n).fill(0).map(function (v, idx) { + return idx; + }); + } + + function flatten(array) { + return array.reduce(function (flat, toFlatten) { + return flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten); + }, []); + } + + + //------------------------------------------------------------------------- + // fcnn generator + // adapted from https://github.com/alexlenail/NN-SVG/blob/master/FCNN.js + //------------------------------------------------------------------------- + + var w, h, svg, g, graph, layer_offsets, link, node; + + var container; + + var architecture = []; + var betweenNodesInLayer = []; + + var largest_layer_width = 0; + + var edgeWidth = 0.5; + var edgeOpacity = 1.0; + + var defaultEdgeColor = '#505050'; + + var nodeDiameter = 50; + var nodeColor = '#ffffff'; + var nodeBorderColor = '#333333'; + + var betweenLayers = 160; + + function init(containerId) { + container = document.getElementById(containerId); + + w = window.innerWidth; + h = window.innerHeight; + + svg = d3.select('#' + containerId) + .append('svg') + .attr('xmlns', NS_SVG); + g = svg.append('g'); + + graph = {}; + layer_offsets = []; + + link = g.selectAll('.link'); + node = g.selectAll('.node'); + + resize(); + } + + function returnId(item) { + return item.id; + } + + function redraw() { + graph.nodes = architecture.map(function (layer_width, layer_index) { + return range(layer_width).map(function (node_index) { + return { + id: ID_PREFIX + getNodeId(layer_index, node_index), + layer: layer_index, + node_index: node_index + }; + }); + }); + graph.links = pairWise(graph.nodes).map(function (nodes) { + return nodes[0].map(function (left) { + return nodes[1].map(function (right) { + if (right.node_index < 0) { + return null; + } + return { + id: ID_PREFIX + left.id + '-' + right.id, + source: left.id, + target: right.id + }; + }); + }); + }); + graph.nodes = flatten(graph.nodes); + graph.links = flatten(graph.links); + + link = link.data(graph.links, returnId); + link.exit().remove(); + link = link.enter() + .insert('path', '.node') + .attr('class', 'link') + .attr('id', returnId) + .merge(link); + + node = node.data(graph.nodes, returnId); + node.exit().remove(); + node = node.enter() + .append('circle') + .attr('r', nodeDiameter/2) + .attr('class', function(d) { return 'node nnlayer' + d.layer; }) + .attr('id', returnId) + .merge(node); + + style(); + } + + function redistribute() { + var layer_widths = architecture.map(function (layer_width, i) { + return layer_width * nodeDiameter + (layer_width - 1) * betweenNodesInLayer[i]; + }); + + largest_layer_width = Math.max.apply(null, layer_widths); + + layer_offsets = layer_widths.map(function (layer_width) { + return (largest_layer_width - layer_width) / 2; + }); + + var indices_from_id = function (id) { + return id.substr(ID_PREFIX.length).split('_').map(function (x) { + return parseInt(x); + }); + }; + + var x = function (layer) { + return layer * (betweenLayers + nodeDiameter) + w/2 - (betweenLayers * layer_offsets.length/3); + }; + var y = function (layer, node_index) { + return layer_offsets[layer] + node_index * (nodeDiameter + betweenNodesInLayer[layer]) + h/2 - largest_layer_width/2; + }; + + node.attr('cx', function(d) { return x(d.layer); }) + .attr('cy', function(d) { return y(d.layer, d.node_index); }); + + link.attr('d', function (d) { + var sourceIndices = indices_from_id(d.source); + var targetIndices = indices_from_id(d.target); + + return 'M' + + x(sourceIndices[0]) + ',' + y(sourceIndices[0], sourceIndices[1]) + ', ' + + x(targetIndices[0]) + ',' + y(targetIndices[0], targetIndices[1]); + }); + } + + function style() { + link.style('stroke-width', edgeWidth); + link.style('stroke-opacity', edgeOpacity); + link.style('stroke', defaultEdgeColor); + + node.attr('r', nodeDiameter/2); + node.style('fill', nodeColor); + node.style('stroke', nodeBorderColor); + + // ml4k-specific + removeAnnotations(); + } + + function resize() { + w = window.innerWidth; + h = window.innerHeight; + svg.attr('viewBox', '0 0 ' + w + ' ' + h); + } + + function set_focus(d) { + // d3.event.stopPropagation(); + node.style('opacity', function(o) { return (d == o || o.layer == d.layer - 1) ? 1 : 0.1; }); + link.style('opacity', function(o) { return (o.target == d.id) ? 1 : 0.02; }); + + // ml4k-specific + setAnnotationsFocus(d); + } + + function remove_focus() { + // d3.event.stopPropagation(); + node.style('opacity', 1); + link.style('opacity', function () { return edgeOpacity; }); + + // ml4k-specific + removeAnnotationsFocus(); + } + + + //----------------------------------------------------------------- + // additional MLforKids-specific functions + //----------------------------------------------------------------- + + var ELEMENT_IDS = { + INPUT_TEXT_CONTAINER : 'input_text_container', + INPUT_TEXT : 'input_text', + OUTPUT_LAYER_CONTAINER : 'output_layer_container', + OUTPUT_LAYER : 'output_layer', + BIAS : 'bias', + WEIGHT : 'weight', + NODE_VALUE : 'value', + PATH_TEXT : 'text', + SEPARATOR : 'separator', + ANNOTATION : 'annotation' + }; + var LAYER_IDS = { + INPUT_TEXT : 0, + INPUT_LAYER : 1 + }; + + function getNodeId(layerIdx, nodeIdx) { + return layerIdx + '_' + nodeIdx; + } + + function getNNNode(layerIdx, nodeIdx) { + return document.getElementById(ID_PREFIX + getNodeId(layerIdx, nodeIdx)); + } + + function addInputExample() { + var inputDataNode = getNNNode(LAYER_IDS.INPUT_TEXT, 0); + var inputLayerX = parseFloat(inputDataNode.getAttribute('cx')); + var inputLayerY = parseFloat(inputDataNode.getAttribute('cy')); + + var inputDataWidth = 120; + var inputDataHeight = 70; + + var exampleTextX = inputLayerX - (inputDataWidth / 2); + var exampleTextY = inputLayerY; + + var exampleTextContainer = createSvgElement(NS_SVG, 'foreignObject', { + 'id': ID_PREFIX + ELEMENT_IDS.INPUT_TEXT_CONTAINER, + 'x': exampleTextX, + 'y': exampleTextY, + 'width': inputDataWidth, + 'height': inputDataHeight, + 'dominant-anchor': 'middle', + 'text-anchor': 'middle', + 'style': 'overflow:visible', + 'class': 'additionalnndiagramelement' + }, inputDataNode.parentNode); + + var exampleText = createSvgElement(NS_HTML, 'div', { + 'id': ID_PREFIX + ELEMENT_IDS.INPUT_TEXT, + 'class': 'inputdata hiddendiagramelement additionalnndiagramelement' + }, exampleTextContainer); + + exampleText.textContent = 'input text'; + exampleTextContainer.setAttributeNS(null, 'y', exampleTextY - (exampleText.clientHeight / 2)); + } + + function addOutputDetail() { + var layerId = architecture.length - 1; + var topOutputDataNode = getNNNode(layerId, 0); + var bottomOutputDataNode = getNNNode(layerId, architecture[layerId] - 1); + + var outputLayerX = parseFloat(topOutputDataNode.getAttribute('cx')); + + var topOutputLayerY = parseFloat(topOutputDataNode.getAttribute('cy')); + var bottomOutputLayerY = parseFloat(bottomOutputDataNode.getAttribute('cy')); + + var outputDataWidth = 460; + var outputDataHeight = 120; + + var detailX = outputLayerX + 40; + var detailY = topOutputLayerY + ((bottomOutputLayerY - topOutputLayerY) / 2) - 60; + + var detailContainer = createSvgElement(NS_SVG, 'foreignObject', { + 'id': ID_PREFIX + ELEMENT_IDS.OUTPUT_LAYER_CONTAINER, + 'x': detailX, + 'y': detailY, + 'width': outputDataWidth, + 'height': outputDataHeight, + 'dominant-anchor': 'middle', + 'text-anchor': 'middle', + 'style': 'overflow:visible', + 'class': 'additionalnndiagramelement' + }, topOutputDataNode.parentNode); + + createSvgElement(NS_HTML, 'div', { + 'id': ID_PREFIX + ELEMENT_IDS.OUTPUT_LAYER, + 'class': 'outputlayerdetail hiddendiagramelement additionalnndiagramelement' + }, detailContainer); + } + + function addLabels() { + loggerService.debug('[fcnn] Adding labels'); + + var largestLayer = { + idx : 0, + size : 0 + }; + + addInputExample(); + addOutputDetail(); + + for (var layerIdx = LAYER_IDS.INPUT_LAYER; layerIdx < architecture.length; layerIdx++) { + if (architecture[layerIdx] > largestLayer.size) { + largestLayer = { + idx : layerIdx, + size : architecture[layerIdx] + }; + } + + if (layerIdx === LAYER_IDS.INPUT_LAYER) { + for (var i = 0; i < architecture[layerIdx]; i++) { + addInputOutputLabel(layerIdx, i, getNodeId(layerIdx, i), true); + } + } + else if (layerIdx === (architecture.length - 1)) { + for (var j = 0; j < architecture[layerIdx]; j++) { + addInputOutputLabel(layerIdx, j, getNodeId(layerIdx, j), false); + } + } + else { + for (var k = 0; k < architecture[layerIdx]; k++) { + addLabel(layerIdx, k, getNodeId(layerIdx, k)); + } + } + } + setViewBox(largestLayer); + } + + function addWeights() { + loggerService.debug('[fcnn] Adding weights'); + + var parentNode = getNNNode(LAYER_IDS.INPUT_TEXT, 0).parentNode; + + for (var layerIdx = LAYER_IDS.INPUT_LAYER; layerIdx < (architecture.length - 1); layerIdx++) { + var nextLayerIdx = layerIdx + 1; + var nextLayerNumNodes = architecture[nextLayerIdx]; + + var numNodes = architecture[layerIdx]; + for (var idx = 0; idx < numNodes; idx++) { + var nodeId = ID_PREFIX + getNodeId(layerIdx, idx); + + for (var nextIdx = 0; nextIdx < nextLayerNumNodes; nextIdx++) { + var pathId = ID_PREFIX + + nodeId + '-' + + ID_PREFIX + getNodeId(nextLayerIdx, nextIdx); + + var pathText = createSvgElement(NS_SVG, 'text', { + 'text-anchor' : 'middle', + 'class' : 'additionalnndiagramelement' + }, parentNode); + + createSvgElement(NS_SVG, 'textPath', { + 'id' : pathId + ELEMENT_IDS.PATH_TEXT, + 'href' : '#' + pathId, + 'startOffset' : '65%', + 'class' : 'nodeweight' + }, pathText); + } + } + } + } + + function addInputOutputLabel(layerIdx, nodeIdx, nodeid, isInput) { + var mynode = getNNNode(layerIdx, nodeIdx); + var mynodex = parseFloat(mynode.getAttribute('cx')); + var mynodey = parseFloat(mynode.getAttribute('cy')); + + createSvgElement(NS_SVG, 'text', { + 'id': ID_PREFIX + ELEMENT_IDS.NODE_VALUE + nodeid, + 'x': mynodex, + 'y': mynodey + 5, + 'dominant-anchor': 'middle', + 'text-anchor': 'middle', + 'class': 'nodevalue' + }, mynode.parentNode); + + if (isInput) { + var annotationContainer = createSvgElement(NS_SVG, 'foreignObject', { + 'x' : mynodex + 20, + 'y' : mynodey - 25, + 'width' : 150, + 'height': 70, + 'dominant-anchor' : 'text-top', + 'text-anchor' : 'start', + 'class' : 'additionalnndiagramelement' + }, mynode.parentNode); + + createSvgElement(NS_HTML, 'div', { + 'id' : ID_PREFIX + ELEMENT_IDS.ANNOTATION + nodeid, + 'class' : 'inputannotation hiddendiagramelement additionalnndiagramelement' + }, annotationContainer); + } + } + + function createSvgElement(ns, type, attrs, parent) { + var elem = document.createElementNS(ns, type); + for (var attrname in attrs) { + elem.setAttributeNS(null, attrname, attrs[attrname]); + } + parent.appendChild(elem); + return elem; + } + + function addLabel(layerIdx, nodeIdx, nodeid) { + var mynode = getNNNode(layerIdx, nodeIdx); + var mynodex = parseFloat(mynode.getAttribute('cx')); + var mynodey = parseFloat(mynode.getAttribute('cy')); + + createSvgElement(NS_SVG, 'text', { + 'id': ID_PREFIX + ELEMENT_IDS.BIAS + nodeid, + 'x': mynodex, + 'y': mynodey - 8, + 'dominant-anchor': 'middle', + 'text-anchor': 'middle', + 'class': 'nodedata' + }, mynode.parentNode); + + createSvgElement(NS_SVG, 'line', { + 'id': ID_PREFIX + ELEMENT_IDS.SEPARATOR + nodeid, + 'x1': mynodex - 20, + 'x2': mynodex + 20, + 'y1': mynodey - 4, + 'y2': mynodey - 4, + 'class': 'nodeseparator hiddendiagramelement' + }, mynode.parentNode); + + createSvgElement(NS_SVG, 'text', { + 'id': ID_PREFIX + ELEMENT_IDS.NODE_VALUE + nodeid, + 'x': mynodex, + 'y': mynodey + 14, + 'dominant-anchor': 'middle', + 'text-anchor': 'middle', + 'class': 'nodevalue' + }, mynode.parentNode); + + var annotationContainer = createSvgElement(NS_SVG, 'foreignObject', { + 'x' : mynodex + 25, + 'y' : mynodey - 30, + 'width' : 150, + 'height' : 70, + 'dominant-anchor' : 'text-top', + 'text-anchor' : 'start', + 'style' : 'overflow: visible', + 'class' : 'additionalnndiagramelement' + }, mynode.parentNode); + createSvgElement(NS_HTML, 'div', { + 'id' : ID_PREFIX + ELEMENT_IDS.ANNOTATION + nodeid, + 'class' : 'hiddenlayerfunction hiddendiagramelement additionalnndiagramelement' + }, annotationContainer); + } + + function updateLabels(nodevalues, highlight) { + for (var nodename in nodevalues) { + var values = nodevalues[nodename]; + + if ('bias' in values) { + if (highlight) { + document.getElementById(ID_PREFIX + nodename).classList.add('highlightedlayer'); + } + else { + document.getElementById(ID_PREFIX + nodename).classList.remove('highlightedlayer'); + } + var biasDecoration = values.bias === undefined ? '' : 'b=' + values.bias; + document.getElementById(ID_PREFIX + ELEMENT_IDS.BIAS + nodename).textContent = biasDecoration; + document.getElementById(ID_PREFIX + ELEMENT_IDS.SEPARATOR + nodename).classList.remove('hiddendiagramelement'); + } + if ('value' in values) { + document.getElementById(ID_PREFIX + nodename).classList.add('highlightedlayer'); + document.getElementById(ID_PREFIX + ELEMENT_IDS.NODE_VALUE + nodename).textContent = values.value; + } + } + } + + function clearInputLabels() { + loggerService.debug('[fcnn] Clear input labels'); + + for (var nodeIdx = 0; nodeIdx < architecture[LAYER_IDS.INPUT_LAYER]; nodeIdx++) { + getNNNode(LAYER_IDS.INPUT_LAYER, nodeIdx).classList.remove('highlightedlayer'); + document.getElementById(ID_PREFIX + ELEMENT_IDS.NODE_VALUE + '1_' + nodeIdx).textContent = ''; + } + } + + function updateInputText(inputtext) { + loggerService.debug('[fcnn] Updating input text', inputtext); + + var exampleText = document.getElementById(ID_PREFIX + ELEMENT_IDS.INPUT_TEXT); + exampleText.textContent = inputtext; + exampleText.classList.remove('hiddendiagramelement'); + + var inputDataNode = getNNNode(LAYER_IDS.INPUT_TEXT, 0); + inputDataNode.classList.add('hiddendiagramelement'); + var inputLayerY = parseFloat(inputDataNode.getAttribute('cy')); + var exampleTextY = inputLayerY; + + var exampleTextContainer = document.getElementById(ID_PREFIX + ELEMENT_IDS.INPUT_TEXT_CONTAINER); + exampleTextContainer.setAttributeNS(null, 'y', exampleTextY - (exampleText.clientHeight / 2)); + exampleTextContainer.classList.remove('hiddendiagramelement'); + } + + function updateOutputHtml(outputhtml) { + loggerService.debug('[fcnn] Updating output detail'); + + var exampleText = document.getElementById(ID_PREFIX + ELEMENT_IDS.OUTPUT_LAYER); + + if (outputhtml) { + exampleText.innerHTML = outputhtml; + exampleText.classList.remove('hiddendiagramelement'); + } + else { + exampleText.classList.add('hiddendiagramelement'); + } + } + + + function showAnnotation(nodeid, annotation) { + var annotationId = ID_PREFIX + ELEMENT_IDS.ANNOTATION + nodeid; + var annotationElement = document.getElementById(annotationId); + annotationElement.innerHTML = annotation; + annotationElement.classList.remove('hiddendiagramelement'); + } + function hideAnnotation(nodeid) { + var annotationId = ID_PREFIX + ELEMENT_IDS.ANNOTATION + nodeid; + var annotationElement = document.getElementById(annotationId); + annotationElement.classList.add('hiddendiagramelement'); + } + + function toggleLayerHighlight(layeridx) { + var nodesinlayer = document.getElementsByClassName('nnlayer' + (layeridx % architecture.length)); + for (var i = 0; i < nodesinlayer.length; i++) { + nodesinlayer[i].classList.toggle('highlightedlayer'); + } + } + + function setViewBox(largestLayerIdx) { + loggerService.debug('[fcnn] Setting the view box based on the location of nodes in layer', largestLayerIdx); + + var inputElem = getNNNode(LAYER_IDS.INPUT_TEXT, 0); + var outputElem = document.getElementById(ID_PREFIX + ELEMENT_IDS.OUTPUT_LAYER_CONTAINER); + var topHiddenElem = getNNNode(largestLayerIdx.idx, 0); + var bottomHiddenElem = getNNNode(largestLayerIdx.idx, architecture[largestLayerIdx.idx - 1]); + + var left = parseFloat(inputElem.getAttribute('cx')); + var right = parseFloat(outputElem.getAttribute('x')); + var top = parseFloat(topHiddenElem.getAttribute('cy')); + var bottom = parseFloat(bottomHiddenElem.getAttribute('cy')); + + if (outputElem) { + w = right - left + 550; + h = bottom - top + 400; + + if (h < 500) { + h = 900; + } + } + else { + w = window.innerWidth; + h = window.innerHeight; + } + + + + svg.attr('viewBox', (left - 80) + ' ' + (top - 30) + ' ' + w + ' ' + h); + } + + function removeAnnotations() { + var elems = container.querySelectorAll('.nodedata, .nodevalue, .nodeseparator, .nodeweight, .additionalnndiagramelement'); + for (var i = 0; i < elems.length; i++) { + elems[i].remove(); + } + } + + function setAnnotationsFocus(d) { + var selectedSeparatorId = ID_PREFIX + ELEMENT_IDS.SEPARATOR + d.id; + var selectedBiasId = ID_PREFIX + ELEMENT_IDS.BIAS + d.id; + var selectedValueId = ID_PREFIX + ELEMENT_IDS.NODE_VALUE + d.id; + + var elems = container.querySelectorAll('.nodeseparator'); + for (var i = 0; i < elems.length; i++) { + var o = elems[i]; + var shouldDisplay = (o.id === selectedSeparatorId); + if (shouldDisplay) { + o.classList.remove('hiddendiagramelement'); + } + o.style.opacity = shouldDisplay ? 1 : 0.1; + } + + elems = container.querySelectorAll('.nodedata'); + for (var j = 0; j < elems.length; j++) { + var p = elems[j]; + var shouldDisplay = (p.id === selectedBiasId); + p.style.opacity = shouldDisplay ? 1 : 0.1; + } + + elems = container.querySelectorAll('.nodevalue'); + for (var k = 0; k < elems.length; k++) { + var q = elems[k]; + var shouldDisplay = q.id === selectedValueId || + q.id.startsWith(ID_PREFIX + ELEMENT_IDS.NODE_VALUE + (d.layer - 1) + '_'); + q.style.opacity = shouldDisplay ? 1 : 0.1; + } + } + + function displayWeights(layerIdx, nodeIdx, weights, highlights) { + var prevLayerIdx = layerIdx - 1; + var prevLayerNumNodes = architecture[prevLayerIdx]; + + for (var idx = 0; idx < prevLayerNumNodes; idx++) { + var nodeId = ID_PREFIX + getNodeId(prevLayerIdx, idx); + var pathId = ID_PREFIX + + nodeId + '-' + + ID_PREFIX + layerIdx + '_' + nodeIdx; + var textId = pathId + ELEMENT_IDS.PATH_TEXT; + + var linkElem = document.getElementById(pathId); + if (highlights.path) { + linkElem.classList.add('highlighted'); + } + else { + linkElem.classList.remove('highlighted'); + } + + var labelElem = document.getElementById(textId); + labelElem.textContent = weights[idx]; + if (highlights.label) { + labelElem.classList.add('highlighted'); + } + else { + labelElem.classList.remove('highlighted'); + } + } + } + + function highlightInputText() { + document.getElementById(ID_PREFIX + ELEMENT_IDS.INPUT_TEXT).classList.add('highlightedlayer'); + } + + function highlightHiddenLayerNode(layerIdx, nodeIdx) { + node.style('opacity', function(o) { + if (o.layer === 0) { + return 0; + } + return ((o.layer === layerIdx && o.node_index === nodeIdx) || o.layer == layerIdx - 1) ? 1 : 0.1; + }); + link.style('opacity', function(o) { + return (o.target == ID_PREFIX + layerIdx + '_' + nodeIdx) ? 1 : 0.02; + }); + document.getElementById(ID_PREFIX + ELEMENT_IDS.INPUT_TEXT).style.opacity = 0.1; + + setAnnotationsFocus({ id : layerIdx + '_' + nodeIdx, layer : layerIdx }); + } + + function restoreOpacity(elems) { + for (var i = 0; i < elems.length; i++) { + elems[i].style.opacity = 1; + } + } + function emptyTextContent(elems) { + for (var i = 0; i < elems.length; i++) { + elems[i].textContent = ''; + } + } + function addHiddenClass(elems) { + for (var i = 0; i < elems.length; i++) { + elems[i].classList.add('hiddendiagramelement'); + } + } + function removeAnnotationsFocus() { + restoreOpacity(container.querySelectorAll('.nodeseparator, .nodedata, .nodevalue')); + emptyTextContent(container.querySelectorAll('.nodeweight')); + addHiddenClass(container.querySelectorAll('.inputannotation')); + node.classed('highlightedlayer', false); + var inputTextElement = document.getElementById(ID_PREFIX + ELEMENT_IDS.INPUT_TEXT); + inputTextElement.classList.remove('highlightedlayer'); + inputTextElement.style.opacity = 1; + } + + function decorate() { + addLabels(); + addWeights(); + + if (architecture[0] > 1) { + var inputDataNode = getNNNode(LAYER_IDS.INPUT_TEXT, 0); + inputDataNode.classList.remove('hiddendiagramelement'); + } + } + + function removeValues() { + link.style('opacity', function(o) { return (o.source === ID_PREFIX + '0_0') ? 0.02 : 1; }); + node.style('opacity', function(o) { return (o.layer === 0) ? 0.02 : 1; }); + + clearInputLabels(); + + document.getElementById(ID_PREFIX + ELEMENT_IDS.INPUT_TEXT).classList.add('hiddendiagramelement'); + document.getElementById(ID_PREFIX + ELEMENT_IDS.INPUT_TEXT_CONTAINER).classList.add('hiddendiagramelement'); + + for (var layerIdx = 1; layerIdx < architecture.length; layerIdx++) { + for (var nodeIdx = 0; nodeIdx < architecture[layerIdx]; nodeIdx++) { + document.getElementById(ID_PREFIX + ELEMENT_IDS.NODE_VALUE + layerIdx + '_' + nodeIdx).textContent = ''; + } + } + } + + + function create(arch, spacing) { + architecture = arch; + betweenNodesInLayer = spacing; + + redraw(); + redistribute(); + decorate(); + } + + + + return { + init : init, + create : create, + + updateLabels : updateLabels, + updateInputText : updateInputText, + updateOutputHtml : updateOutputHtml, + + displayWeights : displayWeights, + + clearInputLabels : clearInputLabels, + + showAnnotation : showAnnotation, + hideAnnotation : hideAnnotation, + + highlightHiddenLayerNode : highlightHiddenLayerNode, + + highlightInputText : highlightInputText, + toggleLayerHighlight : toggleLayerHighlight, + + removeValues : removeValues, + + set_focus : set_focus, + remove_focus : remove_focus + }; + } +})(); diff --git a/public/components/describetextmodel/scratch.txt b/public/components/describetextmodel/scratch.txt new file mode 100644 index 000000000..1979a4389 --- /dev/null +++ b/public/components/describetextmodel/scratch.txt @@ -0,0 +1,28 @@ +fcnnVisualisationService.addWeights(); + +// var newvals = { "1_0" : { "value" : 3 }, "1_1" : { "value" : 4 }, "1_2" : { "value" : 8 }, "1_3" : { "value" : 1 }, "1_4" : { "value" : 0.0 }, "1_5" : { "value" : 12 }, "1_6" : { "value" : 78 } }; +// fcnnVisualisationService.updateLabels(newvals); +// newvals = { "4_0" : { "value" : 0.6 }, "4_1" : { "value" : 0.4 } }; +// fcnnVisualisationService.updateLabels(newvals); +// newvals = { "2_0" : { "weight" : 1.3, "bias" : 10 }, "2_1" : { "weight" : 10.4, "bias" : 200 } }; +// fcnnVisualisationService.updateLabels(newvals); +// newvals = { "2_0" : { "value" : 8888 }, "2_3" : { "value" : 7777 } }; +// fcnnVisualisationService.updateLabels(newvals); +// fcnnVisualisationService.updateInputText("Bacon ipsum dolor amet pork chop venison fatback corned beef shoulder boudin swine kevin capicola. Pastrami ground round ribeye, ball tip tri-tip biltong tongue. Tail turkey t-bone venison frankfurter. "); + +fcnnVisualisationService.showAnnotation("1_0", "Number of swear words"); +fcnnVisualisationService.showAnnotation("1_1", "Number of capital letters"); +fcnnVisualisationService.showAnnotation("1_2", "Number of punctuation marks"); +fcnnVisualisationService.showAnnotation("2_4", "" + +"" + +"" + +"" + +"" + +"" + +"" + +"" + +"" + +"" + +"" + +"" + +"
3x100+
10x 10+
17x 1+
999x 12+
10x 67+
3x200+
17x 97+
90x 45+
42x 26+
= 2467
Describe your model!
+
Describe your model! beta
@@ -439,6 +440,7 @@

ng-disabled="submittingDeleteRequest"> {{ (model.status === 'Training' ? 'MODELS.CANCEL' : 'MODELS.DELETE') | translate }} +
Describe your model! beta
diff --git a/public/components/training/training.controller.js b/public/components/training/training.controller.js index 5ba6fbead..f548b193b 100644 --- a/public/components/training/training.controller.js +++ b/public/components/training/training.controller.js @@ -506,6 +506,8 @@ }; function displayWebcamError(err) { + loggerService.error('[ml4ktraining] displaying webcam error', err); + $scope.webcamerror = err; if (err && err.message) { if (err.name === 'NotAllowedError') { @@ -518,6 +520,8 @@ } $scope.onWebcamError = function(err) { + loggerService.error('[ml4ktraining] webcam error', err); + $scope.webcamInitComplete = true; try { @@ -536,16 +540,20 @@ function getWebcamData() { + loggerService.debug('[ml4ktraining] getting webcam data'); + var hiddenCanvas = document.createElement('canvas'); hiddenCanvas.width = $scope.channel.video.width; hiddenCanvas.height = $scope.channel.video.height; + loggerService.debug('[ml4ktraining] writing to hidden canvas'); var ctx = hiddenCanvas.getContext('2d'); ctx.drawImage($scope.channel.video, 0, 0, $scope.channel.video.width, $scope.channel.video.height); return $q(function(resolve, reject) { + loggerService.debug('[ml4ktraining] extracting blob data'); hiddenCanvas.toBlob(function (blob) { resolve(blob); }, 'image/jpeg'); @@ -569,6 +577,7 @@ $scope.training[label].push(placeholder); + loggerService.debug('[ml4ktraining] uploading webcam data'); trainingService.uploadImage($scope.project.id, $scope.userId, vm.profile.tenant, resp, label) .then(function (newitem) { placeholder.isPlaceholder = false; diff --git a/public/languages/ar.json b/public/languages/ar.json index 5ec5b9ef4..179aaa416 100644 --- a/public/languages/ar.json +++ b/public/languages/ar.json @@ -3,6 +3,7 @@ "TITLE": "تعلم الآلة للأطفال", "BACK": "عودة", + "NEXT": "Next", "BACKTOPROJECT": "< العودة إلى المشروع", "BACKTOMODEL": "< العودة إلى نموذج", "ERROR": "خطأ:", @@ -704,6 +705,164 @@ "NUMBERSONLY": "يمكن وصف نماذج تعلم الآلة فقط لمشاريع الأرقام" } }, + "DESCRIBETEXTMODEL": { + "ZOOM": "Use these controls to zoom in on the diagrams", + "ERRORS": { + "TEXTONLY": "Only neural networks for text projects can be described" + }, + "MOREINFO": "for more detail, try searching for:", + "PAGE1": { + "TITLE": "neural networks", + "TEXT1": "The type of machine learning model you trained in this project is called a neural network.", + "TEXT2": "The next few pages will explain how your model was created.", + "TEXT3": "These diagrams aren't an exact description of your model. Your model is larger and more complicated, but these diagrams are easier to explain." + }, + "PAGE2": { + "TITLE": "deep learning", + "TEXT1": "The model is made of nodes, arranged in vertical layers.", + "TEXT2": "Models with a lot of layers are described as deep.", + "TEXT3": "Deep models can give better results, but take longer to train." + }, + "PAGE3": { + "TITLE": "input layer", + "TEXT1": "Let's start with one of the training examples used to create your model.", + "TEXT2": "Your training example is shown as input on the left." + }, + "PAGE4": { + "TITLE": "encoding", + "TEXT1": "To use your training example to train the model, first the text needs to be turned into a series of numbers.", + "TEXT2": "There are lots of ways to do this.", + "TEXT3": "If you build your own machine learning model, you need to choose a way that works well for your particular project." + }, + "PAGE5": { + "TITLE": "bag of words", + "TEXT1": "One way of turning your text into numbers is to make each number a count of how many times a word is included." + }, + "PAGE6": { + "TITLE": "feature extraction", + "TEXT1": "There are other things you can count. Things that are helpful to count depend on the project you are doing, and what you want your model to learn to recognize patterns in.", + "TEXT2": "Counting things is quick and simple, but not as good for projects where the order of words is important." + }, + "PAGE7": { + "TITLE": "word embeddings", + "TEXT1": "If you build your own machine learning model, you need to choose the method for turning text into numbers.", + "TEXT2": "Your model used a more complicated technique that does include the order of words in the text." + }, + "PAGE8": { + "TITLE": "hidden layer", + "TEXT1": "The numbers from the input layer go into sums that calculate values for the nodes in the next layer.", + "TEXT2": "The lines on the diagram show which input values are used to calculate which values in the next layer." + }, + "PAGE9": { + "TITLE": "activation functions", + "TEXT1": "There are lots of different types of calculation you can use. Not every node in the model has to use the same calculation.", + "TEXT2": "If you build your own machine learning model, you need to choose which equations to use for each node.", + "TEXT3": "The functions to use for each node in your model were chosen for you." + }, + "PAGE10": { + "TITLE": "weight", + "TEXT1": "Each line in the diagram has a weight number that can be used in the sum.", + "TEXT2": "Training the model is how we work out the best number to put on each line, as you'll see in a moment." + }, + "PAGE11": { + "TITLE": "bias", + "TEXT1": "Each node in the diagram has a bias number that is used in the sum as well.", + "TEXT2": "Training the model is also how we work out the right bias number, as you'll see in a moment.", + "TEXT3": "Try to work out what you think the value for this node will be." + }, + "PAGE12": { + "TITLE": "activation functions", + "TEXT1": "This is a common function used in neural networks.", + "TEXT2": "Each input value is multiplied by the value for the line that connected it. These are all added together. Then added to the value for the node itself." + }, + "PAGE13": { + "TITLE": "activation functions", + "TEXT1": "Each node has its own bias value.", + "TEXT2": "Each line has its own weight value." + }, + "PAGE14": { + "TITLE": "hidden layers", + "TEXT1": "Each node in the model can use different equations.", + "TEXT2": "If you build your own machine learning model, you need to choose:", + "LIST1": "how many layers to have", + "LIST2": "how many nodes to put in each layer", + "LIST3": "which functions to use for each node" + }, + "PAGE15": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The number of layers, the number of nodes in each layer, and the functions to use for each node in your model were all chosen for you." + }, + "PAGE16": { + "TITLE": "output layer", + "TEXT1": "The final layer gives the machine learning model's prediction.", + "TEXT2": "There is a node for each bucket you added to your training data." + }, + "PAGE17": { + "TITLE": "loss function", + "TEXT1": "The prediction is compared with the correct answer (the training bucket you put this example in).", + "TEXT2": "The difference is described as the error rate, and tells us how well the machine learning model is doing at this stage of the training." + }, + "PAGE18": { + "TITLE": "back propagation", + "TEXT1": "The error rate is used to go backwards through the layers and nudge the numbers for each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error rate a little smaller." + }, + "PAGE19": { + "TITLE": "neural networks", + "TEXT1": "Next, this is all done over again, with another of your training examples." + }, + "PAGE20": { + "TITLE": "encoding", + "TEXT1": "Remember, the first step is turning the example text into numbers.", + "TEXT2": "Counting things that are in the text is an easy way to do it, but there are more complicated ways to do it if the order of words is important.", + "TEXT3": "The method for your model was chosen for you." + }, + "PAGE21": { + "TITLE": "hidden layer", + "TEXT1": "Remember, nodes in the middle of the model represent sums that are done using the input numbers.", + "TEXT2": "Different calculations can be chosen for each node." + }, + "PAGE22": { + "TITLE": "activation functions", + "TEXT1": "Remember, the calculations use numbers from the nodes on the left that are connected to it, as well as the numbers for the lines that connect them." + }, + "PAGE23": { + "TITLE": "activation functions", + "TEXT1": "The calculations also use a bias number for the node itself." + }, + "PAGE24": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The functions to use for each node in your model were chosen for you." + }, + "PAGE25": { + "TITLE": "output layer", + "TEXT1": "Remember, the output layer gives the machine learning model's prediction.", + "TEXT2": "Each node gives you the prediction for one of the buckets that you added to your training data." + }, + "PAGE26": { + "TITLE": "loss function", + "TEXT1": "Remember, results from the output layer are compared with the correct answer, which shows how well the machine learning model is doing." + }, + "PAGE27": { + "TITLE": "back propagation", + "TEXT1": "Remember that the error rate is used to go backwards through the layers and nudge the numbers associated with each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error a little smaller.", + "TEXT3": "This is how training works out the best numbers to use for each of the nodes and lines." + }, + "PAGE28": { + "TITLE": "epochs", + "TEXT1": "One run-through of every training example you collected through the model is called an epoch.", + "TEXT2": "Each time through, the weights for each node are nudged a little more, until hopefully the error rate for predictions are as low as they can be.", + "TEXT3": "If you build your own machine learning model, you need to choose how many epochs you want to run." + }, + "PAGE29": { + "TITLE": "neural networks", + "TEXT1": "I hope this simplified description gives you an idea what happens when you click on the \"Train new machine learning model\" button.", + "TEXT2": "For an explanation of why this process works, try watching \"How Machines Learn\" by CGP Grey." + } + }, "MAKES": { "TITLE": "اصنع شيئًا باستخدام نموذج تعلم الآلة", "SCRATCH2": "قم بعمل مشروع في الإصدار القديم من Scratch", diff --git a/public/languages/cs.json b/public/languages/cs.json index d4d6abad5..f87047c38 100644 --- a/public/languages/cs.json +++ b/public/languages/cs.json @@ -3,6 +3,7 @@ "TITLE": "Strojové učení pro děti", "BACK": "Zpět", + "NEXT": "Next", "BACKTOPROJECT": "< Zpět na projekt", "BACKTOMODEL": "< Back to model", "ERROR": "Chyba:", @@ -704,6 +705,164 @@ "NUMBERSONLY": "Only machine learning models for numbers projects can be described" } }, + "DESCRIBETEXTMODEL": { + "ZOOM": "Use these controls to zoom in on the diagrams", + "ERRORS": { + "TEXTONLY": "Only neural networks for text projects can be described" + }, + "MOREINFO": "for more detail, try searching for:", + "PAGE1": { + "TITLE": "neural networks", + "TEXT1": "The type of machine learning model you trained in this project is called a neural network.", + "TEXT2": "The next few pages will explain how your model was created.", + "TEXT3": "These diagrams aren't an exact description of your model. Your model is larger and more complicated, but these diagrams are easier to explain." + }, + "PAGE2": { + "TITLE": "deep learning", + "TEXT1": "The model is made of nodes, arranged in vertical layers.", + "TEXT2": "Models with a lot of layers are described as deep.", + "TEXT3": "Deep models can give better results, but take longer to train." + }, + "PAGE3": { + "TITLE": "input layer", + "TEXT1": "Let's start with one of the training examples used to create your model.", + "TEXT2": "Your training example is shown as input on the left." + }, + "PAGE4": { + "TITLE": "encoding", + "TEXT1": "To use your training example to train the model, first the text needs to be turned into a series of numbers.", + "TEXT2": "There are lots of ways to do this.", + "TEXT3": "If you build your own machine learning model, you need to choose a way that works well for your particular project." + }, + "PAGE5": { + "TITLE": "bag of words", + "TEXT1": "One way of turning your text into numbers is to make each number a count of how many times a word is included." + }, + "PAGE6": { + "TITLE": "feature extraction", + "TEXT1": "There are other things you can count. Things that are helpful to count depend on the project you are doing, and what you want your model to learn to recognize patterns in.", + "TEXT2": "Counting things is quick and simple, but not as good for projects where the order of words is important." + }, + "PAGE7": { + "TITLE": "word embeddings", + "TEXT1": "If you build your own machine learning model, you need to choose the method for turning text into numbers.", + "TEXT2": "Your model used a more complicated technique that does include the order of words in the text." + }, + "PAGE8": { + "TITLE": "hidden layer", + "TEXT1": "The numbers from the input layer go into sums that calculate values for the nodes in the next layer.", + "TEXT2": "The lines on the diagram show which input values are used to calculate which values in the next layer." + }, + "PAGE9": { + "TITLE": "activation functions", + "TEXT1": "There are lots of different types of calculation you can use. Not every node in the model has to use the same calculation.", + "TEXT2": "If you build your own machine learning model, you need to choose which equations to use for each node.", + "TEXT3": "The functions to use for each node in your model were chosen for you." + }, + "PAGE10": { + "TITLE": "weight", + "TEXT1": "Each line in the diagram has a weight number that can be used in the sum.", + "TEXT2": "Training the model is how we work out the best number to put on each line, as you'll see in a moment." + }, + "PAGE11": { + "TITLE": "bias", + "TEXT1": "Each node in the diagram has a bias number that is used in the sum as well.", + "TEXT2": "Training the model is also how we work out the right bias number, as you'll see in a moment.", + "TEXT3": "Try to work out what you think the value for this node will be." + }, + "PAGE12": { + "TITLE": "activation functions", + "TEXT1": "This is a common function used in neural networks.", + "TEXT2": "Each input value is multiplied by the value for the line that connected it. These are all added together. Then added to the value for the node itself." + }, + "PAGE13": { + "TITLE": "activation functions", + "TEXT1": "Each node has its own bias value.", + "TEXT2": "Each line has its own weight value." + }, + "PAGE14": { + "TITLE": "hidden layers", + "TEXT1": "Each node in the model can use different equations.", + "TEXT2": "If you build your own machine learning model, you need to choose:", + "LIST1": "how many layers to have", + "LIST2": "how many nodes to put in each layer", + "LIST3": "which functions to use for each node" + }, + "PAGE15": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The number of layers, the number of nodes in each layer, and the functions to use for each node in your model were all chosen for you." + }, + "PAGE16": { + "TITLE": "output layer", + "TEXT1": "The final layer gives the machine learning model's prediction.", + "TEXT2": "There is a node for each bucket you added to your training data." + }, + "PAGE17": { + "TITLE": "loss function", + "TEXT1": "The prediction is compared with the correct answer (the training bucket you put this example in).", + "TEXT2": "The difference is described as the error rate, and tells us how well the machine learning model is doing at this stage of the training." + }, + "PAGE18": { + "TITLE": "back propagation", + "TEXT1": "The error rate is used to go backwards through the layers and nudge the numbers for each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error rate a little smaller." + }, + "PAGE19": { + "TITLE": "neural networks", + "TEXT1": "Next, this is all done over again, with another of your training examples." + }, + "PAGE20": { + "TITLE": "encoding", + "TEXT1": "Remember, the first step is turning the example text into numbers.", + "TEXT2": "Counting things that are in the text is an easy way to do it, but there are more complicated ways to do it if the order of words is important.", + "TEXT3": "The method for your model was chosen for you." + }, + "PAGE21": { + "TITLE": "hidden layer", + "TEXT1": "Remember, nodes in the middle of the model represent sums that are done using the input numbers.", + "TEXT2": "Different calculations can be chosen for each node." + }, + "PAGE22": { + "TITLE": "activation functions", + "TEXT1": "Remember, the calculations use numbers from the nodes on the left that are connected to it, as well as the numbers for the lines that connect them." + }, + "PAGE23": { + "TITLE": "activation functions", + "TEXT1": "The calculations also use a bias number for the node itself." + }, + "PAGE24": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The functions to use for each node in your model were chosen for you." + }, + "PAGE25": { + "TITLE": "output layer", + "TEXT1": "Remember, the output layer gives the machine learning model's prediction.", + "TEXT2": "Each node gives you the prediction for one of the buckets that you added to your training data." + }, + "PAGE26": { + "TITLE": "loss function", + "TEXT1": "Remember, results from the output layer are compared with the correct answer, which shows how well the machine learning model is doing." + }, + "PAGE27": { + "TITLE": "back propagation", + "TEXT1": "Remember that the error rate is used to go backwards through the layers and nudge the numbers associated with each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error a little smaller.", + "TEXT3": "This is how training works out the best numbers to use for each of the nodes and lines." + }, + "PAGE28": { + "TITLE": "epochs", + "TEXT1": "One run-through of every training example you collected through the model is called an epoch.", + "TEXT2": "Each time through, the weights for each node are nudged a little more, until hopefully the error rate for predictions are as low as they can be.", + "TEXT3": "If you build your own machine learning model, you need to choose how many epochs you want to run." + }, + "PAGE29": { + "TITLE": "neural networks", + "TEXT1": "I hope this simplified description gives you an idea what happens when you click on the \"Train new machine learning model\" button.", + "TEXT2": "For an explanation of why this process works, try watching \"How Machines Learn\" by CGP Grey." + } + }, "MAKES": { "TITLE": "Make something with your machine learning model", "SCRATCH2": "Make a project in the old version of Scratch", diff --git a/public/languages/cy.json b/public/languages/cy.json index bb3b997b1..b0faa6e27 100644 --- a/public/languages/cy.json +++ b/public/languages/cy.json @@ -3,6 +3,7 @@ "TITLE": "Dysgu Peiriant i Blant", "BACK": "Yn ôl", + "NEXT": "Next", "BACKTOPROJECT": "< Yn ôl i'r prosiect", "BACKTOMODEL": "< Yn ôl i'r model", "ERROR": "Gwall:", @@ -704,6 +705,164 @@ "NUMBERSONLY": "Dim ond modelau dysgu peiriant ar gyfer prosiectau rhifau y gellir eu disgrifio" } }, + "DESCRIBETEXTMODEL": { + "ZOOM": "Use these controls to zoom in on the diagrams", + "ERRORS": { + "TEXTONLY": "Only neural networks for text projects can be described" + }, + "MOREINFO": "for more detail, try searching for:", + "PAGE1": { + "TITLE": "neural networks", + "TEXT1": "The type of machine learning model you trained in this project is called a neural network.", + "TEXT2": "The next few pages will explain how your model was created.", + "TEXT3": "These diagrams aren't an exact description of your model. Your model is larger and more complicated, but these diagrams are easier to explain." + }, + "PAGE2": { + "TITLE": "deep learning", + "TEXT1": "The model is made of nodes, arranged in vertical layers.", + "TEXT2": "Models with a lot of layers are described as deep.", + "TEXT3": "Deep models can give better results, but take longer to train." + }, + "PAGE3": { + "TITLE": "input layer", + "TEXT1": "Let's start with one of the training examples used to create your model.", + "TEXT2": "Your training example is shown as input on the left." + }, + "PAGE4": { + "TITLE": "encoding", + "TEXT1": "To use your training example to train the model, first the text needs to be turned into a series of numbers.", + "TEXT2": "There are lots of ways to do this.", + "TEXT3": "If you build your own machine learning model, you need to choose a way that works well for your particular project." + }, + "PAGE5": { + "TITLE": "bag of words", + "TEXT1": "One way of turning your text into numbers is to make each number a count of how many times a word is included." + }, + "PAGE6": { + "TITLE": "feature extraction", + "TEXT1": "There are other things you can count. Things that are helpful to count depend on the project you are doing, and what you want your model to learn to recognize patterns in.", + "TEXT2": "Counting things is quick and simple, but not as good for projects where the order of words is important." + }, + "PAGE7": { + "TITLE": "word embeddings", + "TEXT1": "If you build your own machine learning model, you need to choose the method for turning text into numbers.", + "TEXT2": "Your model used a more complicated technique that does include the order of words in the text." + }, + "PAGE8": { + "TITLE": "hidden layer", + "TEXT1": "The numbers from the input layer go into sums that calculate values for the nodes in the next layer.", + "TEXT2": "The lines on the diagram show which input values are used to calculate which values in the next layer." + }, + "PAGE9": { + "TITLE": "activation functions", + "TEXT1": "There are lots of different types of calculation you can use. Not every node in the model has to use the same calculation.", + "TEXT2": "If you build your own machine learning model, you need to choose which equations to use for each node.", + "TEXT3": "The functions to use for each node in your model were chosen for you." + }, + "PAGE10": { + "TITLE": "weight", + "TEXT1": "Each line in the diagram has a weight number that can be used in the sum.", + "TEXT2": "Training the model is how we work out the best number to put on each line, as you'll see in a moment." + }, + "PAGE11": { + "TITLE": "bias", + "TEXT1": "Each node in the diagram has a bias number that is used in the sum as well.", + "TEXT2": "Training the model is also how we work out the right bias number, as you'll see in a moment.", + "TEXT3": "Try to work out what you think the value for this node will be." + }, + "PAGE12": { + "TITLE": "activation functions", + "TEXT1": "This is a common function used in neural networks.", + "TEXT2": "Each input value is multiplied by the value for the line that connected it. These are all added together. Then added to the value for the node itself." + }, + "PAGE13": { + "TITLE": "activation functions", + "TEXT1": "Each node has its own bias value.", + "TEXT2": "Each line has its own weight value." + }, + "PAGE14": { + "TITLE": "hidden layers", + "TEXT1": "Each node in the model can use different equations.", + "TEXT2": "If you build your own machine learning model, you need to choose:", + "LIST1": "how many layers to have", + "LIST2": "how many nodes to put in each layer", + "LIST3": "which functions to use for each node" + }, + "PAGE15": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The number of layers, the number of nodes in each layer, and the functions to use for each node in your model were all chosen for you." + }, + "PAGE16": { + "TITLE": "output layer", + "TEXT1": "The final layer gives the machine learning model's prediction.", + "TEXT2": "There is a node for each bucket you added to your training data." + }, + "PAGE17": { + "TITLE": "loss function", + "TEXT1": "The prediction is compared with the correct answer (the training bucket you put this example in).", + "TEXT2": "The difference is described as the error rate, and tells us how well the machine learning model is doing at this stage of the training." + }, + "PAGE18": { + "TITLE": "back propagation", + "TEXT1": "The error rate is used to go backwards through the layers and nudge the numbers for each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error rate a little smaller." + }, + "PAGE19": { + "TITLE": "neural networks", + "TEXT1": "Next, this is all done over again, with another of your training examples." + }, + "PAGE20": { + "TITLE": "encoding", + "TEXT1": "Remember, the first step is turning the example text into numbers.", + "TEXT2": "Counting things that are in the text is an easy way to do it, but there are more complicated ways to do it if the order of words is important.", + "TEXT3": "The method for your model was chosen for you." + }, + "PAGE21": { + "TITLE": "hidden layer", + "TEXT1": "Remember, nodes in the middle of the model represent sums that are done using the input numbers.", + "TEXT2": "Different calculations can be chosen for each node." + }, + "PAGE22": { + "TITLE": "activation functions", + "TEXT1": "Remember, the calculations use numbers from the nodes on the left that are connected to it, as well as the numbers for the lines that connect them." + }, + "PAGE23": { + "TITLE": "activation functions", + "TEXT1": "The calculations also use a bias number for the node itself." + }, + "PAGE24": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The functions to use for each node in your model were chosen for you." + }, + "PAGE25": { + "TITLE": "output layer", + "TEXT1": "Remember, the output layer gives the machine learning model's prediction.", + "TEXT2": "Each node gives you the prediction for one of the buckets that you added to your training data." + }, + "PAGE26": { + "TITLE": "loss function", + "TEXT1": "Remember, results from the output layer are compared with the correct answer, which shows how well the machine learning model is doing." + }, + "PAGE27": { + "TITLE": "back propagation", + "TEXT1": "Remember that the error rate is used to go backwards through the layers and nudge the numbers associated with each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error a little smaller.", + "TEXT3": "This is how training works out the best numbers to use for each of the nodes and lines." + }, + "PAGE28": { + "TITLE": "epochs", + "TEXT1": "One run-through of every training example you collected through the model is called an epoch.", + "TEXT2": "Each time through, the weights for each node are nudged a little more, until hopefully the error rate for predictions are as low as they can be.", + "TEXT3": "If you build your own machine learning model, you need to choose how many epochs you want to run." + }, + "PAGE29": { + "TITLE": "neural networks", + "TEXT1": "I hope this simplified description gives you an idea what happens when you click on the \"Train new machine learning model\" button.", + "TEXT2": "For an explanation of why this process works, try watching \"How Machines Learn\" by CGP Grey." + } + }, "MAKES": { "TITLE": "Creu rywbeth gyda'ch model dysgu peiriant", "SCRATCH2": "Creu brosiect yn yr hen fersiwn o Scratch", diff --git a/public/languages/de.json b/public/languages/de.json index da0bdca8f..3fb49e4c3 100644 --- a/public/languages/de.json +++ b/public/languages/de.json @@ -3,6 +3,7 @@ "TITLE": "Machine Learning for Kids", "BACK": "Zurück", + "NEXT": "Next", "BACKTOPROJECT": "< Zurück zum Projekt", "BACKTOMODEL": "< Zurück zum Modell", "ERROR": "Fehler:", @@ -704,6 +705,164 @@ "NUMBERSONLY": "Only machine learning models for numbers projects can be described" } }, + "DESCRIBETEXTMODEL": { + "ZOOM": "Use these controls to zoom in on the diagrams", + "ERRORS": { + "TEXTONLY": "Only neural networks for text projects can be described" + }, + "MOREINFO": "for more detail, try searching for:", + "PAGE1": { + "TITLE": "neural networks", + "TEXT1": "The type of machine learning model you trained in this project is called a neural network.", + "TEXT2": "The next few pages will explain how your model was created.", + "TEXT3": "These diagrams aren't an exact description of your model. Your model is larger and more complicated, but these diagrams are easier to explain." + }, + "PAGE2": { + "TITLE": "deep learning", + "TEXT1": "The model is made of nodes, arranged in vertical layers.", + "TEXT2": "Models with a lot of layers are described as deep.", + "TEXT3": "Deep models can give better results, but take longer to train." + }, + "PAGE3": { + "TITLE": "input layer", + "TEXT1": "Let's start with one of the training examples used to create your model.", + "TEXT2": "Your training example is shown as input on the left." + }, + "PAGE4": { + "TITLE": "encoding", + "TEXT1": "To use your training example to train the model, first the text needs to be turned into a series of numbers.", + "TEXT2": "There are lots of ways to do this.", + "TEXT3": "If you build your own machine learning model, you need to choose a way that works well for your particular project." + }, + "PAGE5": { + "TITLE": "bag of words", + "TEXT1": "One way of turning your text into numbers is to make each number a count of how many times a word is included." + }, + "PAGE6": { + "TITLE": "feature extraction", + "TEXT1": "There are other things you can count. Things that are helpful to count depend on the project you are doing, and what you want your model to learn to recognize patterns in.", + "TEXT2": "Counting things is quick and simple, but not as good for projects where the order of words is important." + }, + "PAGE7": { + "TITLE": "word embeddings", + "TEXT1": "If you build your own machine learning model, you need to choose the method for turning text into numbers.", + "TEXT2": "Your model used a more complicated technique that does include the order of words in the text." + }, + "PAGE8": { + "TITLE": "hidden layer", + "TEXT1": "The numbers from the input layer go into sums that calculate values for the nodes in the next layer.", + "TEXT2": "The lines on the diagram show which input values are used to calculate which values in the next layer." + }, + "PAGE9": { + "TITLE": "activation functions", + "TEXT1": "There are lots of different types of calculation you can use. Not every node in the model has to use the same calculation.", + "TEXT2": "If you build your own machine learning model, you need to choose which equations to use for each node.", + "TEXT3": "The functions to use for each node in your model were chosen for you." + }, + "PAGE10": { + "TITLE": "weight", + "TEXT1": "Each line in the diagram has a weight number that can be used in the sum.", + "TEXT2": "Training the model is how we work out the best number to put on each line, as you'll see in a moment." + }, + "PAGE11": { + "TITLE": "bias", + "TEXT1": "Each node in the diagram has a bias number that is used in the sum as well.", + "TEXT2": "Training the model is also how we work out the right bias number, as you'll see in a moment.", + "TEXT3": "Try to work out what you think the value for this node will be." + }, + "PAGE12": { + "TITLE": "activation functions", + "TEXT1": "This is a common function used in neural networks.", + "TEXT2": "Each input value is multiplied by the value for the line that connected it. These are all added together. Then added to the value for the node itself." + }, + "PAGE13": { + "TITLE": "activation functions", + "TEXT1": "Each node has its own bias value.", + "TEXT2": "Each line has its own weight value." + }, + "PAGE14": { + "TITLE": "hidden layers", + "TEXT1": "Each node in the model can use different equations.", + "TEXT2": "If you build your own machine learning model, you need to choose:", + "LIST1": "how many layers to have", + "LIST2": "how many nodes to put in each layer", + "LIST3": "which functions to use for each node" + }, + "PAGE15": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The number of layers, the number of nodes in each layer, and the functions to use for each node in your model were all chosen for you." + }, + "PAGE16": { + "TITLE": "output layer", + "TEXT1": "The final layer gives the machine learning model's prediction.", + "TEXT2": "There is a node for each bucket you added to your training data." + }, + "PAGE17": { + "TITLE": "loss function", + "TEXT1": "The prediction is compared with the correct answer (the training bucket you put this example in).", + "TEXT2": "The difference is described as the error rate, and tells us how well the machine learning model is doing at this stage of the training." + }, + "PAGE18": { + "TITLE": "back propagation", + "TEXT1": "The error rate is used to go backwards through the layers and nudge the numbers for each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error rate a little smaller." + }, + "PAGE19": { + "TITLE": "neural networks", + "TEXT1": "Next, this is all done over again, with another of your training examples." + }, + "PAGE20": { + "TITLE": "encoding", + "TEXT1": "Remember, the first step is turning the example text into numbers.", + "TEXT2": "Counting things that are in the text is an easy way to do it, but there are more complicated ways to do it if the order of words is important.", + "TEXT3": "The method for your model was chosen for you." + }, + "PAGE21": { + "TITLE": "hidden layer", + "TEXT1": "Remember, nodes in the middle of the model represent sums that are done using the input numbers.", + "TEXT2": "Different calculations can be chosen for each node." + }, + "PAGE22": { + "TITLE": "activation functions", + "TEXT1": "Remember, the calculations use numbers from the nodes on the left that are connected to it, as well as the numbers for the lines that connect them." + }, + "PAGE23": { + "TITLE": "activation functions", + "TEXT1": "The calculations also use a bias number for the node itself." + }, + "PAGE24": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The functions to use for each node in your model were chosen for you." + }, + "PAGE25": { + "TITLE": "output layer", + "TEXT1": "Remember, the output layer gives the machine learning model's prediction.", + "TEXT2": "Each node gives you the prediction for one of the buckets that you added to your training data." + }, + "PAGE26": { + "TITLE": "loss function", + "TEXT1": "Remember, results from the output layer are compared with the correct answer, which shows how well the machine learning model is doing." + }, + "PAGE27": { + "TITLE": "back propagation", + "TEXT1": "Remember that the error rate is used to go backwards through the layers and nudge the numbers associated with each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error a little smaller.", + "TEXT3": "This is how training works out the best numbers to use for each of the nodes and lines." + }, + "PAGE28": { + "TITLE": "epochs", + "TEXT1": "One run-through of every training example you collected through the model is called an epoch.", + "TEXT2": "Each time through, the weights for each node are nudged a little more, until hopefully the error rate for predictions are as low as they can be.", + "TEXT3": "If you build your own machine learning model, you need to choose how many epochs you want to run." + }, + "PAGE29": { + "TITLE": "neural networks", + "TEXT1": "I hope this simplified description gives you an idea what happens when you click on the \"Train new machine learning model\" button.", + "TEXT2": "For an explanation of why this process works, try watching \"How Machines Learn\" by CGP Grey." + } + }, "MAKES": { "TITLE": "Nutze dein Machine Learning Model", "SCRATCH2": "Erstelle ein Projekt in der alten Scratch Version", diff --git a/public/languages/el.json b/public/languages/el.json index 90ed14c1a..0c9c6a054 100644 --- a/public/languages/el.json +++ b/public/languages/el.json @@ -3,6 +3,7 @@ "TITLE": "Μηχανική μάθηση για παιδιά", "BACK": "Επιστροφή", + "NEXT": "Next", "BACKTOPROJECT": "< Επιστροφή στο έργο", "BACKTOMODEL": "< Επιστροφή στο μοντέλο", "ERROR": "Σφάλμα:", @@ -704,6 +705,164 @@ "NUMBERSONLY": "Μπορούν να περιγραφούν μόνο μοντέλα μηχανικής μάθησης για έργα αναγνώρισης αριθμών" } }, + "DESCRIBETEXTMODEL": { + "ZOOM": "Use these controls to zoom in on the diagrams", + "ERRORS": { + "TEXTONLY": "Only neural networks for text projects can be described" + }, + "MOREINFO": "for more detail, try searching for:", + "PAGE1": { + "TITLE": "neural networks", + "TEXT1": "The type of machine learning model you trained in this project is called a neural network.", + "TEXT2": "The next few pages will explain how your model was created.", + "TEXT3": "These diagrams aren't an exact description of your model. Your model is larger and more complicated, but these diagrams are easier to explain." + }, + "PAGE2": { + "TITLE": "deep learning", + "TEXT1": "The model is made of nodes, arranged in vertical layers.", + "TEXT2": "Models with a lot of layers are described as deep.", + "TEXT3": "Deep models can give better results, but take longer to train." + }, + "PAGE3": { + "TITLE": "input layer", + "TEXT1": "Let's start with one of the training examples used to create your model.", + "TEXT2": "Your training example is shown as input on the left." + }, + "PAGE4": { + "TITLE": "encoding", + "TEXT1": "To use your training example to train the model, first the text needs to be turned into a series of numbers.", + "TEXT2": "There are lots of ways to do this.", + "TEXT3": "If you build your own machine learning model, you need to choose a way that works well for your particular project." + }, + "PAGE5": { + "TITLE": "bag of words", + "TEXT1": "One way of turning your text into numbers is to make each number a count of how many times a word is included." + }, + "PAGE6": { + "TITLE": "feature extraction", + "TEXT1": "There are other things you can count. Things that are helpful to count depend on the project you are doing, and what you want your model to learn to recognize patterns in.", + "TEXT2": "Counting things is quick and simple, but not as good for projects where the order of words is important." + }, + "PAGE7": { + "TITLE": "word embeddings", + "TEXT1": "If you build your own machine learning model, you need to choose the method for turning text into numbers.", + "TEXT2": "Your model used a more complicated technique that does include the order of words in the text." + }, + "PAGE8": { + "TITLE": "hidden layer", + "TEXT1": "The numbers from the input layer go into sums that calculate values for the nodes in the next layer.", + "TEXT2": "The lines on the diagram show which input values are used to calculate which values in the next layer." + }, + "PAGE9": { + "TITLE": "activation functions", + "TEXT1": "There are lots of different types of calculation you can use. Not every node in the model has to use the same calculation.", + "TEXT2": "If you build your own machine learning model, you need to choose which equations to use for each node.", + "TEXT3": "The functions to use for each node in your model were chosen for you." + }, + "PAGE10": { + "TITLE": "weight", + "TEXT1": "Each line in the diagram has a weight number that can be used in the sum.", + "TEXT2": "Training the model is how we work out the best number to put on each line, as you'll see in a moment." + }, + "PAGE11": { + "TITLE": "bias", + "TEXT1": "Each node in the diagram has a bias number that is used in the sum as well.", + "TEXT2": "Training the model is also how we work out the right bias number, as you'll see in a moment.", + "TEXT3": "Try to work out what you think the value for this node will be." + }, + "PAGE12": { + "TITLE": "activation functions", + "TEXT1": "This is a common function used in neural networks.", + "TEXT2": "Each input value is multiplied by the value for the line that connected it. These are all added together. Then added to the value for the node itself." + }, + "PAGE13": { + "TITLE": "activation functions", + "TEXT1": "Each node has its own bias value.", + "TEXT2": "Each line has its own weight value." + }, + "PAGE14": { + "TITLE": "hidden layers", + "TEXT1": "Each node in the model can use different equations.", + "TEXT2": "If you build your own machine learning model, you need to choose:", + "LIST1": "how many layers to have", + "LIST2": "how many nodes to put in each layer", + "LIST3": "which functions to use for each node" + }, + "PAGE15": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The number of layers, the number of nodes in each layer, and the functions to use for each node in your model were all chosen for you." + }, + "PAGE16": { + "TITLE": "output layer", + "TEXT1": "The final layer gives the machine learning model's prediction.", + "TEXT2": "There is a node for each bucket you added to your training data." + }, + "PAGE17": { + "TITLE": "loss function", + "TEXT1": "The prediction is compared with the correct answer (the training bucket you put this example in).", + "TEXT2": "The difference is described as the error rate, and tells us how well the machine learning model is doing at this stage of the training." + }, + "PAGE18": { + "TITLE": "back propagation", + "TEXT1": "The error rate is used to go backwards through the layers and nudge the numbers for each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error rate a little smaller." + }, + "PAGE19": { + "TITLE": "neural networks", + "TEXT1": "Next, this is all done over again, with another of your training examples." + }, + "PAGE20": { + "TITLE": "encoding", + "TEXT1": "Remember, the first step is turning the example text into numbers.", + "TEXT2": "Counting things that are in the text is an easy way to do it, but there are more complicated ways to do it if the order of words is important.", + "TEXT3": "The method for your model was chosen for you." + }, + "PAGE21": { + "TITLE": "hidden layer", + "TEXT1": "Remember, nodes in the middle of the model represent sums that are done using the input numbers.", + "TEXT2": "Different calculations can be chosen for each node." + }, + "PAGE22": { + "TITLE": "activation functions", + "TEXT1": "Remember, the calculations use numbers from the nodes on the left that are connected to it, as well as the numbers for the lines that connect them." + }, + "PAGE23": { + "TITLE": "activation functions", + "TEXT1": "The calculations also use a bias number for the node itself." + }, + "PAGE24": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The functions to use for each node in your model were chosen for you." + }, + "PAGE25": { + "TITLE": "output layer", + "TEXT1": "Remember, the output layer gives the machine learning model's prediction.", + "TEXT2": "Each node gives you the prediction for one of the buckets that you added to your training data." + }, + "PAGE26": { + "TITLE": "loss function", + "TEXT1": "Remember, results from the output layer are compared with the correct answer, which shows how well the machine learning model is doing." + }, + "PAGE27": { + "TITLE": "back propagation", + "TEXT1": "Remember that the error rate is used to go backwards through the layers and nudge the numbers associated with each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error a little smaller.", + "TEXT3": "This is how training works out the best numbers to use for each of the nodes and lines." + }, + "PAGE28": { + "TITLE": "epochs", + "TEXT1": "One run-through of every training example you collected through the model is called an epoch.", + "TEXT2": "Each time through, the weights for each node are nudged a little more, until hopefully the error rate for predictions are as low as they can be.", + "TEXT3": "If you build your own machine learning model, you need to choose how many epochs you want to run." + }, + "PAGE29": { + "TITLE": "neural networks", + "TEXT1": "I hope this simplified description gives you an idea what happens when you click on the \"Train new machine learning model\" button.", + "TEXT2": "For an explanation of why this process works, try watching \"How Machines Learn\" by CGP Grey." + } + }, "MAKES": { "TITLE": "Φτιάξε κάτι με το μοντέλο σου", "SCRATCH2": "Φτιάξε ένα έργο στην παλιά έκδοση του Scratch", diff --git a/public/languages/en.json b/public/languages/en.json index 323203f20..b0ddede54 100644 --- a/public/languages/en.json +++ b/public/languages/en.json @@ -3,6 +3,7 @@ "TITLE": "Machine Learning for Kids", "BACK": "Back", + "NEXT": "Next", "BACKTOPROJECT": "< Back to project", "BACKTOMODEL": "< Back to model", "ERROR": "Error:", @@ -704,6 +705,164 @@ "NUMBERSONLY": "Only machine learning models for numbers projects can be described" } }, + "DESCRIBETEXTMODEL": { + "ZOOM": "Use these controls to zoom in on the diagrams", + "ERRORS": { + "TEXTONLY": "Only neural networks for text projects can be described" + }, + "MOREINFO": "for more detail, try searching for:", + "PAGE1": { + "TITLE": "neural networks", + "TEXT1": "The type of machine learning model you trained in this project is called a neural network.", + "TEXT2": "The next few pages will explain how your model was created.", + "TEXT3": "These diagrams aren't an exact description of your model. Your model is larger and more complicated, but these diagrams are easier to explain." + }, + "PAGE2": { + "TITLE": "deep learning", + "TEXT1": "The model is made of nodes, arranged in vertical layers.", + "TEXT2": "Models with a lot of layers are described as deep.", + "TEXT3": "Deep models can give better results, but take longer to train." + }, + "PAGE3": { + "TITLE": "input layer", + "TEXT1": "Let's start with one of the training examples used to create your model.", + "TEXT2": "Your training example is shown as input on the left." + }, + "PAGE4": { + "TITLE": "encoding", + "TEXT1": "To use your training example to train the model, first the text needs to be turned into a series of numbers.", + "TEXT2": "There are lots of ways to do this.", + "TEXT3": "If you build your own machine learning model, you need to choose a way that works well for your particular project." + }, + "PAGE5": { + "TITLE": "bag of words", + "TEXT1": "One way of turning your text into numbers is to make each number a count of how many times a word is included." + }, + "PAGE6": { + "TITLE": "feature extraction", + "TEXT1": "There are other things you can count. Things that are helpful to count depend on the project you are doing, and what you want your model to learn to recognize patterns in.", + "TEXT2": "Counting things is quick and simple, but not as good for projects where the order of words is important." + }, + "PAGE7": { + "TITLE": "word embeddings", + "TEXT1": "If you build your own machine learning model, you need to choose the method for turning text into numbers.", + "TEXT2": "Your model used a more complicated technique that does include the order of words in the text." + }, + "PAGE8": { + "TITLE": "hidden layer", + "TEXT1": "The numbers from the input layer go into sums that calculate values for the nodes in the next layer.", + "TEXT2": "The lines on the diagram show which input values are used to calculate which values in the next layer." + }, + "PAGE9": { + "TITLE": "activation functions", + "TEXT1": "There are lots of different types of calculation you can use. Not every node in the model has to use the same calculation.", + "TEXT2": "If you build your own machine learning model, you need to choose which equations to use for each node.", + "TEXT3": "The functions to use for each node in your model were chosen for you." + }, + "PAGE10": { + "TITLE": "weight", + "TEXT1": "Each line in the diagram has a weight number that can be used in the sum.", + "TEXT2": "Training the model is how we work out the best number to put on each line, as you'll see in a moment." + }, + "PAGE11": { + "TITLE": "bias", + "TEXT1": "Each node in the diagram has a bias number that is used in the sum as well.", + "TEXT2": "Training the model is also how we work out the right bias number, as you'll see in a moment.", + "TEXT3": "Try to work out what you think the value for this node will be." + }, + "PAGE12": { + "TITLE": "activation functions", + "TEXT1": "This is a common function used in neural networks.", + "TEXT2": "Each input value is multiplied by the value for the line that connected it. These are all added together. Then added to the value for the node itself." + }, + "PAGE13": { + "TITLE": "activation functions", + "TEXT1": "Each node has its own bias value.", + "TEXT2": "Each line has its own weight value." + }, + "PAGE14": { + "TITLE": "hidden layers", + "TEXT1": "Each node in the model can use different equations.", + "TEXT2": "If you build your own machine learning model, you need to choose:", + "LIST1": "how many layers to have", + "LIST2": "how many nodes to put in each layer", + "LIST3": "which functions to use for each node" + }, + "PAGE15": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The number of layers, the number of nodes in each layer, and the functions to use for each node in your model were all chosen for you." + }, + "PAGE16": { + "TITLE": "output layer", + "TEXT1": "The final layer gives the machine learning model's prediction.", + "TEXT2": "There is a node for each bucket you added to your training data." + }, + "PAGE17": { + "TITLE": "loss function", + "TEXT1": "The prediction is compared with the correct answer (the training bucket you put this example in).", + "TEXT2": "The difference is described as the error rate, and tells us how well the machine learning model is doing at this stage of the training." + }, + "PAGE18": { + "TITLE": "back propagation", + "TEXT1": "The error rate is used to go backwards through the layers and nudge the numbers for each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error rate a little smaller." + }, + "PAGE19": { + "TITLE": "neural networks", + "TEXT1": "Next, this is all done over again, with another of your training examples." + }, + "PAGE20": { + "TITLE": "encoding", + "TEXT1": "Remember, the first step is turning the example text into numbers.", + "TEXT2": "Counting things that are in the text is an easy way to do it, but there are more complicated ways to do it if the order of words is important.", + "TEXT3": "The method for your model was chosen for you." + }, + "PAGE21": { + "TITLE": "hidden layer", + "TEXT1": "Remember, nodes in the middle of the model represent sums that are done using the input numbers.", + "TEXT2": "Different calculations can be chosen for each node." + }, + "PAGE22": { + "TITLE": "activation functions", + "TEXT1": "Remember, the calculations use numbers from the nodes on the left that are connected to it, as well as the numbers for the lines that connect them." + }, + "PAGE23": { + "TITLE": "activation functions", + "TEXT1": "The calculations also use a bias number for the node itself." + }, + "PAGE24": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The functions to use for each node in your model were chosen for you." + }, + "PAGE25": { + "TITLE": "output layer", + "TEXT1": "Remember, the output layer gives the machine learning model's prediction.", + "TEXT2": "Each node gives you the prediction for one of the buckets that you added to your training data." + }, + "PAGE26": { + "TITLE": "loss function", + "TEXT1": "Remember, results from the output layer are compared with the correct answer, which shows how well the machine learning model is doing." + }, + "PAGE27": { + "TITLE": "back propagation", + "TEXT1": "Remember that the error rate is used to go backwards through the layers and nudge the numbers associated with each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error a little smaller.", + "TEXT3": "This is how training works out the best numbers to use for each of the nodes and lines." + }, + "PAGE28": { + "TITLE": "epochs", + "TEXT1": "One run-through of every training example you collected through the model is called an epoch.", + "TEXT2": "Each time through, the weights for each node are nudged a little more, until hopefully the error rate for predictions are as low as they can be.", + "TEXT3": "If you build your own machine learning model, you need to choose how many epochs you want to run." + }, + "PAGE29": { + "TITLE": "neural networks", + "TEXT1": "I hope this simplified description gives you an idea what happens when you click on the \"Train new machine learning model\" button.", + "TEXT2": "For an explanation of why this process works, try watching \"How Machines Learn\" by CGP Grey." + } + }, "MAKES": { "TITLE": "Make something with your machine learning model", "SCRATCH2": "Make a project in the old version of Scratch", diff --git a/public/languages/es.json b/public/languages/es.json index ea36395cf..051bdc787 100644 --- a/public/languages/es.json +++ b/public/languages/es.json @@ -3,6 +3,7 @@ "TITLE": "Aprendizaje Automático para Niños", "BACK": "Volver", + "NEXT": "Next", "BACKTOPROJECT": "< Volver al proyecto", "BACKTOMODEL": "< Back to model", "ERROR": "Error:", @@ -704,6 +705,164 @@ "NUMBERSONLY": "Only machine learning models for numbers projects can be described" } }, + "DESCRIBETEXTMODEL": { + "ZOOM": "Use these controls to zoom in on the diagrams", + "ERRORS": { + "TEXTONLY": "Only neural networks for text projects can be described" + }, + "MOREINFO": "for more detail, try searching for:", + "PAGE1": { + "TITLE": "neural networks", + "TEXT1": "The type of machine learning model you trained in this project is called a neural network.", + "TEXT2": "The next few pages will explain how your model was created.", + "TEXT3": "These diagrams aren't an exact description of your model. Your model is larger and more complicated, but these diagrams are easier to explain." + }, + "PAGE2": { + "TITLE": "deep learning", + "TEXT1": "The model is made of nodes, arranged in vertical layers.", + "TEXT2": "Models with a lot of layers are described as deep.", + "TEXT3": "Deep models can give better results, but take longer to train." + }, + "PAGE3": { + "TITLE": "input layer", + "TEXT1": "Let's start with one of the training examples used to create your model.", + "TEXT2": "Your training example is shown as input on the left." + }, + "PAGE4": { + "TITLE": "encoding", + "TEXT1": "To use your training example to train the model, first the text needs to be turned into a series of numbers.", + "TEXT2": "There are lots of ways to do this.", + "TEXT3": "If you build your own machine learning model, you need to choose a way that works well for your particular project." + }, + "PAGE5": { + "TITLE": "bag of words", + "TEXT1": "One way of turning your text into numbers is to make each number a count of how many times a word is included." + }, + "PAGE6": { + "TITLE": "feature extraction", + "TEXT1": "There are other things you can count. Things that are helpful to count depend on the project you are doing, and what you want your model to learn to recognize patterns in.", + "TEXT2": "Counting things is quick and simple, but not as good for projects where the order of words is important." + }, + "PAGE7": { + "TITLE": "word embeddings", + "TEXT1": "If you build your own machine learning model, you need to choose the method for turning text into numbers.", + "TEXT2": "Your model used a more complicated technique that does include the order of words in the text." + }, + "PAGE8": { + "TITLE": "hidden layer", + "TEXT1": "The numbers from the input layer go into sums that calculate values for the nodes in the next layer.", + "TEXT2": "The lines on the diagram show which input values are used to calculate which values in the next layer." + }, + "PAGE9": { + "TITLE": "activation functions", + "TEXT1": "There are lots of different types of calculation you can use. Not every node in the model has to use the same calculation.", + "TEXT2": "If you build your own machine learning model, you need to choose which equations to use for each node.", + "TEXT3": "The functions to use for each node in your model were chosen for you." + }, + "PAGE10": { + "TITLE": "weight", + "TEXT1": "Each line in the diagram has a weight number that can be used in the sum.", + "TEXT2": "Training the model is how we work out the best number to put on each line, as you'll see in a moment." + }, + "PAGE11": { + "TITLE": "bias", + "TEXT1": "Each node in the diagram has a bias number that is used in the sum as well.", + "TEXT2": "Training the model is also how we work out the right bias number, as you'll see in a moment.", + "TEXT3": "Try to work out what you think the value for this node will be." + }, + "PAGE12": { + "TITLE": "activation functions", + "TEXT1": "This is a common function used in neural networks.", + "TEXT2": "Each input value is multiplied by the value for the line that connected it. These are all added together. Then added to the value for the node itself." + }, + "PAGE13": { + "TITLE": "activation functions", + "TEXT1": "Each node has its own bias value.", + "TEXT2": "Each line has its own weight value." + }, + "PAGE14": { + "TITLE": "hidden layers", + "TEXT1": "Each node in the model can use different equations.", + "TEXT2": "If you build your own machine learning model, you need to choose:", + "LIST1": "how many layers to have", + "LIST2": "how many nodes to put in each layer", + "LIST3": "which functions to use for each node" + }, + "PAGE15": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The number of layers, the number of nodes in each layer, and the functions to use for each node in your model were all chosen for you." + }, + "PAGE16": { + "TITLE": "output layer", + "TEXT1": "The final layer gives the machine learning model's prediction.", + "TEXT2": "There is a node for each bucket you added to your training data." + }, + "PAGE17": { + "TITLE": "loss function", + "TEXT1": "The prediction is compared with the correct answer (the training bucket you put this example in).", + "TEXT2": "The difference is described as the error rate, and tells us how well the machine learning model is doing at this stage of the training." + }, + "PAGE18": { + "TITLE": "back propagation", + "TEXT1": "The error rate is used to go backwards through the layers and nudge the numbers for each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error rate a little smaller." + }, + "PAGE19": { + "TITLE": "neural networks", + "TEXT1": "Next, this is all done over again, with another of your training examples." + }, + "PAGE20": { + "TITLE": "encoding", + "TEXT1": "Remember, the first step is turning the example text into numbers.", + "TEXT2": "Counting things that are in the text is an easy way to do it, but there are more complicated ways to do it if the order of words is important.", + "TEXT3": "The method for your model was chosen for you." + }, + "PAGE21": { + "TITLE": "hidden layer", + "TEXT1": "Remember, nodes in the middle of the model represent sums that are done using the input numbers.", + "TEXT2": "Different calculations can be chosen for each node." + }, + "PAGE22": { + "TITLE": "activation functions", + "TEXT1": "Remember, the calculations use numbers from the nodes on the left that are connected to it, as well as the numbers for the lines that connect them." + }, + "PAGE23": { + "TITLE": "activation functions", + "TEXT1": "The calculations also use a bias number for the node itself." + }, + "PAGE24": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The functions to use for each node in your model were chosen for you." + }, + "PAGE25": { + "TITLE": "output layer", + "TEXT1": "Remember, the output layer gives the machine learning model's prediction.", + "TEXT2": "Each node gives you the prediction for one of the buckets that you added to your training data." + }, + "PAGE26": { + "TITLE": "loss function", + "TEXT1": "Remember, results from the output layer are compared with the correct answer, which shows how well the machine learning model is doing." + }, + "PAGE27": { + "TITLE": "back propagation", + "TEXT1": "Remember that the error rate is used to go backwards through the layers and nudge the numbers associated with each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error a little smaller.", + "TEXT3": "This is how training works out the best numbers to use for each of the nodes and lines." + }, + "PAGE28": { + "TITLE": "epochs", + "TEXT1": "One run-through of every training example you collected through the model is called an epoch.", + "TEXT2": "Each time through, the weights for each node are nudged a little more, until hopefully the error rate for predictions are as low as they can be.", + "TEXT3": "If you build your own machine learning model, you need to choose how many epochs you want to run." + }, + "PAGE29": { + "TITLE": "neural networks", + "TEXT1": "I hope this simplified description gives you an idea what happens when you click on the \"Train new machine learning model\" button.", + "TEXT2": "For an explanation of why this process works, try watching \"How Machines Learn\" by CGP Grey." + } + }, "MAKES": { "TITLE": "Usa tu modelo de aprendizaje automático para crear algo", "SCRATCH2": "Crea un Proyecto con la version antigua de Scratch", diff --git a/public/languages/fr.json b/public/languages/fr.json index a39b7e6c8..48ad34557 100644 --- a/public/languages/fr.json +++ b/public/languages/fr.json @@ -3,6 +3,7 @@ "TITLE": "Machine learning for kids", "BACK": "Retour", + "NEXT": "Next", "BACKTOPROJECT": "< Revenir au projet", "BACKTOMODEL": "< Revenir au modèle", "ERROR": "Erreur :", @@ -704,6 +705,164 @@ "NUMBERSONLY": "Seuls les modèles d'apprentissage machine pour les projets sur les nombres peuvent être décrits" } }, + "DESCRIBETEXTMODEL": { + "ZOOM": "Use these controls to zoom in on the diagrams", + "ERRORS": { + "TEXTONLY": "Only neural networks for text projects can be described" + }, + "MOREINFO": "for more detail, try searching for:", + "PAGE1": { + "TITLE": "neural networks", + "TEXT1": "The type of machine learning model you trained in this project is called a neural network.", + "TEXT2": "The next few pages will explain how your model was created.", + "TEXT3": "These diagrams aren't an exact description of your model. Your model is larger and more complicated, but these diagrams are easier to explain." + }, + "PAGE2": { + "TITLE": "deep learning", + "TEXT1": "The model is made of nodes, arranged in vertical layers.", + "TEXT2": "Models with a lot of layers are described as deep.", + "TEXT3": "Deep models can give better results, but take longer to train." + }, + "PAGE3": { + "TITLE": "input layer", + "TEXT1": "Let's start with one of the training examples used to create your model.", + "TEXT2": "Your training example is shown as input on the left." + }, + "PAGE4": { + "TITLE": "encoding", + "TEXT1": "To use your training example to train the model, first the text needs to be turned into a series of numbers.", + "TEXT2": "There are lots of ways to do this.", + "TEXT3": "If you build your own machine learning model, you need to choose a way that works well for your particular project." + }, + "PAGE5": { + "TITLE": "bag of words", + "TEXT1": "One way of turning your text into numbers is to make each number a count of how many times a word is included." + }, + "PAGE6": { + "TITLE": "feature extraction", + "TEXT1": "There are other things you can count. Things that are helpful to count depend on the project you are doing, and what you want your model to learn to recognize patterns in.", + "TEXT2": "Counting things is quick and simple, but not as good for projects where the order of words is important." + }, + "PAGE7": { + "TITLE": "word embeddings", + "TEXT1": "If you build your own machine learning model, you need to choose the method for turning text into numbers.", + "TEXT2": "Your model used a more complicated technique that does include the order of words in the text." + }, + "PAGE8": { + "TITLE": "hidden layer", + "TEXT1": "The numbers from the input layer go into sums that calculate values for the nodes in the next layer.", + "TEXT2": "The lines on the diagram show which input values are used to calculate which values in the next layer." + }, + "PAGE9": { + "TITLE": "activation functions", + "TEXT1": "There are lots of different types of calculation you can use. Not every node in the model has to use the same calculation.", + "TEXT2": "If you build your own machine learning model, you need to choose which equations to use for each node.", + "TEXT3": "The functions to use for each node in your model were chosen for you." + }, + "PAGE10": { + "TITLE": "weight", + "TEXT1": "Each line in the diagram has a weight number that can be used in the sum.", + "TEXT2": "Training the model is how we work out the best number to put on each line, as you'll see in a moment." + }, + "PAGE11": { + "TITLE": "bias", + "TEXT1": "Each node in the diagram has a bias number that is used in the sum as well.", + "TEXT2": "Training the model is also how we work out the right bias number, as you'll see in a moment.", + "TEXT3": "Try to work out what you think the value for this node will be." + }, + "PAGE12": { + "TITLE": "activation functions", + "TEXT1": "This is a common function used in neural networks.", + "TEXT2": "Each input value is multiplied by the value for the line that connected it. These are all added together. Then added to the value for the node itself." + }, + "PAGE13": { + "TITLE": "activation functions", + "TEXT1": "Each node has its own bias value.", + "TEXT2": "Each line has its own weight value." + }, + "PAGE14": { + "TITLE": "hidden layers", + "TEXT1": "Each node in the model can use different equations.", + "TEXT2": "If you build your own machine learning model, you need to choose:", + "LIST1": "how many layers to have", + "LIST2": "how many nodes to put in each layer", + "LIST3": "which functions to use for each node" + }, + "PAGE15": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The number of layers, the number of nodes in each layer, and the functions to use for each node in your model were all chosen for you." + }, + "PAGE16": { + "TITLE": "output layer", + "TEXT1": "The final layer gives the machine learning model's prediction.", + "TEXT2": "There is a node for each bucket you added to your training data." + }, + "PAGE17": { + "TITLE": "loss function", + "TEXT1": "The prediction is compared with the correct answer (the training bucket you put this example in).", + "TEXT2": "The difference is described as the error rate, and tells us how well the machine learning model is doing at this stage of the training." + }, + "PAGE18": { + "TITLE": "back propagation", + "TEXT1": "The error rate is used to go backwards through the layers and nudge the numbers for each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error rate a little smaller." + }, + "PAGE19": { + "TITLE": "neural networks", + "TEXT1": "Next, this is all done over again, with another of your training examples." + }, + "PAGE20": { + "TITLE": "encoding", + "TEXT1": "Remember, the first step is turning the example text into numbers.", + "TEXT2": "Counting things that are in the text is an easy way to do it, but there are more complicated ways to do it if the order of words is important.", + "TEXT3": "The method for your model was chosen for you." + }, + "PAGE21": { + "TITLE": "hidden layer", + "TEXT1": "Remember, nodes in the middle of the model represent sums that are done using the input numbers.", + "TEXT2": "Different calculations can be chosen for each node." + }, + "PAGE22": { + "TITLE": "activation functions", + "TEXT1": "Remember, the calculations use numbers from the nodes on the left that are connected to it, as well as the numbers for the lines that connect them." + }, + "PAGE23": { + "TITLE": "activation functions", + "TEXT1": "The calculations also use a bias number for the node itself." + }, + "PAGE24": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The functions to use for each node in your model were chosen for you." + }, + "PAGE25": { + "TITLE": "output layer", + "TEXT1": "Remember, the output layer gives the machine learning model's prediction.", + "TEXT2": "Each node gives you the prediction for one of the buckets that you added to your training data." + }, + "PAGE26": { + "TITLE": "loss function", + "TEXT1": "Remember, results from the output layer are compared with the correct answer, which shows how well the machine learning model is doing." + }, + "PAGE27": { + "TITLE": "back propagation", + "TEXT1": "Remember that the error rate is used to go backwards through the layers and nudge the numbers associated with each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error a little smaller.", + "TEXT3": "This is how training works out the best numbers to use for each of the nodes and lines." + }, + "PAGE28": { + "TITLE": "epochs", + "TEXT1": "One run-through of every training example you collected through the model is called an epoch.", + "TEXT2": "Each time through, the weights for each node are nudged a little more, until hopefully the error rate for predictions are as low as they can be.", + "TEXT3": "If you build your own machine learning model, you need to choose how many epochs you want to run." + }, + "PAGE29": { + "TITLE": "neural networks", + "TEXT1": "I hope this simplified description gives you an idea what happens when you click on the \"Train new machine learning model\" button.", + "TEXT2": "For an explanation of why this process works, try watching \"How Machines Learn\" by CGP Grey." + } + }, "MAKES": { "TITLE": "Faites quelque chose avec votre modèle d'apprentissage machine", "SCRATCH2": "Créer un projet dans l'ancienne version de Scratch", diff --git a/public/languages/hr.json b/public/languages/hr.json index df1ff56c8..0d0f3596c 100644 --- a/public/languages/hr.json +++ b/public/languages/hr.json @@ -3,6 +3,7 @@ "TITLE": "Strojno učenje za djecu", "BACK": "Natrag", + "NEXT": "Next", "BACKTOPROJECT": "< Povratak u projekt", "BACKTOMODEL": "< Povratak u model", "ERROR": "Greška:", @@ -704,6 +705,164 @@ "NUMBERSONLY": "Only machine learning models for numbers projects can be described" } }, + "DESCRIBETEXTMODEL": { + "ZOOM": "Use these controls to zoom in on the diagrams", + "ERRORS": { + "TEXTONLY": "Only neural networks for text projects can be described" + }, + "MOREINFO": "for more detail, try searching for:", + "PAGE1": { + "TITLE": "neural networks", + "TEXT1": "The type of machine learning model you trained in this project is called a neural network.", + "TEXT2": "The next few pages will explain how your model was created.", + "TEXT3": "These diagrams aren't an exact description of your model. Your model is larger and more complicated, but these diagrams are easier to explain." + }, + "PAGE2": { + "TITLE": "deep learning", + "TEXT1": "The model is made of nodes, arranged in vertical layers.", + "TEXT2": "Models with a lot of layers are described as deep.", + "TEXT3": "Deep models can give better results, but take longer to train." + }, + "PAGE3": { + "TITLE": "input layer", + "TEXT1": "Let's start with one of the training examples used to create your model.", + "TEXT2": "Your training example is shown as input on the left." + }, + "PAGE4": { + "TITLE": "encoding", + "TEXT1": "To use your training example to train the model, first the text needs to be turned into a series of numbers.", + "TEXT2": "There are lots of ways to do this.", + "TEXT3": "If you build your own machine learning model, you need to choose a way that works well for your particular project." + }, + "PAGE5": { + "TITLE": "bag of words", + "TEXT1": "One way of turning your text into numbers is to make each number a count of how many times a word is included." + }, + "PAGE6": { + "TITLE": "feature extraction", + "TEXT1": "There are other things you can count. Things that are helpful to count depend on the project you are doing, and what you want your model to learn to recognize patterns in.", + "TEXT2": "Counting things is quick and simple, but not as good for projects where the order of words is important." + }, + "PAGE7": { + "TITLE": "word embeddings", + "TEXT1": "If you build your own machine learning model, you need to choose the method for turning text into numbers.", + "TEXT2": "Your model used a more complicated technique that does include the order of words in the text." + }, + "PAGE8": { + "TITLE": "hidden layer", + "TEXT1": "The numbers from the input layer go into sums that calculate values for the nodes in the next layer.", + "TEXT2": "The lines on the diagram show which input values are used to calculate which values in the next layer." + }, + "PAGE9": { + "TITLE": "activation functions", + "TEXT1": "There are lots of different types of calculation you can use. Not every node in the model has to use the same calculation.", + "TEXT2": "If you build your own machine learning model, you need to choose which equations to use for each node.", + "TEXT3": "The functions to use for each node in your model were chosen for you." + }, + "PAGE10": { + "TITLE": "weight", + "TEXT1": "Each line in the diagram has a weight number that can be used in the sum.", + "TEXT2": "Training the model is how we work out the best number to put on each line, as you'll see in a moment." + }, + "PAGE11": { + "TITLE": "bias", + "TEXT1": "Each node in the diagram has a bias number that is used in the sum as well.", + "TEXT2": "Training the model is also how we work out the right bias number, as you'll see in a moment.", + "TEXT3": "Try to work out what you think the value for this node will be." + }, + "PAGE12": { + "TITLE": "activation functions", + "TEXT1": "This is a common function used in neural networks.", + "TEXT2": "Each input value is multiplied by the value for the line that connected it. These are all added together. Then added to the value for the node itself." + }, + "PAGE13": { + "TITLE": "activation functions", + "TEXT1": "Each node has its own bias value.", + "TEXT2": "Each line has its own weight value." + }, + "PAGE14": { + "TITLE": "hidden layers", + "TEXT1": "Each node in the model can use different equations.", + "TEXT2": "If you build your own machine learning model, you need to choose:", + "LIST1": "how many layers to have", + "LIST2": "how many nodes to put in each layer", + "LIST3": "which functions to use for each node" + }, + "PAGE15": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The number of layers, the number of nodes in each layer, and the functions to use for each node in your model were all chosen for you." + }, + "PAGE16": { + "TITLE": "output layer", + "TEXT1": "The final layer gives the machine learning model's prediction.", + "TEXT2": "There is a node for each bucket you added to your training data." + }, + "PAGE17": { + "TITLE": "loss function", + "TEXT1": "The prediction is compared with the correct answer (the training bucket you put this example in).", + "TEXT2": "The difference is described as the error rate, and tells us how well the machine learning model is doing at this stage of the training." + }, + "PAGE18": { + "TITLE": "back propagation", + "TEXT1": "The error rate is used to go backwards through the layers and nudge the numbers for each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error rate a little smaller." + }, + "PAGE19": { + "TITLE": "neural networks", + "TEXT1": "Next, this is all done over again, with another of your training examples." + }, + "PAGE20": { + "TITLE": "encoding", + "TEXT1": "Remember, the first step is turning the example text into numbers.", + "TEXT2": "Counting things that are in the text is an easy way to do it, but there are more complicated ways to do it if the order of words is important.", + "TEXT3": "The method for your model was chosen for you." + }, + "PAGE21": { + "TITLE": "hidden layer", + "TEXT1": "Remember, nodes in the middle of the model represent sums that are done using the input numbers.", + "TEXT2": "Different calculations can be chosen for each node." + }, + "PAGE22": { + "TITLE": "activation functions", + "TEXT1": "Remember, the calculations use numbers from the nodes on the left that are connected to it, as well as the numbers for the lines that connect them." + }, + "PAGE23": { + "TITLE": "activation functions", + "TEXT1": "The calculations also use a bias number for the node itself." + }, + "PAGE24": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The functions to use for each node in your model were chosen for you." + }, + "PAGE25": { + "TITLE": "output layer", + "TEXT1": "Remember, the output layer gives the machine learning model's prediction.", + "TEXT2": "Each node gives you the prediction for one of the buckets that you added to your training data." + }, + "PAGE26": { + "TITLE": "loss function", + "TEXT1": "Remember, results from the output layer are compared with the correct answer, which shows how well the machine learning model is doing." + }, + "PAGE27": { + "TITLE": "back propagation", + "TEXT1": "Remember that the error rate is used to go backwards through the layers and nudge the numbers associated with each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error a little smaller.", + "TEXT3": "This is how training works out the best numbers to use for each of the nodes and lines." + }, + "PAGE28": { + "TITLE": "epochs", + "TEXT1": "One run-through of every training example you collected through the model is called an epoch.", + "TEXT2": "Each time through, the weights for each node are nudged a little more, until hopefully the error rate for predictions are as low as they can be.", + "TEXT3": "If you build your own machine learning model, you need to choose how many epochs you want to run." + }, + "PAGE29": { + "TITLE": "neural networks", + "TEXT1": "I hope this simplified description gives you an idea what happens when you click on the \"Train new machine learning model\" button.", + "TEXT2": "For an explanation of why this process works, try watching \"How Machines Learn\" by CGP Grey." + } + }, "MAKES": { "TITLE": "Make something with your machine learning model", "SCRATCH2": "Make a project in the old version of Scratch", diff --git a/public/languages/it.json b/public/languages/it.json index 1d0aeb969..9047316d0 100644 --- a/public/languages/it.json +++ b/public/languages/it.json @@ -3,6 +3,7 @@ "TITLE": "Machine Learning per bambini", "BACK": "Indietro", + "NEXT": "Next", "BACKTOPROJECT": "< Ritorna ai progetti", "BACKTOMODEL": "< Back to model", "ERROR": "Errore:", @@ -704,6 +705,164 @@ "NUMBERSONLY": "Only machine learning models for numbers projects can be described" } }, + "DESCRIBETEXTMODEL": { + "ZOOM": "Use these controls to zoom in on the diagrams", + "ERRORS": { + "TEXTONLY": "Only neural networks for text projects can be described" + }, + "MOREINFO": "for more detail, try searching for:", + "PAGE1": { + "TITLE": "neural networks", + "TEXT1": "The type of machine learning model you trained in this project is called a neural network.", + "TEXT2": "The next few pages will explain how your model was created.", + "TEXT3": "These diagrams aren't an exact description of your model. Your model is larger and more complicated, but these diagrams are easier to explain." + }, + "PAGE2": { + "TITLE": "deep learning", + "TEXT1": "The model is made of nodes, arranged in vertical layers.", + "TEXT2": "Models with a lot of layers are described as deep.", + "TEXT3": "Deep models can give better results, but take longer to train." + }, + "PAGE3": { + "TITLE": "input layer", + "TEXT1": "Let's start with one of the training examples used to create your model.", + "TEXT2": "Your training example is shown as input on the left." + }, + "PAGE4": { + "TITLE": "encoding", + "TEXT1": "To use your training example to train the model, first the text needs to be turned into a series of numbers.", + "TEXT2": "There are lots of ways to do this.", + "TEXT3": "If you build your own machine learning model, you need to choose a way that works well for your particular project." + }, + "PAGE5": { + "TITLE": "bag of words", + "TEXT1": "One way of turning your text into numbers is to make each number a count of how many times a word is included." + }, + "PAGE6": { + "TITLE": "feature extraction", + "TEXT1": "There are other things you can count. Things that are helpful to count depend on the project you are doing, and what you want your model to learn to recognize patterns in.", + "TEXT2": "Counting things is quick and simple, but not as good for projects where the order of words is important." + }, + "PAGE7": { + "TITLE": "word embeddings", + "TEXT1": "If you build your own machine learning model, you need to choose the method for turning text into numbers.", + "TEXT2": "Your model used a more complicated technique that does include the order of words in the text." + }, + "PAGE8": { + "TITLE": "hidden layer", + "TEXT1": "The numbers from the input layer go into sums that calculate values for the nodes in the next layer.", + "TEXT2": "The lines on the diagram show which input values are used to calculate which values in the next layer." + }, + "PAGE9": { + "TITLE": "activation functions", + "TEXT1": "There are lots of different types of calculation you can use. Not every node in the model has to use the same calculation.", + "TEXT2": "If you build your own machine learning model, you need to choose which equations to use for each node.", + "TEXT3": "The functions to use for each node in your model were chosen for you." + }, + "PAGE10": { + "TITLE": "weight", + "TEXT1": "Each line in the diagram has a weight number that can be used in the sum.", + "TEXT2": "Training the model is how we work out the best number to put on each line, as you'll see in a moment." + }, + "PAGE11": { + "TITLE": "bias", + "TEXT1": "Each node in the diagram has a bias number that is used in the sum as well.", + "TEXT2": "Training the model is also how we work out the right bias number, as you'll see in a moment.", + "TEXT3": "Try to work out what you think the value for this node will be." + }, + "PAGE12": { + "TITLE": "activation functions", + "TEXT1": "This is a common function used in neural networks.", + "TEXT2": "Each input value is multiplied by the value for the line that connected it. These are all added together. Then added to the value for the node itself." + }, + "PAGE13": { + "TITLE": "activation functions", + "TEXT1": "Each node has its own bias value.", + "TEXT2": "Each line has its own weight value." + }, + "PAGE14": { + "TITLE": "hidden layers", + "TEXT1": "Each node in the model can use different equations.", + "TEXT2": "If you build your own machine learning model, you need to choose:", + "LIST1": "how many layers to have", + "LIST2": "how many nodes to put in each layer", + "LIST3": "which functions to use for each node" + }, + "PAGE15": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The number of layers, the number of nodes in each layer, and the functions to use for each node in your model were all chosen for you." + }, + "PAGE16": { + "TITLE": "output layer", + "TEXT1": "The final layer gives the machine learning model's prediction.", + "TEXT2": "There is a node for each bucket you added to your training data." + }, + "PAGE17": { + "TITLE": "loss function", + "TEXT1": "The prediction is compared with the correct answer (the training bucket you put this example in).", + "TEXT2": "The difference is described as the error rate, and tells us how well the machine learning model is doing at this stage of the training." + }, + "PAGE18": { + "TITLE": "back propagation", + "TEXT1": "The error rate is used to go backwards through the layers and nudge the numbers for each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error rate a little smaller." + }, + "PAGE19": { + "TITLE": "neural networks", + "TEXT1": "Next, this is all done over again, with another of your training examples." + }, + "PAGE20": { + "TITLE": "encoding", + "TEXT1": "Remember, the first step is turning the example text into numbers.", + "TEXT2": "Counting things that are in the text is an easy way to do it, but there are more complicated ways to do it if the order of words is important.", + "TEXT3": "The method for your model was chosen for you." + }, + "PAGE21": { + "TITLE": "hidden layer", + "TEXT1": "Remember, nodes in the middle of the model represent sums that are done using the input numbers.", + "TEXT2": "Different calculations can be chosen for each node." + }, + "PAGE22": { + "TITLE": "activation functions", + "TEXT1": "Remember, the calculations use numbers from the nodes on the left that are connected to it, as well as the numbers for the lines that connect them." + }, + "PAGE23": { + "TITLE": "activation functions", + "TEXT1": "The calculations also use a bias number for the node itself." + }, + "PAGE24": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The functions to use for each node in your model were chosen for you." + }, + "PAGE25": { + "TITLE": "output layer", + "TEXT1": "Remember, the output layer gives the machine learning model's prediction.", + "TEXT2": "Each node gives you the prediction for one of the buckets that you added to your training data." + }, + "PAGE26": { + "TITLE": "loss function", + "TEXT1": "Remember, results from the output layer are compared with the correct answer, which shows how well the machine learning model is doing." + }, + "PAGE27": { + "TITLE": "back propagation", + "TEXT1": "Remember that the error rate is used to go backwards through the layers and nudge the numbers associated with each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error a little smaller.", + "TEXT3": "This is how training works out the best numbers to use for each of the nodes and lines." + }, + "PAGE28": { + "TITLE": "epochs", + "TEXT1": "One run-through of every training example you collected through the model is called an epoch.", + "TEXT2": "Each time through, the weights for each node are nudged a little more, until hopefully the error rate for predictions are as low as they can be.", + "TEXT3": "If you build your own machine learning model, you need to choose how many epochs you want to run." + }, + "PAGE29": { + "TITLE": "neural networks", + "TEXT1": "I hope this simplified description gives you an idea what happens when you click on the \"Train new machine learning model\" button.", + "TEXT2": "For an explanation of why this process works, try watching \"How Machines Learn\" by CGP Grey." + } + }, "MAKES": { "TITLE": "Crea qualcosa con il tuo modello di apprendimento automatico", "SCRATCH2": "Crea un progetto nella vecchia versione di Scratch", diff --git a/public/languages/ja.json b/public/languages/ja.json index fe56e69cf..4abcfaa72 100644 --- a/public/languages/ja.json +++ b/public/languages/ja.json @@ -3,6 +3,7 @@ "TITLE": "子供のためのマシーンラーニング", "BACK": "戻る", + "NEXT": "Next", "BACKTOPROJECT": "< プロジェクトに戻る", "BACKTOMODEL": "< Back to model", "ERROR": "エラー:", @@ -704,6 +705,164 @@ "NUMBERSONLY": "Only machine learning models for numbers projects can be described" } }, + "DESCRIBETEXTMODEL": { + "ZOOM": "Use these controls to zoom in on the diagrams", + "ERRORS": { + "TEXTONLY": "Only neural networks for text projects can be described" + }, + "MOREINFO": "for more detail, try searching for:", + "PAGE1": { + "TITLE": "neural networks", + "TEXT1": "The type of machine learning model you trained in this project is called a neural network.", + "TEXT2": "The next few pages will explain how your model was created.", + "TEXT3": "These diagrams aren't an exact description of your model. Your model is larger and more complicated, but these diagrams are easier to explain." + }, + "PAGE2": { + "TITLE": "deep learning", + "TEXT1": "The model is made of nodes, arranged in vertical layers.", + "TEXT2": "Models with a lot of layers are described as deep.", + "TEXT3": "Deep models can give better results, but take longer to train." + }, + "PAGE3": { + "TITLE": "input layer", + "TEXT1": "Let's start with one of the training examples used to create your model.", + "TEXT2": "Your training example is shown as input on the left." + }, + "PAGE4": { + "TITLE": "encoding", + "TEXT1": "To use your training example to train the model, first the text needs to be turned into a series of numbers.", + "TEXT2": "There are lots of ways to do this.", + "TEXT3": "If you build your own machine learning model, you need to choose a way that works well for your particular project." + }, + "PAGE5": { + "TITLE": "bag of words", + "TEXT1": "One way of turning your text into numbers is to make each number a count of how many times a word is included." + }, + "PAGE6": { + "TITLE": "feature extraction", + "TEXT1": "There are other things you can count. Things that are helpful to count depend on the project you are doing, and what you want your model to learn to recognize patterns in.", + "TEXT2": "Counting things is quick and simple, but not as good for projects where the order of words is important." + }, + "PAGE7": { + "TITLE": "word embeddings", + "TEXT1": "If you build your own machine learning model, you need to choose the method for turning text into numbers.", + "TEXT2": "Your model used a more complicated technique that does include the order of words in the text." + }, + "PAGE8": { + "TITLE": "hidden layer", + "TEXT1": "The numbers from the input layer go into sums that calculate values for the nodes in the next layer.", + "TEXT2": "The lines on the diagram show which input values are used to calculate which values in the next layer." + }, + "PAGE9": { + "TITLE": "activation functions", + "TEXT1": "There are lots of different types of calculation you can use. Not every node in the model has to use the same calculation.", + "TEXT2": "If you build your own machine learning model, you need to choose which equations to use for each node.", + "TEXT3": "The functions to use for each node in your model were chosen for you." + }, + "PAGE10": { + "TITLE": "weight", + "TEXT1": "Each line in the diagram has a weight number that can be used in the sum.", + "TEXT2": "Training the model is how we work out the best number to put on each line, as you'll see in a moment." + }, + "PAGE11": { + "TITLE": "bias", + "TEXT1": "Each node in the diagram has a bias number that is used in the sum as well.", + "TEXT2": "Training the model is also how we work out the right bias number, as you'll see in a moment.", + "TEXT3": "Try to work out what you think the value for this node will be." + }, + "PAGE12": { + "TITLE": "activation functions", + "TEXT1": "This is a common function used in neural networks.", + "TEXT2": "Each input value is multiplied by the value for the line that connected it. These are all added together. Then added to the value for the node itself." + }, + "PAGE13": { + "TITLE": "activation functions", + "TEXT1": "Each node has its own bias value.", + "TEXT2": "Each line has its own weight value." + }, + "PAGE14": { + "TITLE": "hidden layers", + "TEXT1": "Each node in the model can use different equations.", + "TEXT2": "If you build your own machine learning model, you need to choose:", + "LIST1": "how many layers to have", + "LIST2": "how many nodes to put in each layer", + "LIST3": "which functions to use for each node" + }, + "PAGE15": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The number of layers, the number of nodes in each layer, and the functions to use for each node in your model were all chosen for you." + }, + "PAGE16": { + "TITLE": "output layer", + "TEXT1": "The final layer gives the machine learning model's prediction.", + "TEXT2": "There is a node for each bucket you added to your training data." + }, + "PAGE17": { + "TITLE": "loss function", + "TEXT1": "The prediction is compared with the correct answer (the training bucket you put this example in).", + "TEXT2": "The difference is described as the error rate, and tells us how well the machine learning model is doing at this stage of the training." + }, + "PAGE18": { + "TITLE": "back propagation", + "TEXT1": "The error rate is used to go backwards through the layers and nudge the numbers for each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error rate a little smaller." + }, + "PAGE19": { + "TITLE": "neural networks", + "TEXT1": "Next, this is all done over again, with another of your training examples." + }, + "PAGE20": { + "TITLE": "encoding", + "TEXT1": "Remember, the first step is turning the example text into numbers.", + "TEXT2": "Counting things that are in the text is an easy way to do it, but there are more complicated ways to do it if the order of words is important.", + "TEXT3": "The method for your model was chosen for you." + }, + "PAGE21": { + "TITLE": "hidden layer", + "TEXT1": "Remember, nodes in the middle of the model represent sums that are done using the input numbers.", + "TEXT2": "Different calculations can be chosen for each node." + }, + "PAGE22": { + "TITLE": "activation functions", + "TEXT1": "Remember, the calculations use numbers from the nodes on the left that are connected to it, as well as the numbers for the lines that connect them." + }, + "PAGE23": { + "TITLE": "activation functions", + "TEXT1": "The calculations also use a bias number for the node itself." + }, + "PAGE24": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The functions to use for each node in your model were chosen for you." + }, + "PAGE25": { + "TITLE": "output layer", + "TEXT1": "Remember, the output layer gives the machine learning model's prediction.", + "TEXT2": "Each node gives you the prediction for one of the buckets that you added to your training data." + }, + "PAGE26": { + "TITLE": "loss function", + "TEXT1": "Remember, results from the output layer are compared with the correct answer, which shows how well the machine learning model is doing." + }, + "PAGE27": { + "TITLE": "back propagation", + "TEXT1": "Remember that the error rate is used to go backwards through the layers and nudge the numbers associated with each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error a little smaller.", + "TEXT3": "This is how training works out the best numbers to use for each of the nodes and lines." + }, + "PAGE28": { + "TITLE": "epochs", + "TEXT1": "One run-through of every training example you collected through the model is called an epoch.", + "TEXT2": "Each time through, the weights for each node are nudged a little more, until hopefully the error rate for predictions are as low as they can be.", + "TEXT3": "If you build your own machine learning model, you need to choose how many epochs you want to run." + }, + "PAGE29": { + "TITLE": "neural networks", + "TEXT1": "I hope this simplified description gives you an idea what happens when you click on the \"Train new machine learning model\" button.", + "TEXT2": "For an explanation of why this process works, try watching \"How Machines Learn\" by CGP Grey." + } + }, "MAKES": { "TITLE": "あなたの機械学習モデルを使って何か作ってみましょう。", "SCRATCH2": "Scratch(Version 2)を使ってプロジェクトを作成する。", diff --git a/public/languages/ko.json b/public/languages/ko.json index fe6dad673..545153e68 100644 --- a/public/languages/ko.json +++ b/public/languages/ko.json @@ -3,6 +3,7 @@ "TITLE": "아이들을 위한 머신러닝", "BACK": "뒤로", + "NEXT": "Next", "BACKTOPROJECT": "< 프로젝트로 돌아가기", "BACKTOMODEL": "< 모델로 돌아가기", "ERROR": "에러:", @@ -704,6 +705,164 @@ "NUMBERSONLY": "Only machine learning models for numbers projects can be described" } }, + "DESCRIBETEXTMODEL": { + "ZOOM": "Use these controls to zoom in on the diagrams", + "ERRORS": { + "TEXTONLY": "Only neural networks for text projects can be described" + }, + "MOREINFO": "for more detail, try searching for:", + "PAGE1": { + "TITLE": "neural networks", + "TEXT1": "The type of machine learning model you trained in this project is called a neural network.", + "TEXT2": "The next few pages will explain how your model was created.", + "TEXT3": "These diagrams aren't an exact description of your model. Your model is larger and more complicated, but these diagrams are easier to explain." + }, + "PAGE2": { + "TITLE": "deep learning", + "TEXT1": "The model is made of nodes, arranged in vertical layers.", + "TEXT2": "Models with a lot of layers are described as deep.", + "TEXT3": "Deep models can give better results, but take longer to train." + }, + "PAGE3": { + "TITLE": "input layer", + "TEXT1": "Let's start with one of the training examples used to create your model.", + "TEXT2": "Your training example is shown as input on the left." + }, + "PAGE4": { + "TITLE": "encoding", + "TEXT1": "To use your training example to train the model, first the text needs to be turned into a series of numbers.", + "TEXT2": "There are lots of ways to do this.", + "TEXT3": "If you build your own machine learning model, you need to choose a way that works well for your particular project." + }, + "PAGE5": { + "TITLE": "bag of words", + "TEXT1": "One way of turning your text into numbers is to make each number a count of how many times a word is included." + }, + "PAGE6": { + "TITLE": "feature extraction", + "TEXT1": "There are other things you can count. Things that are helpful to count depend on the project you are doing, and what you want your model to learn to recognize patterns in.", + "TEXT2": "Counting things is quick and simple, but not as good for projects where the order of words is important." + }, + "PAGE7": { + "TITLE": "word embeddings", + "TEXT1": "If you build your own machine learning model, you need to choose the method for turning text into numbers.", + "TEXT2": "Your model used a more complicated technique that does include the order of words in the text." + }, + "PAGE8": { + "TITLE": "hidden layer", + "TEXT1": "The numbers from the input layer go into sums that calculate values for the nodes in the next layer.", + "TEXT2": "The lines on the diagram show which input values are used to calculate which values in the next layer." + }, + "PAGE9": { + "TITLE": "activation functions", + "TEXT1": "There are lots of different types of calculation you can use. Not every node in the model has to use the same calculation.", + "TEXT2": "If you build your own machine learning model, you need to choose which equations to use for each node.", + "TEXT3": "The functions to use for each node in your model were chosen for you." + }, + "PAGE10": { + "TITLE": "weight", + "TEXT1": "Each line in the diagram has a weight number that can be used in the sum.", + "TEXT2": "Training the model is how we work out the best number to put on each line, as you'll see in a moment." + }, + "PAGE11": { + "TITLE": "bias", + "TEXT1": "Each node in the diagram has a bias number that is used in the sum as well.", + "TEXT2": "Training the model is also how we work out the right bias number, as you'll see in a moment.", + "TEXT3": "Try to work out what you think the value for this node will be." + }, + "PAGE12": { + "TITLE": "activation functions", + "TEXT1": "This is a common function used in neural networks.", + "TEXT2": "Each input value is multiplied by the value for the line that connected it. These are all added together. Then added to the value for the node itself." + }, + "PAGE13": { + "TITLE": "activation functions", + "TEXT1": "Each node has its own bias value.", + "TEXT2": "Each line has its own weight value." + }, + "PAGE14": { + "TITLE": "hidden layers", + "TEXT1": "Each node in the model can use different equations.", + "TEXT2": "If you build your own machine learning model, you need to choose:", + "LIST1": "how many layers to have", + "LIST2": "how many nodes to put in each layer", + "LIST3": "which functions to use for each node" + }, + "PAGE15": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The number of layers, the number of nodes in each layer, and the functions to use for each node in your model were all chosen for you." + }, + "PAGE16": { + "TITLE": "output layer", + "TEXT1": "The final layer gives the machine learning model's prediction.", + "TEXT2": "There is a node for each bucket you added to your training data." + }, + "PAGE17": { + "TITLE": "loss function", + "TEXT1": "The prediction is compared with the correct answer (the training bucket you put this example in).", + "TEXT2": "The difference is described as the error rate, and tells us how well the machine learning model is doing at this stage of the training." + }, + "PAGE18": { + "TITLE": "back propagation", + "TEXT1": "The error rate is used to go backwards through the layers and nudge the numbers for each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error rate a little smaller." + }, + "PAGE19": { + "TITLE": "neural networks", + "TEXT1": "Next, this is all done over again, with another of your training examples." + }, + "PAGE20": { + "TITLE": "encoding", + "TEXT1": "Remember, the first step is turning the example text into numbers.", + "TEXT2": "Counting things that are in the text is an easy way to do it, but there are more complicated ways to do it if the order of words is important.", + "TEXT3": "The method for your model was chosen for you." + }, + "PAGE21": { + "TITLE": "hidden layer", + "TEXT1": "Remember, nodes in the middle of the model represent sums that are done using the input numbers.", + "TEXT2": "Different calculations can be chosen for each node." + }, + "PAGE22": { + "TITLE": "activation functions", + "TEXT1": "Remember, the calculations use numbers from the nodes on the left that are connected to it, as well as the numbers for the lines that connect them." + }, + "PAGE23": { + "TITLE": "activation functions", + "TEXT1": "The calculations also use a bias number for the node itself." + }, + "PAGE24": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The functions to use for each node in your model were chosen for you." + }, + "PAGE25": { + "TITLE": "output layer", + "TEXT1": "Remember, the output layer gives the machine learning model's prediction.", + "TEXT2": "Each node gives you the prediction for one of the buckets that you added to your training data." + }, + "PAGE26": { + "TITLE": "loss function", + "TEXT1": "Remember, results from the output layer are compared with the correct answer, which shows how well the machine learning model is doing." + }, + "PAGE27": { + "TITLE": "back propagation", + "TEXT1": "Remember that the error rate is used to go backwards through the layers and nudge the numbers associated with each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error a little smaller.", + "TEXT3": "This is how training works out the best numbers to use for each of the nodes and lines." + }, + "PAGE28": { + "TITLE": "epochs", + "TEXT1": "One run-through of every training example you collected through the model is called an epoch.", + "TEXT2": "Each time through, the weights for each node are nudged a little more, until hopefully the error rate for predictions are as low as they can be.", + "TEXT3": "If you build your own machine learning model, you need to choose how many epochs you want to run." + }, + "PAGE29": { + "TITLE": "neural networks", + "TEXT1": "I hope this simplified description gives you an idea what happens when you click on the \"Train new machine learning model\" button.", + "TEXT2": "For an explanation of why this process works, try watching \"How Machines Learn\" by CGP Grey." + } + }, "MAKES": { "TITLE": "여러분의 머신러닝 모델로 프로그램을 만들어봅시다.", "SCRATCH2": "예전 버전의 스크래치로 만들어봅시다.", diff --git a/public/languages/nl-be.json b/public/languages/nl-be.json index 9cbd5551a..a190064d4 100644 --- a/public/languages/nl-be.json +++ b/public/languages/nl-be.json @@ -3,6 +3,7 @@ "TITLE": "Machine Learning voor Kids", "BACK": "Terug", + "NEXT": "Next", "BACKTOPROJECT": "< Terug naar project", "BACKTOMODEL": "< Back to model", "ERROR": "Fout:", @@ -704,6 +705,164 @@ "NUMBERSONLY": "Only machine learning models for numbers projects can be described" } }, + "DESCRIBETEXTMODEL": { + "ZOOM": "Use these controls to zoom in on the diagrams", + "ERRORS": { + "TEXTONLY": "Only neural networks for text projects can be described" + }, + "MOREINFO": "for more detail, try searching for:", + "PAGE1": { + "TITLE": "neural networks", + "TEXT1": "The type of machine learning model you trained in this project is called a neural network.", + "TEXT2": "The next few pages will explain how your model was created.", + "TEXT3": "These diagrams aren't an exact description of your model. Your model is larger and more complicated, but these diagrams are easier to explain." + }, + "PAGE2": { + "TITLE": "deep learning", + "TEXT1": "The model is made of nodes, arranged in vertical layers.", + "TEXT2": "Models with a lot of layers are described as deep.", + "TEXT3": "Deep models can give better results, but take longer to train." + }, + "PAGE3": { + "TITLE": "input layer", + "TEXT1": "Let's start with one of the training examples used to create your model.", + "TEXT2": "Your training example is shown as input on the left." + }, + "PAGE4": { + "TITLE": "encoding", + "TEXT1": "To use your training example to train the model, first the text needs to be turned into a series of numbers.", + "TEXT2": "There are lots of ways to do this.", + "TEXT3": "If you build your own machine learning model, you need to choose a way that works well for your particular project." + }, + "PAGE5": { + "TITLE": "bag of words", + "TEXT1": "One way of turning your text into numbers is to make each number a count of how many times a word is included." + }, + "PAGE6": { + "TITLE": "feature extraction", + "TEXT1": "There are other things you can count. Things that are helpful to count depend on the project you are doing, and what you want your model to learn to recognize patterns in.", + "TEXT2": "Counting things is quick and simple, but not as good for projects where the order of words is important." + }, + "PAGE7": { + "TITLE": "word embeddings", + "TEXT1": "If you build your own machine learning model, you need to choose the method for turning text into numbers.", + "TEXT2": "Your model used a more complicated technique that does include the order of words in the text." + }, + "PAGE8": { + "TITLE": "hidden layer", + "TEXT1": "The numbers from the input layer go into sums that calculate values for the nodes in the next layer.", + "TEXT2": "The lines on the diagram show which input values are used to calculate which values in the next layer." + }, + "PAGE9": { + "TITLE": "activation functions", + "TEXT1": "There are lots of different types of calculation you can use. Not every node in the model has to use the same calculation.", + "TEXT2": "If you build your own machine learning model, you need to choose which equations to use for each node.", + "TEXT3": "The functions to use for each node in your model were chosen for you." + }, + "PAGE10": { + "TITLE": "weight", + "TEXT1": "Each line in the diagram has a weight number that can be used in the sum.", + "TEXT2": "Training the model is how we work out the best number to put on each line, as you'll see in a moment." + }, + "PAGE11": { + "TITLE": "bias", + "TEXT1": "Each node in the diagram has a bias number that is used in the sum as well.", + "TEXT2": "Training the model is also how we work out the right bias number, as you'll see in a moment.", + "TEXT3": "Try to work out what you think the value for this node will be." + }, + "PAGE12": { + "TITLE": "activation functions", + "TEXT1": "This is a common function used in neural networks.", + "TEXT2": "Each input value is multiplied by the value for the line that connected it. These are all added together. Then added to the value for the node itself." + }, + "PAGE13": { + "TITLE": "activation functions", + "TEXT1": "Each node has its own bias value.", + "TEXT2": "Each line has its own weight value." + }, + "PAGE14": { + "TITLE": "hidden layers", + "TEXT1": "Each node in the model can use different equations.", + "TEXT2": "If you build your own machine learning model, you need to choose:", + "LIST1": "how many layers to have", + "LIST2": "how many nodes to put in each layer", + "LIST3": "which functions to use for each node" + }, + "PAGE15": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The number of layers, the number of nodes in each layer, and the functions to use for each node in your model were all chosen for you." + }, + "PAGE16": { + "TITLE": "output layer", + "TEXT1": "The final layer gives the machine learning model's prediction.", + "TEXT2": "There is a node for each bucket you added to your training data." + }, + "PAGE17": { + "TITLE": "loss function", + "TEXT1": "The prediction is compared with the correct answer (the training bucket you put this example in).", + "TEXT2": "The difference is described as the error rate, and tells us how well the machine learning model is doing at this stage of the training." + }, + "PAGE18": { + "TITLE": "back propagation", + "TEXT1": "The error rate is used to go backwards through the layers and nudge the numbers for each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error rate a little smaller." + }, + "PAGE19": { + "TITLE": "neural networks", + "TEXT1": "Next, this is all done over again, with another of your training examples." + }, + "PAGE20": { + "TITLE": "encoding", + "TEXT1": "Remember, the first step is turning the example text into numbers.", + "TEXT2": "Counting things that are in the text is an easy way to do it, but there are more complicated ways to do it if the order of words is important.", + "TEXT3": "The method for your model was chosen for you." + }, + "PAGE21": { + "TITLE": "hidden layer", + "TEXT1": "Remember, nodes in the middle of the model represent sums that are done using the input numbers.", + "TEXT2": "Different calculations can be chosen for each node." + }, + "PAGE22": { + "TITLE": "activation functions", + "TEXT1": "Remember, the calculations use numbers from the nodes on the left that are connected to it, as well as the numbers for the lines that connect them." + }, + "PAGE23": { + "TITLE": "activation functions", + "TEXT1": "The calculations also use a bias number for the node itself." + }, + "PAGE24": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The functions to use for each node in your model were chosen for you." + }, + "PAGE25": { + "TITLE": "output layer", + "TEXT1": "Remember, the output layer gives the machine learning model's prediction.", + "TEXT2": "Each node gives you the prediction for one of the buckets that you added to your training data." + }, + "PAGE26": { + "TITLE": "loss function", + "TEXT1": "Remember, results from the output layer are compared with the correct answer, which shows how well the machine learning model is doing." + }, + "PAGE27": { + "TITLE": "back propagation", + "TEXT1": "Remember that the error rate is used to go backwards through the layers and nudge the numbers associated with each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error a little smaller.", + "TEXT3": "This is how training works out the best numbers to use for each of the nodes and lines." + }, + "PAGE28": { + "TITLE": "epochs", + "TEXT1": "One run-through of every training example you collected through the model is called an epoch.", + "TEXT2": "Each time through, the weights for each node are nudged a little more, until hopefully the error rate for predictions are as low as they can be.", + "TEXT3": "If you build your own machine learning model, you need to choose how many epochs you want to run." + }, + "PAGE29": { + "TITLE": "neural networks", + "TEXT1": "I hope this simplified description gives you an idea what happens when you click on the \"Train new machine learning model\" button.", + "TEXT2": "For an explanation of why this process works, try watching \"How Machines Learn\" by CGP Grey." + } + }, "MAKES": { "TITLE": "Maak iets met je machine learning model", "SCRATCH2": "Maak een project in de oude versie van Scratch", diff --git a/public/languages/pl.json b/public/languages/pl.json index 1eab9fe16..20d479612 100644 --- a/public/languages/pl.json +++ b/public/languages/pl.json @@ -3,6 +3,7 @@ "TITLE": "Sztuczna Inteligencja dla dzieci", "BACK": "Powrót", + "NEXT": "Next", "BACKTOPROJECT": "Powrót do projektu", "BACKTOMODEL": "Powrót do modelu", "ERROR": "Bląd", @@ -704,6 +705,164 @@ "NUMBERSONLY": "Only machine learning models for numbers projects can be described" } }, + "DESCRIBETEXTMODEL": { + "ZOOM": "Use these controls to zoom in on the diagrams", + "ERRORS": { + "TEXTONLY": "Only neural networks for text projects can be described" + }, + "MOREINFO": "for more detail, try searching for:", + "PAGE1": { + "TITLE": "neural networks", + "TEXT1": "The type of machine learning model you trained in this project is called a neural network.", + "TEXT2": "The next few pages will explain how your model was created.", + "TEXT3": "These diagrams aren't an exact description of your model. Your model is larger and more complicated, but these diagrams are easier to explain." + }, + "PAGE2": { + "TITLE": "deep learning", + "TEXT1": "The model is made of nodes, arranged in vertical layers.", + "TEXT2": "Models with a lot of layers are described as deep.", + "TEXT3": "Deep models can give better results, but take longer to train." + }, + "PAGE3": { + "TITLE": "input layer", + "TEXT1": "Let's start with one of the training examples used to create your model.", + "TEXT2": "Your training example is shown as input on the left." + }, + "PAGE4": { + "TITLE": "encoding", + "TEXT1": "To use your training example to train the model, first the text needs to be turned into a series of numbers.", + "TEXT2": "There are lots of ways to do this.", + "TEXT3": "If you build your own machine learning model, you need to choose a way that works well for your particular project." + }, + "PAGE5": { + "TITLE": "bag of words", + "TEXT1": "One way of turning your text into numbers is to make each number a count of how many times a word is included." + }, + "PAGE6": { + "TITLE": "feature extraction", + "TEXT1": "There are other things you can count. Things that are helpful to count depend on the project you are doing, and what you want your model to learn to recognize patterns in.", + "TEXT2": "Counting things is quick and simple, but not as good for projects where the order of words is important." + }, + "PAGE7": { + "TITLE": "word embeddings", + "TEXT1": "If you build your own machine learning model, you need to choose the method for turning text into numbers.", + "TEXT2": "Your model used a more complicated technique that does include the order of words in the text." + }, + "PAGE8": { + "TITLE": "hidden layer", + "TEXT1": "The numbers from the input layer go into sums that calculate values for the nodes in the next layer.", + "TEXT2": "The lines on the diagram show which input values are used to calculate which values in the next layer." + }, + "PAGE9": { + "TITLE": "activation functions", + "TEXT1": "There are lots of different types of calculation you can use. Not every node in the model has to use the same calculation.", + "TEXT2": "If you build your own machine learning model, you need to choose which equations to use for each node.", + "TEXT3": "The functions to use for each node in your model were chosen for you." + }, + "PAGE10": { + "TITLE": "weight", + "TEXT1": "Each line in the diagram has a weight number that can be used in the sum.", + "TEXT2": "Training the model is how we work out the best number to put on each line, as you'll see in a moment." + }, + "PAGE11": { + "TITLE": "bias", + "TEXT1": "Each node in the diagram has a bias number that is used in the sum as well.", + "TEXT2": "Training the model is also how we work out the right bias number, as you'll see in a moment.", + "TEXT3": "Try to work out what you think the value for this node will be." + }, + "PAGE12": { + "TITLE": "activation functions", + "TEXT1": "This is a common function used in neural networks.", + "TEXT2": "Each input value is multiplied by the value for the line that connected it. These are all added together. Then added to the value for the node itself." + }, + "PAGE13": { + "TITLE": "activation functions", + "TEXT1": "Each node has its own bias value.", + "TEXT2": "Each line has its own weight value." + }, + "PAGE14": { + "TITLE": "hidden layers", + "TEXT1": "Each node in the model can use different equations.", + "TEXT2": "If you build your own machine learning model, you need to choose:", + "LIST1": "how many layers to have", + "LIST2": "how many nodes to put in each layer", + "LIST3": "which functions to use for each node" + }, + "PAGE15": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The number of layers, the number of nodes in each layer, and the functions to use for each node in your model were all chosen for you." + }, + "PAGE16": { + "TITLE": "output layer", + "TEXT1": "The final layer gives the machine learning model's prediction.", + "TEXT2": "There is a node for each bucket you added to your training data." + }, + "PAGE17": { + "TITLE": "loss function", + "TEXT1": "The prediction is compared with the correct answer (the training bucket you put this example in).", + "TEXT2": "The difference is described as the error rate, and tells us how well the machine learning model is doing at this stage of the training." + }, + "PAGE18": { + "TITLE": "back propagation", + "TEXT1": "The error rate is used to go backwards through the layers and nudge the numbers for each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error rate a little smaller." + }, + "PAGE19": { + "TITLE": "neural networks", + "TEXT1": "Next, this is all done over again, with another of your training examples." + }, + "PAGE20": { + "TITLE": "encoding", + "TEXT1": "Remember, the first step is turning the example text into numbers.", + "TEXT2": "Counting things that are in the text is an easy way to do it, but there are more complicated ways to do it if the order of words is important.", + "TEXT3": "The method for your model was chosen for you." + }, + "PAGE21": { + "TITLE": "hidden layer", + "TEXT1": "Remember, nodes in the middle of the model represent sums that are done using the input numbers.", + "TEXT2": "Different calculations can be chosen for each node." + }, + "PAGE22": { + "TITLE": "activation functions", + "TEXT1": "Remember, the calculations use numbers from the nodes on the left that are connected to it, as well as the numbers for the lines that connect them." + }, + "PAGE23": { + "TITLE": "activation functions", + "TEXT1": "The calculations also use a bias number for the node itself." + }, + "PAGE24": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The functions to use for each node in your model were chosen for you." + }, + "PAGE25": { + "TITLE": "output layer", + "TEXT1": "Remember, the output layer gives the machine learning model's prediction.", + "TEXT2": "Each node gives you the prediction for one of the buckets that you added to your training data." + }, + "PAGE26": { + "TITLE": "loss function", + "TEXT1": "Remember, results from the output layer are compared with the correct answer, which shows how well the machine learning model is doing." + }, + "PAGE27": { + "TITLE": "back propagation", + "TEXT1": "Remember that the error rate is used to go backwards through the layers and nudge the numbers associated with each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error a little smaller.", + "TEXT3": "This is how training works out the best numbers to use for each of the nodes and lines." + }, + "PAGE28": { + "TITLE": "epochs", + "TEXT1": "One run-through of every training example you collected through the model is called an epoch.", + "TEXT2": "Each time through, the weights for each node are nudged a little more, until hopefully the error rate for predictions are as low as they can be.", + "TEXT3": "If you build your own machine learning model, you need to choose how many epochs you want to run." + }, + "PAGE29": { + "TITLE": "neural networks", + "TEXT1": "I hope this simplified description gives you an idea what happens when you click on the \"Train new machine learning model\" button.", + "TEXT2": "For an explanation of why this process works, try watching \"How Machines Learn\" by CGP Grey." + } + }, "MAKES": { "TITLE": "Make something with your machine learning model", "SCRATCH2": "Make a project in the old version of Scratch", diff --git a/public/languages/pt-br.json b/public/languages/pt-br.json index d2f183ee9..9ceb0e070 100644 --- a/public/languages/pt-br.json +++ b/public/languages/pt-br.json @@ -3,6 +3,7 @@ "TITLE": "Machine Learning for Kids", "BACK": "Voltar", + "NEXT": "Next", "BACKTOPROJECT": "< Voltar para o projeto", "BACKTOMODEL": "< Back to model", "ERROR": "Erro:", @@ -704,6 +705,164 @@ "NUMBERSONLY": "Only machine learning models for numbers projects can be described" } }, + "DESCRIBETEXTMODEL": { + "ZOOM": "Use these controls to zoom in on the diagrams", + "ERRORS": { + "TEXTONLY": "Only neural networks for text projects can be described" + }, + "MOREINFO": "for more detail, try searching for:", + "PAGE1": { + "TITLE": "neural networks", + "TEXT1": "The type of machine learning model you trained in this project is called a neural network.", + "TEXT2": "The next few pages will explain how your model was created.", + "TEXT3": "These diagrams aren't an exact description of your model. Your model is larger and more complicated, but these diagrams are easier to explain." + }, + "PAGE2": { + "TITLE": "deep learning", + "TEXT1": "The model is made of nodes, arranged in vertical layers.", + "TEXT2": "Models with a lot of layers are described as deep.", + "TEXT3": "Deep models can give better results, but take longer to train." + }, + "PAGE3": { + "TITLE": "input layer", + "TEXT1": "Let's start with one of the training examples used to create your model.", + "TEXT2": "Your training example is shown as input on the left." + }, + "PAGE4": { + "TITLE": "encoding", + "TEXT1": "To use your training example to train the model, first the text needs to be turned into a series of numbers.", + "TEXT2": "There are lots of ways to do this.", + "TEXT3": "If you build your own machine learning model, you need to choose a way that works well for your particular project." + }, + "PAGE5": { + "TITLE": "bag of words", + "TEXT1": "One way of turning your text into numbers is to make each number a count of how many times a word is included." + }, + "PAGE6": { + "TITLE": "feature extraction", + "TEXT1": "There are other things you can count. Things that are helpful to count depend on the project you are doing, and what you want your model to learn to recognize patterns in.", + "TEXT2": "Counting things is quick and simple, but not as good for projects where the order of words is important." + }, + "PAGE7": { + "TITLE": "word embeddings", + "TEXT1": "If you build your own machine learning model, you need to choose the method for turning text into numbers.", + "TEXT2": "Your model used a more complicated technique that does include the order of words in the text." + }, + "PAGE8": { + "TITLE": "hidden layer", + "TEXT1": "The numbers from the input layer go into sums that calculate values for the nodes in the next layer.", + "TEXT2": "The lines on the diagram show which input values are used to calculate which values in the next layer." + }, + "PAGE9": { + "TITLE": "activation functions", + "TEXT1": "There are lots of different types of calculation you can use. Not every node in the model has to use the same calculation.", + "TEXT2": "If you build your own machine learning model, you need to choose which equations to use for each node.", + "TEXT3": "The functions to use for each node in your model were chosen for you." + }, + "PAGE10": { + "TITLE": "weight", + "TEXT1": "Each line in the diagram has a weight number that can be used in the sum.", + "TEXT2": "Training the model is how we work out the best number to put on each line, as you'll see in a moment." + }, + "PAGE11": { + "TITLE": "bias", + "TEXT1": "Each node in the diagram has a bias number that is used in the sum as well.", + "TEXT2": "Training the model is also how we work out the right bias number, as you'll see in a moment.", + "TEXT3": "Try to work out what you think the value for this node will be." + }, + "PAGE12": { + "TITLE": "activation functions", + "TEXT1": "This is a common function used in neural networks.", + "TEXT2": "Each input value is multiplied by the value for the line that connected it. These are all added together. Then added to the value for the node itself." + }, + "PAGE13": { + "TITLE": "activation functions", + "TEXT1": "Each node has its own bias value.", + "TEXT2": "Each line has its own weight value." + }, + "PAGE14": { + "TITLE": "hidden layers", + "TEXT1": "Each node in the model can use different equations.", + "TEXT2": "If you build your own machine learning model, you need to choose:", + "LIST1": "how many layers to have", + "LIST2": "how many nodes to put in each layer", + "LIST3": "which functions to use for each node" + }, + "PAGE15": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The number of layers, the number of nodes in each layer, and the functions to use for each node in your model were all chosen for you." + }, + "PAGE16": { + "TITLE": "output layer", + "TEXT1": "The final layer gives the machine learning model's prediction.", + "TEXT2": "There is a node for each bucket you added to your training data." + }, + "PAGE17": { + "TITLE": "loss function", + "TEXT1": "The prediction is compared with the correct answer (the training bucket you put this example in).", + "TEXT2": "The difference is described as the error rate, and tells us how well the machine learning model is doing at this stage of the training." + }, + "PAGE18": { + "TITLE": "back propagation", + "TEXT1": "The error rate is used to go backwards through the layers and nudge the numbers for each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error rate a little smaller." + }, + "PAGE19": { + "TITLE": "neural networks", + "TEXT1": "Next, this is all done over again, with another of your training examples." + }, + "PAGE20": { + "TITLE": "encoding", + "TEXT1": "Remember, the first step is turning the example text into numbers.", + "TEXT2": "Counting things that are in the text is an easy way to do it, but there are more complicated ways to do it if the order of words is important.", + "TEXT3": "The method for your model was chosen for you." + }, + "PAGE21": { + "TITLE": "hidden layer", + "TEXT1": "Remember, nodes in the middle of the model represent sums that are done using the input numbers.", + "TEXT2": "Different calculations can be chosen for each node." + }, + "PAGE22": { + "TITLE": "activation functions", + "TEXT1": "Remember, the calculations use numbers from the nodes on the left that are connected to it, as well as the numbers for the lines that connect them." + }, + "PAGE23": { + "TITLE": "activation functions", + "TEXT1": "The calculations also use a bias number for the node itself." + }, + "PAGE24": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The functions to use for each node in your model were chosen for you." + }, + "PAGE25": { + "TITLE": "output layer", + "TEXT1": "Remember, the output layer gives the machine learning model's prediction.", + "TEXT2": "Each node gives you the prediction for one of the buckets that you added to your training data." + }, + "PAGE26": { + "TITLE": "loss function", + "TEXT1": "Remember, results from the output layer are compared with the correct answer, which shows how well the machine learning model is doing." + }, + "PAGE27": { + "TITLE": "back propagation", + "TEXT1": "Remember that the error rate is used to go backwards through the layers and nudge the numbers associated with each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error a little smaller.", + "TEXT3": "This is how training works out the best numbers to use for each of the nodes and lines." + }, + "PAGE28": { + "TITLE": "epochs", + "TEXT1": "One run-through of every training example you collected through the model is called an epoch.", + "TEXT2": "Each time through, the weights for each node are nudged a little more, until hopefully the error rate for predictions are as low as they can be.", + "TEXT3": "If you build your own machine learning model, you need to choose how many epochs you want to run." + }, + "PAGE29": { + "TITLE": "neural networks", + "TEXT1": "I hope this simplified description gives you an idea what happens when you click on the \"Train new machine learning model\" button.", + "TEXT2": "For an explanation of why this process works, try watching \"How Machines Learn\" by CGP Grey." + } + }, "MAKES": { "TITLE": "Faça alguma coisa com seu modelo de aprendizado de máquina", "SCRATCH2": "Faça um projeto na versão atual do Scratch", diff --git a/public/languages/ru.json b/public/languages/ru.json index a541849d9..854acc995 100644 --- a/public/languages/ru.json +++ b/public/languages/ru.json @@ -3,6 +3,7 @@ "TITLE": "Машинное обучение для детей", "BACK": "Назад", + "NEXT": "Next", "BACKTOPROJECT": "< Назад к проекту", "BACKTOMODEL": "< Назад к модели", "ERROR": "Ошибка:", @@ -704,6 +705,164 @@ "NUMBERSONLY": "Only machine learning models for numbers projects can be described" } }, + "DESCRIBETEXTMODEL": { + "ZOOM": "Use these controls to zoom in on the diagrams", + "ERRORS": { + "TEXTONLY": "Only neural networks for text projects can be described" + }, + "MOREINFO": "for more detail, try searching for:", + "PAGE1": { + "TITLE": "neural networks", + "TEXT1": "The type of machine learning model you trained in this project is called a neural network.", + "TEXT2": "The next few pages will explain how your model was created.", + "TEXT3": "These diagrams aren't an exact description of your model. Your model is larger and more complicated, but these diagrams are easier to explain." + }, + "PAGE2": { + "TITLE": "deep learning", + "TEXT1": "The model is made of nodes, arranged in vertical layers.", + "TEXT2": "Models with a lot of layers are described as deep.", + "TEXT3": "Deep models can give better results, but take longer to train." + }, + "PAGE3": { + "TITLE": "input layer", + "TEXT1": "Let's start with one of the training examples used to create your model.", + "TEXT2": "Your training example is shown as input on the left." + }, + "PAGE4": { + "TITLE": "encoding", + "TEXT1": "To use your training example to train the model, first the text needs to be turned into a series of numbers.", + "TEXT2": "There are lots of ways to do this.", + "TEXT3": "If you build your own machine learning model, you need to choose a way that works well for your particular project." + }, + "PAGE5": { + "TITLE": "bag of words", + "TEXT1": "One way of turning your text into numbers is to make each number a count of how many times a word is included." + }, + "PAGE6": { + "TITLE": "feature extraction", + "TEXT1": "There are other things you can count. Things that are helpful to count depend on the project you are doing, and what you want your model to learn to recognize patterns in.", + "TEXT2": "Counting things is quick and simple, but not as good for projects where the order of words is important." + }, + "PAGE7": { + "TITLE": "word embeddings", + "TEXT1": "If you build your own machine learning model, you need to choose the method for turning text into numbers.", + "TEXT2": "Your model used a more complicated technique that does include the order of words in the text." + }, + "PAGE8": { + "TITLE": "hidden layer", + "TEXT1": "The numbers from the input layer go into sums that calculate values for the nodes in the next layer.", + "TEXT2": "The lines on the diagram show which input values are used to calculate which values in the next layer." + }, + "PAGE9": { + "TITLE": "activation functions", + "TEXT1": "There are lots of different types of calculation you can use. Not every node in the model has to use the same calculation.", + "TEXT2": "If you build your own machine learning model, you need to choose which equations to use for each node.", + "TEXT3": "The functions to use for each node in your model were chosen for you." + }, + "PAGE10": { + "TITLE": "weight", + "TEXT1": "Each line in the diagram has a weight number that can be used in the sum.", + "TEXT2": "Training the model is how we work out the best number to put on each line, as you'll see in a moment." + }, + "PAGE11": { + "TITLE": "bias", + "TEXT1": "Each node in the diagram has a bias number that is used in the sum as well.", + "TEXT2": "Training the model is also how we work out the right bias number, as you'll see in a moment.", + "TEXT3": "Try to work out what you think the value for this node will be." + }, + "PAGE12": { + "TITLE": "activation functions", + "TEXT1": "This is a common function used in neural networks.", + "TEXT2": "Each input value is multiplied by the value for the line that connected it. These are all added together. Then added to the value for the node itself." + }, + "PAGE13": { + "TITLE": "activation functions", + "TEXT1": "Each node has its own bias value.", + "TEXT2": "Each line has its own weight value." + }, + "PAGE14": { + "TITLE": "hidden layers", + "TEXT1": "Each node in the model can use different equations.", + "TEXT2": "If you build your own machine learning model, you need to choose:", + "LIST1": "how many layers to have", + "LIST2": "how many nodes to put in each layer", + "LIST3": "which functions to use for each node" + }, + "PAGE15": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The number of layers, the number of nodes in each layer, and the functions to use for each node in your model were all chosen for you." + }, + "PAGE16": { + "TITLE": "output layer", + "TEXT1": "The final layer gives the machine learning model's prediction.", + "TEXT2": "There is a node for each bucket you added to your training data." + }, + "PAGE17": { + "TITLE": "loss function", + "TEXT1": "The prediction is compared with the correct answer (the training bucket you put this example in).", + "TEXT2": "The difference is described as the error rate, and tells us how well the machine learning model is doing at this stage of the training." + }, + "PAGE18": { + "TITLE": "back propagation", + "TEXT1": "The error rate is used to go backwards through the layers and nudge the numbers for each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error rate a little smaller." + }, + "PAGE19": { + "TITLE": "neural networks", + "TEXT1": "Next, this is all done over again, with another of your training examples." + }, + "PAGE20": { + "TITLE": "encoding", + "TEXT1": "Remember, the first step is turning the example text into numbers.", + "TEXT2": "Counting things that are in the text is an easy way to do it, but there are more complicated ways to do it if the order of words is important.", + "TEXT3": "The method for your model was chosen for you." + }, + "PAGE21": { + "TITLE": "hidden layer", + "TEXT1": "Remember, nodes in the middle of the model represent sums that are done using the input numbers.", + "TEXT2": "Different calculations can be chosen for each node." + }, + "PAGE22": { + "TITLE": "activation functions", + "TEXT1": "Remember, the calculations use numbers from the nodes on the left that are connected to it, as well as the numbers for the lines that connect them." + }, + "PAGE23": { + "TITLE": "activation functions", + "TEXT1": "The calculations also use a bias number for the node itself." + }, + "PAGE24": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The functions to use for each node in your model were chosen for you." + }, + "PAGE25": { + "TITLE": "output layer", + "TEXT1": "Remember, the output layer gives the machine learning model's prediction.", + "TEXT2": "Each node gives you the prediction for one of the buckets that you added to your training data." + }, + "PAGE26": { + "TITLE": "loss function", + "TEXT1": "Remember, results from the output layer are compared with the correct answer, which shows how well the machine learning model is doing." + }, + "PAGE27": { + "TITLE": "back propagation", + "TEXT1": "Remember that the error rate is used to go backwards through the layers and nudge the numbers associated with each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error a little smaller.", + "TEXT3": "This is how training works out the best numbers to use for each of the nodes and lines." + }, + "PAGE28": { + "TITLE": "epochs", + "TEXT1": "One run-through of every training example you collected through the model is called an epoch.", + "TEXT2": "Each time through, the weights for each node are nudged a little more, until hopefully the error rate for predictions are as low as they can be.", + "TEXT3": "If you build your own machine learning model, you need to choose how many epochs you want to run." + }, + "PAGE29": { + "TITLE": "neural networks", + "TEXT1": "I hope this simplified description gives you an idea what happens when you click on the \"Train new machine learning model\" button.", + "TEXT2": "For an explanation of why this process works, try watching \"How Machines Learn\" by CGP Grey." + } + }, "MAKES": { "TITLE": "Make something with your machine learning model", "SCRATCH2": "Make a project in the old version of Scratch", diff --git a/public/languages/si-lk.json b/public/languages/si-lk.json index 93c4c844f..1bd3804a4 100644 --- a/public/languages/si-lk.json +++ b/public/languages/si-lk.json @@ -3,6 +3,7 @@ "TITLE": "පොඩ්ඩන්ට Machine Learning", "BACK": "ආපසු", + "NEXT": "Next", "BACKTOPROJECT": "< ආපසු ව්‍යාපෘතියට", "BACKTOMODEL": "< ආපසු මොඩලයට ", "ERROR": "දෝෂය:", @@ -704,6 +705,164 @@ "NUMBERSONLY": "Only machine learning models for numbers projects can be described" } }, + "DESCRIBETEXTMODEL": { + "ZOOM": "Use these controls to zoom in on the diagrams", + "ERRORS": { + "TEXTONLY": "Only neural networks for text projects can be described" + }, + "MOREINFO": "for more detail, try searching for:", + "PAGE1": { + "TITLE": "neural networks", + "TEXT1": "The type of machine learning model you trained in this project is called a neural network.", + "TEXT2": "The next few pages will explain how your model was created.", + "TEXT3": "These diagrams aren't an exact description of your model. Your model is larger and more complicated, but these diagrams are easier to explain." + }, + "PAGE2": { + "TITLE": "deep learning", + "TEXT1": "The model is made of nodes, arranged in vertical layers.", + "TEXT2": "Models with a lot of layers are described as deep.", + "TEXT3": "Deep models can give better results, but take longer to train." + }, + "PAGE3": { + "TITLE": "input layer", + "TEXT1": "Let's start with one of the training examples used to create your model.", + "TEXT2": "Your training example is shown as input on the left." + }, + "PAGE4": { + "TITLE": "encoding", + "TEXT1": "To use your training example to train the model, first the text needs to be turned into a series of numbers.", + "TEXT2": "There are lots of ways to do this.", + "TEXT3": "If you build your own machine learning model, you need to choose a way that works well for your particular project." + }, + "PAGE5": { + "TITLE": "bag of words", + "TEXT1": "One way of turning your text into numbers is to make each number a count of how many times a word is included." + }, + "PAGE6": { + "TITLE": "feature extraction", + "TEXT1": "There are other things you can count. Things that are helpful to count depend on the project you are doing, and what you want your model to learn to recognize patterns in.", + "TEXT2": "Counting things is quick and simple, but not as good for projects where the order of words is important." + }, + "PAGE7": { + "TITLE": "word embeddings", + "TEXT1": "If you build your own machine learning model, you need to choose the method for turning text into numbers.", + "TEXT2": "Your model used a more complicated technique that does include the order of words in the text." + }, + "PAGE8": { + "TITLE": "hidden layer", + "TEXT1": "The numbers from the input layer go into sums that calculate values for the nodes in the next layer.", + "TEXT2": "The lines on the diagram show which input values are used to calculate which values in the next layer." + }, + "PAGE9": { + "TITLE": "activation functions", + "TEXT1": "There are lots of different types of calculation you can use. Not every node in the model has to use the same calculation.", + "TEXT2": "If you build your own machine learning model, you need to choose which equations to use for each node.", + "TEXT3": "The functions to use for each node in your model were chosen for you." + }, + "PAGE10": { + "TITLE": "weight", + "TEXT1": "Each line in the diagram has a weight number that can be used in the sum.", + "TEXT2": "Training the model is how we work out the best number to put on each line, as you'll see in a moment." + }, + "PAGE11": { + "TITLE": "bias", + "TEXT1": "Each node in the diagram has a bias number that is used in the sum as well.", + "TEXT2": "Training the model is also how we work out the right bias number, as you'll see in a moment.", + "TEXT3": "Try to work out what you think the value for this node will be." + }, + "PAGE12": { + "TITLE": "activation functions", + "TEXT1": "This is a common function used in neural networks.", + "TEXT2": "Each input value is multiplied by the value for the line that connected it. These are all added together. Then added to the value for the node itself." + }, + "PAGE13": { + "TITLE": "activation functions", + "TEXT1": "Each node has its own bias value.", + "TEXT2": "Each line has its own weight value." + }, + "PAGE14": { + "TITLE": "hidden layers", + "TEXT1": "Each node in the model can use different equations.", + "TEXT2": "If you build your own machine learning model, you need to choose:", + "LIST1": "how many layers to have", + "LIST2": "how many nodes to put in each layer", + "LIST3": "which functions to use for each node" + }, + "PAGE15": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The number of layers, the number of nodes in each layer, and the functions to use for each node in your model were all chosen for you." + }, + "PAGE16": { + "TITLE": "output layer", + "TEXT1": "The final layer gives the machine learning model's prediction.", + "TEXT2": "There is a node for each bucket you added to your training data." + }, + "PAGE17": { + "TITLE": "loss function", + "TEXT1": "The prediction is compared with the correct answer (the training bucket you put this example in).", + "TEXT2": "The difference is described as the error rate, and tells us how well the machine learning model is doing at this stage of the training." + }, + "PAGE18": { + "TITLE": "back propagation", + "TEXT1": "The error rate is used to go backwards through the layers and nudge the numbers for each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error rate a little smaller." + }, + "PAGE19": { + "TITLE": "neural networks", + "TEXT1": "Next, this is all done over again, with another of your training examples." + }, + "PAGE20": { + "TITLE": "encoding", + "TEXT1": "Remember, the first step is turning the example text into numbers.", + "TEXT2": "Counting things that are in the text is an easy way to do it, but there are more complicated ways to do it if the order of words is important.", + "TEXT3": "The method for your model was chosen for you." + }, + "PAGE21": { + "TITLE": "hidden layer", + "TEXT1": "Remember, nodes in the middle of the model represent sums that are done using the input numbers.", + "TEXT2": "Different calculations can be chosen for each node." + }, + "PAGE22": { + "TITLE": "activation functions", + "TEXT1": "Remember, the calculations use numbers from the nodes on the left that are connected to it, as well as the numbers for the lines that connect them." + }, + "PAGE23": { + "TITLE": "activation functions", + "TEXT1": "The calculations also use a bias number for the node itself." + }, + "PAGE24": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The functions to use for each node in your model were chosen for you." + }, + "PAGE25": { + "TITLE": "output layer", + "TEXT1": "Remember, the output layer gives the machine learning model's prediction.", + "TEXT2": "Each node gives you the prediction for one of the buckets that you added to your training data." + }, + "PAGE26": { + "TITLE": "loss function", + "TEXT1": "Remember, results from the output layer are compared with the correct answer, which shows how well the machine learning model is doing." + }, + "PAGE27": { + "TITLE": "back propagation", + "TEXT1": "Remember that the error rate is used to go backwards through the layers and nudge the numbers associated with each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error a little smaller.", + "TEXT3": "This is how training works out the best numbers to use for each of the nodes and lines." + }, + "PAGE28": { + "TITLE": "epochs", + "TEXT1": "One run-through of every training example you collected through the model is called an epoch.", + "TEXT2": "Each time through, the weights for each node are nudged a little more, until hopefully the error rate for predictions are as low as they can be.", + "TEXT3": "If you build your own machine learning model, you need to choose how many epochs you want to run." + }, + "PAGE29": { + "TITLE": "neural networks", + "TEXT1": "I hope this simplified description gives you an idea what happens when you click on the \"Train new machine learning model\" button.", + "TEXT2": "For an explanation of why this process works, try watching \"How Machines Learn\" by CGP Grey." + } + }, "MAKES": { "TITLE": "Make something with your machine learning model", "SCRATCH2": "Make a project in the current version of Scratch", diff --git a/public/languages/sv-se.json b/public/languages/sv-se.json index 7e3f1458f..f07abba69 100644 --- a/public/languages/sv-se.json +++ b/public/languages/sv-se.json @@ -3,6 +3,7 @@ "TITLE": "Maskininlärning för barn", "BACK": "Tillbaka", + "NEXT": "Next", "BACKTOPROJECT": "< Tillbaka till projekt", "BACKTOMODEL": "< Back to model", "ERROR": "Fel:", @@ -704,6 +705,164 @@ "NUMBERSONLY": "Only machine learning models for numbers projects can be described" } }, + "DESCRIBETEXTMODEL": { + "ZOOM": "Use these controls to zoom in on the diagrams", + "ERRORS": { + "TEXTONLY": "Only neural networks for text projects can be described" + }, + "MOREINFO": "for more detail, try searching for:", + "PAGE1": { + "TITLE": "neural networks", + "TEXT1": "The type of machine learning model you trained in this project is called a neural network.", + "TEXT2": "The next few pages will explain how your model was created.", + "TEXT3": "These diagrams aren't an exact description of your model. Your model is larger and more complicated, but these diagrams are easier to explain." + }, + "PAGE2": { + "TITLE": "deep learning", + "TEXT1": "The model is made of nodes, arranged in vertical layers.", + "TEXT2": "Models with a lot of layers are described as deep.", + "TEXT3": "Deep models can give better results, but take longer to train." + }, + "PAGE3": { + "TITLE": "input layer", + "TEXT1": "Let's start with one of the training examples used to create your model.", + "TEXT2": "Your training example is shown as input on the left." + }, + "PAGE4": { + "TITLE": "encoding", + "TEXT1": "To use your training example to train the model, first the text needs to be turned into a series of numbers.", + "TEXT2": "There are lots of ways to do this.", + "TEXT3": "If you build your own machine learning model, you need to choose a way that works well for your particular project." + }, + "PAGE5": { + "TITLE": "bag of words", + "TEXT1": "One way of turning your text into numbers is to make each number a count of how many times a word is included." + }, + "PAGE6": { + "TITLE": "feature extraction", + "TEXT1": "There are other things you can count. Things that are helpful to count depend on the project you are doing, and what you want your model to learn to recognize patterns in.", + "TEXT2": "Counting things is quick and simple, but not as good for projects where the order of words is important." + }, + "PAGE7": { + "TITLE": "word embeddings", + "TEXT1": "If you build your own machine learning model, you need to choose the method for turning text into numbers.", + "TEXT2": "Your model used a more complicated technique that does include the order of words in the text." + }, + "PAGE8": { + "TITLE": "hidden layer", + "TEXT1": "The numbers from the input layer go into sums that calculate values for the nodes in the next layer.", + "TEXT2": "The lines on the diagram show which input values are used to calculate which values in the next layer." + }, + "PAGE9": { + "TITLE": "activation functions", + "TEXT1": "There are lots of different types of calculation you can use. Not every node in the model has to use the same calculation.", + "TEXT2": "If you build your own machine learning model, you need to choose which equations to use for each node.", + "TEXT3": "The functions to use for each node in your model were chosen for you." + }, + "PAGE10": { + "TITLE": "weight", + "TEXT1": "Each line in the diagram has a weight number that can be used in the sum.", + "TEXT2": "Training the model is how we work out the best number to put on each line, as you'll see in a moment." + }, + "PAGE11": { + "TITLE": "bias", + "TEXT1": "Each node in the diagram has a bias number that is used in the sum as well.", + "TEXT2": "Training the model is also how we work out the right bias number, as you'll see in a moment.", + "TEXT3": "Try to work out what you think the value for this node will be." + }, + "PAGE12": { + "TITLE": "activation functions", + "TEXT1": "This is a common function used in neural networks.", + "TEXT2": "Each input value is multiplied by the value for the line that connected it. These are all added together. Then added to the value for the node itself." + }, + "PAGE13": { + "TITLE": "activation functions", + "TEXT1": "Each node has its own bias value.", + "TEXT2": "Each line has its own weight value." + }, + "PAGE14": { + "TITLE": "hidden layers", + "TEXT1": "Each node in the model can use different equations.", + "TEXT2": "If you build your own machine learning model, you need to choose:", + "LIST1": "how many layers to have", + "LIST2": "how many nodes to put in each layer", + "LIST3": "which functions to use for each node" + }, + "PAGE15": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The number of layers, the number of nodes in each layer, and the functions to use for each node in your model were all chosen for you." + }, + "PAGE16": { + "TITLE": "output layer", + "TEXT1": "The final layer gives the machine learning model's prediction.", + "TEXT2": "There is a node for each bucket you added to your training data." + }, + "PAGE17": { + "TITLE": "loss function", + "TEXT1": "The prediction is compared with the correct answer (the training bucket you put this example in).", + "TEXT2": "The difference is described as the error rate, and tells us how well the machine learning model is doing at this stage of the training." + }, + "PAGE18": { + "TITLE": "back propagation", + "TEXT1": "The error rate is used to go backwards through the layers and nudge the numbers for each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error rate a little smaller." + }, + "PAGE19": { + "TITLE": "neural networks", + "TEXT1": "Next, this is all done over again, with another of your training examples." + }, + "PAGE20": { + "TITLE": "encoding", + "TEXT1": "Remember, the first step is turning the example text into numbers.", + "TEXT2": "Counting things that are in the text is an easy way to do it, but there are more complicated ways to do it if the order of words is important.", + "TEXT3": "The method for your model was chosen for you." + }, + "PAGE21": { + "TITLE": "hidden layer", + "TEXT1": "Remember, nodes in the middle of the model represent sums that are done using the input numbers.", + "TEXT2": "Different calculations can be chosen for each node." + }, + "PAGE22": { + "TITLE": "activation functions", + "TEXT1": "Remember, the calculations use numbers from the nodes on the left that are connected to it, as well as the numbers for the lines that connect them." + }, + "PAGE23": { + "TITLE": "activation functions", + "TEXT1": "The calculations also use a bias number for the node itself." + }, + "PAGE24": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The functions to use for each node in your model were chosen for you." + }, + "PAGE25": { + "TITLE": "output layer", + "TEXT1": "Remember, the output layer gives the machine learning model's prediction.", + "TEXT2": "Each node gives you the prediction for one of the buckets that you added to your training data." + }, + "PAGE26": { + "TITLE": "loss function", + "TEXT1": "Remember, results from the output layer are compared with the correct answer, which shows how well the machine learning model is doing." + }, + "PAGE27": { + "TITLE": "back propagation", + "TEXT1": "Remember that the error rate is used to go backwards through the layers and nudge the numbers associated with each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error a little smaller.", + "TEXT3": "This is how training works out the best numbers to use for each of the nodes and lines." + }, + "PAGE28": { + "TITLE": "epochs", + "TEXT1": "One run-through of every training example you collected through the model is called an epoch.", + "TEXT2": "Each time through, the weights for each node are nudged a little more, until hopefully the error rate for predictions are as low as they can be.", + "TEXT3": "If you build your own machine learning model, you need to choose how many epochs you want to run." + }, + "PAGE29": { + "TITLE": "neural networks", + "TEXT1": "I hope this simplified description gives you an idea what happens when you click on the \"Train new machine learning model\" button.", + "TEXT2": "For an explanation of why this process works, try watching \"How Machines Learn\" by CGP Grey." + } + }, "MAKES": { "TITLE": "Make something with your machine learning model", "SCRATCH2": "Make a project in the old version of Scratch", diff --git a/public/languages/tr.json b/public/languages/tr.json index 34bafef98..6b6d8f180 100644 --- a/public/languages/tr.json +++ b/public/languages/tr.json @@ -3,6 +3,7 @@ "TITLE": "Çocuklar İçin Makine Öğrenimi", "BACK": "Geri", + "NEXT": "Next", "BACKTOPROJECT": "< Projeye dön", "BACKTOMODEL": "< Back to model", "ERROR": "Hata:", @@ -704,6 +705,164 @@ "NUMBERSONLY": "Only machine learning models for numbers projects can be described" } }, + "DESCRIBETEXTMODEL": { + "ZOOM": "Use these controls to zoom in on the diagrams", + "ERRORS": { + "TEXTONLY": "Only neural networks for text projects can be described" + }, + "MOREINFO": "for more detail, try searching for:", + "PAGE1": { + "TITLE": "neural networks", + "TEXT1": "The type of machine learning model you trained in this project is called a neural network.", + "TEXT2": "The next few pages will explain how your model was created.", + "TEXT3": "These diagrams aren't an exact description of your model. Your model is larger and more complicated, but these diagrams are easier to explain." + }, + "PAGE2": { + "TITLE": "deep learning", + "TEXT1": "The model is made of nodes, arranged in vertical layers.", + "TEXT2": "Models with a lot of layers are described as deep.", + "TEXT3": "Deep models can give better results, but take longer to train." + }, + "PAGE3": { + "TITLE": "input layer", + "TEXT1": "Let's start with one of the training examples used to create your model.", + "TEXT2": "Your training example is shown as input on the left." + }, + "PAGE4": { + "TITLE": "encoding", + "TEXT1": "To use your training example to train the model, first the text needs to be turned into a series of numbers.", + "TEXT2": "There are lots of ways to do this.", + "TEXT3": "If you build your own machine learning model, you need to choose a way that works well for your particular project." + }, + "PAGE5": { + "TITLE": "bag of words", + "TEXT1": "One way of turning your text into numbers is to make each number a count of how many times a word is included." + }, + "PAGE6": { + "TITLE": "feature extraction", + "TEXT1": "There are other things you can count. Things that are helpful to count depend on the project you are doing, and what you want your model to learn to recognize patterns in.", + "TEXT2": "Counting things is quick and simple, but not as good for projects where the order of words is important." + }, + "PAGE7": { + "TITLE": "word embeddings", + "TEXT1": "If you build your own machine learning model, you need to choose the method for turning text into numbers.", + "TEXT2": "Your model used a more complicated technique that does include the order of words in the text." + }, + "PAGE8": { + "TITLE": "hidden layer", + "TEXT1": "The numbers from the input layer go into sums that calculate values for the nodes in the next layer.", + "TEXT2": "The lines on the diagram show which input values are used to calculate which values in the next layer." + }, + "PAGE9": { + "TITLE": "activation functions", + "TEXT1": "There are lots of different types of calculation you can use. Not every node in the model has to use the same calculation.", + "TEXT2": "If you build your own machine learning model, you need to choose which equations to use for each node.", + "TEXT3": "The functions to use for each node in your model were chosen for you." + }, + "PAGE10": { + "TITLE": "weight", + "TEXT1": "Each line in the diagram has a weight number that can be used in the sum.", + "TEXT2": "Training the model is how we work out the best number to put on each line, as you'll see in a moment." + }, + "PAGE11": { + "TITLE": "bias", + "TEXT1": "Each node in the diagram has a bias number that is used in the sum as well.", + "TEXT2": "Training the model is also how we work out the right bias number, as you'll see in a moment.", + "TEXT3": "Try to work out what you think the value for this node will be." + }, + "PAGE12": { + "TITLE": "activation functions", + "TEXT1": "This is a common function used in neural networks.", + "TEXT2": "Each input value is multiplied by the value for the line that connected it. These are all added together. Then added to the value for the node itself." + }, + "PAGE13": { + "TITLE": "activation functions", + "TEXT1": "Each node has its own bias value.", + "TEXT2": "Each line has its own weight value." + }, + "PAGE14": { + "TITLE": "hidden layers", + "TEXT1": "Each node in the model can use different equations.", + "TEXT2": "If you build your own machine learning model, you need to choose:", + "LIST1": "how many layers to have", + "LIST2": "how many nodes to put in each layer", + "LIST3": "which functions to use for each node" + }, + "PAGE15": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The number of layers, the number of nodes in each layer, and the functions to use for each node in your model were all chosen for you." + }, + "PAGE16": { + "TITLE": "output layer", + "TEXT1": "The final layer gives the machine learning model's prediction.", + "TEXT2": "There is a node for each bucket you added to your training data." + }, + "PAGE17": { + "TITLE": "loss function", + "TEXT1": "The prediction is compared with the correct answer (the training bucket you put this example in).", + "TEXT2": "The difference is described as the error rate, and tells us how well the machine learning model is doing at this stage of the training." + }, + "PAGE18": { + "TITLE": "back propagation", + "TEXT1": "The error rate is used to go backwards through the layers and nudge the numbers for each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error rate a little smaller." + }, + "PAGE19": { + "TITLE": "neural networks", + "TEXT1": "Next, this is all done over again, with another of your training examples." + }, + "PAGE20": { + "TITLE": "encoding", + "TEXT1": "Remember, the first step is turning the example text into numbers.", + "TEXT2": "Counting things that are in the text is an easy way to do it, but there are more complicated ways to do it if the order of words is important.", + "TEXT3": "The method for your model was chosen for you." + }, + "PAGE21": { + "TITLE": "hidden layer", + "TEXT1": "Remember, nodes in the middle of the model represent sums that are done using the input numbers.", + "TEXT2": "Different calculations can be chosen for each node." + }, + "PAGE22": { + "TITLE": "activation functions", + "TEXT1": "Remember, the calculations use numbers from the nodes on the left that are connected to it, as well as the numbers for the lines that connect them." + }, + "PAGE23": { + "TITLE": "activation functions", + "TEXT1": "The calculations also use a bias number for the node itself." + }, + "PAGE24": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The functions to use for each node in your model were chosen for you." + }, + "PAGE25": { + "TITLE": "output layer", + "TEXT1": "Remember, the output layer gives the machine learning model's prediction.", + "TEXT2": "Each node gives you the prediction for one of the buckets that you added to your training data." + }, + "PAGE26": { + "TITLE": "loss function", + "TEXT1": "Remember, results from the output layer are compared with the correct answer, which shows how well the machine learning model is doing." + }, + "PAGE27": { + "TITLE": "back propagation", + "TEXT1": "Remember that the error rate is used to go backwards through the layers and nudge the numbers associated with each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error a little smaller.", + "TEXT3": "This is how training works out the best numbers to use for each of the nodes and lines." + }, + "PAGE28": { + "TITLE": "epochs", + "TEXT1": "One run-through of every training example you collected through the model is called an epoch.", + "TEXT2": "Each time through, the weights for each node are nudged a little more, until hopefully the error rate for predictions are as low as they can be.", + "TEXT3": "If you build your own machine learning model, you need to choose how many epochs you want to run." + }, + "PAGE29": { + "TITLE": "neural networks", + "TEXT1": "I hope this simplified description gives you an idea what happens when you click on the \"Train new machine learning model\" button.", + "TEXT2": "For an explanation of why this process works, try watching \"How Machines Learn\" by CGP Grey." + } + }, "MAKES": { "TITLE": "Make something with your machine learning model", "SCRATCH2": "Make a project in the old version of Scratch", diff --git a/public/languages/zh-cn.json b/public/languages/zh-cn.json index 8cc39336b..cc2a24bbd 100644 --- a/public/languages/zh-cn.json +++ b/public/languages/zh-cn.json @@ -3,6 +3,7 @@ "TITLE": "儿童机器学习", "BACK": " 返回 ", + "NEXT": "Next", "BACKTOPROJECT": "< 返回项目", "BACKTOMODEL": "< Back to model", "ERROR": "错误: ", @@ -704,6 +705,164 @@ "NUMBERSONLY": "Only machine learning models for numbers projects can be described" } }, + "DESCRIBETEXTMODEL": { + "ZOOM": "Use these controls to zoom in on the diagrams", + "ERRORS": { + "TEXTONLY": "Only neural networks for text projects can be described" + }, + "MOREINFO": "for more detail, try searching for:", + "PAGE1": { + "TITLE": "neural networks", + "TEXT1": "The type of machine learning model you trained in this project is called a neural network.", + "TEXT2": "The next few pages will explain how your model was created.", + "TEXT3": "These diagrams aren't an exact description of your model. Your model is larger and more complicated, but these diagrams are easier to explain." + }, + "PAGE2": { + "TITLE": "deep learning", + "TEXT1": "The model is made of nodes, arranged in vertical layers.", + "TEXT2": "Models with a lot of layers are described as deep.", + "TEXT3": "Deep models can give better results, but take longer to train." + }, + "PAGE3": { + "TITLE": "input layer", + "TEXT1": "Let's start with one of the training examples used to create your model.", + "TEXT2": "Your training example is shown as input on the left." + }, + "PAGE4": { + "TITLE": "encoding", + "TEXT1": "To use your training example to train the model, first the text needs to be turned into a series of numbers.", + "TEXT2": "There are lots of ways to do this.", + "TEXT3": "If you build your own machine learning model, you need to choose a way that works well for your particular project." + }, + "PAGE5": { + "TITLE": "bag of words", + "TEXT1": "One way of turning your text into numbers is to make each number a count of how many times a word is included." + }, + "PAGE6": { + "TITLE": "feature extraction", + "TEXT1": "There are other things you can count. Things that are helpful to count depend on the project you are doing, and what you want your model to learn to recognize patterns in.", + "TEXT2": "Counting things is quick and simple, but not as good for projects where the order of words is important." + }, + "PAGE7": { + "TITLE": "word embeddings", + "TEXT1": "If you build your own machine learning model, you need to choose the method for turning text into numbers.", + "TEXT2": "Your model used a more complicated technique that does include the order of words in the text." + }, + "PAGE8": { + "TITLE": "hidden layer", + "TEXT1": "The numbers from the input layer go into sums that calculate values for the nodes in the next layer.", + "TEXT2": "The lines on the diagram show which input values are used to calculate which values in the next layer." + }, + "PAGE9": { + "TITLE": "activation functions", + "TEXT1": "There are lots of different types of calculation you can use. Not every node in the model has to use the same calculation.", + "TEXT2": "If you build your own machine learning model, you need to choose which equations to use for each node.", + "TEXT3": "The functions to use for each node in your model were chosen for you." + }, + "PAGE10": { + "TITLE": "weight", + "TEXT1": "Each line in the diagram has a weight number that can be used in the sum.", + "TEXT2": "Training the model is how we work out the best number to put on each line, as you'll see in a moment." + }, + "PAGE11": { + "TITLE": "bias", + "TEXT1": "Each node in the diagram has a bias number that is used in the sum as well.", + "TEXT2": "Training the model is also how we work out the right bias number, as you'll see in a moment.", + "TEXT3": "Try to work out what you think the value for this node will be." + }, + "PAGE12": { + "TITLE": "activation functions", + "TEXT1": "This is a common function used in neural networks.", + "TEXT2": "Each input value is multiplied by the value for the line that connected it. These are all added together. Then added to the value for the node itself." + }, + "PAGE13": { + "TITLE": "activation functions", + "TEXT1": "Each node has its own bias value.", + "TEXT2": "Each line has its own weight value." + }, + "PAGE14": { + "TITLE": "hidden layers", + "TEXT1": "Each node in the model can use different equations.", + "TEXT2": "If you build your own machine learning model, you need to choose:", + "LIST1": "how many layers to have", + "LIST2": "how many nodes to put in each layer", + "LIST3": "which functions to use for each node" + }, + "PAGE15": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The number of layers, the number of nodes in each layer, and the functions to use for each node in your model were all chosen for you." + }, + "PAGE16": { + "TITLE": "output layer", + "TEXT1": "The final layer gives the machine learning model's prediction.", + "TEXT2": "There is a node for each bucket you added to your training data." + }, + "PAGE17": { + "TITLE": "loss function", + "TEXT1": "The prediction is compared with the correct answer (the training bucket you put this example in).", + "TEXT2": "The difference is described as the error rate, and tells us how well the machine learning model is doing at this stage of the training." + }, + "PAGE18": { + "TITLE": "back propagation", + "TEXT1": "The error rate is used to go backwards through the layers and nudge the numbers for each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error rate a little smaller." + }, + "PAGE19": { + "TITLE": "neural networks", + "TEXT1": "Next, this is all done over again, with another of your training examples." + }, + "PAGE20": { + "TITLE": "encoding", + "TEXT1": "Remember, the first step is turning the example text into numbers.", + "TEXT2": "Counting things that are in the text is an easy way to do it, but there are more complicated ways to do it if the order of words is important.", + "TEXT3": "The method for your model was chosen for you." + }, + "PAGE21": { + "TITLE": "hidden layer", + "TEXT1": "Remember, nodes in the middle of the model represent sums that are done using the input numbers.", + "TEXT2": "Different calculations can be chosen for each node." + }, + "PAGE22": { + "TITLE": "activation functions", + "TEXT1": "Remember, the calculations use numbers from the nodes on the left that are connected to it, as well as the numbers for the lines that connect them." + }, + "PAGE23": { + "TITLE": "activation functions", + "TEXT1": "The calculations also use a bias number for the node itself." + }, + "PAGE24": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The functions to use for each node in your model were chosen for you." + }, + "PAGE25": { + "TITLE": "output layer", + "TEXT1": "Remember, the output layer gives the machine learning model's prediction.", + "TEXT2": "Each node gives you the prediction for one of the buckets that you added to your training data." + }, + "PAGE26": { + "TITLE": "loss function", + "TEXT1": "Remember, results from the output layer are compared with the correct answer, which shows how well the machine learning model is doing." + }, + "PAGE27": { + "TITLE": "back propagation", + "TEXT1": "Remember that the error rate is used to go backwards through the layers and nudge the numbers associated with each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error a little smaller.", + "TEXT3": "This is how training works out the best numbers to use for each of the nodes and lines." + }, + "PAGE28": { + "TITLE": "epochs", + "TEXT1": "One run-through of every training example you collected through the model is called an epoch.", + "TEXT2": "Each time through, the weights for each node are nudged a little more, until hopefully the error rate for predictions are as low as they can be.", + "TEXT3": "If you build your own machine learning model, you need to choose how many epochs you want to run." + }, + "PAGE29": { + "TITLE": "neural networks", + "TEXT1": "I hope this simplified description gives you an idea what happens when you click on the \"Train new machine learning model\" button.", + "TEXT2": "For an explanation of why this process works, try watching \"How Machines Learn\" by CGP Grey." + } + }, "MAKES": { "TITLE": "Make something with your machine learning model", "SCRATCH2": "Make a project in the old version of Scratch", diff --git a/public/languages/zh-tw.json b/public/languages/zh-tw.json index 5ca81b9ff..3847189c7 100644 --- a/public/languages/zh-tw.json +++ b/public/languages/zh-tw.json @@ -3,6 +3,7 @@ "TITLE": "兒童機器學習", "BACK": "返回", + "NEXT": "Next", "BACKTOPROJECT": "< 返回到專案", "BACKTOMODEL": "< 返回到模型", "ERROR": "錯誤:", @@ -704,6 +705,164 @@ "NUMBERSONLY": "只有數字類型的機器學習專案可以被描述出來" } }, + "DESCRIBETEXTMODEL": { + "ZOOM": "Use these controls to zoom in on the diagrams", + "ERRORS": { + "TEXTONLY": "Only neural networks for text projects can be described" + }, + "MOREINFO": "for more detail, try searching for:", + "PAGE1": { + "TITLE": "neural networks", + "TEXT1": "The type of machine learning model you trained in this project is called a neural network.", + "TEXT2": "The next few pages will explain how your model was created.", + "TEXT3": "These diagrams aren't an exact description of your model. Your model is larger and more complicated, but these diagrams are easier to explain." + }, + "PAGE2": { + "TITLE": "deep learning", + "TEXT1": "The model is made of nodes, arranged in vertical layers.", + "TEXT2": "Models with a lot of layers are described as deep.", + "TEXT3": "Deep models can give better results, but take longer to train." + }, + "PAGE3": { + "TITLE": "input layer", + "TEXT1": "Let's start with one of the training examples used to create your model.", + "TEXT2": "Your training example is shown as input on the left." + }, + "PAGE4": { + "TITLE": "encoding", + "TEXT1": "To use your training example to train the model, first the text needs to be turned into a series of numbers.", + "TEXT2": "There are lots of ways to do this.", + "TEXT3": "If you build your own machine learning model, you need to choose a way that works well for your particular project." + }, + "PAGE5": { + "TITLE": "bag of words", + "TEXT1": "One way of turning your text into numbers is to make each number a count of how many times a word is included." + }, + "PAGE6": { + "TITLE": "feature extraction", + "TEXT1": "There are other things you can count. Things that are helpful to count depend on the project you are doing, and what you want your model to learn to recognize patterns in.", + "TEXT2": "Counting things is quick and simple, but not as good for projects where the order of words is important." + }, + "PAGE7": { + "TITLE": "word embeddings", + "TEXT1": "If you build your own machine learning model, you need to choose the method for turning text into numbers.", + "TEXT2": "Your model used a more complicated technique that does include the order of words in the text." + }, + "PAGE8": { + "TITLE": "hidden layer", + "TEXT1": "The numbers from the input layer go into sums that calculate values for the nodes in the next layer.", + "TEXT2": "The lines on the diagram show which input values are used to calculate which values in the next layer." + }, + "PAGE9": { + "TITLE": "activation functions", + "TEXT1": "There are lots of different types of calculation you can use. Not every node in the model has to use the same calculation.", + "TEXT2": "If you build your own machine learning model, you need to choose which equations to use for each node.", + "TEXT3": "The functions to use for each node in your model were chosen for you." + }, + "PAGE10": { + "TITLE": "weight", + "TEXT1": "Each line in the diagram has a weight number that can be used in the sum.", + "TEXT2": "Training the model is how we work out the best number to put on each line, as you'll see in a moment." + }, + "PAGE11": { + "TITLE": "bias", + "TEXT1": "Each node in the diagram has a bias number that is used in the sum as well.", + "TEXT2": "Training the model is also how we work out the right bias number, as you'll see in a moment.", + "TEXT3": "Try to work out what you think the value for this node will be." + }, + "PAGE12": { + "TITLE": "activation functions", + "TEXT1": "This is a common function used in neural networks.", + "TEXT2": "Each input value is multiplied by the value for the line that connected it. These are all added together. Then added to the value for the node itself." + }, + "PAGE13": { + "TITLE": "activation functions", + "TEXT1": "Each node has its own bias value.", + "TEXT2": "Each line has its own weight value." + }, + "PAGE14": { + "TITLE": "hidden layers", + "TEXT1": "Each node in the model can use different equations.", + "TEXT2": "If you build your own machine learning model, you need to choose:", + "LIST1": "how many layers to have", + "LIST2": "how many nodes to put in each layer", + "LIST3": "which functions to use for each node" + }, + "PAGE15": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The number of layers, the number of nodes in each layer, and the functions to use for each node in your model were all chosen for you." + }, + "PAGE16": { + "TITLE": "output layer", + "TEXT1": "The final layer gives the machine learning model's prediction.", + "TEXT2": "There is a node for each bucket you added to your training data." + }, + "PAGE17": { + "TITLE": "loss function", + "TEXT1": "The prediction is compared with the correct answer (the training bucket you put this example in).", + "TEXT2": "The difference is described as the error rate, and tells us how well the machine learning model is doing at this stage of the training." + }, + "PAGE18": { + "TITLE": "back propagation", + "TEXT1": "The error rate is used to go backwards through the layers and nudge the numbers for each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error rate a little smaller." + }, + "PAGE19": { + "TITLE": "neural networks", + "TEXT1": "Next, this is all done over again, with another of your training examples." + }, + "PAGE20": { + "TITLE": "encoding", + "TEXT1": "Remember, the first step is turning the example text into numbers.", + "TEXT2": "Counting things that are in the text is an easy way to do it, but there are more complicated ways to do it if the order of words is important.", + "TEXT3": "The method for your model was chosen for you." + }, + "PAGE21": { + "TITLE": "hidden layer", + "TEXT1": "Remember, nodes in the middle of the model represent sums that are done using the input numbers.", + "TEXT2": "Different calculations can be chosen for each node." + }, + "PAGE22": { + "TITLE": "activation functions", + "TEXT1": "Remember, the calculations use numbers from the nodes on the left that are connected to it, as well as the numbers for the lines that connect them." + }, + "PAGE23": { + "TITLE": "activation functions", + "TEXT1": "The calculations also use a bias number for the node itself." + }, + "PAGE24": { + "TITLE": "hidden layer", + "TEXT1": "This continues through the rest of the model.", + "TEXT2": "The functions to use for each node in your model were chosen for you." + }, + "PAGE25": { + "TITLE": "output layer", + "TEXT1": "Remember, the output layer gives the machine learning model's prediction.", + "TEXT2": "Each node gives you the prediction for one of the buckets that you added to your training data." + }, + "PAGE26": { + "TITLE": "loss function", + "TEXT1": "Remember, results from the output layer are compared with the correct answer, which shows how well the machine learning model is doing." + }, + "PAGE27": { + "TITLE": "back propagation", + "TEXT1": "Remember that the error rate is used to go backwards through the layers and nudge the numbers associated with each of the lines and nodes.", + "TEXT2": "Each weight and bias number is increased a little bit or decreased a little bit, depending on what would've made the error a little smaller.", + "TEXT3": "This is how training works out the best numbers to use for each of the nodes and lines." + }, + "PAGE28": { + "TITLE": "epochs", + "TEXT1": "One run-through of every training example you collected through the model is called an epoch.", + "TEXT2": "Each time through, the weights for each node are nudged a little more, until hopefully the error rate for predictions are as low as they can be.", + "TEXT3": "If you build your own machine learning model, you need to choose how many epochs you want to run." + }, + "PAGE29": { + "TITLE": "neural networks", + "TEXT1": "I hope this simplified description gives you an idea what happens when you click on the \"Train new machine learning model\" button.", + "TEXT2": "For an explanation of why this process works, try watching \"How Machines Learn\" by CGP Grey." + } + }, "MAKES": { "TITLE": "使用你的機器學習模型製作一些作品吧", "SCRATCH2": "使用舊版本的Scratch進行創作", diff --git a/src/lib/restapi/config.ts b/src/lib/restapi/config.ts index e3f2c380b..9f5228d65 100644 --- a/src/lib/restapi/config.ts +++ b/src/lib/restapi/config.ts @@ -67,6 +67,7 @@ export const CSP_DIRECTIVES = { 'https://www.google-analytics.com', 'https://www.googletagmanager.com', 'https://browser.sentry-cdn.com', + 'https://d3js.org', ], frameSrc: ["'self'", 'http://embed.wakelet.com', diff --git a/src/lib/restapi/models.ts b/src/lib/restapi/models.ts index 068e9efc0..1654ea96a 100644 --- a/src/lib/restapi/models.ts +++ b/src/lib/restapi/models.ts @@ -10,6 +10,7 @@ import * as Types from '../training/training-types'; import * as conversation from '../training/conversation'; import * as visualrec from '../training/visualrecognition'; import * as numbers from '../training/numbers'; +import * as textmodels from '../training/describetext'; import * as notifications from '../notifications/slack'; import * as base64decode from '../utils/base64decode'; import * as download from '../utils/download'; @@ -271,20 +272,30 @@ async function deleteModel(req: auth.RequestWithProject, res: Express.Response) } - async function describeModel(req: auth.RequestWithProject, res: Express.Response) { - if (req.project.type !== 'numbers') { - return errors.notImplemented(res); - } - try { - const classifierInfo = await numbers.getModelVisualisation(req.project); + if (req.project.type === 'numbers') { + const classifierInfo = await numbers.getModelVisualisation(req.project); + + // computing the visualisation data is super expensive + // so ask browsers to cache it forever + res.set(headers.CACHE_1YEAR); - // computing the visualisation data is super expensive - // so ask browsers to cache it forever - res.set(headers.CACHE_1YEAR); + return res.json(classifierInfo); + } + else if (req.project.type === 'text') { + const classifierInfo = await textmodels.getModelVisualisation(req.project); - return res.json(classifierInfo); + // computing this analysis is quite expensiive, so + // ask browsers to cache it for a while + res.set(headers.CACHE_1HOUR); + + return res.json(classifierInfo); + } + else { + // sounds and images not supported yet + return errors.notImplemented(res); + } } catch (err) { return errors.unknownError(res, err); diff --git a/src/lib/training/describetext.ts b/src/lib/training/describetext.ts new file mode 100644 index 000000000..4b702300a --- /dev/null +++ b/src/lib/training/describetext.ts @@ -0,0 +1,175 @@ +// external dependencies +import syllable = require('syllable'); +import nlp = require('compromise'); +import nlpnum = require('compromise-numbers'); +// local dependencies +import * as store from '../db/store'; +import * as Objects from '../db/db-types'; +import * as random from '../utils/random'; +import * as bagofwords from '../utils/bagofwords'; +import * as emoticons from '../utils/emoticons'; + + + +const nlpFunctions: any = nlp.extend(nlpnum); + + + + +function getCustomFeatures(trainingExampleText: string, emoticonsDictionary: string[]): TextModelTrainingAnnotation[] { + return [ + // 1 + { annotation : 'number of letters', value : countLetters(trainingExampleText) }, + // 2 + { annotation : 'punctuation marks', value : countRegexMatches(trainingExampleText, PUNCTUATION_REGEX) }, + // 3 + { annotation : 'number of capital letters', value : countRegexMatches(trainingExampleText, CAPITALLETTER_REGEX) }, + // 4 + { annotation : 'syllables', value : syllable(trainingExampleText) }, + // 5 + { annotation : 'includes a question mark', value : containsQuestionMark(trainingExampleText) }, + // 6 + { annotation : 'number of verbs', value : nlpFunctions(trainingExampleText).verbs().json().length }, + // 7 + { annotation : 'number of emoticons', value : emoticons.countEmoticons(trainingExampleText, emoticonsDictionary) }, + // 8 + { annotation : 'mentions of numbers', value : nlpFunctions(trainingExampleText).numbers().json().length }, + // 9 + { annotation : 'usages of contractions', value : nlpFunctions(trainingExampleText).contractions().json().length }, + ]; +} + +function getRandomFeatures(): TextModelTrainingAnnotation[] { + return [ + // 1 + { annotation : '', value : random.int(1, 5) }, + // 2 + { annotation : '', value : random.int(1, 5) }, + // 3 + { annotation : '', value : random.int(0, 5) }, + // 4 + { annotation : '', value : random.int(1, 5) }, + // 5 + { annotation : '', value : random.int(0, 5) }, + // 6 + { annotation : '', value : random.int(0, 5) }, + // 7 + { annotation : '', value : random.int(0, 5) }, + // 8 + { annotation : '', value : random.int(1, 5) }, + // 9 + { annotation : '', value : random.int(0, 5) }, + // 10 + { annotation : '', value : random.int(1, 5) }, + ]; +} + + + + +function getTrainingExample(trainingdata: Objects.TextTraining, label: string, project: Objects.Project, bowDictionary: string[], emoticonsDictionary: string[]): TextModelTrainingExample { + + const trainingOutput: { [id: string]: number } = {}; + + const example = { + text: trainingdata.textdata, + label, + bagofwords : bagofwords.getTrainingExampleWordCounts(trainingdata.textdata, bowDictionary) + .map((wc) => { + return { + annotation : 'number of times that the word "' + wc.word.toUpperCase() + '" appears', + value: wc.count, + }; + }), + customfeatures : getCustomFeatures(trainingdata.textdata, emoticonsDictionary), + random : getRandomFeatures(), + output: trainingOutput, + }; + + const scores = random.ints(project.labels.length); + for (let i = 0; i < project.labels.length; i++) { + const projectlabel = project.labels[i]; + example.output[projectlabel] = scores[i]; + } + + return example; +} + + +async function getTrainingBagOfWords(project: Objects.Project): Promise { + const allTraining = await store.getTextTraining(project.id, { start : 0, limit : 1000 }); + const counts = bagofwords.getMostCommonWords(allTraining.map(t => t.textdata), 20); + return counts.map(c => c.word); +} + + +export async function getModelVisualisation(project: Objects.Project): Promise { + + const bagOfWordsDictionary = await getTrainingBagOfWords(project); + const emoticonsDictionary = emoticons.getAllKnownEmoticons(); + + const EXAMPLES_PER_LABEL = 5; + + const examplesByLabel: { [label: string]: TextModelTrainingExample[] } = {}; + + const labels = project.labels; + for (const label of labels) { + examplesByLabel[label] = []; + + const examples = await store.getTextTrainingByLabel(project.id, label, { start: 0, limit: EXAMPLES_PER_LABEL }); + examples.forEach((example) => { + const trainingExample = getTrainingExample(example, label, project, bagOfWordsDictionary, emoticonsDictionary); + examplesByLabel[label].push(trainingExample); + }); + } + + const analysis: TextModelDescriptionResponse = { examples: [] }; + for (let i = 0; i < EXAMPLES_PER_LABEL; i++) { + for (const label of labels) { + if (examplesByLabel[label][i]) { + analysis.examples.push(examplesByLabel[label][i]); + } + } + } + + return analysis; +} + + + +function countLetters(text: string): number { + return text.length; +} + +const PUNCTUATION_REGEX = /[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]/g; +const QUESTIONMARK_REGEX = /[?]/g; +const CAPITALLETTER_REGEX = /[A-Z]/g; + + +function countRegexMatches(text: string, regex: RegExp): number { + return ((text || '').match(regex) || []).length; +} +function containsQuestionMark(text: string): number { + return QUESTIONMARK_REGEX.test(text) ? 1 : 0; +} + + + + +export interface TextModelDescriptionResponse { + readonly examples: TextModelTrainingExample[]; +} + +interface TextModelTrainingExample { + readonly text: string; + readonly label: string; + readonly bagofwords: TextModelTrainingAnnotation[]; + readonly customfeatures : TextModelTrainingAnnotation[]; + readonly random: TextModelTrainingAnnotation[]; + readonly output: { [id: string]: number }; +} + +interface TextModelTrainingAnnotation { + readonly annotation: string; + readonly value: number; +} diff --git a/src/lib/utils/bagofwords.ts b/src/lib/utils/bagofwords.ts new file mode 100644 index 000000000..99fad4fc5 --- /dev/null +++ b/src/lib/utils/bagofwords.ts @@ -0,0 +1,143 @@ +// external dependencies +import * as natural from 'natural'; + + + + +const tokenizer = new natural.WordTokenizer(); + + +export function tokenize(text: string): string[] { + return tokenizer.tokenize(text) + .map(w => w.toLowerCase()) + .filter(w => w !== 't' && + w !== 'd' && + w !== 's' && + w !== 'the'); +} + +function countAllWords(texts: string[]): { [word: string]: number } { + const allWords: { [word: string]: number } = {}; + for (const text of texts) { + const words = tokenize(text); + for (const word of words) { + if (!(word in allWords)) { + allWords[word] = 0; + } + allWords[word] += 1; + } + } + return allWords; +} + +function getWordCounts(texts: string[]): WordCount[] { + const allWords = countAllWords(texts); + const allCounts: WordCount[] = []; + for (const word in allWords) { + if (allWords.hasOwnProperty(word)) { + allCounts.push({ word, count: allWords[word] }); + } + } + return allCounts; +} + +const PADDING_WORDS = [ + 'would', + 'water', + 'first', + 'long', + 'time', + 'made', + 'people', + 'there', + 'some', + 'word', +]; + +export function getMostCommonWords(texts: string[], num: number): SortedWordCount[] { + const allWords = getWordCounts(texts); + allWords.sort((x, y) => { + if (x.count === y.count) { + return 0; + } + return x.count < y.count ? 1 : -1; + }); + const mostCommonWords = allWords.slice(0, num); + for (let i = 0; i < PADDING_WORDS.length && mostCommonWords.length < num; i++) { + const paddingWord = PADDING_WORDS[i]; + if (!(mostCommonWords.some(mcw => mcw.word === paddingWord))) { + mostCommonWords.push({ word : paddingWord, count : 0 }); + } + } + return mostCommonWords; +} + + +export function getTrainingExampleWordCounts(trainingExampleText: string, bowDictionary: string[]): WordCount[] { + const REQUIRED_MINIMUM = 10; + + const trainingExampleWords = tokenize(trainingExampleText); + + const trainingExampleWordCounts: { [word: string]: number } = {}; + for (const word of trainingExampleWords) { + if (bowDictionary.includes(word)) { + if (!(word in trainingExampleWordCounts)) { + trainingExampleWordCounts[word] = 0; + } + trainingExampleWordCounts[word] += 1; + } + } + + if (Object.keys(trainingExampleWordCounts).length < 2) { + const wordsToAdd = getMostCommonWords([ trainingExampleText ], 2); + for (const wordToAdd of wordsToAdd) { + trainingExampleWordCounts[wordToAdd.word] = wordToAdd.count; + } + } + + let zeroWordIndex = 0; + let dictionarySizeLimit = REQUIRED_MINIMUM; + if (bowDictionary.length < dictionarySizeLimit) { + dictionarySizeLimit = bowDictionary.length; + } + while (Object.keys(trainingExampleWordCounts).length < dictionarySizeLimit) { // } && zeroWordIndex < bowDictionary.length) { + if (!(bowDictionary[zeroWordIndex] in trainingExampleWordCounts)) { + trainingExampleWordCounts[bowDictionary[zeroWordIndex]] = 0; + } + zeroWordIndex += 1; + } + + if (Object.keys(trainingExampleWordCounts).length < REQUIRED_MINIMUM) { + zeroWordIndex = 0; + const wordsToAdd = getMostCommonWords([ trainingExampleText ], REQUIRED_MINIMUM); + while ((Object.keys(trainingExampleWordCounts).length < REQUIRED_MINIMUM) && (zeroWordIndex < wordsToAdd.length)) { + const wordToAdd = wordsToAdd[zeroWordIndex]; + if (!(wordToAdd.word in trainingExampleWordCounts)) { + trainingExampleWordCounts[wordToAdd.word] = wordToAdd.count; + } + zeroWordIndex += 1; + } + } + + return Object.keys(trainingExampleWordCounts).map(word => { + return { + word, + count : trainingExampleWordCounts[word], + }; + }); +} + + + + + + +export interface WordCount { + readonly word: string; + readonly count: number; +} + +export interface SortedWordCount { + readonly word: string; + readonly count: number; +} diff --git a/src/lib/utils/emoticons.ts b/src/lib/utils/emoticons.ts new file mode 100644 index 000000000..84f96ed3e --- /dev/null +++ b/src/lib/utils/emoticons.ts @@ -0,0 +1,25 @@ +// external dependencies +import * as emoticons from 'emoticon'; + + +export function getAllKnownEmoticons(): string[] { + let allEmoticons: string[] = []; + emoticons.forEach((emoticon: any) => { + allEmoticons = allEmoticons.concat(emoticon.emoticons); + }); + return allEmoticons; +} + +const IGNORE = [ + ':-', +]; + +export function countEmoticons(text: string, emoticonsToSearchFor: string[]): number { + let count = 0; + for (const emoticon of emoticonsToSearchFor) { + if (!IGNORE.includes(emoticon) && text.includes(emoticon)) { + count += 1; + } + } + return count; +} diff --git a/src/lib/utils/random.ts b/src/lib/utils/random.ts index b3aa011ba..b7c3fa264 100644 --- a/src/lib/utils/random.ts +++ b/src/lib/utils/random.ts @@ -1,6 +1,32 @@ +// external dependencies +import * as _ from 'lodash'; + + export function int(min: number, max: number): number { min = Math.ceil(min); max = Math.floor(max) + 1; return Math.floor(Math.random() * (max - min)) + min; } + + +/** + * Generate {num} random numbers that sum to 100. + * @param num + * @param total + */ +export function ints(num: number): number[] { + const numbers = [ + int(40, 60), + ]; + + let runningTotal = numbers[0]; + for (let i = 1; i < num - 1; i++) { + const next = int(0, (95 - runningTotal)); + runningTotal += next; + numbers.push(next); + } + numbers.push(100 - runningTotal); + + return _.shuffle(numbers); +} diff --git a/src/tests/utils/bagofwords.ts b/src/tests/utils/bagofwords.ts new file mode 100644 index 000000000..c7cbf07ee --- /dev/null +++ b/src/tests/utils/bagofwords.ts @@ -0,0 +1,98 @@ +/*eslint-env mocha */ +import * as assert from 'assert'; + +import * as bagofwords from '../../lib/utils/bagofwords'; + + + +describe('Utils - bag of words', () => { + + it('should count the number of occurrences of words', () => { + const input = [ + 'This is a test', + 'Please verify that this works', + 'I want to test that this works and correctly verifies the count', + ]; + const counts = bagofwords.getMostCommonWords(input, 5); + assert.deepStrictEqual(counts, [ + { word : 'this', count : 3 }, + { word : 'test', count : 2 }, + { word : 'that', count : 2 }, + { word : 'works', count : 2 }, + { word : 'is', count : 1 }, + ]); + }); + + it('should filter out punctuation and common partial words', () => { + const input = [ + 'This hasn\'t been fully explained in the UI.', + 'Please? I don\'t want this to show up! Okay?! I\'d like to check that. They\'d be confused if they do.', + 'I\'d like to verify this hasn\'t allowed partial words through', + ]; + const counts = bagofwords.getMostCommonWords(input, 5); + assert.deepStrictEqual(counts, [ + { word : 'this', count : 3 }, + { word : 'i', count : 3 }, + { word : 'to', count : 3 }, + { word : 'hasn', count : 2 }, + { word : 'like', count : 2 }, + ]); + }); + + it('should handle small numbers of words', () => { + const input = [ + 'Hello world', + ]; + const counts = bagofwords.getMostCommonWords(input, 10); + assert.deepStrictEqual(counts, [ + { word : 'hello', count : 1 }, + { word : 'world', count : 1 }, + { word : 'would', count : 0 }, + { word : 'water', count : 0 }, + { word : 'first', count : 0 }, + { word : 'long', count : 0 }, + { word : 'time', count : 0 }, + { word : 'made', count : 0 }, + { word : 'people', count : 0 }, + { word : 'there', count : 0 }, + ]); + }); + + it('should handle small numbers of words from the padding list', () => { + const input = [ + 'would water first', + ]; + const counts = bagofwords.getMostCommonWords(input, 10); + assert.deepStrictEqual(counts, [ + { word : 'would', count : 1 }, + { word : 'water', count : 1 }, + { word : 'first', count : 1 }, + { word : 'long', count : 0 }, + { word : 'time', count : 0 }, + { word : 'made', count : 0 }, + { word : 'people', count : 0 }, + { word : 'there', count : 0 }, + { word : 'some', count : 0 }, + { word : 'word', count : 0 }, + ]); + }); + + it('should handle unusually small dictionaries', () => { + const bowDictionary = [ 'apple', 'banana', 'tomato', 'melon', 'bottle' ]; + const testString = 'I would like to drink a smoothie made from apple, Banana, & MELON. Please'; + + const counts = bagofwords.getTrainingExampleWordCounts(testString, bowDictionary); + assert.deepStrictEqual(counts, [ + { word: 'apple', count: 1 }, + { word: 'banana', count: 1 }, + { word: 'melon', count: 1 }, + { word: 'tomato', count: 0 }, + { word: 'bottle', count: 0 }, + { word: 'i', count: 1 }, + { word: 'would', count: 1 }, + { word: 'like', count: 1 }, + { word: 'to', count: 1 }, + { word: 'drink', count: 1 }, + ]); + }); +}); diff --git a/src/tests/utils/emoticons.ts b/src/tests/utils/emoticons.ts new file mode 100644 index 000000000..ea3069aab --- /dev/null +++ b/src/tests/utils/emoticons.ts @@ -0,0 +1,27 @@ +/*eslint-env mocha */ +import * as assert from 'assert'; + +import * as emoticons from '../../lib/utils/emoticons'; + + + +describe('Utils - emoticons', () => { + + const emoticonsLibrary = emoticons.getAllKnownEmoticons(); + + it('should recognize text without emoticons', () => { + const input = 'This is just plain text'; + assert.strictEqual(emoticons.countEmoticons(input, emoticonsLibrary), 0); + }); + + it('should count the number of emoticons in text', () => { + const input = 'This contains a smiley face :-) to indicate cheerful text'; + assert.strictEqual(emoticons.countEmoticons(input, emoticonsLibrary), 1); + }); + + it('should count the number of emoticons in text', () => { + const input = 'This contains a smiley face :-) and a crying face :\'('; + assert.strictEqual(emoticons.countEmoticons(input, emoticonsLibrary), 2); + }); + +}); diff --git a/src/tests/utils/random.ts b/src/tests/utils/random.ts new file mode 100644 index 000000000..48ca4ca70 --- /dev/null +++ b/src/tests/utils/random.ts @@ -0,0 +1,41 @@ +/*eslint-env mocha */ +import * as assert from 'assert'; + +import * as random from '../../lib/utils/random'; + + + +describe('Utils - random', () => { + + + it('should generate 2 random numbers that sum to 100', () => { + const nums = random.ints(2); + assert.strictEqual(nums.length, 2); + assert.strictEqual(nums[0] + nums[1], 100); + }); + + it('should generate 3 random numbers that sum to 100', () => { + const nums = random.ints(3); + assert.strictEqual(nums.length, 3); + assert.strictEqual(nums[0] + nums[1] + nums[2], 100); + }); + + it('should generate 4 random numbers that sum to 100', () => { + const nums = random.ints(4); + assert.strictEqual(nums.length, 4); + assert.strictEqual(nums[0] + nums[1] + nums[2] + nums[3], 100); + }); + + it('should generate 5 random numbers that sum to 100', () => { + const nums = random.ints(5); + assert.strictEqual(nums.length, 5); + assert.strictEqual(nums[0] + nums[1] + nums[2] + nums[3] + nums[4], 100); + }); + + it('should generate 6 random numbers that sum to 100', () => { + const nums = random.ints(6); + assert.strictEqual(nums.length, 6); + assert.strictEqual(nums[0] + nums[1] + nums[2] + nums[3] + nums[4] + nums[5], 100); + }); + +});