From 0fca54479995bb29cad237908da2387c28ceec23 Mon Sep 17 00:00:00 2001
From: Ben Eltschig <eltschib@hu-berlin.de>
Date: Sun, 4 Apr 2021 19:43:01 +0200
Subject: [PATCH] Formatierungen in SkribblServer.js wiederhergestellt

---
 client/logic/SkribblServer.js | 657 +++++++++++++++++-----------------
 1 file changed, 328 insertions(+), 329 deletions(-)

diff --git a/client/logic/SkribblServer.js b/client/logic/SkribblServer.js
index 63392c7..6ae228d 100644
--- a/client/logic/SkribblServer.js
+++ b/client/logic/SkribblServer.js
@@ -1,12 +1,12 @@
 import { SkribblWord } from "../docs/CustomElements.js";
-import Util, { ConditionFulfilledPromise } from "../util/Util.js";
+import Util, {ConditionFulfilledPromise} from "../util/Util.js";
 import DataChannel from "./networking/DataChannel.js";
 import Signaler from "./networking/Signaler.js";
 import SkribblWords from "./SkribblWords.js";
 
 /**
  * Format of the messages send to the server by the clients.
- * @typedef {{action:"join",name:string}|{action:"startGame"}|{action:"changeSettings",rounds:number,drawTime:number}|{action:"chooseWord",word:number}|{action:"guess",word:string}|ClearOrder|BackgroundOrder|DrawOrder} MessageToServer
+ * @typedef {{action:"join",name:string}|{action:"startGame"}|{action:"changeSettings",rounds:number,drawTime:number}|{action:"chooseWord",word:number}|{action:"guess",word:string}|ClearOrder|DrawOrder|BackgroundOrder} MessageToServer
  */
 /**
  * Format of the messages send to the clients by the server.
@@ -58,6 +58,7 @@ import SkribblWords from "./SkribblWords.js";
  * @property {"changeBackgroundColor"} action
  * @property {string} color
  */
