From 96c80955bf4e93f1760c0a305a078dcd41b5aa10 Mon Sep 17 00:00:00 2001 From: JoshiRaez Date: Tue, 27 Apr 2021 05:45:19 +0200 Subject: [PATCH 1/6] Implemented tests and proof dnd-character --- .../dnd-character/.docs/instructions.md | 33 ++++++ .../practice/dnd-character/.eslintignore | 10 ++ exercises/practice/dnd-character/.eslintrc | 92 +++++++++++++++ .../practice/dnd-character/.meta/config.json | 13 ++ .../practice/dnd-character/.meta/proof.ci.ts | 71 +++++++++++ .../practice/dnd-character/babel.config.js | 20 ++++ .../dnd-character/dnd-character.test.ts | 111 ++++++++++++++++++ .../practice/dnd-character/dnd-character.ts | 38 ++++++ .../practice/dnd-character/jest.config.js | 19 +++ exercises/practice/dnd-character/package.json | 33 ++++++ .../practice/dnd-character/tsconfig.json | 67 +++++++++++ 11 files changed, 507 insertions(+) create mode 100644 exercises/practice/dnd-character/.docs/instructions.md create mode 100644 exercises/practice/dnd-character/.eslintignore create mode 100644 exercises/practice/dnd-character/.eslintrc create mode 100644 exercises/practice/dnd-character/.meta/config.json create mode 100644 exercises/practice/dnd-character/.meta/proof.ci.ts create mode 100644 exercises/practice/dnd-character/babel.config.js create mode 100644 exercises/practice/dnd-character/dnd-character.test.ts create mode 100644 exercises/practice/dnd-character/dnd-character.ts create mode 100644 exercises/practice/dnd-character/jest.config.js create mode 100644 exercises/practice/dnd-character/package.json create mode 100644 exercises/practice/dnd-character/tsconfig.json diff --git a/exercises/practice/dnd-character/.docs/instructions.md b/exercises/practice/dnd-character/.docs/instructions.md new file mode 100644 index 000000000..09543b24e --- /dev/null +++ b/exercises/practice/dnd-character/.docs/instructions.md @@ -0,0 +1,33 @@ +# Description + +For a game of [Dungeons & Dragons][DND], each player starts by generating a +character they can play with. This character has, among other things, six +abilities; strength, dexterity, constitution, intelligence, wisdom and +charisma. These six abilities have scores that are determined randomly. You +do this by rolling four 6-sided dice and record the sum of the largest three +dice. You do this six times, once for each ability. + +Your character's initial hitpoints are 10 + your character's constitution +modifier. You find your character's constitution modifier by subtracting 10 +from your character's constitution, divide by 2 and round down. + +Write a random character generator that follows the rules above. + +For example, the six throws of four dice may look like: + +* 5, 3, 1, 6: You discard the 1 and sum 5 + 3 + 6 = 14, which you assign to strength. +* 3, 2, 5, 3: You discard the 2 and sum 3 + 5 + 3 = 11, which you assign to dexterity. +* 1, 1, 1, 1: You discard the 1 and sum 1 + 1 + 1 = 3, which you assign to constitution. +* 2, 1, 6, 6: You discard the 1 and sum 2 + 6 + 6 = 14, which you assign to intelligence. +* 3, 5, 3, 4: You discard the 3 and sum 5 + 3 + 4 = 12, which you assign to wisdom. +* 6, 6, 6, 6: You discard the 6 and sum 6 + 6 + 6 = 18, which you assign to charisma. + +Because constitution is 3, the constitution modifier is -4 and the hitpoints are 6. + +## Notes + +Most programming languages feature (pseudo-)random generators, but few +programming languages are designed to roll dice. One such language is [Troll]. + +[DND]: https://en.wikipedia.org/wiki/Dungeons_%26_Dragons +[Troll]: http://hjemmesider.diku.dk/~torbenm/Troll/ diff --git a/exercises/practice/dnd-character/.eslintignore b/exercises/practice/dnd-character/.eslintignore new file mode 100644 index 000000000..72f260577 --- /dev/null +++ b/exercises/practice/dnd-character/.eslintignore @@ -0,0 +1,10 @@ +bin/* +dist/* +docs/* +node_modules/* +production_node_modules/* +test/fixtures/* +tmp/* + +babel.config.js +jest.config.js diff --git a/exercises/practice/dnd-character/.eslintrc b/exercises/practice/dnd-character/.eslintrc new file mode 100644 index 000000000..53450de8d --- /dev/null +++ b/exercises/practice/dnd-character/.eslintrc @@ -0,0 +1,92 @@ +{ + "root": true, + "parser": "@typescript-eslint/parser", + "parserOptions": { + "project": "./tsconfig.json", + "ecmaFeatures": { + "jsx": true + }, + "ecmaVersion": 2018, + "sourceType": "module" + }, + "env": { + "browser": true, + "es6": true + }, + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended" + ], + "globals": { + "Atomics": "readonly", + "SharedArrayBuffer": "readonly" + }, + "plugins": ["@typescript-eslint"], + "rules": { + // Code style not forced upon the student + "@typescript-eslint/array-type": "off", + + // Prevent bugs + "@typescript-eslint/explicit-function-return-type": [ + "warn", + { + "allowExpressions": false, + "allowTypedFunctionExpressions": true, + "allowHigherOrderFunctions": true + } + ], + + // Code style not forced upon the student + "@typescript-eslint/explicit-member-accessibility": "off", + + // Code style not forced upon the student + "@typescript-eslint/indent": "off", + + "@typescript-eslint/no-inferrable-types": [ + "error", + { + "ignoreParameters": true + } + ], + + // Code style not forced upon the student + "@typescript-eslint/member-delimiter-style": "off", + + // Code style not forced upon the student + "@typescript-eslint/no-non-null-assertion": "off", + + // Only disallow readonly without an access modifier + "@typescript-eslint/no-parameter-properties": [ + "warn", + { + "allows": [ + "private", + "protected", + "public", + "private readonly", + "protected readonly", + "public readonly" + ] + } + ], + + // Covered by the tsc compiler (noUnusedLocals) + "@typescript-eslint/no-unused-vars": "off", + + // Prevent bugs, not styling + "@typescript-eslint/no-use-before-define": [ + "error", + { + "functions": false, + "typedefs": false + } + ], + + // Always disable base-rule + "semi": "off", + + // Code style not forced upon student + "@typescript-eslint/semi": "off" + } +} diff --git a/exercises/practice/dnd-character/.meta/config.json b/exercises/practice/dnd-character/.meta/config.json new file mode 100644 index 000000000..b0f80f9a4 --- /dev/null +++ b/exercises/practice/dnd-character/.meta/config.json @@ -0,0 +1,13 @@ +{ + "blurb": "Randomly generate Dungeons & Dragons characters.", + "authors": ["JoshiRaez"], + "contributors": [], + "files": { + "solution": ["dnd-character.ts"], + "test": ["dnd-character.test.ts"], + "example": [".meta/proof.ci.ts"] + }, + "source": "Simon Shine, Erik Schierboom", + "source_url": "https://github.com/exercism/problem-specifications/issues/616#issuecomment-437358945" + } + \ No newline at end of file diff --git a/exercises/practice/dnd-character/.meta/proof.ci.ts b/exercises/practice/dnd-character/.meta/proof.ci.ts new file mode 100644 index 000000000..ed598f542 --- /dev/null +++ b/exercises/practice/dnd-character/.meta/proof.ci.ts @@ -0,0 +1,71 @@ +export class DnDCharacter { + + private hitpoints: number + + private str: number + private dex: number + private con: number + private int: number + private wis: number + private cha: number + + constructor() { + + this.str = DnDCharacter.generateAbilityScore() + this.dex = DnDCharacter.generateAbilityScore() + this.con = DnDCharacter.generateAbilityScore() + this.int = DnDCharacter.generateAbilityScore() + this.wis = DnDCharacter.generateAbilityScore() + this.cha = DnDCharacter.generateAbilityScore() + + this.hitpoints = 10 + DnDCharacter.getModifierFor(this.getConstitution()) + } + + static generateAbilityScore() : number { + return this.rollDice(4).sort().slice(1,4).reduce((acu, act) => acu + act, 0) + } + + static getModifierFor(abilityValue : number) : number { + return Math.floor((abilityValue - 10) / 2) + } + + getHitpoints() : number { + return this.hitpoints + } + + getStrength() : number { + return this.str + } + + getDexterity() : number { + return this.dex + } + + getConstitution() : number { + return this.con + } + + getIntelligence() : number { + return this.int + } + + getWisdom() : number { + return this.wis + } + + getCharisma() : number { + return this.cha + } + + private static rollDice(quantity: number) : number[] { + + return new Array(quantity) + .fill(0) + .map(() => this.rollDie()) + } + + private static rollDie() { + + return Math.floor(Math.random() * (6)) + 1; + } +} diff --git a/exercises/practice/dnd-character/babel.config.js b/exercises/practice/dnd-character/babel.config.js new file mode 100644 index 000000000..ef0dfebc5 --- /dev/null +++ b/exercises/practice/dnd-character/babel.config.js @@ -0,0 +1,20 @@ +module.exports = { + presets: [ + [ + '@babel/preset-env', + { + targets: { + node: 'current', + }, + useBuiltIns: 'entry', + corejs: 3, + }, + ], + '@babel/preset-typescript', + ], + plugins: [ + '@babel/proposal-class-properties', + '@babel/proposal-object-rest-spread', + '@babel/plugin-syntax-bigint', + ], +} diff --git a/exercises/practice/dnd-character/dnd-character.test.ts b/exercises/practice/dnd-character/dnd-character.test.ts new file mode 100644 index 000000000..de5183570 --- /dev/null +++ b/exercises/practice/dnd-character/dnd-character.test.ts @@ -0,0 +1,111 @@ +import { DnDCharacter } from './dnd-character' + +describe('Ability modifier', () => { + + test('Ability modifier for score 3 is -4', () => { + expect(DnDCharacter.getModifierFor(3)).toEqual(-4) + }) + + test('Ability modifier for score 4 is -3', () => { + expect(DnDCharacter.getModifierFor(4)).toEqual(-3) + }) + + test('Ability modifier for score 5 is -3', () => { + expect(DnDCharacter.getModifierFor(5)).toEqual(-3) + }) + + test('Ability modifier for score 6 is -2', () => { + expect(DnDCharacter.getModifierFor(6)).toEqual(-2) + }) + + test('Ability modifier for score 7 is -2', () => { + expect(DnDCharacter.getModifierFor(7)).toEqual(-2) + }) + + test('Ability modifier for score 8 is -1', () => { + expect(DnDCharacter.getModifierFor(8)).toEqual(-1) + }) + + test('Ability modifier for score 9 is -1', () => { + expect(DnDCharacter.getModifierFor(9)).toEqual(-1) + }) + + test('Ability modifier for score 10 is 0', () => { + expect(DnDCharacter.getModifierFor(10)).toEqual(0) + }) + + test('Ability modifier for score 11 is 0', () => { + expect(DnDCharacter.getModifierFor(11)).toEqual(0) + }) + + test('Ability modifier for score 12 is 1', () => { + expect(DnDCharacter.getModifierFor(12)).toEqual(1) + }) + + test('Ability modifier for score 13 is 1', () => { + expect(DnDCharacter.getModifierFor(13)).toEqual(1) + }) + + test('Ability modifier for score 14 is 2', () => { + expect(DnDCharacter.getModifierFor(14)).toEqual(2) + }) + + test('Ability modifier for score 15 is 2', () => { + expect(DnDCharacter.getModifierFor(15)).toEqual(2) + }) + + test('Ability modifier for score 16 is 3', () => { + expect(DnDCharacter.getModifierFor(16)).toEqual(3) + }) + + test('Ability modifier for score 17 is 3', () => { + expect(DnDCharacter.getModifierFor(17)).toEqual(3) + }) + + test('Ability modifier for score 18 is 4', () => { + expect(DnDCharacter.getModifierFor(18)).toEqual(4) + }) +}) + +describe('Ability generator', () => { + + test('Random ability is within range', () => { + const abilityScore = DnDCharacter.generateAbilityScore() + expect(abilityScore).toBeGreaterThanOrEqual(3) + expect(abilityScore).toBeLessThanOrEqual(18) + }) +}) + +describe('Character creation', () => { + + test('Random character is valid', () => { + const character = new DnDCharacter() + + expect(character.getHitpoints()).toEqual(10 + DnDCharacter.getModifierFor(character.getConstitution())) + + expect(character.getStrength()).toBeGreaterThanOrEqual(3) + expect(character.getStrength()).toBeLessThanOrEqual(18) + + expect(character.getDexterity()).toBeGreaterThanOrEqual(3) + expect(character.getDexterity()).toBeLessThanOrEqual(18) + + expect(character.getConstitution()).toBeGreaterThanOrEqual(3) + expect(character.getConstitution()).toBeLessThanOrEqual(18) + + expect(character.getIntelligence()).toBeGreaterThanOrEqual(3) + expect(character.getIntelligence()).toBeLessThanOrEqual(18) + + expect(character.getWisdom()).toBeGreaterThanOrEqual(3) + expect(character.getWisdom()).toBeLessThanOrEqual(18) + + expect(character.getCharisma()).toBeGreaterThanOrEqual(3) + expect(character.getCharisma()).toBeLessThanOrEqual(18) + }) + + test('Each ability is only calculated once', () => { + const character = new DnDCharacter() + + expect(character.getStrength() == character.getStrength()).toBeTruthy() + }) +}) + diff --git a/exercises/practice/dnd-character/dnd-character.ts b/exercises/practice/dnd-character/dnd-character.ts new file mode 100644 index 000000000..e289cfd2d --- /dev/null +++ b/exercises/practice/dnd-character/dnd-character.ts @@ -0,0 +1,38 @@ +export class DnDCharacter { + + static generateAbilityScore() : number { + throw new Error('Remove this statement and implement this function') + } + + static getModifierFor(abilityValue : number) : number { + throw new Error('Remove this statement and implement this function') + } + + getHitpoints() : number { + throw new Error('Remove this statement and implement this function') + } + + getStrength() : number { + throw new Error('Remove this statement and implement this function') + } + + getDexterity() : number { + throw new Error('Remove this statement and implement this function') + } + + getConstitution() : number { + throw new Error('Remove this statement and implement this function') + } + + getIntelligence() : number { + throw new Error('Remove this statement and implement this function') + } + + getWisdom() : number { + throw new Error('Remove this statement and implement this function') + } + + getCharisma() : number { + throw new Error('Remove this statement and implement this function') + } +} diff --git a/exercises/practice/dnd-character/jest.config.js b/exercises/practice/dnd-character/jest.config.js new file mode 100644 index 000000000..d6b552072 --- /dev/null +++ b/exercises/practice/dnd-character/jest.config.js @@ -0,0 +1,19 @@ +module.exports = { + verbose: true, + projects: [''], + testMatch: [ + '**/__tests__/**/*.[jt]s?(x)', + '**/test/**/*.[jt]s?(x)', + '**/?(*.)+(spec|test).[jt]s?(x)', + ], + testPathIgnorePatterns: [ + '/(?:production_)?node_modules/', + '.d.ts$', + '/test/fixtures', + '/test/helpers', + '__mocks__', + ], + transform: { + '^.+\\.[jt]sx?$': 'babel-jest', + }, +} diff --git a/exercises/practice/dnd-character/package.json b/exercises/practice/dnd-character/package.json new file mode 100644 index 000000000..e2a3c1b81 --- /dev/null +++ b/exercises/practice/dnd-character/package.json @@ -0,0 +1,33 @@ +{ + "name": "@exercism/typescript-dnd-character", + "description": "Exercism practice exercise on dnd-character", + "private": true, + "repository": { + "type": "git", + "url": "https://github.com/exercism/typescript" + }, + "devDependencies": { + "@babel/core": "^7.13.16", + "@babel/plugin-proposal-class-properties": "^7.13.0", + "@babel/plugin-proposal-object-rest-spread": "^7.13.8", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/preset-env": "^7.13.15", + "@babel/preset-typescript": "^7.13.0", + "@types/jest": "^26.0.22", + "@types/node": "^14.14.41", + "@typescript-eslint/eslint-plugin": "^4.21.0", + "@typescript-eslint/parser": "^4.21.0", + "babel-jest": "^26.6.3", + "core-js": "^3.11.0", + "eslint": "^7.25.0", + "eslint-plugin-import": "^2.22.1", + "jest": "^26.6.3", + "typescript": "^4.2.4" + }, + "scripts": { + "test": "yarn lint:types && jest --no-cache", + "lint": "yarn lint:types && yarn lint:ci", + "lint:types": "yarn tsc --noEmit -p .", + "lint:ci": "eslint . --ext .tsx,.ts" + } +} diff --git a/exercises/practice/dnd-character/tsconfig.json b/exercises/practice/dnd-character/tsconfig.json new file mode 100644 index 000000000..bb1a9c2f4 --- /dev/null +++ b/exercises/practice/dnd-character/tsconfig.json @@ -0,0 +1,67 @@ +{ + "compilerOptions": { + /* Basic Options */ + "target": "esnext" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */, + "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, + "lib": [ + "esnext", + "es2016", + "es2017" + ] /* Specify library files to be included in the compilation. */, + // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + // "declaration": true, /* Generates corresponding '.d.ts' file. */ + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + // "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + // "outDir": "./build", /* Redirect output structure to the directory. */ + // "rootDirs": ["./"], /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "removeComments": true, /* Do not emit comments to output. */ + "noEmit": true /* Do not emit outputs. */, + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + "isolatedModules": true /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */, + // "noEmitOnError": true, /* Do not emit outputs when compilation fails. */ + + /* Strict Type-Checking Options */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + "noUnusedParameters": true /* Report errors on unused parameters. */, + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + + /* Module Resolution Options */ + "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": { "~src/*": ["./src/*"] }, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + "allowSyntheticDefaultImports": true /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */, + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + }, + "compileOnSave": true, + "exclude": ["node_modules"] +} From 33dab280f6116d414d454b0ead4d5011169c37c7 Mon Sep 17 00:00:00 2001 From: JoshiRaez Date: Wed, 28 Apr 2021 01:48:45 +0200 Subject: [PATCH 2/6] Implemented exercise dnd character --- .../practice/dnd-character/.meta/proof.ci.ts | 22 +++--- .../practice/dnd-character/.meta/tests.toml | 76 +++++++++++++++++++ .../practice/dnd-character/dnd-character.ts | 18 ++--- 3 files changed, 96 insertions(+), 20 deletions(-) create mode 100644 exercises/practice/dnd-character/.meta/tests.toml diff --git a/exercises/practice/dnd-character/.meta/proof.ci.ts b/exercises/practice/dnd-character/.meta/proof.ci.ts index ed598f542..02f1dd70d 100644 --- a/exercises/practice/dnd-character/.meta/proof.ci.ts +++ b/exercises/practice/dnd-character/.meta/proof.ci.ts @@ -21,39 +21,39 @@ export class DnDCharacter { this.hitpoints = 10 + DnDCharacter.getModifierFor(this.getConstitution()) } - static generateAbilityScore() : number { + public static generateAbilityScore() : number { return this.rollDice(4).sort().slice(1,4).reduce((acu, act) => acu + act, 0) } - static getModifierFor(abilityValue : number) : number { + public static getModifierFor(abilityValue : number) : number { return Math.floor((abilityValue - 10) / 2) } - getHitpoints() : number { + public getHitpoints() : number { return this.hitpoints } - getStrength() : number { + public getStrength() : number { return this.str } - getDexterity() : number { + public getDexterity() : number { return this.dex } - getConstitution() : number { + public getConstitution() : number { return this.con } - getIntelligence() : number { + public getIntelligence() : number { return this.int } - getWisdom() : number { + public getWisdom() : number { return this.wis } - getCharisma() : number { + public getCharisma() : number { return this.cha } @@ -64,8 +64,8 @@ export class DnDCharacter { .map(() => this.rollDie()) } - private static rollDie() { + private static rollDie() : number { - return Math.floor(Math.random() * (6)) + 1; + return Math.floor(Math.random() * (6)) + 1 } } diff --git a/exercises/practice/dnd-character/.meta/tests.toml b/exercises/practice/dnd-character/.meta/tests.toml new file mode 100644 index 000000000..eedfb2c4c --- /dev/null +++ b/exercises/practice/dnd-character/.meta/tests.toml @@ -0,0 +1,76 @@ +[1e9ae1dc-35bd-43ba-aa08-e4b94c20fa37] +description = "Ability modifier for score 3 is -4" +include = true + +[cc9bb24e-56b8-4e9e-989d-a0d1a29ebb9c] +description = "Ability modifier for score 4 is -3" +include = true + +[5b519fcd-6946-41ee-91fe-34b4f9808326] +description = "Ability modifier for score 5 is -3" +include = true + +[dc2913bd-6d7a-402e-b1e2-6d568b1cbe21] +description = "Ability modifier for score 6 is -2" +include = true + +[099440f5-0d66-4b1a-8a10-8f3a03cc499f] +description = "Ability modifier for score 7 is -2" +include = true + +[cfda6e5c-3489-42f0-b22b-4acb47084df0] +description = "Ability modifier for score 8 is -1" +include = true + +[c70f0507-fa7e-4228-8463-858bfbba1754] +description = "Ability modifier for score 9 is -1" +include = true + +[6f4e6c88-1cd9-46a0-92b8-db4a99b372f7] +description = "Ability modifier for score 10 is 0" +include = true + +[e00d9e5c-63c8-413f-879d-cd9be9697097] +description = "Ability modifier for score 11 is 0" +include = true + +[eea06f3c-8de0-45e7-9d9d-b8cab4179715] +description = "Ability modifier for score 12 is 1" +include = true + +[9c51f6be-db72-4af7-92ac-b293a02c0dcd] +description = "Ability modifier for score 13 is 1" +include = true + +[94053a5d-53b6-4efc-b669-a8b5098f7762] +description = "Ability modifier for score 14 is 2" +include = true + +[8c33e7ca-3f9f-4820-8ab3-65f2c9e2f0e2] +description = "Ability modifier for score 15 is 2" +include = true + +[c3ec871e-1791-44d0-b3cc-77e5fb4cd33d] +description = "Ability modifier for score 16 is 3" +include = true + +[3d053cee-2888-4616-b9fd-602a3b1efff4] +description = "Ability modifier for score 17 is 3" +include = true + +[bafd997a-e852-4e56-9f65-14b60261faee] +description = "Ability modifier for score 18 is 4" +include = true + +[4f28f19c-2e47-4453-a46a-c0d365259c14] +description = "Random ability is within range" +include = true + +[385d7e72-864f-4e88-8279-81a7d75b04ad] +description = "Random character is valid" +include = true + +[2ca77b9b-c099-46c3-a02c-0d0f68ffa0fe] +description = "Each ability is only calculated once" +include = true + diff --git a/exercises/practice/dnd-character/dnd-character.ts b/exercises/practice/dnd-character/dnd-character.ts index e289cfd2d..017c6bb7f 100644 --- a/exercises/practice/dnd-character/dnd-character.ts +++ b/exercises/practice/dnd-character/dnd-character.ts @@ -1,38 +1,38 @@ export class DnDCharacter { - static generateAbilityScore() : number { + public static generateAbilityScore() : number { throw new Error('Remove this statement and implement this function') } - static getModifierFor(abilityValue : number) : number { + public static getModifierFor(abilityValue : number) : number { throw new Error('Remove this statement and implement this function') } - getHitpoints() : number { + public getHitpoints() : number { throw new Error('Remove this statement and implement this function') } - getStrength() : number { + public getStrength() : number { throw new Error('Remove this statement and implement this function') } - getDexterity() : number { + public getDexterity() : number { throw new Error('Remove this statement and implement this function') } - getConstitution() : number { + public getConstitution() : number { throw new Error('Remove this statement and implement this function') } - getIntelligence() : number { + public getIntelligence() : number { throw new Error('Remove this statement and implement this function') } - getWisdom() : number { + public getWisdom() : number { throw new Error('Remove this statement and implement this function') } - getCharisma() : number { + public getCharisma() : number { throw new Error('Remove this statement and implement this function') } } From 81553187ff21688fe1b0fc2ae622cca951601198 Mon Sep 17 00:00:00 2001 From: JoshiRaez Date: Wed, 28 Apr 2021 01:55:01 +0200 Subject: [PATCH 3/6] Finished DnD character exercise --- config.json | 9 ++++ .../dnd-character/.docs/instructions.md | 18 ++++---- .../practice/dnd-character/.meta/config.json | 23 +++++------ .../practice/dnd-character/.meta/proof.ci.ts | 41 +++++++++---------- .../dnd-character/dnd-character.test.ts | 12 +++--- .../practice/dnd-character/dnd-character.ts | 23 +++++------ 6 files changed, 64 insertions(+), 62 deletions(-) diff --git a/config.json b/config.json index 838abb99f..2a22a5c1b 100644 --- a/config.json +++ b/config.json @@ -87,6 +87,15 @@ "difficulty": 2, "topics": ["classes", "floating_point_numbers"] }, + { + "slug": "dnd-character", + "name": "DnD Character", + "uuid": "6f34eb4d-4028-4f89-9965-c9a887f416a0", + "practices": [], + "prerequisites": [], + "difficulty": 2, + "topics": ["classes"] + }, { "slug": "pangram", "name": "Pangram", diff --git a/exercises/practice/dnd-character/.docs/instructions.md b/exercises/practice/dnd-character/.docs/instructions.md index 09543b24e..f1ccc3b7b 100644 --- a/exercises/practice/dnd-character/.docs/instructions.md +++ b/exercises/practice/dnd-character/.docs/instructions.md @@ -1,6 +1,6 @@ # Description -For a game of [Dungeons & Dragons][DND], each player starts by generating a +For a game of [Dungeons & Dragons][dnd], each player starts by generating a character they can play with. This character has, among other things, six abilities; strength, dexterity, constitution, intelligence, wisdom and charisma. These six abilities have scores that are determined randomly. You @@ -15,12 +15,12 @@ Write a random character generator that follows the rules above. For example, the six throws of four dice may look like: -* 5, 3, 1, 6: You discard the 1 and sum 5 + 3 + 6 = 14, which you assign to strength. -* 3, 2, 5, 3: You discard the 2 and sum 3 + 5 + 3 = 11, which you assign to dexterity. -* 1, 1, 1, 1: You discard the 1 and sum 1 + 1 + 1 = 3, which you assign to constitution. -* 2, 1, 6, 6: You discard the 1 and sum 2 + 6 + 6 = 14, which you assign to intelligence. -* 3, 5, 3, 4: You discard the 3 and sum 5 + 3 + 4 = 12, which you assign to wisdom. -* 6, 6, 6, 6: You discard the 6 and sum 6 + 6 + 6 = 18, which you assign to charisma. +- 5, 3, 1, 6: You discard the 1 and sum 5 + 3 + 6 = 14, which you assign to strength. +- 3, 2, 5, 3: You discard the 2 and sum 3 + 5 + 3 = 11, which you assign to dexterity. +- 1, 1, 1, 1: You discard the 1 and sum 1 + 1 + 1 = 3, which you assign to constitution. +- 2, 1, 6, 6: You discard the 1 and sum 2 + 6 + 6 = 14, which you assign to intelligence. +- 3, 5, 3, 4: You discard the 3 and sum 5 + 3 + 4 = 12, which you assign to wisdom. +- 6, 6, 6, 6: You discard the 6 and sum 6 + 6 + 6 = 18, which you assign to charisma. Because constitution is 3, the constitution modifier is -4 and the hitpoints are 6. @@ -29,5 +29,5 @@ Because constitution is 3, the constitution modifier is -4 and the hitpoints are Most programming languages feature (pseudo-)random generators, but few programming languages are designed to roll dice. One such language is [Troll]. -[DND]: https://en.wikipedia.org/wiki/Dungeons_%26_Dragons -[Troll]: http://hjemmesider.diku.dk/~torbenm/Troll/ +[dnd]: https://en.wikipedia.org/wiki/Dungeons_%26_Dragons +[troll]: http://hjemmesider.diku.dk/~torbenm/Troll/ diff --git a/exercises/practice/dnd-character/.meta/config.json b/exercises/practice/dnd-character/.meta/config.json index b0f80f9a4..baf248681 100644 --- a/exercises/practice/dnd-character/.meta/config.json +++ b/exercises/practice/dnd-character/.meta/config.json @@ -1,13 +1,12 @@ { - "blurb": "Randomly generate Dungeons & Dragons characters.", - "authors": ["JoshiRaez"], - "contributors": [], - "files": { - "solution": ["dnd-character.ts"], - "test": ["dnd-character.test.ts"], - "example": [".meta/proof.ci.ts"] - }, - "source": "Simon Shine, Erik Schierboom", - "source_url": "https://github.com/exercism/problem-specifications/issues/616#issuecomment-437358945" - } - \ No newline at end of file + "blurb": "Randomly generate Dungeons & Dragons characters.", + "authors": ["JoshiRaez"], + "contributors": [], + "files": { + "solution": ["dnd-character.ts"], + "test": ["dnd-character.test.ts"], + "example": [".meta/proof.ci.ts"] + }, + "source": "Simon Shine, Erik Schierboom", + "source_url": "https://github.com/exercism/problem-specifications/issues/616#issuecomment-437358945" +} diff --git a/exercises/practice/dnd-character/.meta/proof.ci.ts b/exercises/practice/dnd-character/.meta/proof.ci.ts index 02f1dd70d..cc721e2bf 100644 --- a/exercises/practice/dnd-character/.meta/proof.ci.ts +++ b/exercises/practice/dnd-character/.meta/proof.ci.ts @@ -1,7 +1,6 @@ export class DnDCharacter { - private hitpoints: number - + private str: number private dex: number private con: number @@ -10,7 +9,6 @@ export class DnDCharacter { private cha: number constructor() { - this.str = DnDCharacter.generateAbilityScore() this.dex = DnDCharacter.generateAbilityScore() this.con = DnDCharacter.generateAbilityScore() @@ -21,51 +19,50 @@ export class DnDCharacter { this.hitpoints = 10 + DnDCharacter.getModifierFor(this.getConstitution()) } - public static generateAbilityScore() : number { - return this.rollDice(4).sort().slice(1,4).reduce((acu, act) => acu + act, 0) + public static generateAbilityScore(): number { + return this.rollDice(4) + .sort() + .slice(1, 4) + .reduce((acu, act) => acu + act, 0) } - public static getModifierFor(abilityValue : number) : number { + public static getModifierFor(abilityValue: number): number { return Math.floor((abilityValue - 10) / 2) } - public getHitpoints() : number { + public getHitpoints(): number { return this.hitpoints } - public getStrength() : number { + public getStrength(): number { return this.str } - public getDexterity() : number { + public getDexterity(): number { return this.dex } - public getConstitution() : number { + public getConstitution(): number { return this.con } - public getIntelligence() : number { + public getIntelligence(): number { return this.int } - public getWisdom() : number { - return this.wis + public getWisdom(): number { + return this.wis } - public getCharisma() : number { + public getCharisma(): number { return this.cha } - private static rollDice(quantity: number) : number[] { - - return new Array(quantity) - .fill(0) - .map(() => this.rollDie()) + private static rollDice(quantity: number): number[] { + return new Array(quantity).fill(0).map(() => this.rollDie()) } - private static rollDie() : number { - - return Math.floor(Math.random() * (6)) + 1 + private static rollDie(): number { + return Math.floor(Math.random() * 6) + 1 } } diff --git a/exercises/practice/dnd-character/dnd-character.test.ts b/exercises/practice/dnd-character/dnd-character.test.ts index de5183570..de10be468 100644 --- a/exercises/practice/dnd-character/dnd-character.test.ts +++ b/exercises/practice/dnd-character/dnd-character.test.ts @@ -1,7 +1,6 @@ import { DnDCharacter } from './dnd-character' describe('Ability modifier', () => { - test('Ability modifier for score 3 is -4', () => { expect(DnDCharacter.getModifierFor(3)).toEqual(-4) }) @@ -68,7 +67,6 @@ describe('Ability modifier', () => { }) describe('Ability generator', () => { - test('Random ability is within range', () => { const abilityScore = DnDCharacter.generateAbilityScore() expect(abilityScore).toBeGreaterThanOrEqual(3) @@ -77,15 +75,16 @@ describe('Ability generator', () => { }) describe('Character creation', () => { - test('Random character is valid', () => { const character = new DnDCharacter() - expect(character.getHitpoints()).toEqual(10 + DnDCharacter.getModifierFor(character.getConstitution())) - + expect(character.getHitpoints()).toEqual( + 10 + DnDCharacter.getModifierFor(character.getConstitution()) + ) + expect(character.getStrength()).toBeGreaterThanOrEqual(3) expect(character.getStrength()).toBeLessThanOrEqual(18) - + expect(character.getDexterity()).toBeGreaterThanOrEqual(3) expect(character.getDexterity()).toBeLessThanOrEqual(18) @@ -108,4 +107,3 @@ describe('Character creation', () => { expect(character.getStrength() == character.getStrength()).toBeTruthy() }) }) - diff --git a/exercises/practice/dnd-character/dnd-character.ts b/exercises/practice/dnd-character/dnd-character.ts index 017c6bb7f..831c08563 100644 --- a/exercises/practice/dnd-character/dnd-character.ts +++ b/exercises/practice/dnd-character/dnd-character.ts @@ -1,38 +1,37 @@ export class DnDCharacter { - - public static generateAbilityScore() : number { + public static generateAbilityScore(): number { throw new Error('Remove this statement and implement this function') } - public static getModifierFor(abilityValue : number) : number { - throw new Error('Remove this statement and implement this function') + public static getModifierFor(abilityValue: number): number { + throw new Error('Remove this statement and implement this function') } - public getHitpoints() : number { + public getHitpoints(): number { throw new Error('Remove this statement and implement this function') } - public getStrength() : number { + public getStrength(): number { throw new Error('Remove this statement and implement this function') } - public getDexterity() : number { + public getDexterity(): number { throw new Error('Remove this statement and implement this function') } - public getConstitution() : number { + public getConstitution(): number { throw new Error('Remove this statement and implement this function') } - public getIntelligence() : number { + public getIntelligence(): number { throw new Error('Remove this statement and implement this function') } - public getWisdom() : number { - throw new Error('Remove this statement and implement this function') + public getWisdom(): number { + throw new Error('Remove this statement and implement this function') } - public getCharisma() : number { + public getCharisma(): number { throw new Error('Remove this statement and implement this function') } } From 433949ab31f148a2ffcff4c6932c7d0b88351956 Mon Sep 17 00:00:00 2001 From: Derk-Jan Karrenbeld Date: Tue, 7 Sep 2021 00:39:14 +0200 Subject: [PATCH 4/6] Sync exercise --- .../practice/dnd-character/.eslintignore | 16 ++-- exercises/practice/dnd-character/.eslintrc | 89 +++---------------- .../practice/dnd-character/babel.config.js | 2 +- exercises/practice/dnd-character/package.json | 26 +++--- .../practice/dnd-character/tsconfig.json | 72 +++------------ 5 files changed, 45 insertions(+), 160 deletions(-) diff --git a/exercises/practice/dnd-character/.eslintignore b/exercises/practice/dnd-character/.eslintignore index 72f260577..e3e45c396 100644 --- a/exercises/practice/dnd-character/.eslintignore +++ b/exercises/practice/dnd-character/.eslintignore @@ -1,10 +1,12 @@ -bin/* -dist/* -docs/* +!.meta + +# Protected or generated +.git +.vscode + +# When using npm node_modules/* -production_node_modules/* -test/fixtures/* -tmp/* +# Configuration files babel.config.js -jest.config.js +jest.config.js \ No newline at end of file diff --git a/exercises/practice/dnd-character/.eslintrc b/exercises/practice/dnd-character/.eslintrc index 53450de8d..3fbb9032c 100644 --- a/exercises/practice/dnd-character/.eslintrc +++ b/exercises/practice/dnd-character/.eslintrc @@ -6,87 +6,18 @@ "ecmaFeatures": { "jsx": true }, - "ecmaVersion": 2018, + "ecmaVersion": 2020, "sourceType": "module" }, + "extends": "@exercism/eslint-config-typescript", "env": { - "browser": true, - "es6": true + "jest": true }, - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/eslint-recommended", - "plugin:@typescript-eslint/recommended" - ], - "globals": { - "Atomics": "readonly", - "SharedArrayBuffer": "readonly" - }, - "plugins": ["@typescript-eslint"], - "rules": { - // Code style not forced upon the student - "@typescript-eslint/array-type": "off", - - // Prevent bugs - "@typescript-eslint/explicit-function-return-type": [ - "warn", - { - "allowExpressions": false, - "allowTypedFunctionExpressions": true, - "allowHigherOrderFunctions": true - } - ], - - // Code style not forced upon the student - "@typescript-eslint/explicit-member-accessibility": "off", - - // Code style not forced upon the student - "@typescript-eslint/indent": "off", - - "@typescript-eslint/no-inferrable-types": [ - "error", - { - "ignoreParameters": true - } - ], - - // Code style not forced upon the student - "@typescript-eslint/member-delimiter-style": "off", - - // Code style not forced upon the student - "@typescript-eslint/no-non-null-assertion": "off", - - // Only disallow readonly without an access modifier - "@typescript-eslint/no-parameter-properties": [ - "warn", - { - "allows": [ - "private", - "protected", - "public", - "private readonly", - "protected readonly", - "public readonly" - ] - } - ], - - // Covered by the tsc compiler (noUnusedLocals) - "@typescript-eslint/no-unused-vars": "off", - - // Prevent bugs, not styling - "@typescript-eslint/no-use-before-define": [ - "error", - { - "functions": false, - "typedefs": false - } - ], - - // Always disable base-rule - "semi": "off", - - // Code style not forced upon student - "@typescript-eslint/semi": "off" - } + "overrides": [ + { + "files": [".meta/proof.ci.ts", ".meta/exemplar.ts", "*.test.ts"], + "excludedFiles": ["custom.test.ts"], + "extends": "@exercism/eslint-config-typescript/maintainers" + } + ] } diff --git a/exercises/practice/dnd-character/babel.config.js b/exercises/practice/dnd-character/babel.config.js index ef0dfebc5..eca257951 100644 --- a/exercises/practice/dnd-character/babel.config.js +++ b/exercises/practice/dnd-character/babel.config.js @@ -7,7 +7,7 @@ module.exports = { node: 'current', }, useBuiltIns: 'entry', - corejs: 3, + corejs: '3.17', }, ], '@babel/preset-typescript', diff --git a/exercises/practice/dnd-character/package.json b/exercises/practice/dnd-character/package.json index e2a3c1b81..10679111f 100644 --- a/exercises/practice/dnd-character/package.json +++ b/exercises/practice/dnd-character/package.json @@ -1,5 +1,6 @@ { "name": "@exercism/typescript-dnd-character", + "version": "1.0.0", "description": "Exercism practice exercise on dnd-character", "private": true, "repository": { @@ -7,22 +8,21 @@ "url": "https://github.com/exercism/typescript" }, "devDependencies": { - "@babel/core": "^7.13.16", - "@babel/plugin-proposal-class-properties": "^7.13.0", - "@babel/plugin-proposal-object-rest-spread": "^7.13.8", + "@babel/core": "^7.15.5", + "@babel/plugin-proposal-class-properties": "^7.14.5", + "@babel/plugin-proposal-object-rest-spread": "^7.14.7", "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/preset-env": "^7.13.15", - "@babel/preset-typescript": "^7.13.0", - "@types/jest": "^26.0.22", - "@types/node": "^14.14.41", - "@typescript-eslint/eslint-plugin": "^4.21.0", - "@typescript-eslint/parser": "^4.21.0", + "@babel/preset-env": "^7.15.4", + "@babel/preset-typescript": "^7.15.0", + "@types/jest": "^26.0.24", + "@types/node": "^14.17.14", + "@exercism/eslint-config-typescript": "^0.3.0", "babel-jest": "^26.6.3", - "core-js": "^3.11.0", - "eslint": "^7.25.0", - "eslint-plugin-import": "^2.22.1", + "core-js": "^3.17.2", + "eslint": "^7.32.0", + "eslint-plugin-import": "^2.24.2", "jest": "^26.6.3", - "typescript": "^4.2.4" + "typescript": "^4.4.2" }, "scripts": { "test": "yarn lint:types && jest --no-cache", diff --git a/exercises/practice/dnd-character/tsconfig.json b/exercises/practice/dnd-character/tsconfig.json index bb1a9c2f4..7314e3544 100644 --- a/exercises/practice/dnd-character/tsconfig.json +++ b/exercises/practice/dnd-character/tsconfig.json @@ -1,67 +1,19 @@ { + "display": "Configuration for Node LTS", "compilerOptions": { - /* Basic Options */ - "target": "esnext" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */, - "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, - "lib": [ - "esnext", - "es2016", - "es2017" - ] /* Specify library files to be included in the compilation. */, - // "allowJs": true, /* Allow javascript files to be compiled. */ - // "checkJs": true, /* Report errors in .js files. */ - // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ - // "declaration": true, /* Generates corresponding '.d.ts' file. */ - // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ - // "sourceMap": true, /* Generates corresponding '.map' file. */ - // "outFile": "./", /* Concatenate and emit output to single file. */ - // "outDir": "./build", /* Redirect output structure to the directory. */ - // "rootDirs": ["./"], /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ - // "composite": true, /* Enable project compilation */ - // "removeComments": true, /* Do not emit comments to output. */ - "noEmit": true /* Do not emit outputs. */, - // "importHelpers": true, /* Import emit helpers from 'tslib'. */ - // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ - "isolatedModules": true /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */, - // "noEmitOnError": true, /* Do not emit outputs when compilation fails. */ + "lib": ["es2020"], + "module": "commonjs", + "target": "es2020", - /* Strict Type-Checking Options */ - "strict": true /* Enable all strict type-checking options. */, - // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* Enable strict null checks. */ - // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ - // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ - // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ - // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, - /* Additional Checks */ - // "noUnusedLocals": true, /* Report errors on unused locals. */ - "noUnusedParameters": true /* Report errors on unused parameters. */, - // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - - /* Module Resolution Options */ - "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, - // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ - // "paths": { "~src/*": ["./src/*"] }, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ - // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ - // "typeRoots": [], /* List of folders to include type definitions from. */ - // "types": [], /* Type declaration files to be included in compilation. */ - "allowSyntheticDefaultImports": true /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */, - "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ - // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ - - /* Source Map Options */ - // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ - // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ - - /* Experimental Options */ - // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ - // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + // Because we'll be using babel + // Ensure that Babel can safely transpile files in the TypeScript project + "isolatedModules": true }, - "compileOnSave": true, + "include": ["*", ".meta/*"], "exclude": ["node_modules"] } From 642adac4358c21983f1dcbfdd9bddbd816794848 Mon Sep 17 00:00:00 2001 From: Derk-Jan Karrenbeld Date: Tue, 7 Sep 2021 00:43:18 +0200 Subject: [PATCH 5/6] Make idiomatic for TypeScript --- .../practice/dnd-character/.meta/config.json | 2 +- .../practice/dnd-character/.meta/proof.ci.ts | 56 +++++-------------- .../dnd-character/dnd-character.test.ts | 30 +++++----- .../practice/dnd-character/dnd-character.ts | 28 ---------- 4 files changed, 30 insertions(+), 86 deletions(-) diff --git a/exercises/practice/dnd-character/.meta/config.json b/exercises/practice/dnd-character/.meta/config.json index baf248681..4df44f7e9 100644 --- a/exercises/practice/dnd-character/.meta/config.json +++ b/exercises/practice/dnd-character/.meta/config.json @@ -1,6 +1,6 @@ { "blurb": "Randomly generate Dungeons & Dragons characters.", - "authors": ["JoshiRaez"], + "authors": ["JoshiRaez", "SleeplessByte"], "contributors": [], "files": { "solution": ["dnd-character.ts"], diff --git a/exercises/practice/dnd-character/.meta/proof.ci.ts b/exercises/practice/dnd-character/.meta/proof.ci.ts index cc721e2bf..9a1b05d92 100644 --- a/exercises/practice/dnd-character/.meta/proof.ci.ts +++ b/exercises/practice/dnd-character/.meta/proof.ci.ts @@ -1,22 +1,22 @@ export class DnDCharacter { - private hitpoints: number + public readonly hitpoints: number - private str: number - private dex: number - private con: number - private int: number - private wis: number - private cha: number + public readonly strength: number + public readonly dexterity: number + public readonly constitution: number + public readonly intelligence: number + public readonly wisdom: number + public readonly charisma: number constructor() { - this.str = DnDCharacter.generateAbilityScore() - this.dex = DnDCharacter.generateAbilityScore() - this.con = DnDCharacter.generateAbilityScore() - this.int = DnDCharacter.generateAbilityScore() - this.wis = DnDCharacter.generateAbilityScore() - this.cha = DnDCharacter.generateAbilityScore() + this.strength = DnDCharacter.generateAbilityScore() + this.dexterity = DnDCharacter.generateAbilityScore() + this.constitution = DnDCharacter.generateAbilityScore() + this.intelligence = DnDCharacter.generateAbilityScore() + this.wisdom = DnDCharacter.generateAbilityScore() + this.charisma = DnDCharacter.generateAbilityScore() - this.hitpoints = 10 + DnDCharacter.getModifierFor(this.getConstitution()) + this.hitpoints = 10 + DnDCharacter.getModifierFor(this.constitution) } public static generateAbilityScore(): number { @@ -30,34 +30,6 @@ export class DnDCharacter { return Math.floor((abilityValue - 10) / 2) } - public getHitpoints(): number { - return this.hitpoints - } - - public getStrength(): number { - return this.str - } - - public getDexterity(): number { - return this.dex - } - - public getConstitution(): number { - return this.con - } - - public getIntelligence(): number { - return this.int - } - - public getWisdom(): number { - return this.wis - } - - public getCharisma(): number { - return this.cha - } - private static rollDice(quantity: number): number[] { return new Array(quantity).fill(0).map(() => this.rollDie()) } diff --git a/exercises/practice/dnd-character/dnd-character.test.ts b/exercises/practice/dnd-character/dnd-character.test.ts index de10be468..e3547fc56 100644 --- a/exercises/practice/dnd-character/dnd-character.test.ts +++ b/exercises/practice/dnd-character/dnd-character.test.ts @@ -78,32 +78,32 @@ describe('Character creation', () => { test('Random character is valid', () => { const character = new DnDCharacter() - expect(character.getHitpoints()).toEqual( - 10 + DnDCharacter.getModifierFor(character.getConstitution()) + expect(character.hitpoints).toEqual( + 10 + DnDCharacter.getModifierFor(character.constitution) ) - expect(character.getStrength()).toBeGreaterThanOrEqual(3) - expect(character.getStrength()).toBeLessThanOrEqual(18) + expect(character.strength).toBeGreaterThanOrEqual(3) + expect(character.strength).toBeLessThanOrEqual(18) - expect(character.getDexterity()).toBeGreaterThanOrEqual(3) - expect(character.getDexterity()).toBeLessThanOrEqual(18) + expect(character.dexterity).toBeGreaterThanOrEqual(3) + expect(character.dexterity).toBeLessThanOrEqual(18) - expect(character.getConstitution()).toBeGreaterThanOrEqual(3) - expect(character.getConstitution()).toBeLessThanOrEqual(18) + expect(character.constitution).toBeGreaterThanOrEqual(3) + expect(character.constitution).toBeLessThanOrEqual(18) - expect(character.getIntelligence()).toBeGreaterThanOrEqual(3) - expect(character.getIntelligence()).toBeLessThanOrEqual(18) + expect(character.intelligence).toBeGreaterThanOrEqual(3) + expect(character.intelligence).toBeLessThanOrEqual(18) - expect(character.getWisdom()).toBeGreaterThanOrEqual(3) - expect(character.getWisdom()).toBeLessThanOrEqual(18) + expect(character.wisdom).toBeGreaterThanOrEqual(3) + expect(character.wisdom).toBeLessThanOrEqual(18) - expect(character.getCharisma()).toBeGreaterThanOrEqual(3) - expect(character.getCharisma()).toBeLessThanOrEqual(18) + expect(character.charisma).toBeGreaterThanOrEqual(3) + expect(character.charisma).toBeLessThanOrEqual(18) }) test('Each ability is only calculated once', () => { const character = new DnDCharacter() - expect(character.getStrength() == character.getStrength()).toBeTruthy() + expect(character.strength == character.strength).toBeTruthy() }) }) diff --git a/exercises/practice/dnd-character/dnd-character.ts b/exercises/practice/dnd-character/dnd-character.ts index 831c08563..c3391a155 100644 --- a/exercises/practice/dnd-character/dnd-character.ts +++ b/exercises/practice/dnd-character/dnd-character.ts @@ -6,32 +6,4 @@ export class DnDCharacter { public static getModifierFor(abilityValue: number): number { throw new Error('Remove this statement and implement this function') } - - public getHitpoints(): number { - throw new Error('Remove this statement and implement this function') - } - - public getStrength(): number { - throw new Error('Remove this statement and implement this function') - } - - public getDexterity(): number { - throw new Error('Remove this statement and implement this function') - } - - public getConstitution(): number { - throw new Error('Remove this statement and implement this function') - } - - public getIntelligence(): number { - throw new Error('Remove this statement and implement this function') - } - - public getWisdom(): number { - throw new Error('Remove this statement and implement this function') - } - - public getCharisma(): number { - throw new Error('Remove this statement and implement this function') - } } From 82678cf491d35e5fe7d0acd215e5dfa23c8acd15 Mon Sep 17 00:00:00 2001 From: Derk-Jan Karrenbeld Date: Tue, 7 Sep 2021 00:45:20 +0200 Subject: [PATCH 6/6] Fix linter --- exercises/practice/dnd-character/dnd-character.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/practice/dnd-character/dnd-character.test.ts b/exercises/practice/dnd-character/dnd-character.test.ts index e3547fc56..fbb1eab11 100644 --- a/exercises/practice/dnd-character/dnd-character.test.ts +++ b/exercises/practice/dnd-character/dnd-character.test.ts @@ -104,6 +104,6 @@ describe('Character creation', () => { test('Each ability is only calculated once', () => { const character = new DnDCharacter() - expect(character.strength == character.strength).toBeTruthy() + expect(character.strength === character.strength).toBeTruthy() }) })