-
Notifications
You must be signed in to change notification settings - Fork 1
/
startproject.xml
1 lines (1 loc) · 33.9 KB
/
startproject.xml
1
<project name="wf_digitaler_assistent_1" app="Snap! 6, https://snap.berkeley.edu" version="1"><notes></notes><thumbnail>data:image/png;base64,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</thumbnail><stage name="Stage" width="480" height="360" costume="0" color="255,255,255,1" tempo="60" threadsafe="false" penlog="false" volume="100" pan="0" lines="round" ternary="false" hyperops="true" codify="false" inheritance="true" sublistIDs="false" scheduled="false" id="1"><pentrails>data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAeAAAAFoCAYAAACPNyggAAAAAXNSR0IArs4c6QAADoVJREFUeF7t1cEJAAAIxDDdf2m3sJ+4wEEQuuMIECBAgACBd4F9XzRIgAABAgQIjAB7AgIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECAiwHyBAgAABAoGAAAfoJgkQIECAgAD7AQIECBAgEAgIcIBukgABAgQICLAfIECAAAECgYAAB+gmCRAgQICAAPsBAgQIECAQCAhwgG6SAAECBAgIsB8gQIAAAQKBgAAH6CYJECBAgIAA+wECBAgQIBAICHCAbpIAAQIECByxcQFpoRMBzwAAAABJRU5ErkJggg==</pentrails><costumes><list struct="atomic" id="2"></list></costumes><sounds><list struct="atomic" id="3"></list></sounds><variables></variables><blocks></blocks><scripts></scripts><sprites><sprite name="Sprite" idx="1" x="3.7350604464238586" y="-4.897040465168516" heading="90" scale="1" volume="100" pan="0" rotation="1" draggable="true" costume="0" color="80,80,80,1" pen="tip" id="8"><costumes><list struct="atomic" id="9"></list></costumes><sounds><list struct="atomic" id="10"></list></sounds><blocks></blocks><variables></variables><scripts><script x="23.076923076923077" y="33.23973911549692"><block s="receiveGo"></block><custom-block s="verbinde mit dem Raum %txt"><l>GIB DEINEN RAUMNAMEN HIER EIN</l></custom-block><block s="doDeclareVariables"><list><l>erkannte Stimmung</l></list></block><block s="doForever"><script><block s="doSetVar"><l>erkannte Stimmung</l><custom-block s="Sage Kategorie vorher für %s"><custom-block s="letzte Eingabe"></custom-block></custom-block></block><block s="doIfElse"><block s="reportEquals"><block var="erkannte Stimmung"/><l>positiv</l></block><script><custom-block s="setze Emotion auf %code"><l>smiling</l></custom-block></script><script><custom-block s="setze Emotion auf %code"><l>sad</l></custom-block></script></block></script></block></script><script x="381.9230769230769" y="171.86134247917695"><custom-block s="erstelle Klassifikator"></custom-block><custom-block s="Traininiere Klassifikator mit Liste: %l Kategorie: %s"><block s="reportNewList"><list><l>Mir geht es großartig</l><l>Alles super!</l><l>Ich fühle mich fantastisch!</l></list></block><l>positiv</l></custom-block><custom-block s="Traininiere Klassifikator mit Liste: %l Kategorie: %s"><block s="reportNewList"><list><l>Mir geht es total schlecht.</l><l>Ich fühle mich absolut miserabel</l><l>Ach frag mich nicht...</l></list></block><l>negativ</l></custom-block></script><comment x="483.8461538461538" y="7.692307692307692" w="90" collapsed="false">Hier sind die Blöcke, die für das Training relevant sind</comment><script x="387.8613424791769" y="96.4510860689206"><custom-block s="lade notwendige Funktionalität"></custom-block></script><script x="366.38461538461536" y="299.4615384615384"><custom-block s="Sage Kategorie vorher für %s"><l>Ich fühle mich großartig</l></custom-block></script><script x="345.7692307692308" y="373.17948717948724"><custom-block s="letzte Eingabe"></custom-block></script></scripts></sprite><watcher var="ws" style="slider" min="0" max="100" x="1.5656135006745444" y="1.5656135006745657" color="243,118,29" hidden="true"/><watcher var="count" style="normal" x="-2.1212637991900465" y="49.29775155357521" color="243,118,29"/></sprites></stage><hidden></hidden><headers></headers><code></code><blocks><block-definition s="test" type="reporter" category="pen"><header></header><code></code><translations></translations><inputs></inputs><script><block s="doReport"><l></l></block></script></block-definition><block-definition s="setze Emotion auf %'Emotion'" type="command" category="sensing"><header></header><code></code><translations></translations><inputs><input type="%code">smiling<options>smiling
checkright
checkleft
giggling
dubitative
sad
reallysad
bored
dubitative
chock
suspicious
satisfied
pong
killthehumans
hal9000
recorder</options></input></inputs><script><custom-block s="send %s to websocket %obj"><block var="Emotion"/><block var="ws"/></custom-block></script></block-definition><block-definition s="verbinde mit dem Raum %'room'" type="command" category="sensing"><header></header><code></code><translations></translations><inputs><input type="%txt"></input></inputs><script><block s="doSetVar"><l>ws</l><custom-block s="open websocket to ws:// %txt %s"><l>localhost:8080/</l><block var="room"/></custom-block></block></script></block-definition><block-definition s="open websocket to ws:// %'url' %'room'" type="reporter" category="sensing"><header></header><code></code><translations></translations><inputs><input type="%txt">localhost:8080/</input><input type="%s"></input></inputs><script><block s="doReport"><block s="evaluate"><block s="reportJSFunction"><list><l>url</l><l>room</l></list><l>if (window.ws && window.ws.readyState == 1){
 window.ws.close()
window.ws = undefined
}
if (window.ws !== undefined){
return}

