diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..80043d7 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,123 @@ +{ + "name": "js-scrabble", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "add-matchers": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/add-matchers/-/add-matchers-0.5.0.tgz", + "integrity": "sha1-UCGQ5HUM1XIWGDkyaLYaFXNm52U=" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "eslint-plugin-jasmine": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jasmine/-/eslint-plugin-jasmine-2.9.1.tgz", + "integrity": "sha1-IuGaWfFvOl9kOgSroEQ40OMEcDA=" + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "jasmine": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz", + "integrity": "sha1-awicChFXax8W3xG4AUbZHU6Lij4=", + "requires": { + "exit": "0.1.2", + "glob": "7.1.2", + "jasmine-core": "2.8.0" + } + }, + "jasmine-core": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz", + "integrity": "sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=" + }, + "jasmine-expect": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/jasmine-expect/-/jasmine-expect-3.8.1.tgz", + "integrity": "sha512-klARdR5AVX9nZhHhYDlbDYgxgi6kl9DGS0vguhaioKoSwr8HL1uOQ7FFUBASq/sqBL/s2nkh/1efqZ2ugcknFA==", + "requires": { + "add-matchers": "0.5.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "1.1.8" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + } + } +} diff --git a/scrabble.js b/scrabble.js index 7a1f161..e6b77fd 100644 --- a/scrabble.js +++ b/scrabble.js @@ -1,14 +1,125 @@ const Scrabble = { - score: function(word) { - // TODO: implement score - } + _isValidWord: function _isValidWord(word) { + if ((typeof word === 'string') && (/^[a-zA-Z]+$/.test(word)) && (word.length < 8) && (word.length > 0)) { + return true; + } throw new Error('Invalid Word'); + }, + score: function score(word) { + const letters = { + 1: ['A', 'E', 'I', 'O', 'U', 'L', 'N', 'R', 'S', 'T'], + 2: ['D', 'G'], + 3: ['B', 'C', 'M', 'P'], + 4: ['F', 'H', 'V', 'W', 'Y'], + 5: ['K'], + 8: ['J', 'X'], + 10: ['Q', 'Z'], + }; + const keys = Object.keys(letters); + let totalScore = 0; + if (Scrabble._isValidWord(word)) { + const chars = word.toUpperCase().match(/\S/g); + chars.forEach((element) => { + keys.forEach((num) => { + const numLetters = letters[num]; + if (numLetters.includes(element)) { + totalScore += parseFloat(num); + } + }); + }); + if (word.length === 7) { + totalScore += 50; + } + } + return totalScore; + }, + + highestScoreFrom: function highestScoreFrom(array) { + if ((!Array.isArray(array)) || (array.length === 0)) { + throw new Error('Invalid Array'); + } + const words = array.map(word => new Scrabble.Word(word)); + words.sort(Scrabble._compareWordScores); + return words.slice(-1)[0].word; + }, - // TODO: add the highestScoreFrom method + _compareWordScores: function _compareWordScores(a, b) { + const scoreA = a.score; + const scoreB = b.score; + const lengthA = a.word.length; + const lengthB = b.word.length; -}; + let comparison = 0; + if (scoreA > scoreB) { // greater score wins + comparison = 1; + } else if (scoreA < scoreB) { // lower score loses + comparison = -1; + } else if (lengthA === 7) { // tied score, 7 letter word wins + comparison = 1; + } else if (lengthB === 7) { // tied lose if other word is 7 letters + comparison = -1; + } else if (lengthA < lengthB) { // tied shorter word wins, + comparison = 1; + } else if (lengthA > lengthB) { // tied longer word loses + comparison = -1; + } else if (lengthA === lengthB) { // return first word + comparison = 1; + } + return comparison; + }, +}; // end of class! Scrabble.Player = class { - // TODO: implement the Player class -}; + constructor(name) { + if (Scrabble.Player._isValidName(name)) { + this.name = name; + this.plays = []; + this.words = []; + } + } + + static _isValidName(name) { + if (name.length > 0) { + return true; + } throw new Error('Invalid Name'); + } + + play(word) { + if (!this.hasWon()) { + const playedWord = new Scrabble.Word(word); + this.plays.push(playedWord.word); + this.words.push(playedWord); + this.words.sort(Scrabble._compareWordScores); + this.totalScore(); + return playedWord.word; + } return false; + } + + hasWon() { + const currentScore = this.totalScore(); + if (currentScore >= 100) { + return true; + } return false; + } + + totalScore() { + const score = this.words.reduce((a, b) => a + b.score, 0); + return score; + } + + highestScoringWord() { + return this.words.slice(-1)[0].word; + } + + highestWordScore() { + return this.words.slice(-1)[0].score; + } +}; // end of Player class + +Scrabble.Word = class { + constructor(word) { + this.word = word; + this.score = Scrabble.score(word); + } +}; // end of Word class module.exports = Scrabble; diff --git a/spec/scrabble_spec.js b/spec/scrabble_spec.js index c195a03..2b3f6dd 100644 --- a/spec/scrabble_spec.js +++ b/spec/scrabble_spec.js @@ -1,3 +1,5 @@ + +/* eslint-disable */ const Scrabble = require('../scrabble'); describe('score', function() {