Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ampers: Abinnet #40

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
120 changes: 120 additions & 0 deletions scrabble.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,135 @@

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;

const regex_key = /^[a-z]+$/i;

word = word.toUpperCase().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";
}
})
}

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;
}
});

return (word.length === 7) ? (total + 50) : total;
},

highestScoreFrom(arrayOfWords) {
if (arrayOfWords.length === 0){
throw "must enter a valid list of words to score."
}

let highScore = 0;
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;
}
}
}

return highestScoringWord;
},
};

Scrabble.Player = class {
constructor(name) {
this.name = name;
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;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

even though in JavaScript this works, it is best practice to always have curly braces around a one-line if statement:

if (this.hasWon()) { return false; }

or

if (this.hasWon()) {
  return false;
}


this.plays.push(word);
return true;
}

hasWon() {
if (this.totalScore() < 100) {
return false;
}

return true;
}

totalScore() {
let total = 0;

this.plays.forEach(function(word) {
total += Scrabble.score(word);
});

return total;
}

highestScoringWord() {
if (this.plays.length === 0) {
throw "you must play at least one word";
}
return Scrabble.highestScoreFrom(this.plays);

}
};


Expand Down
95 changes: 65 additions & 30 deletions specs/scrabble.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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';

Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -98,27 +98,27 @@ 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();
});
});

describe('play', () => {
test.skip('Records the played word', () => {
test('Records the played word', () => {
const word = 'dog';
const player = new Scrabble.Player('test player');

Expand All @@ -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);
Expand All @@ -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
Expand All @@ -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}];
Expand All @@ -181,43 +181,78 @@ 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);
});
});

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();
});
});

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', () => {


});
Expand Down