Skip to content

Commit

Permalink
finish up a first working version
Browse files Browse the repository at this point in the history
  • Loading branch information
jesse-kroon committed Jan 29, 2024
1 parent dadead9 commit 3f9d225
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 25 deletions.
61 changes: 60 additions & 1 deletion exercises/practice/dnd-character/.meta/example.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,62 @@
package dndcharacter

// TODO: make an actual example that passes the test
import (
"math"
"math/rand"
"slices"
)

type CharacterSheet struct {
Strength int
Dexterity int
Constitution int
Intelligence int
Wisdom int
Charisma int
Hitpoints int
}

// Modifier should calculate the correct modifier for a given score
func Modifier(score int) int {
return int(math.Floor(float64(score-10) / 2.0))
}

// Ability should generate the score for a random ability
func Ability() int {
var scores []int

for i := 0; i < 4; i++ {
roll := RollDice()
scores = append(scores, roll)
}

return CalculateAbilityScore(scores)
}

// Character should return a CharacterSheet with valid ability scores
func Character() CharacterSheet {
return CharacterSheet{
Strength: Ability(),
Dexterity: Ability(),
Constitution: Ability(),
Intelligence: Ability(),
Wisdom: Ability(),
Charisma: Ability(),
Hitpoints: 10 + Modifier(Ability()),
}
}

// CalculateAbilityScore expects an array of 4 dice scores and returns the sum of the 3 highest numbers
func CalculateAbilityScore(scores []int) int {
var sum int

for _, score := range scores {
sum += score
}

return sum - slices.Min(scores)
}

func RollDice() int {
return rand.Intn(6) + 1
}
38 changes: 16 additions & 22 deletions exercises/practice/dnd-character/dnd_character.go
Original file line number Diff line number Diff line change
@@ -1,37 +1,31 @@
// TODO:
// include a comment in each function briefly explaining what the function should do. This is a bit of quality of life for
// students, to help them know which part of the instructions that function should implement.

// One thing that slightly annoys me in this exercise is that the instructions mention that to get the value for an ability,
// you should roll 4 dice, discard the worst result and sum the 3 best dice rolls. But with the functions we have currently
// (which are the ones most tracks have), that logic is never enforced or tested anywhere. I think it would make sense to
// make students write a function (which would be included in the skeleton given to them) that should take an array of 4
// elements, or receive 4 arguments, and return the sum of the 3 biggest ones.
// We could then also write manual tests for this function.

package dndcharacter

type CharacterSheet struct {
Strength string
Dexterity string
Constitution string
Intelligence string
Wisdom string
Charisma string
Hitpoints string
Strength int
Dexterity int
Constitution int
Intelligence int
Wisdom int
Charisma int
Hitpoints int
}

// Modifier
// Modifier should calculate the correct modifier for a given score
func Modifier(score int) int {
panic("Please implement the 'Modifier' function")
}

// Ability
func Ability() string {
// Ability should generate the score for a random ability
func Ability() int {
panic("Please implement the 'Ability' function")
}

// Character
// Character should return a CharacterSheet with valid ability scores
func Character() CharacterSheet {
panic("Please implement the 'Character' function")
}

// CalculateAbilityScore expects an array of 4 dice scores and returns the sum of the 3 highest numbers
func CalculateAbilityScore(scores []int) int {
panic("Please implement the 'CalculateAbilityScore' function")
}
35 changes: 33 additions & 2 deletions exercises/practice/dnd-character/dnd_character_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// TODO: implement test cases
package dndcharacter

import "testing"
Expand All @@ -15,11 +14,31 @@ func TestModifier(t *testing.T) {
}

func TestAbility(t *testing.T) {

for i := 0; i < 10; i++ {
t.Run("", func(t *testing.T) {
got := Ability()
if !inAcceptedRange(got) {
t.Fatal("Ability score is not within accepted range (3-18)")
}
})
}
}

func TestCharacter(t *testing.T) {
t.Run("should generate a character sheet with random ability scores", func(t *testing.T) {
character := Character()

assertAbilityScoreInRange(t, "Charisma", character.Charisma)
assertAbilityScoreInRange(t, "Strength", character.Strength)
assertAbilityScoreInRange(t, "Dexterity", character.Dexterity)
assertAbilityScoreInRange(t, "Wisdom", character.Wisdom)
assertAbilityScoreInRange(t, "Intelligence", character.Intelligence)
assertAbilityScoreInRange(t, "Constitution", character.Constitution)

if character.Hitpoints < 10 {
t.Fatalf("Character's base hitpoints are incorrect. Got %d", character.Hitpoints)
}
})
}

func BenchmarkAbility(b *testing.B) {
Expand All @@ -39,3 +58,15 @@ func BenchmarkModifier(b *testing.B) {
Modifier(i)
}
}

func inAcceptedRange(score int) bool {
return score >= 3 && score <= 18
}

func assertAbilityScoreInRange(t testing.TB, ability string, score int) {
t.Helper()

if !inAcceptedRange(score) {
t.Fatalf("%s score is not withing accepted range. Got %d", ability, score)
}
}

0 comments on commit 3f9d225

Please sign in to comment.