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

Ana Lisa Sutherland - Octos C9- JS Scrabble #38

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"license": "ISC",
"dependencies": {
"fs": "0.0.1-security",
"npm": "^5.8.0"
"npm": "^5.10.0"
},
"scripts": {
"test": "jest"
Expand Down
124 changes: 122 additions & 2 deletions scrabble.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,135 @@

//A, E, I, O, U, L, N, R, S, T 1
// D, G 2
// B, C, M, P 3
// F, H, V, W, Y 4
// K 5
// J, X 8
// Q, Z 10
const Scrabble = {
scoreBoard: {
'A': 1, 'E': 1, 'I': 1, 'O': 1, 'U': 1, 'L': 1, 'N': 1, 'R': 1, 'S': 1, 'T': 1,
'D': 2, 'G': 2,
'B': 3, 'C': 3, 'M': 3, 'P': 3,

Choose a reason for hiding this comment

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

I like the use of a hash to store this info.

'F': 4, 'H': 4, 'V': 4, 'W': 4, 'Y': 4,
'K': 5,
'J': 8, 'X': 8,
'Q': 10, 'Z': 10
},

score(word) {
let totalScore = 0;

// throws if word contains invalid characters
// .search will return -1 if there is a match
// throws if word is empty
//throws if word is longer then 7 characters
if (word.search(/[^a-zA-Z]+/) !== -1 || word.length === 0 || word.length > 7) {
throw 'Invalid word.';
}

Choose a reason for hiding this comment

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

Instead of throwing a string, you should throw an instance of Error. That gives you access to stack trace information. Something like this:

if (condition) {
  throw new Error(`Invalid word ${word}`);
}


// split our word into an array of Uppercase characters
let upcase_word = word.toUpperCase()
let wordArray = upcase_word.split("");

// if the word <= 7 in length proceed
while (wordArray.length <= 7) {

// look at each letter in the array and scoreboard and then reassign value at index to value from scoreBoard wordArray[i] = scoreBoard[wordArray[i]]
for (let i = 0; i < wordArray.length; i++) {
wordArray[i] = Scrabble.scoreBoard[wordArray[i]]
//gets a sum of this array now that values have been assigned
totalScore = wordArray.reduce((x, y) => x + y);
}

// Adds 50 points if you play a 7 letter word, else just returns your normal score
if (wordArray.length === 7) {
return totalScore + 50;
} else {
return totalScore;
}
}
},

highestScoreFrom(arrayOfWords) {
// throw if no words are passed
if (arrayOfWords.length === 0 || Array.isArray(arrayOfWords) !== true) {
throw "No played words.";
}

},
const tieBreak = function tieBreak(best_word, challenger_word) {
console.log(`Best Word: ${best_word}`);
console.log(`Challenger Word: ${challenger_word}`);
if (best_word.length === 7) {

Choose a reason for hiding this comment

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

Good use of a helper function to clarify this logic.

return best_word;
} else if (challenger_word.length === 7) {
return challenger_word;
} else if (challenger_word.length < best_word.length) {
return challenger_word;
} else {
return best_word
}
};

let bestWord = arrayOfWords[0];
let bestScore = this.score(bestWord);

arrayOfWords.forEach((word) => {
if (this.score(word) > bestScore) {
bestWord = word;
bestScore = this.score(word);
} else if (this.score(word) === bestScore) {
bestWord = tieBreak(bestWord, word);
}
})
return bestWord
}
};

Scrabble.Player = class {
constructor(name) {
this.name = name;
if (arguments.length === 0) {
throw 'Must provide a name.';
}
this.plays = [];
this.score = 0;
}

play(word) {
let word_score = 0;
if (this.hasWon()) {
return false;
}

if (word.search(/[^a-zA-Z]+/) !== -1 || word.length > 7) {
throw 'You must enter a real word that is 7 characters or under.';
}

if (this.plays.includes(word)) {
throw "This word was used already.";
} else {
this.plays.push(word);
word_score = Scrabble.score(word);
this.score += word_score
}
return word_score;
}

totalScore() {
return this.score;
}

hasWon() {
return this.score >= 100;
}

highestScoringWord() {
return Scrabble.highestScoreFrom(this.plays);
}

highestWordScore() {
// ran out of time to implement and test this.
}
};


Expand Down
70 changes: 39 additions & 31 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,51 @@ describe('Player', () => {
});

describe('hasWon', () => {
test.skip('returns false when score < 100', () => {

test('returns false when score < 100', () => {
const player = new Scrabble.Player('test player');
player.score = 99

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.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.score = 101

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');
player.play('mirror');

expect(player.highestScoringWord()).toBe('mirror');
});

test.skip('throws an error if no words have been played', () => {
test('throws an error if no words have been played', () => {


});
});

describe('highestWordScore', () => {
test.skip('returns the score of the highest scoring word played', () => {
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