From 1218a8163e4f0b63c020001170adb9d3aeebac40 Mon Sep 17 00:00:00 2001 From: marikoja Date: Tue, 15 May 2018 18:27:04 -0700 Subject: [PATCH 1/4] workd score code, passes test for correctly scoring simple words --- package.json | 2 +- scrabble.js | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) 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..2be0418 100644 --- a/scrabble.js +++ b/scrabble.js @@ -1,7 +1,49 @@ +const letterValues = { + '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 + }; + const Scrabble = { + score(word) { + word = word.toUpperCase(); + let letters = word.split(''); + + let wordScore = 0 + for (let letter of letters) { + for (let value in letterValues) { + if (letter === value) { + wordScore += letterValues[value] + } + } + } + return wordScore }, highestScoreFrom(arrayOfWords) { From 967abcb5768414ecbdd792f63a1e129f19959d32 Mon Sep 17 00:00:00 2001 From: marikoja Date: Tue, 15 May 2018 18:48:16 -0700 Subject: [PATCH 2/4] code for alphanermic chekc, passes test fot throws on bad characters --- scrabble.js | 7 +++++++ specs/scrabble.spec.js | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/scrabble.js b/scrabble.js index 2be0418..04a95bf 100644 --- a/scrabble.js +++ b/scrabble.js @@ -32,6 +32,13 @@ const Scrabble = { score(word) { word = word.toUpperCase(); + + let letterCheck = /^[a-zA-Z]+$/; + + if (!letterCheck.test(word)) { + throw 'Invalid characters'; + } + let letters = word.split(''); let wordScore = 0 diff --git a/specs/scrabble.spec.js b/specs/scrabble.spec.js index b562037..5f38086 100644 --- a/specs/scrabble.spec.js +++ b/specs/scrabble.spec.js @@ -15,7 +15,7 @@ describe('score', () => { expect(Scrabble.score('academy')).toBe(65); }); - test.skip('throws on bad characters', () => { + test('throws on bad characters', () => { expect(() => { Scrabble.score('char^'); }).toThrow(); From 97f1c67d2bec7a18e1124deb57ddfae642c854e1 Mon Sep 17 00:00:00 2001 From: marikoja Date: Wed, 16 May 2018 01:09:41 -0700 Subject: [PATCH 3/4] adds 50 to wordScore if word is 7 letters --- scrabble.js | 6 +++++- specs/scrabble.spec.js | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/scrabble.js b/scrabble.js index 04a95bf..4128ccf 100644 --- a/scrabble.js +++ b/scrabble.js @@ -38,11 +38,15 @@ const Scrabble = { if (!letterCheck.test(word)) { throw 'Invalid characters'; } - let letters = word.split(''); let wordScore = 0 + if (word.length === 7) { + wordScore += 50 + } + +// separate into a function that gets called? for (let letter of letters) { for (let value in letterValues) { if (letter === value) { diff --git a/specs/scrabble.spec.js b/specs/scrabble.spec.js index 5f38086..263321d 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); }); From 673e25e8c17257c5c269624359e52a461d5740a0 Mon Sep 17 00:00:00 2001 From: marikoja Date: Fri, 18 May 2018 00:29:56 -0700 Subject: [PATCH 4/4] completes code and tests for primary requirements, all tests passing --- README.md | 2 +- feedback.md | 2 +- scrabble.js | 160 +++++++++++++++++++++++++++++------------ specs/scrabble.spec.js | 114 ++++++++++++++++------------- 4 files changed, 181 insertions(+), 97 deletions(-) diff --git a/README.md b/README.md index 0b98488..2ab1ba8 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ There are many possible answers to this question, but according to the tests the ### Primary Requirements Create the following methods within the `Scrabble` object. - `score(word)`: returns the total score value for the given word. The word is input as a string (case insensitive). The chart below shows the point value for a given letter. -- `highestScoreFrom(arrayOfWords)`: returns **the word in the array with the highest score**. +- `highestScoringWord(arrayOfWords)`: returns **the word in the array with the highest score**. - Note that it’s better to use fewer tiles, so if the top score is tied between multiple words, pick the one with the fewest letters. - Note that there is a bonus (50 points) for using all seven letters. If the top score is tied between multiple words and one used all seven letters, choose the one with seven letters over the one with fewer tiles. - If the there are multiple words that are the same score and same length, pick the first one in supplied list. diff --git a/feedback.md b/feedback.md index 2a9cfa8..4076d96 100644 --- a/feedback.md +++ b/feedback.md @@ -8,7 +8,7 @@ Git hygiene | Comprehension questions | **General** | `score` calculates score, has appropriate params and return value | -`highestScoreFrom` calculates highest scoring word, has appropriate params and return value | +`highestScoringWord` calculates highest scoring word, has appropriate params and return value | **`Player` object** | Has `name` and `plays` properties | Has `play`, `totalScore`, `hasWon` functions | diff --git a/scrabble.js b/scrabble.js index 4128ccf..989e40a 100644 --- a/scrabble.js +++ b/scrabble.js @@ -1,39 +1,40 @@ const letterValues = { - '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 - }; + '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 +}; const Scrabble = { + // score: function(word) {} same as vv score(word) { word = word.toUpperCase(); - let letterCheck = /^[a-zA-Z]+$/; + let letterCheck = /^[A-Z]+$/; if (!letterCheck.test(word)) { throw 'Invalid characters'; @@ -42,28 +43,97 @@ const Scrabble = { let wordScore = 0 - if (word.length === 7) { - wordScore += 50 - } + if (word.length > 7 || typeof word !== 'string' || word.length < 1) { + throw 'Word is invlaid';} + + if (word.length === 7) { + wordScore += 50 + } -// separate into a function that gets called? - for (let letter of letters) { - for (let value in letterValues) { - if (letter === value) { - wordScore += letterValues[value] + for (let letter of letters) { + for (let value in letterValues) { + if (letter === value) { + wordScore += letterValues[value] + } } } - } - return wordScore - }, - highestScoreFrom(arrayOfWords) { - }, -}; + return wordScore + }, -Scrabble.Player = class { + highestScoringWord(arrayOfWords) { + if (arrayOfWords.length < 1 || !Array.isArray(arrayOfWords)){ + throw 'No words to find high score'; + } else if (arrayOfWords.length === 1) { + return arrayOfWords[0]; + } else { + let highestWordScore = 0; + let highestWord = ''; -}; + for (let i = 0; i < arrayOfWords.length; i++) { + let currentWordScore = this.score(arrayOfWords[i]); + + if (currentWordScore > highestWordScore) { + highestWordScore = currentWordScore; + highestWord = arrayOfWords[i]; + } else if (currentWordScore === highestWordScore); { + if (highestWord.length !== 7 && (arrayOfWords[i].length === 7 || + arrayOfWords[i].length < highestWord.length)) { + highestWordScore = currentWordScore; + highestWord = arrayOfWords[i]; + } + } + } + return highestWord; + } + }, + + highestWordScore(arrayOfWords) { + return Scrabble.score(Scrabble.highestScoringWord(arrayOfWords)); + }, + + }; + + Scrabble.Player = class { + constructor(name) { + this.name = name; + if (name === undefined) { + throw 'Players must have a name' + } + this.plays = []; + } + play(word) { + + if (word === undefined || typeof(word) !== 'string') { + throw 'Invalid word' + } + + if (this.hasWon()) { + return false + } else { + this.plays.push(word); + return true; + } + } + + hasWon() { + if (this.totalScore() >= 100) { + return true + } else { + return false + } + } + + totalScore() { + let total = 0; + + for (let i = 0; i < this.plays.length; i++) { + total += Scrabble.score(this.plays[i]); + } + return total; + } + + }; -module.exports = Scrabble; + module.exports = Scrabble; diff --git a/specs/scrabble.spec.js b/specs/scrabble.spec.js index 263321d..fcd48f0 100644 --- a/specs/scrabble.spec.js +++ b/specs/scrabble.spec.js @@ -21,46 +21,46 @@ describe('score', () => { }).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', () => { - expect(Scrabble.highestScoreFrom).toBeDefined(); +describe('highestScoringWord', () => { + test('is defined', () => { + expect(Scrabble.highestScoringWord).toBeDefined(); }); - test.skip('throws if no words were passed', () => { - expect(() => { Scrabble.highestScoreFrom([]); }).toThrow(); - expect(() => { Scrabble.highestScoreFrom('not array'); }).toThrow(); + test('throws if no words were passed', () => { + expect(() => { Scrabble.highestScoringWord([]); }).toThrow(); + expect(() => { Scrabble.highestScoringWord('not array'); }).toThrow(); }); - test.skip('returns the only word in a length-1 array', () => { - expect(Scrabble.highestScoreFrom(['dog'])).toBe('dog'); + test('returns the only word in a length-1 array', () => { + expect(Scrabble.highestScoringWord(['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); // Test the functionality - expect(Scrabble.highestScoreFrom(['dog', 'pig'])).toBe('pig'); - expect(Scrabble.highestScoreFrom(['pig', 'dog'])).toBe('pig'); + expect(Scrabble.highestScoringWord(['dog', 'pig'])).toBe('pig'); + expect(Scrabble.highestScoringWord(['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'; @@ -69,48 +69,48 @@ describe('highestScoreFrom', () => { expect(Scrabble.score(winner)).toBe(60); // Test functionality - expect(Scrabble.highestScoreFrom([loser, winner])).toBe(winner); - expect(Scrabble.highestScoreFrom([winner, loser])).toBe(winner); + expect(Scrabble.highestScoringWord([loser, winner])).toBe(winner); + expect(Scrabble.highestScoringWord([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); // Test functionality - expect(Scrabble.highestScoreFrom(['dog', 'goat'])).toBe('dog'); - expect(Scrabble.highestScoreFrom(['goat', 'dog'])).toBe('dog'); + expect(Scrabble.highestScoringWord(['dog', 'goat'])).toBe('dog'); + expect(Scrabble.highestScoringWord(['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); expect(Scrabble.score('cat')).toBe(5); // Test the functionality - expect(Scrabble.highestScoreFrom(['dog', 'dog'])).toBe('dog'); - expect(Scrabble.highestScoreFrom(['dog', 'cat'])).toBe('dog'); - expect(Scrabble.highestScoreFrom(['cat', 'dog'])).toBe('cat'); - expect(Scrabble.highestScoreFrom(['i', 'dog', 'cat'])).toBe('dog'); + expect(Scrabble.highestScoringWord(['dog', 'dog'])).toBe('dog'); + expect(Scrabble.highestScoringWord(['dog', 'cat'])).toBe('dog'); + expect(Scrabble.highestScoringWord(['cat', 'dog'])).toBe('cat'); + expect(Scrabble.highestScoringWord(['i', 'dog', 'cat'])).toBe('dog'); }); }); 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(); @@ -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 @@ -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}]; @@ -181,44 +181,58 @@ 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); + player.play('qqqq'); // score: 90 + 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') + player.play('qqqq'); // score: 40 + player.play('qqqq'); // score: 80 + player.play('qq'); // score: 100 + 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'); + player.play('qqqq'); // score: 40 + player.play('qqqq'); // score: 80 + player.play('qqqq'); // score: 120 + 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', () => { + let plays = ['qqqq', 'aaaa']; + expect(Scrabble.highestScoringWord(plays)).toBe('qqqq'); }); - test.skip('throws an error if no words have been played', () => { - - + test('throws an error if no words have been played', () => { + let plays = []; + expect( () => {Scrabble.highestScoringWord(plays)}).toThrow(); }); }); describe('highestWordScore', () => { - test.skip('returns the score of the highest scoring word played', () => { - + test('returns the score of the highest scoring word played', () => { + let plays = ['qqqq', 'aaaa']; + expect(Scrabble.highestWordScore(plays)).toBe(40); + plays = ['qqqq', 'aaaa', 'zzzzz']; + expect(Scrabble.highestWordScore(plays)).toBe(50); }); - test.skip('throws an error if no words have been played', () => { - + test('throws an error if no words have been played', () => { + let plays = []; + expect( () => {Scrabble.highestScoringScore(plays)}).toThrow(); }); });