From 83a7031319010bdd6967e3d295e2edb589ddba13 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Tue, 15 May 2018 21:17:56 -0700 Subject: [PATCH 1/8] added function to calc word score and tall max scoring words --- scrabble.js | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/scrabble.js b/scrabble.js index e95f352..fbaeb82 100644 --- a/scrabble.js +++ b/scrabble.js @@ -1,10 +1,57 @@ const Scrabble = { score(word) { + const onePoint = ['A','E','I','O','U','L','N','R','S','T'] + const twoPoint = ['D','G'] + const threePoint = ['B','C','M', 'P'] + const fourPoint = ['F','H','V','W','Y'] + const fivePoint = ['K'] + const eightPoint = ['J','X'] + const tenPoint = ['Q','Z'] + let total = 0 + word = word.split("") + + word.forEach(function (char) { + if (onePoint.includes(char)){ + total += 1; + }else if (twoPoint.includes(char)){ + total += 2; + }else if (threePoint.includes(char)){ + total += 3; + }else if (fourPoint.includes(char)){ + total += 4; + }else if (fivePoint.includes(char)){ + total += 5; + }else if (eightPoint.includes(char)){ + total += 8; + }else if (tenPoint.includes(char)){ + total += 10; + } + }); + + if (word.length === 7) { + total += 50; + } + + return total }, + highestScoreFrom(arrayOfWords) { + let maxScoreWord = { + word: [null], + score: 0 + }; + arrayOfWords.forEach(function (wordCompareScore) { + let new_word = new Scrabble(wordCompareScore); + if (new_word.score(wordCompareScore) > maxScoreWord.score) { + maxScoreWord.word = wordCompareScore; + maxScoreWord.score = new_word.score(wordCompareScore); + } else if (new_word.score(wordCompareScore) === maxScoreWord.score){ + maxScoreWord.word.push(wordCompareScore); + } + }); }, }; From 849ad914493125b2b0611da49a26733b537fe944 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Wed, 16 May 2018 17:15:42 -0700 Subject: [PATCH 2/8] added logic for calculating score and some for determining highest scoring word --- scrabble.js | 181 +++++++++++++++++++++++++++++++---------- specs/scrabble.spec.js | 24 +++--- 2 files changed, 149 insertions(+), 56 deletions(-) diff --git a/scrabble.js b/scrabble.js index fbaeb82..fa720df 100644 --- a/scrabble.js +++ b/scrabble.js @@ -1,58 +1,151 @@ const Scrabble = { score(word) { - const onePoint = ['A','E','I','O','U','L','N','R','S','T'] - const twoPoint = ['D','G'] - const threePoint = ['B','C','M', 'P'] - const fourPoint = ['F','H','V','W','Y'] - const fivePoint = ['K'] - const eightPoint = ['J','X'] - const tenPoint = ['Q','Z'] - - let total = 0 - word = word.split("") - - word.forEach(function (char) { - if (onePoint.includes(char)){ - total += 1; - }else if (twoPoint.includes(char)){ - total += 2; - }else if (threePoint.includes(char)){ - total += 3; - }else if (fourPoint.includes(char)){ - total += 4; - }else if (fivePoint.includes(char)){ - total += 5; - }else if (eightPoint.includes(char)){ - total += 8; - }else if (tenPoint.includes(char)){ - total += 10; - } - }); + const onePoint = ['A','E','I','O','U','L','N','R','S','T']; + const twoPoint = ['D','G']; + const threePoint = ['B','C','M', 'P']; + const fourPoint = ['F','H','V','W','Y']; + const fivePoint = ['K']; + const eightPoint = ['J','X']; + const tenPoint = ['Q','Z']; + + let total = 0; + + const regex_key = /^[a-z]+$/i; - if (word.length === 7) { - total += 50; + word = word.split(''); + + if (word.length == 0) { + throw "word cannot be an empty string"; + } else if (word.length > 7) { + throw "word cannot be longer than 7 letters"; + } else { + word.forEach(function (char) { + if (regex_key.test(char) === false) { + throw "word can only contain letters"; + } + }) } - return total + word = word.join() + word = word.toUpperCase().split('') + + // optional? Edits guesses to remove non letter guesses + // const regex_key = /^[a-z]+$/i; + // word.forEach( function (char){ + // if (regex_key.test(char)) { + // word.pop(char); + // } + // }) + + word.forEach(function (char) { + if (onePoint.includes(char)){ + total += 1; + }else if (twoPoint.includes(char)){ + total += 2; + }else if (threePoint.includes(char)){ + total += 3; + }else if (fourPoint.includes(char)){ + total += 4; + }else if (fivePoint.includes(char)){ + total += 5; + }else if (eightPoint.includes(char)){ + total += 8; + }else if (tenPoint.includes(char)){ + total += 10; + } + }); + + // why doesn't this work when i try + // word.length === 7 ? total += 50 : total ; + + word.length > 6 ? total += 50 : total ; + console.log(total); + return total; }, highestScoreFrom(arrayOfWords) { - let maxScoreWord = { - word: [null], - score: 0 - }; - - arrayOfWords.forEach(function (wordCompareScore) { - let new_word = new Scrabble(wordCompareScore); - if (new_word.score(wordCompareScore) > maxScoreWord.score) { - maxScoreWord.word = wordCompareScore; - maxScoreWord.score = new_word.score(wordCompareScore); - } else if (new_word.score(wordCompareScore) === maxScoreWord.score){ - maxScoreWord.word.push(wordCompareScore); + if (arrayOfWords.length === 0){ + throw "must enter a valid list of words to score." + } + //array to be populated with objects containing word and their score + let trackScore = []; + +//makes an array of objects with word and its score + arrayOfWords.forEach(function (word) { + trackScore.push({ + 'word': word, + 'score': Scrabble.score(word), + }); + } + + // highest score + let highScore = 0; + + trackScore.forEach( function (object){ + if (object.score > highScore) { + highScore = object.score; + } + }) + + let highScoreWords = []; + + trackScore.forEach( function (object){ + if (object.score === highScore) { + highScoreWords.push(object.word); + } + }) + + highScoreWords.forEach (function (word){ + if (word.length == 7){ + return word; + } + }) + + let shortestWord = "1234567" + highScoreWords.forEach (function (word){ + if (word.length < shortestWord) { + shortestWord = word; + } + }) + + + // this should be dealt with by other throws...no? + // if (highScore < 1){ + // throw "Words must have a score" + // } + + + // tied btwn words < 7 longer, take shorter word + // tied with word == 7 take 7 letter word: + + // tied with same length take first scored word: order matters so keep array + + maxScoringWord = arrayOfWords[0]; + + + if (scored_word > maxScoreWord.score) { + maxScoreWord.score = scored_word; + maxScoreWord.word = [unscored_word]; + } else if (scored_word === maxScoreWord.score){ + maxScoreWord.word.push(unscored_word); + } + }) + + if (maxScoreWord.word.length === 1){ + return maxScoreWord[0]; + } else if (maxScoreWord.word.length > 1){ + let shortestWord = ["12345678"]; + maxScoreWord.forEach(function (word) { + if (word.length < shortestWord[0].length){ + shortestWord = [word]; + }else if (word.length === shortestWord.length) { + shortestWord.push(word); } }); - }, + return shortestWord[0]; + } +}, }; Scrabble.Player = class { diff --git a/specs/scrabble.spec.js b/specs/scrabble.spec.js index b562037..5c05066 100644 --- a/specs/scrabble.spec.js +++ b/specs/scrabble.spec.js @@ -11,46 +11,46 @@ describe('score', () => { expect(Scrabble.score('pig')).toBe(6); }); - test.skip('adds 50 points for a 7-letter word', () => { + test('adds 50 points for a 7-letter word', () => { expect(Scrabble.score('academy')).toBe(65); }); - test.skip('throws on bad characters', () => { + test('throws on bad characters', () => { expect(() => { Scrabble.score('char^'); }).toThrow(); }); - test.skip('handles all upper- and lower-case letters', () => { + test('handles all upper- and lower-case letters', () => { expect(Scrabble.score('dog')).toBe(5); expect(Scrabble.score('DOG')).toBe(5); expect(Scrabble.score('DoG')).toBe(5); }); - test.skip('does not allow words > 7 letters', () => { + test('does not allow words > 7 letters', () => { expect(() => { Scrabble.score('abcdefgh'); }).toThrow(); }); - test.skip('does not allow empty words', () => { + test('does not allow empty words', () => { expect(() => { Scrabble.score(''); }).toThrow(); }); }); describe('highestScoreFrom', () => { - test.skip('is defined', () => { + test('is defined', () => { expect(Scrabble.highestScoreFrom).toBeDefined(); }); - test.skip('throws if no words were passed', () => { + test('throws if no words were passed', () => { expect(() => { Scrabble.highestScoreFrom([]); }).toThrow(); expect(() => { Scrabble.highestScoreFrom('not array'); }).toThrow(); }); - test.skip('returns the only word in a length-1 array', () => { + test('returns the only word in a length-1 array', () => { expect(Scrabble.highestScoreFrom(['dog'])).toBe('dog'); }); - test.skip('returns the highest word if there are two words', () => { + test('returns the highest word if there are two words', () => { // Check score assumptions expect(Scrabble.score('dog')).toBe(5); expect(Scrabble.score('pig')).toBe(6); @@ -60,7 +60,7 @@ describe('highestScoreFrom', () => { expect(Scrabble.highestScoreFrom(['pig', 'dog'])).toBe('pig'); }); - test.skip('if tied, prefer a word with 7 letters', () => { + test('if tied, prefer a word with 7 letters', () => { const loser = 'zzzzzz'; const winner = 'iiiiddd'; @@ -73,7 +73,7 @@ describe('highestScoreFrom', () => { expect(Scrabble.highestScoreFrom([winner, loser])).toBe(winner); }); - test.skip('if tied and no word has 7 letters, prefers the word with fewer letters', () => { + test('if tied and no word has 7 letters, prefers the word with fewer letters', () => { // Check score assumptions expect(Scrabble.score('dog')).toBe(5); expect(Scrabble.score('goat')).toBe(5); @@ -83,7 +83,7 @@ describe('highestScoreFrom', () => { expect(Scrabble.highestScoreFrom(['goat', 'dog'])).toBe('dog'); }); - test.skip('returns the first word of a tie with same letter count', () => { + test('returns the first word of a tie with same letter count', () => { // Check score assumptions expect(Scrabble.score('i')).toBe(1); expect(Scrabble.score('dog')).toBe(5); From ba1aa0fb304faea0c650dd88d660cd306ba71cf5 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Wed, 16 May 2018 18:15:55 -0700 Subject: [PATCH 3/8] s/o Mariano fixing my bug with split/join...max scoring word returned and accounts for scrabble rules and order played --- scrabble.js | 113 ++++++++++------------------------------------------ 1 file changed, 20 insertions(+), 93 deletions(-) diff --git a/scrabble.js b/scrabble.js index fa720df..63f0b4c 100644 --- a/scrabble.js +++ b/scrabble.js @@ -13,9 +13,9 @@ const Scrabble = { const regex_key = /^[a-z]+$/i; - word = word.split(''); + word = word.toUpperCase().split(''); - if (word.length == 0) { + if (word.length === 0) { throw "word cannot be an empty string"; } else if (word.length > 7) { throw "word cannot be longer than 7 letters"; @@ -27,17 +27,6 @@ const Scrabble = { }) } - word = word.join() - word = word.toUpperCase().split('') - - // optional? Edits guesses to remove non letter guesses - // const regex_key = /^[a-z]+$/i; - // word.forEach( function (char){ - // if (regex_key.test(char)) { - // word.pop(char); - // } - // }) - word.forEach(function (char) { if (onePoint.includes(char)){ total += 1; @@ -56,96 +45,34 @@ const Scrabble = { } }); - // why doesn't this work when i try - // word.length === 7 ? total += 50 : total ; - - word.length > 6 ? total += 50 : total ; - console.log(total); - return total; + return (word.length === 7) ? (total + 50) : total; }, highestScoreFrom(arrayOfWords) { if (arrayOfWords.length === 0){ throw "must enter a valid list of words to score." } - //array to be populated with objects containing word and their score - let trackScore = []; - -//makes an array of objects with word and its score - arrayOfWords.forEach(function (word) { - trackScore.push({ - 'word': word, - 'score': Scrabble.score(word), - }); - } - // highest score let highScore = 0; - - trackScore.forEach( function (object){ - if (object.score > highScore) { - highScore = object.score; - } - }) - - let highScoreWords = []; - - trackScore.forEach( function (object){ - if (object.score === highScore) { - highScoreWords.push(object.word); - } - }) - - highScoreWords.forEach (function (word){ - if (word.length == 7){ - return word; - } - }) - - let shortestWord = "1234567" - highScoreWords.forEach (function (word){ - if (word.length < shortestWord) { - shortestWord = word; + let highestScoringWord = ''; + + for (let i = 0; i < arrayOfWords.length; i++) { + let word = arrayOfWords[i]; + let score = Scrabble.score(word); + + if (score > highScore) { + highScore = score; + highestScoringWord = word; + } else if (score === highScore) { + if (highestScoringWord.length != 7 && + (word.length === 7 || word.length < highestScoringWord.length)) { + highestScoringWord = word; + } } - }) - - - // this should be dealt with by other throws...no? - // if (highScore < 1){ - // throw "Words must have a score" - // } - - - // tied btwn words < 7 longer, take shorter word - // tied with word == 7 take 7 letter word: - - // tied with same length take first scored word: order matters so keep array - - maxScoringWord = arrayOfWords[0]; - - - if (scored_word > maxScoreWord.score) { - maxScoreWord.score = scored_word; - maxScoreWord.word = [unscored_word]; - } else if (scored_word === maxScoreWord.score){ - maxScoreWord.word.push(unscored_word); } - }) - - if (maxScoreWord.word.length === 1){ - return maxScoreWord[0]; - } else if (maxScoreWord.word.length > 1){ - let shortestWord = ["12345678"]; - maxScoreWord.forEach(function (word) { - if (word.length < shortestWord[0].length){ - shortestWord = [word]; - }else if (word.length === shortestWord.length) { - shortestWord.push(word); - } - }); - return shortestWord[0]; - } -}, + + return highestScoringWord; + }, }; Scrabble.Player = class { From e784044df9564c213723907e95b6eacdef798b24 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Wed, 16 May 2018 18:22:53 -0700 Subject: [PATCH 4/8] player class constructor created and throws error for invalid instance of player (no name) --- scrabble.js | 7 ++++++- specs/scrabble.spec.js | 12 ++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/scrabble.js b/scrabble.js index 63f0b4c..405720d 100644 --- a/scrabble.js +++ b/scrabble.js @@ -76,7 +76,12 @@ const Scrabble = { }; Scrabble.Player = class { - + constructor(name) { + this.name = name; + if (name === null || name === undefined) { + throw "every player must have a name"; + } + } }; diff --git a/specs/scrabble.spec.js b/specs/scrabble.spec.js index 5c05066..dcd29b9 100644 --- a/specs/scrabble.spec.js +++ b/specs/scrabble.spec.js @@ -98,19 +98,19 @@ describe('highestScoreFrom', () => { }); describe('Player', () => { - test.skip('is defined', () => { + test('is defined', () => { expect(Scrabble.Player).toBeDefined(); }); describe('Constructor', () => { - test.skip('Creates a new player', () => { + test('Creates a new player', () => { const name = 'test name'; const player = new Scrabble.Player(name); expect(player.name).toBe(name); }); - test.skip('Requires a name', () => { + test('Requires a name', () => { expect(() => { new Scrabble.Player(); }).toThrow(); @@ -211,13 +211,13 @@ describe('Player', () => { }); }); - describe('highestWordScore', () => { - test.skip('returns the score of the highest scoring word played', () => { + xdescribe('highestWordScore', () => { + test('returns the score of the highest scoring word played', () => { }); - test.skip('throws an error if no words have been played', () => { + test('throws an error if no words have been played', () => { }); From e0c3d12048621ddabc3b40c91cb73327c2fe3575 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Wed, 16 May 2018 18:59:07 -0700 Subject: [PATCH 5/8] determines if player has one, and if they submit a play a valid word --- scrabble.js | 36 ++++++++++++++++++++++++++++++++++++ specs/scrabble.spec.js | 6 +++--- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/scrabble.js b/scrabble.js index 405720d..446b9b7 100644 --- a/scrabble.js +++ b/scrabble.js @@ -81,6 +81,42 @@ Scrabble.Player = class { if (name === null || name === undefined) { throw "every player must have a name"; } + + this.plays = []; + } + + play(word) { + if (word === null || word === undefined) { + throw "every word must letters"; + } else { + const regex_key = /^[a-z]+$/i; + const splitWord = word.split(''); + + splitWord.forEach(function (char) { + if (!regex_key.test(char)) { + throw "word can only contain letters"; + } + }); + } + + if (this.hasWon()) return false; + + this.plays.push(word); + return true; + } + + hasWon() { + let totalScore = 0; + + this.plays.forEach(function(word) { + totalScore += Scrabble.score(word); + }); + + if (totalScore > 100) { + return true; + } + + return false; } }; diff --git a/specs/scrabble.spec.js b/specs/scrabble.spec.js index dcd29b9..0826cf2 100644 --- a/specs/scrabble.spec.js +++ b/specs/scrabble.spec.js @@ -118,7 +118,7 @@ describe('Player', () => { }); describe('play', () => { - test.skip('Records the played word', () => { + test('Records the played word', () => { const word = 'dog'; const player = new Scrabble.Player('test player'); @@ -130,7 +130,7 @@ describe('Player', () => { expect(player.plays[0]).toBe(word); }); - test.skip('Requires a real word', () => { + test('Requires a real word', () => { const player = new Scrabble.Player('test player'); expect(player.plays.length).toBe(0); @@ -142,7 +142,7 @@ describe('Player', () => { expect(player.plays.length).toBe(0); }); - test.skip('Returns false and does not update plays if the player has already won', () => { + test('Returns false and does not update plays if the player has already won', () => { const player = new Scrabble.Player('test player'); expect(player.play('zzzzzzz')).toBeTruthy(); // +120 pts From 789d1653f9aafb03b40ac24408a42f2dc657b518 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Wed, 16 May 2018 19:09:12 -0700 Subject: [PATCH 6/8] has won fully functioning and tested --- scrabble.js | 6 +++--- specs/scrabble.spec.js | 23 ++++++++++++++++++----- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/scrabble.js b/scrabble.js index 446b9b7..1b865e4 100644 --- a/scrabble.js +++ b/scrabble.js @@ -112,11 +112,11 @@ Scrabble.Player = class { totalScore += Scrabble.score(word); }); - if (totalScore > 100) { - return true; + if (totalScore < 100) { + return false; } - return false; + return true; } }; diff --git a/specs/scrabble.spec.js b/specs/scrabble.spec.js index 0826cf2..9896833 100644 --- a/specs/scrabble.spec.js +++ b/specs/scrabble.spec.js @@ -181,19 +181,32 @@ describe('Player', () => { }); describe('hasWon', () => { - test.skip('returns false when score < 100', () => { - + test('returns false when score < 100', () => { + const player = new Scrabble.Player('test player'); + expect(player.hasWon()).toBe(false); + // 30 points + expect(player.play('zzz')).toBeTruthy(); + expect(player.plays.length).toBe(1); + expect(player.hasWon()).toBe(false); }); - test.skip('returns true when score == 100', () => { + test('returns true when score == 100', () => { + const player = new Scrabble.Player('test player'); + expect(player.play('zzzkkkk')).toBeTruthy(); + expect(player.plays.length).toBe(1); + expect(player.hasWon()).toBe(true); }); - test.skip('returns true when score > 100', () => { - + test('returns true when score > 100', () => { + const player = new Scrabble.Player('test player'); + /// 130 pts + expect(player.play('zzzzzzz')).toBeTruthy(); + expect(player.plays.length).toBe(1); + expect(player.hasWon()).toBe(true); }); }); From 8475edbbd71ab31ac7e4f5f784d70f7e87b229d7 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Wed, 16 May 2018 19:12:54 -0700 Subject: [PATCH 7/8] total score method works --- scrabble.js | 18 +++++++++++------- specs/scrabble.spec.js | 4 ++-- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/scrabble.js b/scrabble.js index 1b865e4..e49fee6 100644 --- a/scrabble.js +++ b/scrabble.js @@ -106,18 +106,22 @@ Scrabble.Player = class { } hasWon() { - let totalScore = 0; - - this.plays.forEach(function(word) { - totalScore += Scrabble.score(word); - }); - - if (totalScore < 100) { + if (this.totalScore() < 100) { return false; } return true; } + + totalScore() { + let total = 0; + + this.plays.forEach(function(word) { + total += Scrabble.score(word); + }); + + return total; + } }; diff --git a/specs/scrabble.spec.js b/specs/scrabble.spec.js index 9896833..2f1b7b4 100644 --- a/specs/scrabble.spec.js +++ b/specs/scrabble.spec.js @@ -155,13 +155,13 @@ describe('Player', () => { }); describe('totalScore', () => { - test.skip('Is zero if the player has not played anything', () => { + test('Is zero if the player has not played anything', () => { const player = new Scrabble.Player('test player'); expect(player.totalScore()).toBe(0); }); - test.skip('Is updated by play', () => { + test('Is updated by play', () => { // Arrange const player = new Scrabble.Player('test player'); const words = [{word: 'dog', score: 5}, {word: 'cat', score: 5}, {word: 'goat', score: 5}]; From afa87c230849202d3f85f334cc101d9fdba39226 Mon Sep 17 00:00:00 2001 From: Abiaina Date: Wed, 16 May 2018 19:26:37 -0700 Subject: [PATCH 8/8] determines highest scoring word played, tests passing and written --- scrabble.js | 8 ++++++++ specs/scrabble.spec.js | 26 ++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/scrabble.js b/scrabble.js index e49fee6..e77afe8 100644 --- a/scrabble.js +++ b/scrabble.js @@ -122,6 +122,14 @@ Scrabble.Player = class { return total; } + + highestScoringWord() { + if (this.plays.length === 0) { + throw "you must play at least one word"; + } + return Scrabble.highestScoreFrom(this.plays); + + } }; diff --git a/specs/scrabble.spec.js b/specs/scrabble.spec.js index 2f1b7b4..97815cd 100644 --- a/specs/scrabble.spec.js +++ b/specs/scrabble.spec.js @@ -213,14 +213,36 @@ describe('Player', () => { describe('highestScoringWord', () => { // Tie-breaking logic is already described in the tests // for highestWordFrom, so we will not repeat it here. - test.skip('returns the highest scoring word played', () => { + test('returns the highest scoring word played', () => { + const player = new Scrabble.Player('test player'); + // / 50 pts + player.play('zzzzz'); + // 20 pts + player.play('zz'); + expect(player.plays.length).toBe(2); + expect(player.highestScoringWord()).toBe('zzzzz'); }); + test('returns the highest scoring word played regardless of order played', () => { + const player = new Scrabble.Player('test player'); + //20pts + player.play('kkkk'); + // / 50 pts + player.play('zzzzz'); + // 20 pts + player.play('zz'); + expect(player.plays.length).toBe(3); - test.skip('throws an error if no words have been played', () => { + expect(player.highestScoringWord()).toBe('zzzzz'); + + }); + test('throws an error if no words have been played', () => { + const player = new Scrabble.Player('test player'); + expect(player.plays.length).toBe(0); + expect(() => { player.highestScoringWord(); }).toThrow(); }); });