Skip to content

Commit

Permalink
Type fixes (#43)
Browse files Browse the repository at this point in the history
## Description

<!-- Describe your changes in detail -->
<!-- Does this fix a bug, implement a new feature, etc? -->

### Related Issue(s)
- Removes .d.ts file in favor of defining types alongside their main
usage
- refactors code due to typescript warnings / errors

<!-- Reference the issue this PR relates to -->
<!-- Use keywords if possible (ex. Closes #10 ) -->
<!--
https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/using-keywords-in-issues-and-pull-requests
-->

## Screenshots

<!-- (if applicable) -->
  • Loading branch information
riccjohn authored Jun 11, 2024
2 parents ba81e3d + 6f9072a commit 51b616f
Show file tree
Hide file tree
Showing 10 changed files with 212 additions and 215 deletions.
6 changes: 6 additions & 0 deletions src/dice/Randomization.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,11 @@ describe('Randomization', () => {

expect(uniqueItems.length).toBeGreaterThan(1)
})

test('given an empty array, throws error', () => {
expect(() => Randomization.getRandomItem([])).toThrow(
new Error('Cannot get a random item from an empty array'),
)
})
})
})
8 changes: 5 additions & 3 deletions src/dice/Randomization.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
class Randomization {
public static getRandomItem = <T>(list: T[]): T => {
const length = list.length
const randomIndex = Math.floor(Math.random() * length)
return list[randomIndex]
if (list.length === 0) {
throw new Error('Cannot get a random item from an empty array')
}
const randomIndex = Math.floor(Math.random() * list.length)
return list[randomIndex]!
}
}

Expand Down
6 changes: 5 additions & 1 deletion src/dice/__mocks__/Randomization.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
class Randomization {
public static getRandomItem = <T>(list: T[]): T => {
return list[0]
if (list.length === 0) {
throw new Error('Cannot get a random item from an empty array')
} else {
return list[0]!
}
}
}

Expand Down
118 changes: 33 additions & 85 deletions src/knave/Character.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { vi } from 'vitest'
import KnaveCharacter from './Character'

vi.mock('../dice/Dice')
Expand All @@ -7,101 +8,42 @@ vi.mock('../dice/Randomization')

