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/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..989e40a 100644 --- a/scrabble.js +++ b/scrabble.js @@ -1,16 +1,139 @@ +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: function(word) {} same as vv score(word) { + word = word.toUpperCase(); - }, - highestScoreFrom(arrayOfWords) { + let letterCheck = /^[A-Z]+$/; - }, -}; + if (!letterCheck.test(word)) { + throw 'Invalid characters'; + } + let letters = word.split(''); -Scrabble.Player = class { + let wordScore = 0 -}; + if (word.length > 7 || typeof word !== 'string' || word.length < 1) { + throw 'Word is invlaid';} + + if (word.length === 7) { + wordScore += 50 + } + + for (let letter of letters) { + for (let value in letterValues) { + if (letter === value) { + wordScore += letterValues[value] + } + } + } + + return wordScore + }, + + 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 b562037..fcd48f0 100644 --- a/specs/scrabble.spec.js +++ b/specs/scrabble.spec.js @@ -11,56 +11,56 @@ 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', () => { - 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(); }); });