+
 /**
  * @typedef {object} WordReveal
  * @property {"revealWord"} action
@@ -70,343 +71,341 @@ import SkribblWords from "./SkribblWords.js";
  * A local server. Handles all the important game logic, and communicates with clients via DataChannels.
  */
 export default class SkribblServer {
-    /**
-     * Starts a new SkribblServer.
-     */
-    constructor() {
-        this._readyPromise = (async() => {
-            /** @type {{name:string,dataChannel:DataChannel<MessageToClient,MessageToServer>,points:number,guessedWord:boolean,guessedIndex:number}[]} */
-            this._clients = [];
-            this._hasGameStarted = false;
-            /** current round, starts counting at 1, only 0 when the game hasn't started yet */
-            this._round = 0;
-            this._rounds = 3;
-            this._drawTime = 180;
-            /** index of the currently drawing player in the player list */
-            this._drawingPlayer = 0;
-            /**
-             * word that is currently being drawn, or list of words a word is currently getting choosen from
-             * @type {string|string[]}
-             */
-            this._word = null;
-            this._id = await Signaler.host(dataChannel => {
-                this.connect(DataChannel.from(dataChannel, JSON.stringify, JSON.parse));
-            });
-            /** @type {[DataChannel<MessageToServer,MessageToClient>,DataChannel<MessageToClient,MessageToServer>]} */
-            let [endpointA, endpointB] = DataChannel.createPair();
-            this._dataChannel = endpointA;
-            this.connect(endpointB);
-        })();
-    }
-
-    /**
-     * Waits until the server is ready.
-     */
-    async waitUntilReady() {
-        return this._readyPromise;
-    }
-
-    /**
-     * A dataChannel talking to this server like any other client.
-     * @readonly
-     */
-    get dataChannel() {
-        return this._dataChannel;
-    }
-
-    /**
-     * The ID others can use to connect to this server.
-     * @readonly
-     */
-    get id() {
-        return this._id;
-    }
-
-    /**
-     * Returns the full url others can use to connect to this server.
-     * @readonly
-     */
-    get url() {
-        return document.location.host + document.location.pathname + "#" + this._id;
-    }
-
-    /**
-     * Adds an incoming connection as a client.
-     * @param {DataChannel<MessageToClient,MessageToServer>} dataChannel
-     */
-    connect(dataChannel) {
-        (async() => {
-            let message = await dataChannel.next();
-            console.log("message: ", message);
-            if (message.action === "join") {
-                let name = message.name;
-                if (name.length < 30 && name.length >= 1) {
-                    dataChannel.send("yup");
-                    this._clients.push({ name, dataChannel, points: 0, guessedWord: false, guessedIndex: 0 });
-                    this._sendStateUpdate();
-                    if (!this._hasGameStarted) {
-                        dataChannel.send({ action: "settingsUpdate", rounds: this._rounds, drawTime: this._drawTime });
-                    }
-                    dataChannel.onMessage(message => {
-                        let playerIndex = this._clients.map(({ dataChannel }) => dataChannel).indexOf(dataChannel);
-                        let isHost = (playerIndex == 0);
-                        if (message.action == "startGame") {
-                            if (isHost && !this._hasGameStarted) {
-                                this._startGame();
-                            }
-                        } else if (message.action == "changeSettings") {
-                            if (isHost && !this._hasGameStarted) {
-                                this._rounds = message.rounds;
-                                this._drawTime = message.drawTime;
-                                this._sendToAll({ action: "settingsUpdate", rounds: this._rounds, drawTime: this._drawTime });
-                            }
-                        } else if (message.action == "guess") {
-                            this._handleGuess(playerIndex, message.word);
-                        } else if (message.action == "clearCanvas" || message.action == "changeBackgroundColor" || message.action == "draw" || message.action == "erase") {
-                            // sends the drawing order to all connected clients iff the player is currently drawing and has already chosen a word
-                            if (this._hasGameStarted && this._drawingPlayer == playerIndex && typeof this._word == "string") {
-                                this._sendToAll(message);
-                            }
-                        }
-                    });
-                } else {
-                    dataChannel.send("nope");
-                    dataChannel.close();
-                }
-            } else {
-                dataChannel.send("nope");
-                dataChannel.close();
-            }
-        })();
-    }
+	/**
+	 * Starts a new SkribblServer.
+	 */
+	constructor(){
+		this._readyPromise = (async()=>{
+			/** @type {{name:string,dataChannel:DataChannel<MessageToClient,MessageToServer>,points:number,guessedWord:boolean,guessedIndex:number}[]} */
+			this._clients = [];
+			this._hasGameStarted = false;
+			/** current round, starts counting at 1, only 0 when the game hasn't started yet */
+			this._round = 0;
+			this._rounds = 3;
+			this._drawTime = 180;
+			/** index of the currently drawing player in the player list */
+			this._drawingPlayer = 0;
+			/**
+			 * word that is currently being drawn, or list of words a word is currently getting choosen from
+			 * @type {string|string[]}
+			 */
+			this._word = null;
+			this._id = await Signaler.host(dataChannel=>{
+				this.connect(DataChannel.from(dataChannel,JSON.stringify,JSON.parse));
+			});
+			/** @type {[DataChannel<MessageToServer,MessageToClient>,DataChannel<MessageToClient,MessageToServer>]} */
+			let [endpointA,endpointB] = DataChannel.createPair();
+			this._dataChannel = endpointA;
+			this.connect(endpointB);
+		})();
+	}
 
-    /**
-     * Sends a message to all currently connected clients.
-     * @param {MessageToClient} message 
-     */
-    _sendToAll(message) {
-        this._clients.forEach(({ dataChannel }) => {
-            dataChannel.send(message);
-        })
-    }
+	/**
+	 * Waits until the server is ready.
+	 */
+	async waitUntilReady(){
+		return this._readyPromise;
+	}
 
-    /**
-     * Starts the game if it hasn't already started.
-     */
-    _startGame() {
-        if (this._hasGameStarted) {
-            console.warn("Tried to start a game that has already started.");
-        } else {
-            this._hasGameStarted = true;
-            this._clients.forEach(client => {
-                client.points = 0;
-                client.guessedWord = false;
-                client.guessedIndex = 0;
-            });
-            (async() => {
-                for (this._round = 1; this._round <= this._rounds; this._round++) {
-                    for (this._drawingPlayer = 0; this._drawingPlayer < this._clients.length; this._drawingPlayer++) {
-                        let words = await Promise.all([SkribblWords.get(), SkribblWords.get(), SkribblWords.get()]);
-                        this._word = words.map(({ word }) => word);
-                        this._sendStateUpdate();
-                        /** @type {number} */
-                        let wordIndex = await new Promise(async resolve => {
-                            let cancelled = false;
-                            setTimeout(() => {
-                                cancelled = true;
-                                resolve(Math.floor(Math.random() * 3));
-                            }, 10000);
-                            let dataChannel = this._clients[this._drawingPlayer].dataChannel;
-                            while (!cancelled) {
-                                let message = await dataChannel.next();
-                                if (message.action == "chooseWord") {
-                                    resolve(message.word);
-                                }
-                            }
-                        });
-                        this._word = words[wordIndex].word;
-                        this._sendToAll({ action: "clearCanvas" });
-                        this._sendStateUpdate();
-                        this._allGuessedPromise = new ConditionFulfilledPromise(() => {
-                            return this._clients.every((client, index) => client.guessedWord || index == this._drawingPlayer);
-                        });
-                        let timeOverPromise = Util.wait(this._drawTime);
-                        await Promise.race([this._allGuessedPromise, timeOverPromise]);
-                        let points = this._awardPoints();
-                        this._sendStateUpdate();
-                        this._sendToAll({ action: "revealWord", word: this._word, description: words[wordIndex].description, macros: await SkribblWords.macros, points });
-                        await Util.wait(8);
-                    }
-                }
-                this._hasGameStarted = false;
-                this._sendStateUpdate();
-            })();
-        }
-    }
+	/**
+	 * A dataChannel talking to this server like any other client.
+	 * @readonly
+	 */
+	get dataChannel(){
+		return this._dataChannel;
+	}
 
-    /**
-     * Sends a state update to all connected clients (that is, clients that have already joined the game).
-     */
-    _sendStateUpdate() {
-        console.log("sending state update! players:", this._clients);
-        if (this._hasGameStarted) {
-            let players = this._clients.map(({ name, points, guessedWord }) => ({ name, points, guessedWord }));
-            this._clients.forEach(({ dataChannel }, index) => {
-                let host = index == 0;
-                let word = this._drawingPlayer == index ? this._word : (typeof this._word == "string" ? this._word.replace(/[^ -]/g, "_") : null);
-                /** @type {ActiveGameState} */
-                let state = { players, playerIndex: index, host, hasGameStarted: true, rounds: this._rounds, round: this._round, drawingPlayer: this._drawingPlayer, word };
-                dataChannel.send({ action: "stateUpdate", newState: state });
-            });
-        } else {
-            let players = this._clients.map(({ name }) => ({ name }));
-            this._clients.forEach(({ dataChannel }, index) => {
-                dataChannel.send({ action: "stateUpdate", newState: { players, playerIndex: index, host: index == 0, hasGameStarted: false } });
-            });
-        }
-    }
+	/**
+	 * The ID others can use to connect to this server.
+	 * @readonly
+	 */
+	get id(){
+		return this._id;
+	}
 
-    /**
-     * Handles a guess send from a given dataChannel.
-     * @param {number} playerIndex
-     * @param {string} word
-     */
-    _handleGuess(playerIndex, word) {
-        let player = this._clients[playerIndex];
-        if (this._hasGameStarted) {
-            if (player.guessedWord || playerIndex == this._drawingPlayer) {
-                // TODO let people who already know the word send ghost messages to others who already know it too
-            } else if (typeof this._word == "string" && SkribblServer._isCorrect(word, this._word)) {
-                player.guessedWord = true;
-                player.guessedIndex = Math.max(...this._clients.map(client => client.guessedIndex)) + 1;
-                this._clients.forEach((client, index) => {
-                    if (index == playerIndex) {
-                        client.dataChannel.send({ action: "guessedWord", player: playerIndex, correct: true, word });
-                    } else {
-                        client.dataChannel.send({ action: "guessedWord", player: playerIndex, correct: true });
-                    }
-                });
-                this._allGuessedPromise.checkCondition();
-            } else {
-                this._clients.forEach((client, index) => {
-                    let close = typeof this._word == "string" ? SkribblServer._isClose(word, this._word) : false;
-                    if (index == playerIndex) {
-                        client.dataChannel.send({ action: "guessedWord", player: playerIndex, correct: false, word, close });
-                    } else {
-                        client.dataChannel.send({ action: "guessedWord", player: playerIndex, correct: false, word });
-                    }
-                });
-            }
-        }
-    }
+	/**
+	 * Returns the full url others can use to connect to this server.
+	 * @readonly
+	 */
+	get url(){
+		return document.location.host+document.location.pathname+"#"+this._id;
+	}
 
-    /**
-     * Awards points to each player based on if and when they guessed the word, resets the corresponding properties and then returns the list of points each player got.
-     * @todo find better formula for the number of points each player should get
-     */
-    _awardPoints() {
-        let guessingPlayers = this._clients.length - 1;
-        let successfullPlayers = Math.max(...this._clients.map(client => client.guessedIndex));
-        let points = this._clients.map((client, index) => {
-            let points;
-            if (this._drawingPlayer == index) {
-                points = successfullPlayers * 50;
-            } else if (client.guessedIndex != 0) {
-                points = ((guessingPlayers - client.guessedIndex + 1) ** 2) / guessingPlayers * 100;
-            } else {
-                points = 0;
-            }
-            points = Math.round(points / 5) * 5;
-            client.points += points;
-            client.guessedWord = false;
-            client.guessedIndex = 0;
-            return points;
-        });
-        return points;
-    }
+	/**
+	 * Adds an incoming connection as a client.
+	 * @param {DataChannel<MessageToClient,MessageToServer>} dataChannel
+	 */
+	connect(dataChannel){
+		(async()=>{
+			let message = await dataChannel.next();
+			console.log("message: ",message);
+			if (message.action==="join"){
+				let name = message.name;
+				if (name.length<30&&name.length>=1){
+					dataChannel.send("yup");
+					this._clients.push({name,dataChannel,points:0,guessedWord:false,guessedIndex:0});
+					this._sendStateUpdate();
+					if (!this._hasGameStarted){
+						dataChannel.send({action:"settingsUpdate",rounds:this._rounds,drawTime:this._drawTime});
+					}
+					dataChannel.onMessage(message=>{
+						let playerIndex = this._clients.map(({dataChannel})=>dataChannel).indexOf(dataChannel);
+						let isHost = (playerIndex==0);
+						if (message.action=="startGame"){
+							if (isHost&&!this._hasGameStarted){
+								this._startGame();
+							}
+						}else if(message.action=="changeSettings"){
+							if (isHost&&!this._hasGameStarted){
+								this._rounds = message.rounds;
+								this._drawTime = message.drawTime;
+								this._sendToAll({action:"settingsUpdate",rounds:this._rounds,drawTime:this._drawTime});
+							}
+						}else if (message.action=="guess"){
+							this._handleGuess(playerIndex,message.word);
+						}else if (message.action=="clearCanvas"||message.action=="draw"||message.action=="erase"){
+							// sends the drawing order to all connected clients iff the player is currently drawing and has already chosen a word
+							if (this._hasGameStarted&&this._drawingPlayer==playerIndex&&typeof this._word=="string"){
+								this._sendToAll(message);
+							}
+						}
+					});
+				}else{
+					dataChannel.send("nope");
+					dataChannel.close();
+				}
+			}else{
+				dataChannel.send("nope");
+				dataChannel.close();
+			}
+		})();
+	}
 
-    /**
-     * Checks whether a given guess is close to the given word. A guess counts as close, if one letter is wrong,
-     * two letters are swapped or the guess has one letter too much or too little.
-     * @param {string} guess
-     * @param {string} word
-     */
-    static _isClose(guess, word) {
-        guess = guess.toLowerCase().replace(/-/g, " ");
-        word = word.toLowerCase().replace(/-/g, " ");
-        const wordArray = Array.from(word);
-        const guessArray = Array.from(guess);
+	/**
+	 * Sends a message to all currently connected clients.
+	 * @param {MessageToClient} message 
+	 */
+	_sendToAll(message){
+		this._clients.forEach(({dataChannel})=>{
+			dataChannel.send(message);
+		})
+	}
 
-        //if equal
-        if (guess == word) {
-            return true;
-        }
+	/**
+	 * Starts the game if it hasn't already started.
+	 */
+	_startGame(){
+		if (this._hasGameStarted){
+			console.warn("Tried to start a game that has already started.");
+		}else{
+			this._hasGameStarted = true;
+			this._clients.forEach(client=>{
+				client.points = 0;
+				client.guessedWord = false;
+				client.guessedIndex = 0;
+			});
+			(async()=>{
+				for (this._round=1;this._round<=this._rounds;this._round++){
+					for (this._drawingPlayer=0;this._drawingPlayer<this._clients.length;this._drawingPlayer++){
+						let words = await Promise.all([SkribblWords.get(),SkribblWords.get(),SkribblWords.get()]);
+						this._word = words.map(({word})=>word);
+						this._sendStateUpdate();
+						/** @type {number} */
+						let wordIndex = await new Promise(async resolve=>{
+							let cancelled = false;
+							setTimeout(()=>{
+								cancelled = true;
+								resolve(Math.floor(Math.random()*3));
+							},10000);
+							let dataChannel = this._clients[this._drawingPlayer].dataChannel;
+							while (!cancelled){
+								let message = await dataChannel.next();
+								if (message.action=="chooseWord"){
+									resolve(message.word);
+								}
+							}
+						});
+						this._word = words[wordIndex].word;
+						this._sendToAll({action:"clearCanvas"});
+						this._sendStateUpdate();
+						this._allGuessedPromise = new ConditionFulfilledPromise(()=>{
+							return this._clients.every((client,index)=>client.guessedWord||index==this._drawingPlayer);
+						});
+						let timeOverPromise = Util.wait(this._drawTime);
+						await Promise.race([this._allGuessedPromise,timeOverPromise]);
+						let points = this._awardPoints();
+						this._sendStateUpdate();
+						this._sendToAll({action:"revealWord",word:this._word,description:words[wordIndex].description,macros:await SkribblWords.macros,points});
+						await Util.wait(8);
+					}
+				}
+				this._hasGameStarted = false;
+				this._sendStateUpdate();
+			})();
+		}
+	}
 
-        //either one letter wrong or two letters swapped
-        if (guess.length == word.length) {
-            //Counts the mistakes and their position
-            let errorCounter = 0;
-            let errorPos = 0;
-            for (var i = 0; i < wordArray.length; i++) {
-                if (wordArray[i] != guessArray[i]) {
-                    if (errorCounter == 0) {
-                        errorPos = i;
-                    }
-                    if (errorCounter == 1) { //if a second mistake occurs, either the letters are swapped or it is not correct
-                        //but there could be a third mistake, so in the case of a swap, true is not directly returned.
-                        if ((wordArray[i] != guessArray[errorPos]) || (wordArray[errorPos] != guessArray[i])) {
-                            return false;
-                        }
-                    }
-                    if (errorCounter >= 2) { //with two or more mistakes, the word is not close
-                        return false;
-                    }
-                    errorCounter++;
-                }
-            }
-            //if it hasnt returned false by now, the guess is close
-            return true;
-        }
+	/**
+	 * Sends a state update to all connected clients (that is, clients that have already joined the game).
+	 */
+	_sendStateUpdate(){
+		console.log("sending state update! players:",this._clients);
+		if (this._hasGameStarted){
+			let players = this._clients.map(({name,points,guessedWord})=>({name,points,guessedWord}));
+			this._clients.forEach(({dataChannel},index)=>{
+				let host = index==0;
+				let word = this._drawingPlayer==index?this._word:(typeof this._word=="string"?this._word.replace(/[^ -]/g,"_"):null);
+				/** @type {ActiveGameState} */
+				let state = {players,playerIndex:index,host,hasGameStarted:true,rounds:this._rounds,round:this._round,drawingPlayer:this._drawingPlayer,word};
+				dataChannel.send({action:"stateUpdate",newState:state});
+			});
+		}else{
+			let players = this._clients.map(({name})=>({name}));
+			this._clients.forEach(({dataChannel},index)=>{
+				dataChannel.send({action:"stateUpdate",newState:{players,playerIndex:index,host:index==0,hasGameStarted:false}});
+			});
+		}
+	}
 
-        //if one letter too much
-        if (guess.length - 1 == word.length) {
-            let errorCounter = 0; //also the offset
-            for (var i = 0; i < wordArray.length; i++) {
-                if (wordArray[i] != guessArray[i + errorCounter]) {
-                    errorCounter++;
-                    if (errorCounter >= 2) {
-                        return false;
-                    }
-                }
-            }
-            return true;
-        }
+	/**
+	 * Handles a guess send from a given dataChannel.
+	 * @param {number} playerIndex
+	 * @param {string} word
+	 */
+	_handleGuess(playerIndex,word){
+		let player = this._clients[playerIndex];
+		if (this._hasGameStarted){
+			if (player.guessedWord||playerIndex==this._drawingPlayer){
+				// TODO let people who already know the word send ghost messages to others who already know it too
+			}else if (typeof this._word=="string"&&SkribblServer._isCorrect(word,this._word)){
+				player.guessedWord = true;
+				player.guessedIndex = Math.max(...this._clients.map(client=>client.guessedIndex))+1;
+				this._clients.forEach((client,index)=>{
+					if (index==playerIndex){
+						client.dataChannel.send({action:"guessedWord",player:playerIndex,correct:true,word});
+					}else{
+						client.dataChannel.send({action:"guessedWord",player:playerIndex,correct:true});
+					}
+				});
+				this._allGuessedPromise.checkCondition();
+			}else{
+				this._clients.forEach((client,index)=>{
+					let close = typeof this._word=="string"?SkribblServer._isClose(word,this._word):false;
+					if (index==playerIndex){
+						client.dataChannel.send({action:"guessedWord",player:playerIndex,correct:false,word,close});
+					}else{
+						client.dataChannel.send({action:"guessedWord",player:playerIndex,correct:false,word});
+					}
+				});
+			}
+		}
+	}
 
-        //if one letter too little
-        if (guess.length + 1 == word.length) {
-            let errorCounter = 0; //also the offset
-            for (var i = 0; i < guessArray.length; i++) {
-                if (wordArray[i + errorCounter] != guessArray[i]) {
-                    errorCounter++;
-                    if (errorCounter >= 2) {
-                        return false;
-                    }
-                }
-            }
-            return true;
-        }
+	/**
+	 * Awards points to each player based on if and when they guessed the word, resets the corresponding properties and then returns the list of points each player got.
+	 * @todo find better formula for the number of points each player should get
+	 */
+	_awardPoints(){
+		let guessingPlayers = this._clients.length-1;
+		let successfullPlayers = Math.max(...this._clients.map(client=>client.guessedIndex));
+		let points = this._clients.map((client,index)=>{
+			let points;
+			if (this._drawingPlayer==index){
+				points = successfullPlayers*50;
+			}else if(client.guessedIndex!=0){
+				points = ((guessingPlayers-client.guessedIndex+1)**2)/guessingPlayers*100;
+			}else{
+				points = 0;
+			}
+			points = Math.round(points/5)*5;
+			client.points += points;
+			client.guessedWord = false;
+			client.guessedIndex = 0;
+			return points;
+		});
+		return points;
+	}
 
-        return false;
-    }
+	/**
+	 * Checks whether a given guess is close to the given word. A guess counts as close, if one letter is wrong,
+	 * two letters are swapped or the guess has one letter too much or too little.
+	 * @param {string} guess
+	 * @param {string} word
+	 */
+	static _isClose(guess,word) {
+		guess = guess.toLowerCase().replace(/-/g," ");
+		word = word.toLowerCase().replace(/-/g," ");
+		const wordArray = Array.from(word);
+		const guessArray = Array.from(guess);
+	
+		//if equal
+		if (guess == word) { 
+			return true;
+		}
+		
+		//either one letter wrong or two letters swapped
+		if (guess.length == word.length) {
+			//Counts the mistakes and their position
+			let errorCounter = 0;
+			let errorPos = 0;
+			for (var i = 0; i < wordArray.length; i++) {
+				if (wordArray[i] != guessArray[i]) {
+					if (errorCounter == 0) {
+						errorPos = i;
+					} if (errorCounter == 1) { //if a second mistake occurs, either the letters are swapped or it is not correct
+												//but there could be a third mistake, so in the case of a swap, true is not directly returned.
+						if ((wordArray[i] != guessArray[errorPos]) || (wordArray[errorPos] != guessArray[i])) {
+							return false;
+						}
+					} if (errorCounter >= 2) { //with two or more mistakes, the word is not close
+						return false;
+					}
+					errorCounter++;
+				}
+			}
+			//if it hasnt returned false by now, the guess is close
+			return true;
+		}
+	
+		//if one letter too much
+		if (guess.length - 1 == word.length)  {
+			let errorCounter = 0; //also the offset
+			for (var i = 0; i < wordArray.length; i++) {
+				if (wordArray[i] != guessArray[i + errorCounter]) {
+					errorCounter++;
+					if (errorCounter >= 2) {
+						return false;
+					}
+				}
+			}
+			return true;
+		}
+	
+		//if one letter too little
+		if (guess.length + 1 == word.length) {
+			let errorCounter = 0; //also the offset
+			for (var i = 0; i < guessArray.length; i++) {
+				if (wordArray[i + errorCounter] != guessArray[i]) {
+					errorCounter++;
+					if (errorCounter >= 2) {
+						return false;
+					}
+				}
+			}
+			return true;
+		}
+	
+		return false;
+	}
 
-    /**
-     * Checks if the guess is correct. It is not case-sensitive.
-     * @param {string} guess
-     * @param {string} word
-     */
-    static _isCorrect(guess, word) {
-        guess = guess.toLowerCase().replace(/-/g, " ");
-        word = word.toLowerCase().replace(/-/g, " ");
-        return guess == word;
-    }
+	/**
+	 * Checks if the guess is correct. It is not case-sensitive.
+	 * @param {string} guess
+	 * @param {string} word
+	 */
+	static _isCorrect(guess, word) {
+		guess = guess.toLowerCase().replace(/-/g," ");
+		word = word.toLowerCase().replace(/-/g," ");
+		return guess==word;
+	}
 }
\ No newline at end of file
-- 
GitLab