describe('KnaveCharacter', () => {
describe('generate()', () => {
let generatedCharacter: KnaveCharacter

beforeEach(() => {
generatedCharacter = new KnaveCharacter()
})

test('generates a level 1 character by default', () => {
const generatedCharacter = new KnaveCharacter()
expect(generatedCharacter.level).toBe(1)
})

describe('abilities', () => {
describe('charisma', () => {
test('generates a random charisma', () => {
expect(generatedCharacter.charisma.bonus).toBeLessThanOrEqual(6)
expect(generatedCharacter.charisma.bonus).toBeGreaterThanOrEqual(1)
})

test('has a charisma defense that is 10 higher than the bonus', () => {
expect(generatedCharacter.charisma.defense).toEqual(
generatedCharacter.charisma.bonus + 10,
)
})
})

describe('constitution', () => {
test('generates a random constitution', () => {
expect(generatedCharacter.constitution.bonus).toBeLessThanOrEqual(6)
expect(generatedCharacter.constitution.bonus).toBeGreaterThanOrEqual(
1,
)
})

test('has a constitution defense that is 10 higher than the bonus', () => {
expect(generatedCharacter.constitution.defense).toEqual(
generatedCharacter.constitution.bonus + 10,
)
})
})

describe('dexterity', () => {
test('generates a random dexterity', () => {
expect(generatedCharacter.dexterity.bonus).toBeLessThanOrEqual(6)
expect(generatedCharacter.dexterity.bonus).toBeGreaterThanOrEqual(1)
})

test('has a dexterity defense that is 10 higher than the bonus', () => {
expect(generatedCharacter.dexterity.defense).toEqual(
generatedCharacter.dexterity.bonus + 10,
)
})
})

describe('intelligence', () => {
test('generates a random intelligence', () => {
expect(generatedCharacter.intelligence.bonus).toBeLessThanOrEqual(6)
expect(generatedCharacter.intelligence.bonus).toBeGreaterThanOrEqual(
1,
)
})

test('has a intelligence defense that is 10 higher than the bonus', () => {
expect(generatedCharacter.intelligence.defense).toEqual(
generatedCharacter.intelligence.bonus + 10,
)
})
})

describe('strength', () => {
test('generates a random strength', () => {
expect(generatedCharacter.strength.bonus).toBeLessThanOrEqual(6)
expect(generatedCharacter.strength.bonus).toBeGreaterThanOrEqual(1)
})

test('has a strength defense that is 10 higher than the bonus', () => {
expect(generatedCharacter.strength.defense).toEqual(
generatedCharacter.strength.bonus + 10,
)
})
})

describe('wisdom', () => {
test('generates a random wisdom', () => {
expect(generatedCharacter.wisdom.bonus).toBeLessThanOrEqual(6)
expect(generatedCharacter.wisdom.bonus).toBeGreaterThanOrEqual(1)
})
const abilityNames = [
'charisma',
'constitution',
'dexterity',
'intelligence',
'strength',
'wisdom',
]
test.each(abilityNames)(
'generates a random %s bonus between 1-6 (inclusive)',
ability => {
const generatedCharacter = new KnaveCharacter()
expect(generatedCharacter[ability].bonus).toBeLessThanOrEqual(6)
expect(generatedCharacter[ability].bonus).toBeGreaterThanOrEqual(1)
},
)

test('has a wisdom defense that is 10 higher than the bonus', () => {
expect(generatedCharacter.wisdom.defense).toEqual(
generatedCharacter.wisdom.bonus + 10,
test.each(abilityNames)(
'generates a %s defense that is 10 higher than the bonus',
ability => {
const generatedCharacter = new KnaveCharacter()
expect(generatedCharacter[ability].defense).toEqual(
generatedCharacter[ability].bonus + 10,
)
})
})
},
)

describe('abilityScores', () => {
test('has a getter method to get all ability scores', () => {
const generatedCharacter = new KnaveCharacter()
const abilities = generatedCharacter.abilityScores
const abilityNames = Object.keys(abilities)
expect(abilityNames.sort()).toEqual([
Expand All @@ -117,30 +59,36 @@ describe('KnaveCharacter', () => {
})

test('has a number of item slots equal to the constitution defense', () => {
const generatedCharacter = new KnaveCharacter()
expect(generatedCharacter.itemSlots).toBe(
generatedCharacter.constitution.defense,
)
})

test('has a randomly generated starting copper pieces', () => {
const generatedCharacter = new KnaveCharacter()
expect(generatedCharacter.copperPieces).toBeGreaterThanOrEqual(23)
expect(generatedCharacter.copperPieces).toBeLessThanOrEqual(38)
})

test('has a maxHP stat between 1 and 8', () => {
const generatedCharacter = new KnaveCharacter()
expect(generatedCharacter.maxHp).toBeGreaterThanOrEqual(1)
expect(generatedCharacter.maxHp).toBeLessThanOrEqual(8)
})

test('generates a list of items', () => {
const generatedCharacter = new KnaveCharacter()
expect(generatedCharacter.items.length).toBeGreaterThan(1)
})

test('randomly generates armor', () => {
const generatedCharacter = new KnaveCharacter()
expect(generatedCharacter.armor).toBeTruthy()
})

test('randomly generates a weapon', () => {
const generatedCharacter = new KnaveCharacter()
expect(generatedCharacter.weapon).toBeTruthy()
})
})
Expand Down
54 changes: 42 additions & 12 deletions src/knave/Character.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,25 @@
import { KnaveDescription, KnaveGear } from './'
import { Dice } from '../dice'
import type { Traits } from './Description'
import type { ArmorItem, GearItem, WeaponItem } from './Gear'

type Abilities = Record<AbilityName, Ability>

type AbilityName =
| 'charisma'
| 'constitution'
| 'dexterity'
| 'intelligence'
| 'strength'
| 'wisdom'

type Ability = {
bonus: number
defense: number
}

class Character {
public armor: IArmor = {
public armor: ArmorItem = {
count: 0,
defense: 0,
name: '',
Expand All @@ -11,11 +28,11 @@ class Character {
type: 'armor',
}
public copperPieces: number = 0
public items: IGear[] = [{ name: '', count: 0, type: 'food', slots: 0 }]
public items: GearItem[] = [{ name: '', count: 0, type: 'food', slots: 0 }]
public itemSlots: number = 13
public level: number = 1
public maxHp: number = 4
public traits: ITraits = {
public traits: Traits = {
physique: '',
face: '',
skin: '',
Expand All @@ -27,17 +44,17 @@ class Character {
background: '',
misfortune: '',
}
public weapon: IWeapon = {
count: 1,
damage: 'd6',
hand: 1,
public weapon: WeaponItem = {
count: 0,
damage: '',
hand: 0,
name: '',
quality: 0,
slots: 1,
type: 'weapon',
}

private abilities: IAbilities = {
private abilities: Abilities = {
charisma: { bonus: 3, defense: 13 },
constitution: { bonus: 3, defense: 13 },
dexterity: { bonus: 3, defense: 13 },
Expand Down Expand Up @@ -103,9 +120,22 @@ class Character {
return Dice.roll(8)
}

private generateAbilities = (): IAbilities => {
const [charisma, constitution, dexterity, intelligence, strength, wisdom] =
Array(6).fill(undefined).map(this.rollAbilityScore)
private generateAbilities = (): Abilities => {
const {
charisma,
constitution,
dexterity,
intelligence,
strength,
wisdom,
} = {
charisma: this.rollAbilityScore(),
constitution: this.rollAbilityScore(),
dexterity: this.rollAbilityScore(),
intelligence: this.rollAbilityScore(),
strength: this.rollAbilityScore(),
wisdom: this.rollAbilityScore(),
}

const abilities = {
charisma: { bonus: charisma, defense: charisma + 10 },
Expand All @@ -124,7 +154,7 @@ class Character {
return Math.min(...rolls)
}

private generateTraits = (): ITraits => {
private generateTraits = (): Traits => {
return new KnaveDescription().traits
}
}
Expand Down
7 changes: 4 additions & 3 deletions src/knave/Description.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { vi } from 'vitest'
import Description from './Description'
import traitsData from './data/traits.json'

Expand All @@ -8,12 +9,12 @@ describe('Description', () => {
const nouns = Object.keys(traitsData)

const description = new Description()
const traits: ITraits = description.traits
const traits = description.traits

nouns.forEach(noun => {
test(`generates a ${noun} trait`, () => {
const possibleTraits = traitsData[noun as INoun]
expect(possibleTraits.includes(traits[noun as INoun])).toBeTruthy()
const possibleTraits = traitsData[noun]
expect(possibleTraits.includes(traits[noun])).toBeTruthy()
})
})
})
Expand Down
54 changes: 44 additions & 10 deletions src/knave/Description.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,60 @@
import traitsData from './data/traits.json'
import { Randomization } from '../dice'

export type Noun =
| 'physique'
| 'face'
| 'skin'
| 'hair'
| 'clothing'
| 'virtue'
| 'vice'
| 'speech'
| 'background'
| 'misfortune'

export type Traits = Record<Noun, string>

class Description {
public traits
public traits: Traits

constructor() {
this.traits = this.generateRandomTraits()
}

private generateRandomTraits() {
const nouns: string[] = Object.keys(traitsData)
private generateRandomTraits = () => {
const defaultTraits: Traits = {
physique: '',
face: '',
skin: '',
hair: '',
clothing: '',
virtue: '',
vice: '',
speech: '',
background: '',
misfortune: '',
}

const parsedTraitData = this.getTraitData()

const randomTraits: Record<INoun, string> = nouns.reduce(
(acc: Record<string, string>, curr: string) => {
acc[curr] = Randomization.getRandomItem(traitsData[curr as INoun])
return acc
},
{},
)
const nouns = Object.keys(parsedTraitData)

const randomTraits = nouns.reduce((acc, curr) => {
const currentTrait = curr as Noun
const randomTraitValue = Randomization.getRandomItem(
parsedTraitData[currentTrait],
)
acc[currentTrait] = randomTraitValue
return acc
}, defaultTraits)

return randomTraits
}

private getTraitData = () => {
return traitsData satisfies Record<Noun, string[]>
}
}

export default Description
Loading

0 comments on commit 51b616f

Please sign in to comment.