window.ws = new WebSocket('ws://' + url + room);

ws.addEventListener('message', function (event) {
 console.log('Message from server ', event.data);
window.lastInput = event.data.split("heard:")[1]
});
</l></block><list><block var="url"/><block var="room"/></list></block></block></script></block-definition><block-definition s="send %'emotion' to websocket %'ws'" type="command" category="sensing"><header></header><code></code><translations></translations><inputs><input type="%s"></input><input type="%obj"></input></inputs><script><block s="doRun"><block s="evaluate"><block var="ws"/><list><l>send</l></list></block><list><block var="emotion"/></list></block></script></block-definition><block-definition s="test2" type="command" category="control"><header></header><code></code><translations></translations><inputs></inputs></block-definition><block-definition s="lade notwendige Funktionalität" type="command" category="operators"><comment x="0" y="0" w="90" collapsed="false">https://github.com/andreekeberg/ml-classify-text-js MIT Licence
</comment><header></header><code></code><translations></translations><inputs></inputs><script><block s="doRun"><block s="reportJSFunction"><list><l></l></list><l>class Model {
 constructor(config = {}) {
 if (!(config instanceof Object) || config.constructor !== Object) {
 throw new Error("config must be an object literal");
 }

 config = {
 nGramMin: 1,
 nGramMax: 1,
 vocabulary: [],
 data: {},
 ...config,
 };

 if (config.nGramMin !== parseInt(config.nGramMin, 10)) {
 throw new Error("Config value nGramMin must be an integer");
 }

 if (config.nGramMax !== parseInt(config.nGramMax, 10)) {
 throw new Error("Config value nGramMax must be an integer");
 }

 if (config.nGramMin < 1) {
 throw new Error("Config value nGramMin must be at least 1");
 }

 if (config.nGramMax < 1) {
 throw new Error("Config value nGramMax must be at least 1");
 }

 if (config.nGramMax < config.nGramMin) {
 throw new Error("Invalid nGramMin/nGramMax combination in config");
 }

 if (
 config.vocabulary !== false &&
 !(config.vocabulary instanceof Vocabulary)
 ) {
 config.vocabulary = new Vocabulary(config.vocabulary);
 }

 if (
 !(config.data instanceof Object) ||
 config.data.constructor !== Object
 ) {
 throw new Error("Config value data must be an object literal");
 }

 this._nGramMin = config.nGramMin;
 this._nGramMax = config.nGramMax;
 this._vocabulary = config.vocabulary;
 this._data = { ...config.data };
 }

 /**
 * Minimum n-gram size
 *
 * @type {int}
 */
 get nGramMin() {
 return this._nGramMin;
 }

 set nGramMin(size) {
 if (size !== parseInt(size, 10)) {
 throw new Error("nGramMin must be an integer");
 }

 this._nGramMin = size;
 }

 /**
 * Maximum n-gram size
 *
 * @type {int}
 */
 get nGramMax() {
 return this._nGramMax;
 }

 set nGramMax(size) {
 if (size !== parseInt(size, 10)) {
 throw new Error("nGramMax must be an integer");
 }

 this._nGramMax = size;
 }

 /**
 * Vocabulary instance
 *
 * @type {(Vocabulary|false)}
 */
 get vocabulary() {
 return this._vocabulary;
 }

 set vocabulary(vocabulary) {
 if (vocabulary !== false && !(vocabulary instanceof Vocabulary)) {
 vocabulary = new Vocabulary(vocabulary);
 }

 this._vocabulary = vocabulary;
 }

 /**
 * Model data
 *
 * @type {Object}
 */
 get data() {
 return this._data;
 }

 set data(data) {
 if (!(data instanceof Object) || data.constructor !== Object) {
 throw new Error("data must be an object literal");
 }

 this._data = { ...data };
 }

 /**
 * Return the model in its current state an an object literal, including the
 * configured n-gram min/max values, the vocabulary as an array (if any,
 * otherwise false), and an object literal with all the training data
 *
 * @return {Object}
 */
 serialize() {
 return {
 nGramMin: this._nGramMin,
 nGramMax: this._nGramMax,
 vocabulary: Array.from(this._vocabulary.terms),
 data: this._data,
 };
 }
}

