From 2a0c16e396192a07e68fcd9dabb2215833337606 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Tue, 15 May 2018 16:13:14 -0700 Subject: [PATCH 01/11] adds total word score method with input validations --- package.json | 2 +- scrabble.js | 56 +++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 50444a7..ec337f6 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "license": "ISC", "dependencies": { "fs": "0.0.1-security", - "npm": "^5.8.0" + "npm": "^5.10.0" }, "scripts": { "test": "jest" diff --git a/scrabble.js b/scrabble.js index e95f352..94af177 100644 --- a/scrabble.js +++ b/scrabble.js @@ -1,16 +1,62 @@ + const Scrabble = { + A: 1, + B: 3, + C: 3, + D: 2, + E: 1, + F: 4, + G: 2, + H: 4, + I: 1, + J: 8, + K: 5, + L: 1, + M: 3, + N: 1, + O: 1, + P: 3, + Q: 10, + R: 1, + S: 1, + T: 1, + U: 1, + V: 4, + W: 4, + X: 8, + Y: 4, + Z: 10, + score(word) { + let total = 0; + if (typeof word != 'string' ) { + throw "Invalid word played, must be a string." + } + for (let letter of word) { + let capLetter = letter.toUpperCase(); + if (this[capLetter]) { + total += this[capLetter]; + } else { + throw "Invalid word played, includes invalid letter." + } + } + console.log(`Total score for "${word}" is ${total} points.`); }, - highestScoreFrom(arrayOfWords) { - }, + // highestScoreFrom(arrayOfWords) { + // + // }, + }; -Scrabble.Player = class { +// Scrabble.Player = class { +// +// }; -}; +// module.exports = Scrabble; -module.exports = Scrabble; +//// +Scrabble.score('hellothere') From d478f6c425e26fd077273b457074d715d7cc44c7 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Tue, 15 May 2018 16:28:35 -0700 Subject: [PATCH 02/11] adds scrabble#score throw error for empty string --- scrabble.js | 12 +++++------- specs/scrabble.spec.js | 6 +++--- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/scrabble.js b/scrabble.js index 94af177..baa9fcc 100644 --- a/scrabble.js +++ b/scrabble.js @@ -1,5 +1,3 @@ - - const Scrabble = { A: 1, B: 3, @@ -30,19 +28,19 @@ const Scrabble = { score(word) { let total = 0; - if (typeof word != 'string' ) { - throw "Invalid word played, must be a string." + if (typeof word != 'string' || word.length < 1 ) { + throw "Word must be a string." } for (let letter of word) { let capLetter = letter.toUpperCase(); if (this[capLetter]) { total += this[capLetter]; } else { - throw "Invalid word played, includes invalid letter." + throw "Word includes an invalid letter." } } - console.log(`Total score for "${word}" is ${total} points.`); + return total; }, // highestScoreFrom(arrayOfWords) { @@ -56,7 +54,7 @@ const Scrabble = { // }; -// module.exports = Scrabble; +module.exports = Scrabble; //// Scrabble.score('hellothere') diff --git a/specs/scrabble.spec.js b/specs/scrabble.spec.js index b562037..cfd5bbc 100644 --- a/specs/scrabble.spec.js +++ b/specs/scrabble.spec.js @@ -15,13 +15,13 @@ describe('score', () => { 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); @@ -31,7 +31,7 @@ describe('score', () => { expect(() => { Scrabble.score('abcdefgh'); }).toThrow(); }); - test.skip('does not allow empty words', () => { + test('does not allow empty words', () => { expect(() => { Scrabble.score(''); }).toThrow(); }); }); From 72f5275e625341db7e4cca7c077d59a7c906522d Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Tue, 15 May 2018 16:51:53 -0700 Subject: [PATCH 03/11] adds scrabble#score throw for words greater than 7 chars --- scrabble.js | 11 ++++++++--- specs/scrabble.spec.js | 10 ++++++---- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/scrabble.js b/scrabble.js index baa9fcc..0507041 100644 --- a/scrabble.js +++ b/scrabble.js @@ -28,9 +28,15 @@ const Scrabble = { score(word) { let total = 0; - if (typeof word != 'string' || word.length < 1 ) { - throw "Word must be a string." + + if (typeof word != 'string' || word.length < 1 || word.length > 7) { + throw "Word must be a non-empty string less than 8 chars." + } + + if (word.length === 7) { + total += 50; } + for (let letter of word) { let capLetter = letter.toUpperCase(); if (this[capLetter]) { @@ -57,4 +63,3 @@ const Scrabble = { module.exports = Scrabble; //// -Scrabble.score('hellothere') diff --git a/specs/scrabble.spec.js b/specs/scrabble.spec.js index cfd5bbc..039dc0e 100644 --- a/specs/scrabble.spec.js +++ b/specs/scrabble.spec.js @@ -11,7 +11,7 @@ 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); }); @@ -27,13 +27,15 @@ describe('score', () => { expect(Scrabble.score('DoG')).toBe(5); }); - test.skip('does not allow words > 7 letters', () => { - expect(() => { Scrabble.score('abcdefgh'); }).toThrow(); - }); test('does not allow empty words', () => { expect(() => { Scrabble.score(''); }).toThrow(); }); + + test('does not allow words > 7 letters', () => { + expect(() => { Scrabble.score('abcdefgh'); }).toThrow(); + }); + }); describe('highestScoreFrom', () => { From 91412362a0b81d0af40f9e3120dfbc8abf4cd5cc Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Tue, 15 May 2018 21:10:25 -0700 Subject: [PATCH 04/11] scrabble#highestwordfrom accounts for all test cases except choosing least length in case of tie --- scrabble.js | 38 ++++++++++++++++++++++++++++---------- specs/scrabble.spec.js | 14 +++++++------- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/scrabble.js b/scrabble.js index 0507041..4178d59 100644 --- a/scrabble.js +++ b/scrabble.js @@ -30,10 +30,8 @@ const Scrabble = { let total = 0; if (typeof word != 'string' || word.length < 1 || word.length > 7) { - throw "Word must be a non-empty string less than 8 chars." - } - - if (word.length === 7) { + throw "Word must be a non-empty string less than 8 chars."; + } else if (word.length === 7) { total += 50; } @@ -42,16 +40,38 @@ const Scrabble = { if (this[capLetter]) { total += this[capLetter]; } else { - throw "Word includes an invalid letter." + throw "Word includes an invalid letter."; } } return total; }, - // highestScoreFrom(arrayOfWords) { - // - // }, + highestScoreFrom(arrayOfWords) { + let highestScore = ["", 0] + + if (arrayOfWords.length < 1 || !Array.isArray(arrayOfWords)) { + throw "Must contain an array."; + } else if (arrayOfWords.length === 1) { + return arrayOfWords[0]; + } + + for (let i = 0; i < arrayOfWords.length; i++) { + + + if (this.score(arrayOfWords[i]) === highestScore[1]) { + if (arrayOfWords[i].length === 7 || highestScore[0].length === 7) { + return (arrayOfWords[i].length === 7 ? arrayOfWords[i] : highestScore[0]); + } else { + return (arrayOfWords[i].length < highestScore[1].length ? arrayOfWords[i] : highestScore[0]); + } + } else if (this.score(arrayOfWords[i]) >= highestScore[1]) { + highestScore[0] = arrayOfWords[i]; + highestScore[1] = this.score(arrayOfWords[i]); + } + } + return highestScore[0] + }, }; @@ -61,5 +81,3 @@ const Scrabble = { module.exports = Scrabble; - -//// diff --git a/specs/scrabble.spec.js b/specs/scrabble.spec.js index 039dc0e..1335ce8 100644 --- a/specs/scrabble.spec.js +++ b/specs/scrabble.spec.js @@ -39,20 +39,20 @@ describe('score', () => { }); 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); @@ -62,7 +62,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'; @@ -75,7 +75,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); @@ -85,7 +85,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 dece1ccb2369578160483987808239c594467341 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Tue, 15 May 2018 22:00:04 -0700 Subject: [PATCH 05/11] scrabble#highestwordfrom passes all test --- scrabble.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scrabble.js b/scrabble.js index 4178d59..96c2b23 100644 --- a/scrabble.js +++ b/scrabble.js @@ -57,13 +57,11 @@ const Scrabble = { } for (let i = 0; i < arrayOfWords.length; i++) { - - if (this.score(arrayOfWords[i]) === highestScore[1]) { if (arrayOfWords[i].length === 7 || highestScore[0].length === 7) { return (arrayOfWords[i].length === 7 ? arrayOfWords[i] : highestScore[0]); } else { - return (arrayOfWords[i].length < highestScore[1].length ? arrayOfWords[i] : highestScore[0]); + return (arrayOfWords[i].length < highestScore[0].length ? arrayOfWords[i] : highestScore[0]); } } else if (this.score(arrayOfWords[i]) >= highestScore[1]) { highestScore[0] = arrayOfWords[i]; From d60427d1caea565aae856b21a8b02b204839be81 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Wed, 16 May 2018 13:38:24 -0700 Subject: [PATCH 06/11] beginning Scrabble.Player class outline --- scrabble.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/scrabble.js b/scrabble.js index 96c2b23..3e4fce4 100644 --- a/scrabble.js +++ b/scrabble.js @@ -43,7 +43,6 @@ const Scrabble = { throw "Word includes an invalid letter."; } } - return total; }, @@ -73,9 +72,13 @@ const Scrabble = { }; -// Scrabble.Player = class { -// -// }; + +Scrabble.Player = class { + constructor(name) { + this.name = name; + } + +}; module.exports = Scrabble; From 531ea36ef023b6c1d25814932d6bdecc2bdd78b1 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Wed, 16 May 2018 13:52:26 -0700 Subject: [PATCH 07/11] Scrabble.Player constructor throws error for empty name --- scrabble.js | 17 +++++++++++++++++ specs/scrabble.spec.js | 6 +++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/scrabble.js b/scrabble.js index 3e4fce4..a07fb8f 100644 --- a/scrabble.js +++ b/scrabble.js @@ -76,6 +76,23 @@ const Scrabble = { Scrabble.Player = class { constructor(name) { this.name = name; + if (this.name.length < 1) { + throw "Player name cannot be empty." + } + this.plays = []; + } + + play(word) { + this.plays.push(word) + } + + totalScore() { + + + } + + hasWon() { + } }; diff --git a/specs/scrabble.spec.js b/specs/scrabble.spec.js index 1335ce8..771da78 100644 --- a/specs/scrabble.spec.js +++ b/specs/scrabble.spec.js @@ -100,19 +100,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(); From 2e67b304f2ce473de84cbfbf088945cc66507a8d Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Wed, 16 May 2018 14:15:31 -0700 Subject: [PATCH 08/11] Player throws error if word is invalid --- scrabble.js | 9 +++++++-- specs/scrabble.spec.js | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/scrabble.js b/scrabble.js index a07fb8f..d44b3ed 100644 --- a/scrabble.js +++ b/scrabble.js @@ -83,12 +83,17 @@ Scrabble.Player = class { } play(word) { - this.plays.push(word) + if (word.length < 1 || typeof word != 'string') { + throw "Word is invalid." + } else { + this.plays.push(word); + return this.plays; + } } totalScore() { - + } hasWon() { diff --git a/specs/scrabble.spec.js b/specs/scrabble.spec.js index 771da78..c84d6f9 100644 --- a/specs/scrabble.spec.js +++ b/specs/scrabble.spec.js @@ -120,7 +120,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'); @@ -132,7 +132,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); From 3f4490a79b3d6b5004abcdc4a7b70d7d5433acf9 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Wed, 16 May 2018 14:38:42 -0700 Subject: [PATCH 09/11] player#hasWon returns true and false scores under and over 100, passes tests --- scrabble.js | 14 +++++++++++++- specs/scrabble.spec.js | 12 ++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/scrabble.js b/scrabble.js index d44b3ed..cd8bd76 100644 --- a/scrabble.js +++ b/scrabble.js @@ -85,6 +85,8 @@ Scrabble.Player = class { play(word) { if (word.length < 1 || typeof word != 'string') { throw "Word is invalid." + } else if (this.hasWon()) { + return false; } else { this.plays.push(word); return this.plays; @@ -92,11 +94,21 @@ Scrabble.Player = class { } totalScore() { + let playerScore = 0; - + this.plays.forEach((word) => { + playerScore += Scrabble.score(word) + }); + + return playerScore; } hasWon() { + if (this.totalScore() > 100) { + return true; + } else { + return false; + } } diff --git a/specs/scrabble.spec.js b/specs/scrabble.spec.js index c84d6f9..4d5d87b 100644 --- a/specs/scrabble.spec.js +++ b/specs/scrabble.spec.js @@ -144,7 +144,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 @@ -157,13 +157,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}]; @@ -183,9 +183,13 @@ describe('Player', () => { }); describe('hasWon', () => { - test.skip('returns false when score < 100', () => { + test('returns false when score < 100', () => { + const player = new Scrabble.Player('test'); + player.play('snail'); + player.play('wow'); + expect(player.hasWon()).toBe(false) }); test.skip('returns true when score == 100', () => { From cfb31b4e360f9ea03830942ac65bf87fb1a3ddb2 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Wed, 16 May 2018 16:46:34 -0700 Subject: [PATCH 10/11] passes all tests --- scrabble.js | 22 +++++++++++++++++----- specs/scrabble.spec.js | 36 ++++++++++++++++++++++++++++-------- 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/scrabble.js b/scrabble.js index cd8bd76..c1d35d2 100644 --- a/scrabble.js +++ b/scrabble.js @@ -47,7 +47,7 @@ const Scrabble = { }, highestScoreFrom(arrayOfWords) { - let highestScore = ["", 0] + let highestScore = ["", 0]; if (arrayOfWords.length < 1 || !Array.isArray(arrayOfWords)) { throw "Must contain an array."; @@ -68,8 +68,7 @@ const Scrabble = { } } return highestScore[0] - }, - + } }; @@ -104,15 +103,28 @@ Scrabble.Player = class { } hasWon() { - if (this.totalScore() > 100) { + if (this.totalScore() >= 100) { return true; } else { return false; } + } + highestScoringWord() { + if (this.plays.length < 1) { + throw "No words have been played yet." + } else { + return Scrabble.highestScoreFrom(this.plays); + } } + highestWordScore() { + if (this.plays.length < 1 ){ + throw "No words have been played yet."; + } else { + return Scrabble.score(this.highestScoringWord()); + } + } }; - module.exports = Scrabble; diff --git a/specs/scrabble.spec.js b/specs/scrabble.spec.js index 4d5d87b..c9c8f65 100644 --- a/specs/scrabble.spec.js +++ b/specs/scrabble.spec.js @@ -192,40 +192,60 @@ describe('Player', () => { 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.play('zzzzz'); + player.play('zzzzz'); + 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.play('zzzzz'); + player.play('zzzzz'); + player.play('quail'); + expect(player.hasWon()).toBe(true); }); }); 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.play('quail'); + player.play('and'); + expect(player.highestScoringWord()).toBe('quail') }); - test.skip('throws an error if no words have been played', () => { - + test('throws an error if no words have been played', () => { + const player = new Scrabble.Player('test'); + expect(() => { player.highestScoringWord(); }).toThrow(); }); }); describe('highestWordScore', () => { - test.skip('returns the score of the highest scoring word played', () => { + test('returns the score of the highest scoring word played', () => { + const player = new Scrabble.Player('test'); + player.play('dog'); + player.play('quail'); + let highest = Scrabble.score('quail'); + expect(player.highestWordScore()).toBe(highest); }); - test.skip('throws an error if no words have been played', () => { - + test('throws an error if no words have been played', () => { + const player = new Scrabble.Player('test'); + expect(() => { player.highestWordScore(); }).toThrow(); }); }); }); From a0d3a1d7847f53cf28982faebf345348e7399765 Mon Sep 17 00:00:00 2001 From: Alexandria Brown Date: Wed, 16 May 2018 16:49:57 -0700 Subject: [PATCH 11/11] minor cleaning --- scrabble.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/scrabble.js b/scrabble.js index c1d35d2..0b39d10 100644 --- a/scrabble.js +++ b/scrabble.js @@ -105,25 +105,22 @@ Scrabble.Player = class { hasWon() { if (this.totalScore() >= 100) { return true; - } else { - return false; } + return false; } highestScoringWord() { if (this.plays.length < 1) { throw "No words have been played yet." - } else { - return Scrabble.highestScoreFrom(this.plays); } + return Scrabble.highestScoreFrom(this.plays); } highestWordScore() { if (this.plays.length < 1 ){ throw "No words have been played yet."; - } else { - return Scrabble.score(this.highestScoringWord()); } + return Scrabble.score(this.highestScoringWord()); } };