class Prediction {
 constructor(prediction = {}) {
 if (
 !(prediction instanceof Object) ||
 prediction.constructor !== Object
 ) {
 throw new Error("prediction must be an object literal");
 }

 prediction = {
 label: "",
 confidence: 0,
 ...prediction,
 };

 this._label = prediction.label;
 this._confidence = prediction.confidence;
 }

 /**
 * Label of the prediction
 *
 * @type {string}
 */
 get label() {
 return this._label;
 }

 set label(label) {
 if (typeof label !== "string") {
 throw new Error("label must be a string");
 }

 this._label = label;
 }

 /**
 * Confidence of the prediction
 *
 * @type {number}
 */
 get confidence() {
 return this._confidence;
 }

 set confidence(confidence) {
 if (typeof confidence !== "number") {
 throw new Error("confidence must be a number");
 }

 this._confidence = confidence;
 }
}

class Vocabulary {
 constructor(terms = []) {
 if (!(terms instanceof Array) && !(terms instanceof Set)) {
 throw new Error("terms must be either an Array or a Set");
 }

 this._terms = new Set(terms);
 }

 /**
 * Vocabulary size
 *
 * @type {number}
 */
 get size() {
 return this._terms.size;
 }

 /**
 * Vocabulary terms
 *
 * @type {(Array|Set)}
 */
 get terms() {
 return this._terms;
 }

 set terms(terms) {
 if (!(terms instanceof Array) && !(terms instanceof Set)) {
 throw new Error("terms must be either an Array or a Set");
 }

 this._terms = new Set(terms);
 }

 /**
 * Add one or more terms to the vocabulary
 *
 * @param {(string|Array|Set)} terms
 * @return {this}
 */
 add(terms) {
 if (
 typeof terms !== "string" &&
 !(terms instanceof Array) &&
 !(terms instanceof Set)
 ) {
 throw new Error("terms must be either a string, Array or Set");
 }

 if (typeof terms === "string") {
 terms = [terms];
 } else if (terms instanceof Set) {
 terms = Array.from(terms);
 }

 terms.forEach((term) => {
 this._terms.add(term);
 });

 return this;
 }

 /**
 * Remove one or more terms from the vocabulary
 *
 * @param {(string|Array|Set)} terms
 * @return {this}
 */
 remove(terms) {
 if (
 typeof terms !== "string" &&
 !(terms instanceof Array) &&
 !(terms instanceof Set)
 ) {
 throw new Error("terms must be either a string, Array or Set");
 }

 if (typeof terms === "string") {
 terms = [terms];
 } else if (terms instanceof Set) {
 terms = Array.from(terms);
 }

 terms.forEach((term) => {
 this._terms.delete(term);
 });

 return this;
 }

 /**
 * Return whether the vocabulary contains a certain term
 *
 * @param {string} term
 * @return {bool}
 */
 has(term) {
 return this._terms.has(term);
 }

 /**
 * Return the index of a term in the vocabulary (returns -1 if not found)
 *
 * @param {string} term
 * @return {number}
 */
 indexOf(term) {
 if (!this._terms.has(term)) {
 return -1;
 }

 return Array.from(this._terms).indexOf(term);
 }
}

window.Classifier = class Classifier {
 constructor(model = {}) {
 if (!(model instanceof Model)) {
 model = new Model(model);
 }

 this._model = model;
 }

 /**
 * Model instance
 *
 * @type {Model}
 */
 get model() {
 return this._model;
 }

 set model(model) {
 if (!(model instanceof Model)) {
 model = new Model(model);
 }

 this._model = model;
 }

 /**
 * Train the current model using an input string (or array of strings) and a corresponding label
 *
 * @param {(string|string[])} input - String, or an array of strings
 * @param {string} label - Corresponding label
 * @return {this}
 */
 train(input, label) {
 if (typeof input !== "string" && !(input instanceof Array)) {
 throw new Error("input must be either a string or Array");
 }

 if (typeof label !== "string") {
 throw new Error("label must be a string");
 }

 // If input isn't an array, convert to a single item array
 if (!(input instanceof Array)) {
 input = [input];
 }

 input.forEach((string) => {
 // Convert the string to a tokenized object
 let tokens = this.tokenize(string);

 // If we're using a vocabulary, convert the tokens to a vector where all
 // indexes reference vocabulary terms (all terms not already in the
 // vocabulary are automatically added)
 if (this._model.vocabulary !== false) {
 tokens = this.vectorize(tokens);
 }

 // Set up an empty entry for the label if it does not exist
 if (typeof this._model.data[label] === "undefined") {
 this._model.data[label] = {};
 }

 // Add all occurrences to our model entry
 Object.keys(tokens).forEach((index) => {
 let occurrences = tokens[index];

 if (typeof this._model.data[label][index] === "undefined") {
 this._model.data[label][index] = 0;
 }

 this._model.data[label][index] += occurrences;
 });
 });

 return this;
 }

 /**
 * Return an array of one or more Prediction instances
 *
 * @param {string} input - Input string to make a prediction from
 * @param {int} [maxMatches=1] Maximum number of predictions to return
 * @param {float} [minimumConfidence=0.2] Minimum confidence required to include a prediction
 * @return {Array}
 */
 predict(input, maxMatches = 1, minimumConfidence = 0.2) {
 if (typeof input !== "string") {
 throw new Error("input must be a string");
 }

 if (typeof minimumConfidence !== "number") {
 throw new Error("minimumConfidence must be a number");
 }

 if (minimumConfidence < 0) {
 throw new Error("minimumConfidence can not be lower than 0");
 }

 if (minimumConfidence > 1) {
 throw new Error("minimumConfidence can not be higher than 1");
 }

 let tokens = this.tokenize(input);

 if (this.vocabulary !== false) {
 tokens = this.vectorize(tokens);
 }

 let predictions = [];

 Object.keys(this._model.data).forEach((label) => {
 let entry = this._model.data[label];

 let confidence = this.cosineSimilarity(tokens, entry);

 if (confidence >= minimumConfidence) {
 predictions.push(
 new Prediction({
 label,
 confidence,
 })
 );
 }
 });

 /* istanbul ignore next */
 predictions.sort((a, b) => {
 if (a.confidence === b.confidence) {
 return 0;
 }

 return a.confidence > b.confidence ? -1 : 1;
 });

 return predictions.slice(0, Math.min(predictions.length, maxMatches));
 }

 /**
 * Split a string into an array of lowercase words, with all non-letter characters removed
 *
 * @param {string} input
 * @return {Array}
 */
 splitWords(input) {
 if (typeof input !== "string") {
 throw new Error("input must be a string");
 }

 // Remove all apostrophes and dashes to keep words intact
 input = input.replace(/'|´|’|-/g, "");

 // Lowercase all letters and replace all non-letter characters with a space
 input = input
 .toLocaleLowerCase()
 .replace(/[^a-z]/gi, " ")
 .trim();
 /*input = XRegExp.replace(
 input.toLocaleLowerCase(),
 XRegExp("\\P{L}+", "g"),
 " "
 ).trim();*/

 return input.split(" ");
 }

 /**
 * Create an object literal of unique tokens (n-grams) as keys, and their
 * respective occurrences as values based on an input string, or array of words
 *
 * @param {(string|string[])} input
 * @return {Object}
 */
 tokenize(input) {
 let words = typeof input === "string" ? this.splitWords(input) : input;

 if (!(words instanceof Array)) {
 throw new Error("input must be either a string or Array");
 }

 if (this._model.nGramMax < this._model.nGramMin) {
 throw new Error(
 "Invalid nGramMin/nGramMax combination in model config"
 );
 }

 let tokens = {};

 // Generate a list of n-grams along with their respective occurrences
 // based on the models configured min/max values
 words.forEach((word, index) => {
 let sequence = "";

 words.slice(index).forEach((nextWord) => {
 sequence += sequence ? " " + nextWord : nextWord;
 let tokenCount = sequence.split(" ").length;

 if (
 tokenCount < this._model.nGramMin ||
 tokenCount > this._model.nGramMax
 ) {
 return;
 }

 if (typeof tokens[sequence] === "undefined") {
 tokens[sequence] = 0;
 }

 ++tokens[sequence];
 });
 });

 return tokens;
 }

 /**
 * Convert a tokenized object into a new object with all keys (terms)
 * translated to their index in the vocabulary (adding all terms to
 * the vocabulary that do not already exist)
 *
 * @param {Object} tokens
 * @return {Object}
 */
 vectorize(tokens) {
 if (!(tokens instanceof Object) || tokens.constructor !== Object) {
 throw new Error("tokens must be an object literal");
 }

 /* istanbul ignore next */
 if (this._model.vocabulary === false) {
 throw new Error("Cannot vectorize tokens when vocabulary is false");
 }

 let vector = {};

 Object.keys(tokens).forEach((token) => {
 let vocabularyIndex = this._model.vocabulary.indexOf(token);

 if (vocabularyIndex === -1) {
 this._model.vocabulary.add(token);

 vocabularyIndex = this._model.vocabulary.size - 1;
 }

 vector[vocabularyIndex] = tokens[token];
 });

 return vector;
 }

 /**
 * Return the cosine similarity between two vectors
 *
 * @param {Object} v1
 * @param {Object} v2
 * @return {float}
 */
 cosineSimilarity(v1, v2) {
 if (!(v1 instanceof Object) || v1.constructor !== Object) {
 throw new Error("v1 must be an object literal");
 }
 if (!(v2 instanceof Object) || v2.constructor !== Object) {
 throw new Error("v2 must be an object literal");
 }

 let prod = 0.0;
 let v1Norm = 0.0;

 Object.keys(v1).forEach((i) => {
 let xi = v1[i];

 if (typeof v2[i] !== "undefined") {
 prod += xi * v2[i];
 }

 v1Norm += xi * xi;
 });

 v1Norm = Math.sqrt(v1Norm);

 if (v1Norm === 0) {
 return 0;
 }

 let v2Norm = 0.0;

 Object.keys(v2).forEach((i) => {
 let xi = v2[i];

 v2Norm += xi * xi;
 });

 v2Norm = Math.sqrt(v2Norm);

 if (v2Norm === 0) {
 return 0;
 }

 return prod / (v1Norm * v2Norm);
 }
};
</l></block><list></list></block></script></block-definition><block-definition s="erstelle Klassifikator" type="command" category="sensing"><header></header><code></code><translations></translations><inputs></inputs><script><block s="doRun"><block s="reportJSFunction"><list></list><l>window.classifier = new Classifier()</l></block><list></list></block></script></block-definition><block-definition s="Traininiere Klassifikator mit Liste: %'liste' Kategorie: %'category'" type="command" category="sensing"><header></header><code></code><translations></translations><inputs><input type="%l"></input><input type="%s"></input></inputs><script><block s="doRun"><block s="reportJSFunction"><list><l>list</l><l>category</l></list><l>window.classifier.train(list.contents, category);</l></block><list><block var="liste"/><block var="category"/></list></block></script></block-definition><block-definition s="Sage Kategorie vorher für %'eingabe'" type="reporter" category="sensing"><header></header><code></code><translations></translations><inputs><input type="%s"></input></inputs><script><block s="doDeclareVariables"><list><l>a</l></list></block><block s="doSetVar"><l>a</l><block s="evaluate"><block s="reportJSFunction"><list><l>input</l></list><l>let predictions = window.classifier.predict(input)
let result = []
if (predictions.length) {
 predictions.forEach((prediction, i) => {
 console.log(`${prediction.label} (${prediction.confidence})`)
 result[i] = [prediction.label]//, prediction.confidence]
 })
} else {
 console.log('No predictions returned')
}
console.log(result)
return result</l></block><list><block var="eingabe"/></list></block></block><block s="doReport"><block var="a"/></block></script><scripts><script x="163.07692307692307" y="327.66666666666697"><block s="doRun"><block s="reifyScript"><script></script><list></list></block><list><l></l></list></block></script><script x="83.07692307692308" y="325.0000000000001"><block s="doIfElse"><l/><script></script><script></script></block></script></scripts></block-definition><block-definition s="letzte Eingabe" type="reporter" category="sensing"><header></header><code></code><translations></translations><inputs></inputs><script><block s="doReport"><block s="evaluate"><block s="reportJSFunction"><list></list><l>return window.lastInput</l></block><list></list></block></block></script></block-definition></blocks><variables><variable name="count"><l>0</l></variable><variable name="ws"><l>message => {
 if(message == 'send')
 return data => ws.send(data);
 if(message == 'close')
 return () => ws.close();
 if(message == 'onmessage') {
 return proc => {
 ws.onmessage = (e) => {
 var stage = this.parentThatIsA(StageMorph) || this;
 var process = new Process();
 process.initializeFor(proc, new List([e.data]));
 stage.threads.processes.push(process);
 }
 }
 }
}</l></variable></variables></project>