From a552397eb108c3f803fce7e4b6ba9f71b7a1e8b9 Mon Sep 17 00:00:00 2001 From: Jesse Kroon Date: Wed, 24 Jan 2024 22:14:08 +0100 Subject: [PATCH 01/24] add auto generated files --- config.json | 222 +++++++++--------- .../dnd-character/.docs/instructions.md | 31 +++ .../practice/dnd-character/.meta/config.json | 17 ++ .../practice/dnd-character/.meta/example.go | 0 .../practice/dnd-character/.meta/tests.toml | 72 ++++++ .../practice/dnd-character/dnd_character.go | 0 .../dnd-character/dnd_character_test.go | 0 7 files changed, 231 insertions(+), 111 deletions(-) create mode 100644 exercises/practice/dnd-character/.docs/instructions.md create mode 100644 exercises/practice/dnd-character/.meta/config.json create mode 100644 exercises/practice/dnd-character/.meta/example.go create mode 100644 exercises/practice/dnd-character/.meta/tests.toml create mode 100644 exercises/practice/dnd-character/dnd_character.go create mode 100644 exercises/practice/dnd-character/dnd_character_test.go diff --git a/config.json b/config.json index ec479d9f6..a75e1283d 100644 --- a/config.json +++ b/config.json @@ -35,8 +35,8 @@ "exercises": { "concept": [ { - "name": "Gopher's Gorgeous Lasagna", "slug": "lasagna", + "name": "Gopher's Gorgeous Lasagna", "uuid": "6396fe40-ff11-4ff5-b880-9681bce30a6e", "concepts": [ "basics" @@ -171,8 +171,8 @@ "status": "beta" }, { - "name": "Lasagna Master", "slug": "lasagna-master", + "name": "Lasagna Master", "uuid": "41167bbf-c2e6-4946-83d8-0ea108e5ce8d", "concepts": [ "functions" @@ -188,8 +188,8 @@ "status": "beta" }, { - "name": "Need For Speed", "slug": "need-for-speed", + "name": "Need For Speed", "uuid": "b165c8b4-429f-4e9f-b157-a636d22b217f", "concepts": [ "structs" @@ -201,8 +201,8 @@ "status": "beta" }, { - "name": "Elon's Toys", "slug": "elons-toys", + "name": "Elon's Toys", "uuid": "18fb2aa2-9748-481e-a321-6b6844c1deb6", "concepts": [ "methods" @@ -239,8 +239,8 @@ "status": "beta" }, { - "name": "Card Tricks", "slug": "card-tricks", + "name": "Card Tricks", "uuid": "154660c2-db8c-4ec1-91f2-6b1275eabbc0", "concepts": [ "slices", @@ -254,8 +254,8 @@ "status": "beta" }, { - "name": "Logs, Logs, Logs!", "slug": "logs-logs-logs", + "name": "Logs, Logs, Logs!", "uuid": "81230a7c-4e47-4a4d-a004-14eae32ec914", "concepts": [ "runes" @@ -270,8 +270,8 @@ "status": "beta" }, { - "name": "Sorting Room", "slug": "sorting-room", + "name": "Sorting Room", "uuid": "411f4f1e-7ee2-4f11-955d-8af86da69c2a", "concepts": [ "type-assertion", @@ -284,8 +284,8 @@ "status": "beta" }, { - "name": "Chessboard", "slug": "chessboard", + "name": "Chessboard", "uuid": "b5f1c789-adf6-487c-95b0-c6bce23d711b", "concepts": [ "range-iteration", @@ -301,8 +301,8 @@ "status": "beta" }, { - "name": "Airport Robot", "slug": "airport-robot", + "name": "Airport Robot", "uuid": "e8e4de51-3ad8-4474-9965-50689abe4045", "concepts": [ "interfaces" @@ -316,8 +316,8 @@ "status": "beta" }, { - "name": "The Farm", "slug": "the-farm", + "name": "The Farm", "uuid": "43e12a9e-ed8e-4552-a889-d86e284b21c0", "concepts": [ "errors" @@ -334,8 +334,8 @@ "status": "beta" }, { - "name": "Census", "slug": "census", + "name": "Census", "uuid": "fa4735f8-4d8a-4fb1-85ed-9cf03e9f7b7a", "concepts": [ "zero-values" @@ -354,8 +354,8 @@ "status": "beta" }, { - "name": "Welcome To Tech Palace!", "slug": "welcome-to-tech-palace", + "name": "Welcome To Tech Palace!", "uuid": "934af0f6-87b3-424b-a255-60a9002360d4", "concepts": [ "strings", @@ -367,8 +367,8 @@ "status": "beta" }, { - "name": "Election Day", "slug": "election-day", + "name": "Election Day", "uuid": "b9f43f40-2540-48be-b721-71117dee2250", "concepts": [ "pointers" @@ -501,10 +501,10 @@ "practices": [], "prerequisites": [], "difficulty": 1, + "status": "deprecated", "topics": [ "lists" - ], - "status": "deprecated" + ] }, { "slug": "binary", @@ -513,7 +513,6 @@ "practices": [], "prerequisites": [], "difficulty": 1, - "topics": null, "status": "deprecated" }, { @@ -523,7 +522,6 @@ "practices": [], "prerequisites": [], "difficulty": 1, - "topics": null, "status": "deprecated" }, { @@ -533,7 +531,6 @@ "practices": [], "prerequisites": [], "difficulty": 1, - "topics": null, "status": "deprecated" }, { @@ -543,7 +540,6 @@ "practices": [], "prerequisites": [], "difficulty": 1, - "topics": null, "status": "deprecated" }, { @@ -553,7 +549,6 @@ "practices": [], "prerequisites": [], "difficulty": 1, - "topics": null, "status": "deprecated" }, { @@ -664,7 +659,6 @@ "uuid": "55e1ab2e-b4ec-43ae-8f95-3f14c8dc6ce9", "practices": [], "prerequisites": [], - "topics": [], "difficulty": 2 }, { @@ -834,7 +828,6 @@ "uuid": "5ad1122f-9e7f-44e7-8fa1-3b93a22d1bde", "practices": [], "prerequisites": [], - "topics": [], "difficulty": 3 }, { @@ -1047,12 +1040,12 @@ "practices": [], "prerequisites": [], "difficulty": 3, + "status": "deprecated", "topics": [ "loops", "strings", "text_formatting" - ], - "status": "deprecated" + ] }, { "slug": "sublist", @@ -1099,12 +1092,12 @@ "uuid": "e6e1e960-1dcf-44cd-99e1-c26063965d13", "practices": [], "prerequisites": [], + "difficulty": 3, "topics": [ "loops", "strings", "text_formatting" - ], - "difficulty": 3 + ] }, { "slug": "twelve-days", @@ -1262,11 +1255,11 @@ "practices": [], "prerequisites": [], "difficulty": 4, + "status": "deprecated", "topics": [ "pattern_matching", "strings" - ], - "status": "deprecated" + ] }, { "slug": "resistor-color-trio", @@ -1274,7 +1267,6 @@ "uuid": "b10b1604-bd88-4f4a-bf84-c0508df34f1a", "practices": [], "prerequisites": [], - "topics": [], "difficulty": 4 }, { @@ -2017,199 +2009,207 @@ "loops", "searching" ] + }, + { + "slug": "dnd-character", + "name": "D&D Character", + "uuid": "fb42541e-6334-495f-b63b-e3c3d4ac1ed6", + "practices": [], + "prerequisites": [], + "difficulty": 1 } ] }, "concepts": [ { - "name": "Arithmetic Operators", + "uuid": "e01b00b9-5814-4784-a2f2-06182e8d9f7e", "slug": "arithmetic-operators", - "uuid": "e01b00b9-5814-4784-a2f2-06182e8d9f7e" + "name": "Arithmetic Operators" }, { - "name": "Basics", + "uuid": "5d2b4677-1850-4ee4-890d-dc55a1654626", "slug": "basics", - "uuid": "5d2b4677-1850-4ee4-890d-dc55a1654626" + "name": "Basics" }, { - "name": "Booleans", + "uuid": "e3942921-34ec-41eb-a999-a5d85a6623fd", "slug": "booleans", - "uuid": "e3942921-34ec-41eb-a999-a5d85a6623fd" + "name": "Booleans" }, { - "name": "Comments", + "uuid": "9ee93eab-b413-442c-b7fb-76bf044eea2d", "slug": "comments", - "uuid": "9ee93eab-b413-442c-b7fb-76bf044eea2d" + "name": "Comments" }, { - "name": "Conditionals If", + "uuid": "b3731323-f5bb-4b38-931c-2d734667bf8d", "slug": "conditionals-if", - "uuid": "b3731323-f5bb-4b38-931c-2d734667bf8d" + "name": "Conditionals If" }, { - "name": "Conditionals Switch", + "uuid": "6a4103e0-e7a9-427e-b1bd-716870580c45", "slug": "conditionals-switch", - "uuid": "6a4103e0-e7a9-427e-b1bd-716870580c45" + "name": "Conditionals Switch" }, { - "name": "Constants", + "uuid": "b56f68de-44ef-4bd4-8b14-2c50b2a366dd", "slug": "constants", - "uuid": "b56f68de-44ef-4bd4-8b14-2c50b2a366dd" + "name": "Constants" }, { - "name": "Errors", + "uuid": "a960da78-c940-4725-8069-929f42564cdb", "slug": "errors", - "uuid": "a960da78-c940-4725-8069-929f42564cdb" + "name": "Errors" }, { - "name": "Interfaces", + "uuid": "a492060c-11e7-448e-bdbd-6a907cec9493", "slug": "interfaces", - "uuid": "a492060c-11e7-448e-bdbd-6a907cec9493" + "name": "Interfaces" }, { - "name": "Functions", + "uuid": "e737f47b-5d1a-423a-8d6a-cd201a6e4e44", "slug": "functions", - "uuid": "e737f47b-5d1a-423a-8d6a-cd201a6e4e44" + "name": "Functions" }, { - "name": "First class functions", + "uuid": "66968174-701b-484c-a84d-f919b4756022", "slug": "first-class-functions", - "uuid": "66968174-701b-484c-a84d-f919b4756022" + "name": "First class functions" }, { - "name": "Floating-point numbers", + "uuid": "542b0434-59fd-4976-9d5b-c3c5c07e78d7", "slug": "floating-point-numbers", - "uuid": "542b0434-59fd-4976-9d5b-c3c5c07e78d7" + "name": "Floating-point numbers" }, { - "name": "For Loops", + "uuid": "9cf34401-7993-4b09-8a5e-55347acda4ca", "slug": "for-loops", - "uuid": "9cf34401-7993-4b09-8a5e-55347acda4ca" + "name": "For Loops" }, { - "name": "Maps", + "uuid": "625aa065-b006-4fc5-b276-28e048376b46", "slug": "maps", - "uuid": "625aa065-b006-4fc5-b276-28e048376b46" + "name": "Maps" }, { - "name": "Methods", + "uuid": "d25c6e6b-c6d4-40ce-80f9-cecbc5a72254", "slug": "methods", - "uuid": "d25c6e6b-c6d4-40ce-80f9-cecbc5a72254" + "name": "Methods" }, { - "name": "Multiple Return Values", + "uuid": "ba2c60fd-7dc5-4852-93d0-83cc25554163", "slug": "multiple-return-values", - "uuid": "ba2c60fd-7dc5-4852-93d0-83cc25554163" + "name": "Multiple Return Values" }, { - "name": "Numbers", + "uuid": "82cff17e-88cd-4707-a6d7-b5143251f029", "slug": "numbers", - "uuid": "82cff17e-88cd-4707-a6d7-b5143251f029" + "name": "Numbers" }, { - "name": "Packages", + "uuid": "2062bff8-33ed-4081-8ad6-774b3410c450", "slug": "packages", - "uuid": "2062bff8-33ed-4081-8ad6-774b3410c450" + "name": "Packages" }, { - "name": "Range Iteration", + "uuid": "8f644992-59ec-4fff-8b40-36b5ed61404d", "slug": "range-iteration", - "uuid": "8f644992-59ec-4fff-8b40-36b5ed61404d" + "name": "Range Iteration" }, { - "name": "Randomness", + "uuid": "5d354412-a87d-458b-af6c-fadfa58cfdc3", "slug": "randomness", - "uuid": "5d354412-a87d-458b-af6c-fadfa58cfdc3" + "name": "Randomness" }, { - "name": "Regular Expressions", + "uuid": "fa43f573-0dcb-47cf-a006-8d464112f7db", "slug": "regular-expressions", - "uuid": "fa43f573-0dcb-47cf-a006-8d464112f7db" + "name": "Regular Expressions" }, { - "name": "Runes", + "uuid": "6b221481-bbb3-4ccf-8be1-a5e0a20bbd01", "slug": "runes", - "uuid": "6b221481-bbb3-4ccf-8be1-a5e0a20bbd01" + "name": "Runes" }, { - "name": "Slices", + "uuid": "23e1c40a-300c-4a44-bc32-f3440a057216", "slug": "slices", - "uuid": "23e1c40a-300c-4a44-bc32-f3440a057216" + "name": "Slices" }, { - "name": "Strings", + "uuid": "43374ffa-090d-4295-802c-a3d9efc22c99", "slug": "strings", - "uuid": "43374ffa-090d-4295-802c-a3d9efc22c99" + "name": "Strings" }, { - "name": "String Formatting", + "uuid": "eeae05c6-b751-44a2-b843-517ec7b83ef7", "slug": "string-formatting", - "uuid": "eeae05c6-b751-44a2-b843-517ec7b83ef7" + "name": "String Formatting" }, { - "name": "Strings Package", + "uuid": "33708451-a03f-44ce-be05-eaacc1d5793c", "slug": "strings-package", - "uuid": "33708451-a03f-44ce-be05-eaacc1d5793c" + "name": "Strings Package" }, { - "name": "Stringers", + "uuid": "288c0d5b-173a-4446-b9a6-05f91fddd63e", "slug": "stringers", - "uuid": "288c0d5b-173a-4446-b9a6-05f91fddd63e" + "name": "Stringers" }, { - "name": "Structs", + "uuid": "5bd431cf-c30d-4f5c-a16d-c62e51720fbd", "slug": "structs", - "uuid": "5bd431cf-c30d-4f5c-a16d-c62e51720fbd" + "name": "Structs" }, { - "name": "Time", + "uuid": "4673000c-7822-4252-88c5-723f47d6ad06", "slug": "time", - "uuid": "4673000c-7822-4252-88c5-723f47d6ad06" + "name": "Time" }, { - "name": "Type Assertion", + "uuid": "601911e6-ecb8-4e37-bc11-395aaa2be3ce", "slug": "type-assertion", - "uuid": "601911e6-ecb8-4e37-bc11-395aaa2be3ce" + "name": "Type Assertion" }, { - "name": "Type Conversion", + "uuid": "4f3d535e-cec8-4303-ac5a-ed91a53bd594", "slug": "type-conversion", - "uuid": "4f3d535e-cec8-4303-ac5a-ed91a53bd594" + "name": "Type Conversion" }, { - "name": "Type Definitions", + "uuid": "ef4bfcfb-fa81-4d80-be63-a50c47653490", "slug": "type-definitions", - "uuid": "ef4bfcfb-fa81-4d80-be63-a50c47653490" + "name": "Type Definitions" }, { - "name": "Zero Values", + "uuid": "a50b4ed6-6198-4ab2-8075-3770900db4c9", "slug": "zero-values", - "uuid": "a50b4ed6-6198-4ab2-8075-3770900db4c9" + "name": "Zero Values" }, { - "name": "Comparison", + "uuid": "f7abb288-9526-447d-9eb8-45d756f2ae9b", "slug": "comparison", - "uuid": "f7abb288-9526-447d-9eb8-45d756f2ae9b" + "name": "Comparison" }, { - "name": "Pointers", + "uuid": "57477550-cecf-4334-903a-85a6c32d61d0", "slug": "pointers", - "uuid": "57477550-cecf-4334-903a-85a6c32d61d0" + "name": "Pointers" }, { - "name": "Variables", + "uuid": "76e36f06-f809-4ce7-9ebd-4b1e010bc938", "slug": "variables", - "uuid": "76e36f06-f809-4ce7-9ebd-4b1e010bc938" + "name": "Variables" }, { - "name": "Variadic Functions", + "uuid": "7c9ad69f-b28a-4366-affc-870fc48e51eb", "slug": "variadic-functions", - "uuid": "7c9ad69f-b28a-4366-affc-870fc48e51eb" + "name": "Variadic Functions" }, { - "name": "Error Wrapping", + "uuid": "f22b0e85-4d86-4ecf-9415-ea27c93ebcd6", "slug": "error-wrapping", - "uuid": "f22b0e85-4d86-4ecf-9415-ea27c93ebcd6" + "name": "Error Wrapping" } ], "key_features": [ @@ -2245,15 +2245,15 @@ } ], "tags": [ - "paradigm/procedural", - "paradigm/imperative", - "typing/static", - "typing/strong", "execution_mode/compiled", - "platform/windows", - "platform/mac", + "paradigm/imperative", + "paradigm/procedural", "platform/linux", + "platform/mac", + "platform/windows", "runtime/standalone_executable", + "typing/static", + "typing/strong", "used_for/backends", "used_for/cross_platform_development", "used_for/web_development" diff --git a/exercises/practice/dnd-character/.docs/instructions.md b/exercises/practice/dnd-character/.docs/instructions.md new file mode 100644 index 000000000..b0a603591 --- /dev/null +++ b/exercises/practice/dnd-character/.docs/instructions.md @@ -0,0 +1,31 @@ +# Instructions + +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][troll]. + +[dnd]: https://en.wikipedia.org/wiki/Dungeons_%26_Dragons +[troll]: https://di.ku.dk/Ansatte/?pure=da%2Fpublications%2Ftroll-a-language-for-specifying-dicerolls(84a45ff0-068b-11df-825d-000ea68e967b)%2Fexport.html diff --git a/exercises/practice/dnd-character/.meta/config.json b/exercises/practice/dnd-character/.meta/config.json new file mode 100644 index 000000000..3fe331c9a --- /dev/null +++ b/exercises/practice/dnd-character/.meta/config.json @@ -0,0 +1,17 @@ +{ + "authors": ["jesse-kroon"], + "files": { + "solution": [ + "dnd_character.go" + ], + "test": [ + "dnd_character_test.go" + ], + "example": [ + ".meta/example.go" + ] + }, + "blurb": "Randomly generate Dungeons & Dragons characters.", + "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/example.go b/exercises/practice/dnd-character/.meta/example.go new file mode 100644 index 000000000..e69de29bb diff --git a/exercises/practice/dnd-character/.meta/tests.toml b/exercises/practice/dnd-character/.meta/tests.toml new file mode 100644 index 000000000..719043b25 --- /dev/null +++ b/exercises/practice/dnd-character/.meta/tests.toml @@ -0,0 +1,72 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[1e9ae1dc-35bd-43ba-aa08-e4b94c20fa37] +description = "ability modifier -> ability modifier for score 3 is -4" + +[cc9bb24e-56b8-4e9e-989d-a0d1a29ebb9c] +description = "ability modifier -> ability modifier for score 4 is -3" + +[5b519fcd-6946-41ee-91fe-34b4f9808326] +description = "ability modifier -> ability modifier for score 5 is -3" + +[dc2913bd-6d7a-402e-b1e2-6d568b1cbe21] +description = "ability modifier -> ability modifier for score 6 is -2" + +[099440f5-0d66-4b1a-8a10-8f3a03cc499f] +description = "ability modifier -> ability modifier for score 7 is -2" + +[cfda6e5c-3489-42f0-b22b-4acb47084df0] +description = "ability modifier -> ability modifier for score 8 is -1" + +[c70f0507-fa7e-4228-8463-858bfbba1754] +description = "ability modifier -> ability modifier for score 9 is -1" + +[6f4e6c88-1cd9-46a0-92b8-db4a99b372f7] +description = "ability modifier -> ability modifier for score 10 is 0" + +[e00d9e5c-63c8-413f-879d-cd9be9697097] +description = "ability modifier -> ability modifier for score 11 is 0" + +[eea06f3c-8de0-45e7-9d9d-b8cab4179715] +description = "ability modifier -> ability modifier for score 12 is +1" + +[9c51f6be-db72-4af7-92ac-b293a02c0dcd] +description = "ability modifier -> ability modifier for score 13 is +1" + +[94053a5d-53b6-4efc-b669-a8b5098f7762] +description = "ability modifier -> ability modifier for score 14 is +2" + +[8c33e7ca-3f9f-4820-8ab3-65f2c9e2f0e2] +description = "ability modifier -> ability modifier for score 15 is +2" + +[c3ec871e-1791-44d0-b3cc-77e5fb4cd33d] +description = "ability modifier -> ability modifier for score 16 is +3" + +[3d053cee-2888-4616-b9fd-602a3b1efff4] +description = "ability modifier -> ability modifier for score 17 is +3" + +[bafd997a-e852-4e56-9f65-14b60261faee] +description = "ability modifier -> ability modifier for score 18 is +4" + +[4f28f19c-2e47-4453-a46a-c0d365259c14] +description = "random ability is within range" + +[385d7e72-864f-4e88-8279-81a7d75b04ad] +description = "random character is valid" + +[2ca77b9b-c099-46c3-a02c-0d0f68ffa0fe] +description = "each ability is only calculated once" +include = false + +[dca2b2ec-f729-4551-84b9-078876bb4808] +description = "each ability is only calculated once" +reimplements = "2ca77b9b-c099-46c3-a02c-0d0f68ffa0fe" diff --git a/exercises/practice/dnd-character/dnd_character.go b/exercises/practice/dnd-character/dnd_character.go new file mode 100644 index 000000000..e69de29bb diff --git a/exercises/practice/dnd-character/dnd_character_test.go b/exercises/practice/dnd-character/dnd_character_test.go new file mode 100644 index 000000000..e69de29bb From 36b36449676ee9fdb2bd859ee822a2bea4c38c25 Mon Sep 17 00:00:00 2001 From: Jesse Kroon Date: Wed, 24 Jan 2024 22:30:32 +0100 Subject: [PATCH 02/24] undo weird changes done by Goland --- config.json | 232 +++++++++++++++++++++++++++------------------------- 1 file changed, 120 insertions(+), 112 deletions(-) diff --git a/config.json b/config.json index a75e1283d..951f61684 100644 --- a/config.json +++ b/config.json @@ -35,8 +35,8 @@ "exercises": { "concept": [ { - "slug": "lasagna", "name": "Gopher's Gorgeous Lasagna", + "slug": "lasagna", "uuid": "6396fe40-ff11-4ff5-b880-9681bce30a6e", "concepts": [ "basics" @@ -171,8 +171,8 @@ "status": "beta" }, { - "slug": "lasagna-master", "name": "Lasagna Master", + "slug": "lasagna-master", "uuid": "41167bbf-c2e6-4946-83d8-0ea108e5ce8d", "concepts": [ "functions" @@ -188,8 +188,8 @@ "status": "beta" }, { - "slug": "need-for-speed", "name": "Need For Speed", + "slug": "need-for-speed", "uuid": "b165c8b4-429f-4e9f-b157-a636d22b217f", "concepts": [ "structs" @@ -201,8 +201,8 @@ "status": "beta" }, { - "slug": "elons-toys", "name": "Elon's Toys", + "slug": "elons-toys", "uuid": "18fb2aa2-9748-481e-a321-6b6844c1deb6", "concepts": [ "methods" @@ -239,8 +239,8 @@ "status": "beta" }, { - "slug": "card-tricks", "name": "Card Tricks", + "slug": "card-tricks", "uuid": "154660c2-db8c-4ec1-91f2-6b1275eabbc0", "concepts": [ "slices", @@ -254,8 +254,8 @@ "status": "beta" }, { - "slug": "logs-logs-logs", "name": "Logs, Logs, Logs!", + "slug": "logs-logs-logs", "uuid": "81230a7c-4e47-4a4d-a004-14eae32ec914", "concepts": [ "runes" @@ -270,8 +270,8 @@ "status": "beta" }, { - "slug": "sorting-room", "name": "Sorting Room", + "slug": "sorting-room", "uuid": "411f4f1e-7ee2-4f11-955d-8af86da69c2a", "concepts": [ "type-assertion", @@ -284,8 +284,8 @@ "status": "beta" }, { - "slug": "chessboard", "name": "Chessboard", + "slug": "chessboard", "uuid": "b5f1c789-adf6-487c-95b0-c6bce23d711b", "concepts": [ "range-iteration", @@ -301,8 +301,8 @@ "status": "beta" }, { - "slug": "airport-robot", "name": "Airport Robot", + "slug": "airport-robot", "uuid": "e8e4de51-3ad8-4474-9965-50689abe4045", "concepts": [ "interfaces" @@ -316,8 +316,8 @@ "status": "beta" }, { - "slug": "the-farm", "name": "The Farm", + "slug": "the-farm", "uuid": "43e12a9e-ed8e-4552-a889-d86e284b21c0", "concepts": [ "errors" @@ -334,8 +334,8 @@ "status": "beta" }, { - "slug": "census", "name": "Census", + "slug": "census", "uuid": "fa4735f8-4d8a-4fb1-85ed-9cf03e9f7b7a", "concepts": [ "zero-values" @@ -354,8 +354,8 @@ "status": "beta" }, { - "slug": "welcome-to-tech-palace", "name": "Welcome To Tech Palace!", + "slug": "welcome-to-tech-palace", "uuid": "934af0f6-87b3-424b-a255-60a9002360d4", "concepts": [ "strings", @@ -367,8 +367,8 @@ "status": "beta" }, { - "slug": "election-day", "name": "Election Day", + "slug": "election-day", "uuid": "b9f43f40-2540-48be-b721-71117dee2250", "concepts": [ "pointers" @@ -501,10 +501,10 @@ "practices": [], "prerequisites": [], "difficulty": 1, - "status": "deprecated", "topics": [ "lists" - ] + ], + "status": "deprecated" }, { "slug": "binary", @@ -513,6 +513,7 @@ "practices": [], "prerequisites": [], "difficulty": 1, + "topics": null, "status": "deprecated" }, { @@ -522,6 +523,7 @@ "practices": [], "prerequisites": [], "difficulty": 1, + "topics": null, "status": "deprecated" }, { @@ -531,6 +533,7 @@ "practices": [], "prerequisites": [], "difficulty": 1, + "topics": null, "status": "deprecated" }, { @@ -540,6 +543,7 @@ "practices": [], "prerequisites": [], "difficulty": 1, + "topics": null, "status": "deprecated" }, { @@ -549,6 +553,7 @@ "practices": [], "prerequisites": [], "difficulty": 1, + "topics": null, "status": "deprecated" }, { @@ -576,6 +581,14 @@ "time" ] }, + { + "slug": "dnd-character", + "name": "D&D Character", + "uuid": "fb42541e-6334-495f-b63b-e3c3d4ac1ed6", + "practices": [], + "prerequisites": [], + "difficulty": 1 + }, { "slug": "hamming", "name": "Hamming", @@ -659,6 +672,7 @@ "uuid": "55e1ab2e-b4ec-43ae-8f95-3f14c8dc6ce9", "practices": [], "prerequisites": [], + "topics": [], "difficulty": 2 }, { @@ -828,6 +842,7 @@ "uuid": "5ad1122f-9e7f-44e7-8fa1-3b93a22d1bde", "practices": [], "prerequisites": [], + "topics": [], "difficulty": 3 }, { @@ -1040,12 +1055,12 @@ "practices": [], "prerequisites": [], "difficulty": 3, - "status": "deprecated", "topics": [ "loops", "strings", "text_formatting" - ] + ], + "status": "deprecated" }, { "slug": "sublist", @@ -1092,12 +1107,12 @@ "uuid": "e6e1e960-1dcf-44cd-99e1-c26063965d13", "practices": [], "prerequisites": [], - "difficulty": 3, "topics": [ "loops", "strings", "text_formatting" - ] + ], + "difficulty": 3 }, { "slug": "twelve-days", @@ -1255,11 +1270,11 @@ "practices": [], "prerequisites": [], "difficulty": 4, - "status": "deprecated", "topics": [ "pattern_matching", "strings" - ] + ], + "status": "deprecated" }, { "slug": "resistor-color-trio", @@ -1267,6 +1282,7 @@ "uuid": "b10b1604-bd88-4f4a-bf84-c0508df34f1a", "practices": [], "prerequisites": [], + "topics": [], "difficulty": 4 }, { @@ -2009,207 +2025,199 @@ "loops", "searching" ] - }, - { - "slug": "dnd-character", - "name": "D&D Character", - "uuid": "fb42541e-6334-495f-b63b-e3c3d4ac1ed6", - "practices": [], - "prerequisites": [], - "difficulty": 1 } ] }, "concepts": [ { - "uuid": "e01b00b9-5814-4784-a2f2-06182e8d9f7e", + "name": "Arithmetic Operators", "slug": "arithmetic-operators", - "name": "Arithmetic Operators" + "uuid": "e01b00b9-5814-4784-a2f2-06182e8d9f7e" }, { - "uuid": "5d2b4677-1850-4ee4-890d-dc55a1654626", + "name": "Basics", "slug": "basics", - "name": "Basics" + "uuid": "5d2b4677-1850-4ee4-890d-dc55a1654626" }, { - "uuid": "e3942921-34ec-41eb-a999-a5d85a6623fd", + "name": "Booleans", "slug": "booleans", - "name": "Booleans" + "uuid": "e3942921-34ec-41eb-a999-a5d85a6623fd" }, { - "uuid": "9ee93eab-b413-442c-b7fb-76bf044eea2d", + "name": "Comments", "slug": "comments", - "name": "Comments" + "uuid": "9ee93eab-b413-442c-b7fb-76bf044eea2d" }, { - "uuid": "b3731323-f5bb-4b38-931c-2d734667bf8d", + "name": "Conditionals If", "slug": "conditionals-if", - "name": "Conditionals If" + "uuid": "b3731323-f5bb-4b38-931c-2d734667bf8d" }, { - "uuid": "6a4103e0-e7a9-427e-b1bd-716870580c45", + "name": "Conditionals Switch", "slug": "conditionals-switch", - "name": "Conditionals Switch" + "uuid": "6a4103e0-e7a9-427e-b1bd-716870580c45" }, { - "uuid": "b56f68de-44ef-4bd4-8b14-2c50b2a366dd", + "name": "Constants", "slug": "constants", - "name": "Constants" + "uuid": "b56f68de-44ef-4bd4-8b14-2c50b2a366dd" }, { - "uuid": "a960da78-c940-4725-8069-929f42564cdb", + "name": "Errors", "slug": "errors", - "name": "Errors" + "uuid": "a960da78-c940-4725-8069-929f42564cdb" }, { - "uuid": "a492060c-11e7-448e-bdbd-6a907cec9493", + "name": "Interfaces", "slug": "interfaces", - "name": "Interfaces" + "uuid": "a492060c-11e7-448e-bdbd-6a907cec9493" }, { - "uuid": "e737f47b-5d1a-423a-8d6a-cd201a6e4e44", + "name": "Functions", "slug": "functions", - "name": "Functions" + "uuid": "e737f47b-5d1a-423a-8d6a-cd201a6e4e44" }, { - "uuid": "66968174-701b-484c-a84d-f919b4756022", + "name": "First class functions", "slug": "first-class-functions", - "name": "First class functions" + "uuid": "66968174-701b-484c-a84d-f919b4756022" }, { - "uuid": "542b0434-59fd-4976-9d5b-c3c5c07e78d7", + "name": "Floating-point numbers", "slug": "floating-point-numbers", - "name": "Floating-point numbers" + "uuid": "542b0434-59fd-4976-9d5b-c3c5c07e78d7" }, { - "uuid": "9cf34401-7993-4b09-8a5e-55347acda4ca", + "name": "For Loops", "slug": "for-loops", - "name": "For Loops" + "uuid": "9cf34401-7993-4b09-8a5e-55347acda4ca" }, { - "uuid": "625aa065-b006-4fc5-b276-28e048376b46", + "name": "Maps", "slug": "maps", - "name": "Maps" + "uuid": "625aa065-b006-4fc5-b276-28e048376b46" }, { - "uuid": "d25c6e6b-c6d4-40ce-80f9-cecbc5a72254", + "name": "Methods", "slug": "methods", - "name": "Methods" + "uuid": "d25c6e6b-c6d4-40ce-80f9-cecbc5a72254" }, { - "uuid": "ba2c60fd-7dc5-4852-93d0-83cc25554163", + "name": "Multiple Return Values", "slug": "multiple-return-values", - "name": "Multiple Return Values" + "uuid": "ba2c60fd-7dc5-4852-93d0-83cc25554163" }, { - "uuid": "82cff17e-88cd-4707-a6d7-b5143251f029", + "name": "Numbers", "slug": "numbers", - "name": "Numbers" + "uuid": "82cff17e-88cd-4707-a6d7-b5143251f029" }, { - "uuid": "2062bff8-33ed-4081-8ad6-774b3410c450", + "name": "Packages", "slug": "packages", - "name": "Packages" + "uuid": "2062bff8-33ed-4081-8ad6-774b3410c450" }, { - "uuid": "8f644992-59ec-4fff-8b40-36b5ed61404d", + "name": "Range Iteration", "slug": "range-iteration", - "name": "Range Iteration" + "uuid": "8f644992-59ec-4fff-8b40-36b5ed61404d" }, { - "uuid": "5d354412-a87d-458b-af6c-fadfa58cfdc3", + "name": "Randomness", "slug": "randomness", - "name": "Randomness" + "uuid": "5d354412-a87d-458b-af6c-fadfa58cfdc3" }, { - "uuid": "fa43f573-0dcb-47cf-a006-8d464112f7db", + "name": "Regular Expressions", "slug": "regular-expressions", - "name": "Regular Expressions" + "uuid": "fa43f573-0dcb-47cf-a006-8d464112f7db" }, { - "uuid": "6b221481-bbb3-4ccf-8be1-a5e0a20bbd01", + "name": "Runes", "slug": "runes", - "name": "Runes" + "uuid": "6b221481-bbb3-4ccf-8be1-a5e0a20bbd01" }, { - "uuid": "23e1c40a-300c-4a44-bc32-f3440a057216", + "name": "Slices", "slug": "slices", - "name": "Slices" + "uuid": "23e1c40a-300c-4a44-bc32-f3440a057216" }, { - "uuid": "43374ffa-090d-4295-802c-a3d9efc22c99", + "name": "Strings", "slug": "strings", - "name": "Strings" + "uuid": "43374ffa-090d-4295-802c-a3d9efc22c99" }, { - "uuid": "eeae05c6-b751-44a2-b843-517ec7b83ef7", + "name": "String Formatting", "slug": "string-formatting", - "name": "String Formatting" + "uuid": "eeae05c6-b751-44a2-b843-517ec7b83ef7" }, { - "uuid": "33708451-a03f-44ce-be05-eaacc1d5793c", + "name": "Strings Package", "slug": "strings-package", - "name": "Strings Package" + "uuid": "33708451-a03f-44ce-be05-eaacc1d5793c" }, { - "uuid": "288c0d5b-173a-4446-b9a6-05f91fddd63e", + "name": "Stringers", "slug": "stringers", - "name": "Stringers" + "uuid": "288c0d5b-173a-4446-b9a6-05f91fddd63e" }, { - "uuid": "5bd431cf-c30d-4f5c-a16d-c62e51720fbd", + "name": "Structs", "slug": "structs", - "name": "Structs" + "uuid": "5bd431cf-c30d-4f5c-a16d-c62e51720fbd" }, { - "uuid": "4673000c-7822-4252-88c5-723f47d6ad06", + "name": "Time", "slug": "time", - "name": "Time" + "uuid": "4673000c-7822-4252-88c5-723f47d6ad06" }, { - "uuid": "601911e6-ecb8-4e37-bc11-395aaa2be3ce", + "name": "Type Assertion", "slug": "type-assertion", - "name": "Type Assertion" + "uuid": "601911e6-ecb8-4e37-bc11-395aaa2be3ce" }, { - "uuid": "4f3d535e-cec8-4303-ac5a-ed91a53bd594", + "name": "Type Conversion", "slug": "type-conversion", - "name": "Type Conversion" + "uuid": "4f3d535e-cec8-4303-ac5a-ed91a53bd594" }, { - "uuid": "ef4bfcfb-fa81-4d80-be63-a50c47653490", + "name": "Type Definitions", "slug": "type-definitions", - "name": "Type Definitions" + "uuid": "ef4bfcfb-fa81-4d80-be63-a50c47653490" }, { - "uuid": "a50b4ed6-6198-4ab2-8075-3770900db4c9", + "name": "Zero Values", "slug": "zero-values", - "name": "Zero Values" + "uuid": "a50b4ed6-6198-4ab2-8075-3770900db4c9" }, { - "uuid": "f7abb288-9526-447d-9eb8-45d756f2ae9b", + "name": "Comparison", "slug": "comparison", - "name": "Comparison" + "uuid": "f7abb288-9526-447d-9eb8-45d756f2ae9b" }, { - "uuid": "57477550-cecf-4334-903a-85a6c32d61d0", + "name": "Pointers", "slug": "pointers", - "name": "Pointers" + "uuid": "57477550-cecf-4334-903a-85a6c32d61d0" }, { - "uuid": "76e36f06-f809-4ce7-9ebd-4b1e010bc938", + "name": "Variables", "slug": "variables", - "name": "Variables" + "uuid": "76e36f06-f809-4ce7-9ebd-4b1e010bc938" }, { - "uuid": "7c9ad69f-b28a-4366-affc-870fc48e51eb", + "name": "Variadic Functions", "slug": "variadic-functions", - "name": "Variadic Functions" + "uuid": "7c9ad69f-b28a-4366-affc-870fc48e51eb" }, { - "uuid": "f22b0e85-4d86-4ecf-9415-ea27c93ebcd6", + "name": "Error Wrapping", "slug": "error-wrapping", - "name": "Error Wrapping" + "uuid": "f22b0e85-4d86-4ecf-9415-ea27c93ebcd6" } ], "key_features": [ @@ -2245,17 +2253,17 @@ } ], "tags": [ - "execution_mode/compiled", - "paradigm/imperative", "paradigm/procedural", - "platform/linux", - "platform/mac", - "platform/windows", - "runtime/standalone_executable", + "paradigm/imperative", "typing/static", "typing/strong", + "execution_mode/compiled", + "platform/windows", + "platform/mac", + "platform/linux", + "runtime/standalone_executable", "used_for/backends", "used_for/cross_platform_development", "used_for/web_development" ] -} +} \ No newline at end of file From b81dbb8dc32d8f14853da2d4e2172a47bfe189dd Mon Sep 17 00:00:00 2001 From: Jesse Kroon Date: Thu, 25 Jan 2024 16:23:06 +0100 Subject: [PATCH 03/24] add package name and generate test cases --- .../practice/dnd-character/.meta/example.go | 1 + exercises/practice/dnd-character/.meta/gen.go | 143 ++++++++++++++ .../practice/dnd-character/cases_test.go | 187 ++++++++++++++++++ .../practice/dnd-character/dnd_character.go | 1 + .../dnd-character/dnd_character_test.go | 1 + 5 files changed, 333 insertions(+) create mode 100644 exercises/practice/dnd-character/.meta/gen.go create mode 100644 exercises/practice/dnd-character/cases_test.go diff --git a/exercises/practice/dnd-character/.meta/example.go b/exercises/practice/dnd-character/.meta/example.go index e69de29bb..ff29fc748 100644 --- a/exercises/practice/dnd-character/.meta/example.go +++ b/exercises/practice/dnd-character/.meta/example.go @@ -0,0 +1 @@ +package dndcharacter diff --git a/exercises/practice/dnd-character/.meta/gen.go b/exercises/practice/dnd-character/.meta/gen.go new file mode 100644 index 000000000..044ebd7f2 --- /dev/null +++ b/exercises/practice/dnd-character/.meta/gen.go @@ -0,0 +1,143 @@ +package main + +import ( + "log" + "text/template" + + "../../../../gen" +) + +func main() { + t, err := template.New("").Parse(tmpl) + if err != nil { + log.Fatal(err) + } + var j = map[string]interface{}{ + "modifier": &[]modifierTestCase{}, + "ability": &[]abilityTestCase{}, + "character": &[]characterTestCase{}, + "strength": &[]strengthTestCase{}, + } + if err := gen.Gen("dnd-character", j, t); err != nil { + log.Fatal(err) + } +} + +type modifierTestCase struct { + Description string `json:"description"` + Input struct { + Score int `json:"score"` + } `json:"input"` + Expected int `json:"expected"` +} + +type abilityTestCase struct { + Description string `json:"description"` + Input struct{} `json:"input"` + Expected string `json:"expected"` +} + +type characterTestCase struct { + Description string `json:"description"` + Input struct{} `json:"input"` + Expected struct { + Strength string `json:"strength"` + Dexterity string `json:"dexterity"` + Constitution string `json:"constitution"` + Wisdom string `json:"wisdom"` + Intelligence string `json:"intelligence"` + Charisma string `json:"charisma"` + Hitpoints string `json:"hitpoints"` + } `json:"expected"` +} + +type strengthTestCase struct { + Description string `json:"description"` + Input struct{} `json:"input"` + Expected string `json:"expected"` +} + +var tmpl = `package dndcharacter + +{{.Header}} + +var modifierTests = []struct { + description string + score int + expected int +}{ + {{range .J.modifier}} + { + description: {{printf "%q" .Description}}, + score: {{printf "%d" .Input.Score}}, + expected: {{printf "%d" .Expected}}, + }, + {{end}} +} + +var abilityTests = []struct { + description string + input struct{} + expected string +}{ + {{range .J.ability}} + { + description: {{printf "%q" .Description}}, + input: {{printf "%#v" .Input}}, + expected: {{printf "%q" .Expected}}, + }, + {{end}} +} + +var characterTests = []struct { + description string + input struct{} + expected struct{ + Strength string + Dexterity string + Constitution string + Intelligence string + Wisdom string + Charisma string + Hitpoints string + } +}{ + {{range .J.character}} + { + description: {{printf "%q" .Description}}, + input: {{printf "%#v" .Input}}, + expected: struct{ + Strength string + Dexterity string + Constitution string + Intelligence string + Wisdom string + Charisma string + Hitpoints string + }{ + Strength: {{ printf "%q" .Expected.Strength }}, + Dexterity: {{ printf "%q" .Expected.Dexterity }}, + Constitution: {{ printf "%q" .Expected.Constitution }}, + Intelligence: {{ printf "%q" .Expected.Intelligence }}, + Wisdom: {{ printf "%q" .Expected.Wisdom }}, + Charisma: {{ printf "%q" .Expected.Charisma }}, + Hitpoints: {{ printf "%q" .Expected.Hitpoints }}, + }, + }, + {{end}} +} + +var strengthTests = []struct { + description string + input struct{} + expected string +}{ + {{range .J.strength}} + { + description: {{printf "%q" .Description}}, + input: {{printf "%#v" .Input}}, + expected: {{printf "%q" .Expected}}, + }, + {{end}} +} +` diff --git a/exercises/practice/dnd-character/cases_test.go b/exercises/practice/dnd-character/cases_test.go new file mode 100644 index 000000000..28de42d58 --- /dev/null +++ b/exercises/practice/dnd-character/cases_test.go @@ -0,0 +1,187 @@ +package dndcharacter + +// This is an auto-generated file. Do not change it manually. Run the generator to update the file. +// See https://github.com/exercism/go#synchronizing-tests-and-instructions +// Source: exercism/problem-specifications +// Commit: 02209d7 Reimplement test case in DnD Character (#2338) + +var modifierTests = []struct { + description string + score int + expected int +}{ + + { + description: "ability modifier for score 3 is -4", + score: 3, + expected: -4, + }, + + { + description: "ability modifier for score 4 is -3", + score: 4, + expected: -3, + }, + + { + description: "ability modifier for score 5 is -3", + score: 5, + expected: -3, + }, + + { + description: "ability modifier for score 6 is -2", + score: 6, + expected: -2, + }, + + { + description: "ability modifier for score 7 is -2", + score: 7, + expected: -2, + }, + + { + description: "ability modifier for score 8 is -1", + score: 8, + expected: -1, + }, + + { + description: "ability modifier for score 9 is -1", + score: 9, + expected: -1, + }, + + { + description: "ability modifier for score 10 is 0", + score: 10, + expected: 0, + }, + + { + description: "ability modifier for score 11 is 0", + score: 11, + expected: 0, + }, + + { + description: "ability modifier for score 12 is +1", + score: 12, + expected: 1, + }, + + { + description: "ability modifier for score 13 is +1", + score: 13, + expected: 1, + }, + + { + description: "ability modifier for score 14 is +2", + score: 14, + expected: 2, + }, + + { + description: "ability modifier for score 15 is +2", + score: 15, + expected: 2, + }, + + { + description: "ability modifier for score 16 is +3", + score: 16, + expected: 3, + }, + + { + description: "ability modifier for score 17 is +3", + score: 17, + expected: 3, + }, + + { + description: "ability modifier for score 18 is +4", + score: 18, + expected: 4, + }, +} + +var abilityTests = []struct { + description string + input struct{} + expected string +}{ + + { + description: "random ability is within range", + input: struct{}{}, + expected: "score >= 3 && score <= 18", + }, +} + +var characterTests = []struct { + description string + input struct{} + expected struct { + Strength string + Dexterity string + Constitution string + Intelligence string + Wisdom string + Charisma string + Hitpoints string + } +}{ + + { + description: "random character is valid", + input: struct{}{}, + expected: struct { + Strength string + Dexterity string + Constitution string + Intelligence string + Wisdom string + Charisma string + Hitpoints string + }{ + Strength: "strength >= 3 && strength <= 18", + Dexterity: "dexterity >= 3 && dexterity <= 18", + Constitution: "constitution >= 3 && constitution <= 18", + Intelligence: "intelligence >= 3 && intelligence <= 18", + Wisdom: "wisdom >= 3 && wisdom <= 18", + Charisma: "charisma >= 3 && charisma <= 18", + Hitpoints: "hitpoints == 10 + modifier(constitution)", + }, + }, + + { + description: "each ability is only calculated once", + input: struct{}{}, + expected: struct { + Strength string + Dexterity string + Constitution string + Intelligence string + Wisdom string + Charisma string + Hitpoints string + }{ + Strength: "strength == strength", + Dexterity: "dexterity == dexterity", + Constitution: "constitution == constitution", + Intelligence: "intelligence == intelligence", + Wisdom: "wisdom == wisdom", + Charisma: "charisma == charisma", + Hitpoints: "", + }, + }, +} + +var strengthTests = []struct { + description string + input struct{} + expected string +}{} diff --git a/exercises/practice/dnd-character/dnd_character.go b/exercises/practice/dnd-character/dnd_character.go index e69de29bb..ff29fc748 100644 --- a/exercises/practice/dnd-character/dnd_character.go +++ b/exercises/practice/dnd-character/dnd_character.go @@ -0,0 +1 @@ +package dndcharacter diff --git a/exercises/practice/dnd-character/dnd_character_test.go b/exercises/practice/dnd-character/dnd_character_test.go index e69de29bb..ff29fc748 100644 --- a/exercises/practice/dnd-character/dnd_character_test.go +++ b/exercises/practice/dnd-character/dnd_character_test.go @@ -0,0 +1 @@ +package dndcharacter From 657e1156c60a2aac0017a32487c9208fe1f3679e Mon Sep 17 00:00:00 2001 From: Jesse Kroon Date: Thu, 25 Jan 2024 16:53:03 +0100 Subject: [PATCH 04/24] ran go mod init and added basic contents for dnd_character*.go files --- .../practice/dnd-character/dnd_character.go | 22 ++++++++++++ .../dnd-character/dnd_character_test.go | 35 +++++++++++++++++++ exercises/practice/dnd-character/go.mod | 3 ++ 3 files changed, 60 insertions(+) create mode 100644 exercises/practice/dnd-character/go.mod diff --git a/exercises/practice/dnd-character/dnd_character.go b/exercises/practice/dnd-character/dnd_character.go index ff29fc748..e606225db 100644 --- a/exercises/practice/dnd-character/dnd_character.go +++ b/exercises/practice/dnd-character/dnd_character.go @@ -1 +1,23 @@ package dndcharacter + +type CharacterSheet struct { + Strength string + Dexterity string + Constitution string + Intelligence string + Wisdom string + Charisma string + Hitpoints string +} + +func Modifier(score int) int { + panic("implement me") +} + +func Ability() string { + panic("implement me") +} + +func Character() CharacterSheet { + panic("implement me") +} diff --git a/exercises/practice/dnd-character/dnd_character_test.go b/exercises/practice/dnd-character/dnd_character_test.go index ff29fc748..6e76e2586 100644 --- a/exercises/practice/dnd-character/dnd_character_test.go +++ b/exercises/practice/dnd-character/dnd_character_test.go @@ -1 +1,36 @@ package dndcharacter + +import "testing" + +func TestModifier(t *testing.T) { + for _, tc := range modifierTests { + t.Run(tc.description, func(t *testing.T) { + actual := Modifier(tc.input.Score) + if actual != tc.expected { + t.Fatalf("Modifier(%#v) = %#v, want %#v", tc.input, actual, tc.expected) + } + }) + } +} + +func TestAbility(t *testing.T) { + for _, tc := range abilityTests { + t.Run(tc.description, func(t *testing.T) { + actual := Ability() + if actual != tc.expected { + t.Fatalf("Ability(%#v) = %#v, want %#v", tc.input, actual, tc.expected) + } + }) + } +} + +func TestCharacter(t *testing.T) { + for _, tc := range characterTests { + t.Run(tc.description, func(t *testing.T) { + actual := Character() + if actual != tc.expected { + t.Fatalf("Character(%#v) = %#v, want %#v", tc.input, actual, tc.expected) + } + }) + } +} diff --git a/exercises/practice/dnd-character/go.mod b/exercises/practice/dnd-character/go.mod new file mode 100644 index 000000000..17656a59b --- /dev/null +++ b/exercises/practice/dnd-character/go.mod @@ -0,0 +1,3 @@ +module dnd-character + +go 1.21.6 From 31c0b2e05a135a915699bcace33b771b2a33a0bb Mon Sep 17 00:00:00 2001 From: Jesse Kroon Date: Thu, 25 Jan 2024 16:53:29 +0100 Subject: [PATCH 05/24] fix some incorrect field values --- exercises/practice/dnd-character/.meta/gen.go | 6 +- .../practice/dnd-character/cases_test.go | 98 ++++++++++++------- 2 files changed, 69 insertions(+), 35 deletions(-) diff --git a/exercises/practice/dnd-character/.meta/gen.go b/exercises/practice/dnd-character/.meta/gen.go index 044ebd7f2..c39f68715 100644 --- a/exercises/practice/dnd-character/.meta/gen.go +++ b/exercises/practice/dnd-character/.meta/gen.go @@ -63,13 +63,15 @@ var tmpl = `package dndcharacter var modifierTests = []struct { description string - score int + input struct { Score int } expected int }{ {{range .J.modifier}} { description: {{printf "%q" .Description}}, - score: {{printf "%d" .Input.Score}}, + input: struct{ Score int }{ + Score: {{printf "%d" .Input.Score}}, + }, expected: {{printf "%d" .Expected}}, }, {{end}} diff --git a/exercises/practice/dnd-character/cases_test.go b/exercises/practice/dnd-character/cases_test.go index 28de42d58..301e48d39 100644 --- a/exercises/practice/dnd-character/cases_test.go +++ b/exercises/practice/dnd-character/cases_test.go @@ -7,104 +7,136 @@ package dndcharacter var modifierTests = []struct { description string - score int + input struct{ Score int } expected int }{ { description: "ability modifier for score 3 is -4", - score: 3, - expected: -4, + input: struct{ Score int }{ + Score: 3, + }, + expected: -4, }, { description: "ability modifier for score 4 is -3", - score: 4, - expected: -3, + input: struct{ Score int }{ + Score: 4, + }, + expected: -3, }, { description: "ability modifier for score 5 is -3", - score: 5, - expected: -3, + input: struct{ Score int }{ + Score: 5, + }, + expected: -3, }, { description: "ability modifier for score 6 is -2", - score: 6, - expected: -2, + input: struct{ Score int }{ + Score: 6, + }, + expected: -2, }, { description: "ability modifier for score 7 is -2", - score: 7, - expected: -2, + input: struct{ Score int }{ + Score: 7, + }, + expected: -2, }, { description: "ability modifier for score 8 is -1", - score: 8, - expected: -1, + input: struct{ Score int }{ + Score: 8, + }, + expected: -1, }, { description: "ability modifier for score 9 is -1", - score: 9, - expected: -1, + input: struct{ Score int }{ + Score: 9, + }, + expected: -1, }, { description: "ability modifier for score 10 is 0", - score: 10, - expected: 0, + input: struct{ Score int }{ + Score: 10, + }, + expected: 0, }, { description: "ability modifier for score 11 is 0", - score: 11, - expected: 0, + input: struct{ Score int }{ + Score: 11, + }, + expected: 0, }, { description: "ability modifier for score 12 is +1", - score: 12, - expected: 1, + input: struct{ Score int }{ + Score: 12, + }, + expected: 1, }, { description: "ability modifier for score 13 is +1", - score: 13, - expected: 1, + input: struct{ Score int }{ + Score: 13, + }, + expected: 1, }, { description: "ability modifier for score 14 is +2", - score: 14, - expected: 2, + input: struct{ Score int }{ + Score: 14, + }, + expected: 2, }, { description: "ability modifier for score 15 is +2", - score: 15, - expected: 2, + input: struct{ Score int }{ + Score: 15, + }, + expected: 2, }, { description: "ability modifier for score 16 is +3", - score: 16, - expected: 3, + input: struct{ Score int }{ + Score: 16, + }, + expected: 3, }, { description: "ability modifier for score 17 is +3", - score: 17, - expected: 3, + input: struct{ Score int }{ + Score: 17, + }, + expected: 3, }, { description: "ability modifier for score 18 is +4", - score: 18, - expected: 4, + input: struct{ Score int }{ + Score: 18, + }, + expected: 4, }, } From a7e6102fffe3381cfbc6e4252d69652cb7a52f31 Mon Sep 17 00:00:00 2001 From: Jesse Kroon Date: Thu, 25 Jan 2024 16:55:14 +0100 Subject: [PATCH 06/24] update exercise info in config --- config.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/config.json b/config.json index 951f61684..8acb5eae6 100644 --- a/config.json +++ b/config.json @@ -585,9 +585,13 @@ "slug": "dnd-character", "name": "D&D Character", "uuid": "fb42541e-6334-495f-b63b-e3c3d4ac1ed6", + "topics": [ + "structs", + "randomness" + ], "practices": [], "prerequisites": [], - "difficulty": 1 + "difficulty": 2 }, { "slug": "hamming", From 17bb7ad7815657c51864f31b17bb520b5255f502 Mon Sep 17 00:00:00 2001 From: Jesse Kroon Date: Sun, 28 Jan 2024 19:54:29 +0100 Subject: [PATCH 07/24] use correct version of Go --- exercises/practice/dnd-character/go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/practice/dnd-character/go.mod b/exercises/practice/dnd-character/go.mod index 17656a59b..039a5795a 100644 --- a/exercises/practice/dnd-character/go.mod +++ b/exercises/practice/dnd-character/go.mod @@ -1,3 +1,3 @@ module dnd-character -go 1.21.6 +go 1.18 From dadead96333f5ab33039b5426fb7323c8afaf115 Mon Sep 17 00:00:00 2001 From: Jesse Kroon Date: Sun, 28 Jan 2024 22:42:30 +0100 Subject: [PATCH 08/24] implement feedback --- .../practice/dnd-character/.meta/example.go | 2 + exercises/practice/dnd-character/.meta/gen.go | 122 +++--------------- .../practice/dnd-character/cases_test.go | 116 +++-------------- .../practice/dnd-character/dnd_character.go | 20 ++- .../dnd-character/dnd_character_test.go | 35 ++--- 5 files changed, 81 insertions(+), 214 deletions(-) diff --git a/exercises/practice/dnd-character/.meta/example.go b/exercises/practice/dnd-character/.meta/example.go index ff29fc748..ec19888f8 100644 --- a/exercises/practice/dnd-character/.meta/example.go +++ b/exercises/practice/dnd-character/.meta/example.go @@ -1 +1,3 @@ package dndcharacter + +// TODO: make an actual example that passes the test diff --git a/exercises/practice/dnd-character/.meta/gen.go b/exercises/practice/dnd-character/.meta/gen.go index c39f68715..2a61e09e7 100644 --- a/exercises/practice/dnd-character/.meta/gen.go +++ b/exercises/practice/dnd-character/.meta/gen.go @@ -14,132 +14,52 @@ func main() { } var j = map[string]interface{}{ "modifier": &[]modifierTestCase{}, - "ability": &[]abilityTestCase{}, - "character": &[]characterTestCase{}, - "strength": &[]strengthTestCase{}, + "ability": &[]emptyTestCase{}, + "character": &[]emptyTestCase{}, } if err := gen.Gen("dnd-character", j, t); err != nil { log.Fatal(err) } } -type modifierTestCase struct { - Description string `json:"description"` - Input struct { - Score int `json:"score"` - } `json:"input"` - Expected int `json:"expected"` -} - -type abilityTestCase struct { - Description string `json:"description"` - Input struct{} `json:"input"` - Expected string `json:"expected"` -} +// The problem specifications expect properties "Ability" and "Character" to be present +// but, we don't want to generate test cases for these as they don't have any input. To +// circumvent the test generator failing on missing properties, we've introduced +// the emptyTestCase struct. +type emptyTestCase struct{} -type characterTestCase struct { - Description string `json:"description"` - Input struct{} `json:"input"` - Expected struct { - Strength string `json:"strength"` - Dexterity string `json:"dexterity"` - Constitution string `json:"constitution"` - Wisdom string `json:"wisdom"` - Intelligence string `json:"intelligence"` - Charisma string `json:"charisma"` - Hitpoints string `json:"hitpoints"` - } `json:"expected"` +type modifierTestInput struct { + Score int `json:"score"` } -type strengthTestCase struct { - Description string `json:"description"` - Input struct{} `json:"input"` - Expected string `json:"expected"` +type modifierTestCase struct { + Description string `json:"description"` + Input modifierTestInput `json:"input"` + Expected int `json:"expected"` } -var tmpl = `package dndcharacter +var tmpl = ` +package dndcharacter {{.Header}} +type modifierTestInput struct { + Score int +} + var modifierTests = []struct { description string - input struct { Score int } + input modifierTestInput expected int }{ {{range .J.modifier}} { description: {{printf "%q" .Description}}, - input: struct{ Score int }{ + input: modifierTestInput { Score: {{printf "%d" .Input.Score}}, }, expected: {{printf "%d" .Expected}}, }, {{end}} } - -var abilityTests = []struct { - description string - input struct{} - expected string -}{ - {{range .J.ability}} - { - description: {{printf "%q" .Description}}, - input: {{printf "%#v" .Input}}, - expected: {{printf "%q" .Expected}}, - }, - {{end}} -} - -var characterTests = []struct { - description string - input struct{} - expected struct{ - Strength string - Dexterity string - Constitution string - Intelligence string - Wisdom string - Charisma string - Hitpoints string - } -}{ - {{range .J.character}} - { - description: {{printf "%q" .Description}}, - input: {{printf "%#v" .Input}}, - expected: struct{ - Strength string - Dexterity string - Constitution string - Intelligence string - Wisdom string - Charisma string - Hitpoints string - }{ - Strength: {{ printf "%q" .Expected.Strength }}, - Dexterity: {{ printf "%q" .Expected.Dexterity }}, - Constitution: {{ printf "%q" .Expected.Constitution }}, - Intelligence: {{ printf "%q" .Expected.Intelligence }}, - Wisdom: {{ printf "%q" .Expected.Wisdom }}, - Charisma: {{ printf "%q" .Expected.Charisma }}, - Hitpoints: {{ printf "%q" .Expected.Hitpoints }}, - }, - }, - {{end}} -} - -var strengthTests = []struct { - description string - input struct{} - expected string -}{ - {{range .J.strength}} - { - description: {{printf "%q" .Description}}, - input: {{printf "%#v" .Input}}, - expected: {{printf "%q" .Expected}}, - }, - {{end}} -} ` diff --git a/exercises/practice/dnd-character/cases_test.go b/exercises/practice/dnd-character/cases_test.go index 301e48d39..b000387a4 100644 --- a/exercises/practice/dnd-character/cases_test.go +++ b/exercises/practice/dnd-character/cases_test.go @@ -5,15 +5,19 @@ package dndcharacter // Source: exercism/problem-specifications // Commit: 02209d7 Reimplement test case in DnD Character (#2338) +type modifierTestInput struct { + Score int +} + var modifierTests = []struct { description string - input struct{ Score int } + input modifierTestInput expected int }{ { description: "ability modifier for score 3 is -4", - input: struct{ Score int }{ + input: modifierTestInput{ Score: 3, }, expected: -4, @@ -21,7 +25,7 @@ var modifierTests = []struct { { description: "ability modifier for score 4 is -3", - input: struct{ Score int }{ + input: modifierTestInput{ Score: 4, }, expected: -3, @@ -29,7 +33,7 @@ var modifierTests = []struct { { description: "ability modifier for score 5 is -3", - input: struct{ Score int }{ + input: modifierTestInput{ Score: 5, }, expected: -3, @@ -37,7 +41,7 @@ var modifierTests = []struct { { description: "ability modifier for score 6 is -2", - input: struct{ Score int }{ + input: modifierTestInput{ Score: 6, }, expected: -2, @@ -45,7 +49,7 @@ var modifierTests = []struct { { description: "ability modifier for score 7 is -2", - input: struct{ Score int }{ + input: modifierTestInput{ Score: 7, }, expected: -2, @@ -53,7 +57,7 @@ var modifierTests = []struct { { description: "ability modifier for score 8 is -1", - input: struct{ Score int }{ + input: modifierTestInput{ Score: 8, }, expected: -1, @@ -61,7 +65,7 @@ var modifierTests = []struct { { description: "ability modifier for score 9 is -1", - input: struct{ Score int }{ + input: modifierTestInput{ Score: 9, }, expected: -1, @@ -69,7 +73,7 @@ var modifierTests = []struct { { description: "ability modifier for score 10 is 0", - input: struct{ Score int }{ + input: modifierTestInput{ Score: 10, }, expected: 0, @@ -77,7 +81,7 @@ var modifierTests = []struct { { description: "ability modifier for score 11 is 0", - input: struct{ Score int }{ + input: modifierTestInput{ Score: 11, }, expected: 0, @@ -85,7 +89,7 @@ var modifierTests = []struct { { description: "ability modifier for score 12 is +1", - input: struct{ Score int }{ + input: modifierTestInput{ Score: 12, }, expected: 1, @@ -93,7 +97,7 @@ var modifierTests = []struct { { description: "ability modifier for score 13 is +1", - input: struct{ Score int }{ + input: modifierTestInput{ Score: 13, }, expected: 1, @@ -101,7 +105,7 @@ var modifierTests = []struct { { description: "ability modifier for score 14 is +2", - input: struct{ Score int }{ + input: modifierTestInput{ Score: 14, }, expected: 2, @@ -109,7 +113,7 @@ var modifierTests = []struct { { description: "ability modifier for score 15 is +2", - input: struct{ Score int }{ + input: modifierTestInput{ Score: 15, }, expected: 2, @@ -117,7 +121,7 @@ var modifierTests = []struct { { description: "ability modifier for score 16 is +3", - input: struct{ Score int }{ + input: modifierTestInput{ Score: 16, }, expected: 3, @@ -125,7 +129,7 @@ var modifierTests = []struct { { description: "ability modifier for score 17 is +3", - input: struct{ Score int }{ + input: modifierTestInput{ Score: 17, }, expected: 3, @@ -133,87 +137,9 @@ var modifierTests = []struct { { description: "ability modifier for score 18 is +4", - input: struct{ Score int }{ + input: modifierTestInput{ Score: 18, }, expected: 4, }, } - -var abilityTests = []struct { - description string - input struct{} - expected string -}{ - - { - description: "random ability is within range", - input: struct{}{}, - expected: "score >= 3 && score <= 18", - }, -} - -var characterTests = []struct { - description string - input struct{} - expected struct { - Strength string - Dexterity string - Constitution string - Intelligence string - Wisdom string - Charisma string - Hitpoints string - } -}{ - - { - description: "random character is valid", - input: struct{}{}, - expected: struct { - Strength string - Dexterity string - Constitution string - Intelligence string - Wisdom string - Charisma string - Hitpoints string - }{ - Strength: "strength >= 3 && strength <= 18", - Dexterity: "dexterity >= 3 && dexterity <= 18", - Constitution: "constitution >= 3 && constitution <= 18", - Intelligence: "intelligence >= 3 && intelligence <= 18", - Wisdom: "wisdom >= 3 && wisdom <= 18", - Charisma: "charisma >= 3 && charisma <= 18", - Hitpoints: "hitpoints == 10 + modifier(constitution)", - }, - }, - - { - description: "each ability is only calculated once", - input: struct{}{}, - expected: struct { - Strength string - Dexterity string - Constitution string - Intelligence string - Wisdom string - Charisma string - Hitpoints string - }{ - Strength: "strength == strength", - Dexterity: "dexterity == dexterity", - Constitution: "constitution == constitution", - Intelligence: "intelligence == intelligence", - Wisdom: "wisdom == wisdom", - Charisma: "charisma == charisma", - Hitpoints: "", - }, - }, -} - -var strengthTests = []struct { - description string - input struct{} - expected string -}{} diff --git a/exercises/practice/dnd-character/dnd_character.go b/exercises/practice/dnd-character/dnd_character.go index e606225db..d26e7b6fd 100644 --- a/exercises/practice/dnd-character/dnd_character.go +++ b/exercises/practice/dnd-character/dnd_character.go @@ -1,3 +1,14 @@ +// 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 { @@ -10,14 +21,17 @@ type CharacterSheet struct { Hitpoints string } +// Modifier func Modifier(score int) int { - panic("implement me") + panic("Please implement the 'Modifier' function") } +// Ability func Ability() string { - panic("implement me") + panic("Please implement the 'Ability' function") } +// Character func Character() CharacterSheet { - panic("implement me") + panic("Please implement the 'Character' function") } diff --git a/exercises/practice/dnd-character/dnd_character_test.go b/exercises/practice/dnd-character/dnd_character_test.go index 6e76e2586..f9557252b 100644 --- a/exercises/practice/dnd-character/dnd_character_test.go +++ b/exercises/practice/dnd-character/dnd_character_test.go @@ -1,3 +1,4 @@ +// TODO: implement test cases package dndcharacter import "testing" @@ -14,23 +15,27 @@ func TestModifier(t *testing.T) { } func TestAbility(t *testing.T) { - for _, tc := range abilityTests { - t.Run(tc.description, func(t *testing.T) { - actual := Ability() - if actual != tc.expected { - t.Fatalf("Ability(%#v) = %#v, want %#v", tc.input, actual, tc.expected) - } - }) - } + } func TestCharacter(t *testing.T) { - for _, tc := range characterTests { - t.Run(tc.description, func(t *testing.T) { - actual := Character() - if actual != tc.expected { - t.Fatalf("Character(%#v) = %#v, want %#v", tc.input, actual, tc.expected) - } - }) + +} + +func BenchmarkAbility(b *testing.B) { + for i := 0; i < b.N; i++ { + Ability() + } +} + +func BenchmarkCharacter(b *testing.B) { + for i := 0; i < b.N; i++ { + Character() + } +} + +func BenchmarkModifier(b *testing.B) { + for i := 0; i < b.N; i++ { + Modifier(i) } } From 3f9d225d0d34d7113fa707f67ab53ae83c1acc30 Mon Sep 17 00:00:00 2001 From: Jesse Kroon Date: Mon, 29 Jan 2024 09:01:54 +0100 Subject: [PATCH 09/24] finish up a first working version --- .../practice/dnd-character/.meta/example.go | 61 ++++++++++++++++++- .../practice/dnd-character/dnd_character.go | 38 +++++------- .../dnd-character/dnd_character_test.go | 35 ++++++++++- 3 files changed, 109 insertions(+), 25 deletions(-) diff --git a/exercises/practice/dnd-character/.meta/example.go b/exercises/practice/dnd-character/.meta/example.go index ec19888f8..0f552b80f 100644 --- a/exercises/practice/dnd-character/.meta/example.go +++ b/exercises/practice/dnd-character/.meta/example.go @@ -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 +} diff --git a/exercises/practice/dnd-character/dnd_character.go b/exercises/practice/dnd-character/dnd_character.go index d26e7b6fd..ccb5c2f16 100644 --- a/exercises/practice/dnd-character/dnd_character.go +++ b/exercises/practice/dnd-character/dnd_character.go @@ -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") +} diff --git a/exercises/practice/dnd-character/dnd_character_test.go b/exercises/practice/dnd-character/dnd_character_test.go index f9557252b..5d2cae25b 100644 --- a/exercises/practice/dnd-character/dnd_character_test.go +++ b/exercises/practice/dnd-character/dnd_character_test.go @@ -1,4 +1,3 @@ -// TODO: implement test cases package dndcharacter import "testing" @@ -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) { @@ -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) + } +} From 74d6c553f64b7d02f27e0e560685e565b0a8bdbd Mon Sep 17 00:00:00 2001 From: Jesse Kroon Date: Mon, 29 Jan 2024 16:27:48 +0100 Subject: [PATCH 10/24] use crypto/rand instead of math/rand to generate dice roll gosec linter was complaining about using weak random numbers. --- exercises/practice/dnd-character/.meta/example.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/exercises/practice/dnd-character/.meta/example.go b/exercises/practice/dnd-character/.meta/example.go index 0f552b80f..6b83ea335 100644 --- a/exercises/practice/dnd-character/.meta/example.go +++ b/exercises/practice/dnd-character/.meta/example.go @@ -1,8 +1,10 @@ package dndcharacter import ( + "crypto/rand" + "fmt" "math" - "math/rand" + "math/big" "slices" ) @@ -58,5 +60,11 @@ func CalculateAbilityScore(scores []int) int { } func RollDice() int { - return rand.Intn(6) + 1 + randomNumber, err := rand.Int(rand.Reader, big.NewInt(6)) + if err != nil { + fmt.Println("Error generating random code:", err) + return 0 + } + + return int(randomNumber.Int64()) + 1 } From dd9be069fbcbb475b0c7c741d98596519ed0acf2 Mon Sep 17 00:00:00 2001 From: Jesse Kroon Date: Mon, 29 Jan 2024 19:02:01 +0100 Subject: [PATCH 11/24] correct issue in example and rename some functions --- .../practice/dnd-character/.meta/example.go | 25 ++++++++----------- .../practice/dnd-character/dnd_character.go | 8 +++--- .../dnd-character/dnd_character_test.go | 8 +++--- 3 files changed, 18 insertions(+), 23 deletions(-) diff --git a/exercises/practice/dnd-character/.meta/example.go b/exercises/practice/dnd-character/.meta/example.go index 6b83ea335..60b0ce9e8 100644 --- a/exercises/practice/dnd-character/.meta/example.go +++ b/exercises/practice/dnd-character/.meta/example.go @@ -1,14 +1,12 @@ package dndcharacter import ( - "crypto/rand" - "fmt" "math" - "math/big" + "math/rand" "slices" ) -type CharacterSheet struct { +type Character struct { Strength int Dexterity int Constitution int @@ -35,17 +33,20 @@ func Ability() int { return CalculateAbilityScore(scores) } -// Character should return a CharacterSheet with valid ability scores -func Character() CharacterSheet { - return CharacterSheet{ +// GenerateCharacter should return a Character with valid ability scores +func GenerateCharacter() Character { + character := Character{ Strength: Ability(), Dexterity: Ability(), Constitution: Ability(), Intelligence: Ability(), Wisdom: Ability(), Charisma: Ability(), - Hitpoints: 10 + Modifier(Ability()), } + + character.Hitpoints = 10 + character.Constitution + + return character } // CalculateAbilityScore expects an array of 4 dice scores and returns the sum of the 3 highest numbers @@ -60,11 +61,5 @@ func CalculateAbilityScore(scores []int) int { } func RollDice() int { - randomNumber, err := rand.Int(rand.Reader, big.NewInt(6)) - if err != nil { - fmt.Println("Error generating random code:", err) - return 0 - } - - return int(randomNumber.Int64()) + 1 + return rand.Intn(6) + 1 } diff --git a/exercises/practice/dnd-character/dnd_character.go b/exercises/practice/dnd-character/dnd_character.go index ccb5c2f16..69c1e1cfa 100644 --- a/exercises/practice/dnd-character/dnd_character.go +++ b/exercises/practice/dnd-character/dnd_character.go @@ -1,6 +1,6 @@ package dndcharacter -type CharacterSheet struct { +type Character struct { Strength int Dexterity int Constitution int @@ -20,9 +20,9 @@ func Ability() int { panic("Please implement the 'Ability' function") } -// Character should return a CharacterSheet with valid ability scores -func Character() CharacterSheet { - panic("Please implement the 'Character' function") +// GenerateCharacter should return a Character with valid ability scores +func GenerateCharacter() Character { + panic("Please implement the 'GenerateCharacter' function") } // CalculateAbilityScore expects an array of 4 dice scores and returns the sum of the 3 highest numbers diff --git a/exercises/practice/dnd-character/dnd_character_test.go b/exercises/practice/dnd-character/dnd_character_test.go index 5d2cae25b..13866b735 100644 --- a/exercises/practice/dnd-character/dnd_character_test.go +++ b/exercises/practice/dnd-character/dnd_character_test.go @@ -24,9 +24,9 @@ func TestAbility(t *testing.T) { } } -func TestCharacter(t *testing.T) { - t.Run("should generate a character sheet with random ability scores", func(t *testing.T) { - character := Character() +func TestGenerateCharacter(t *testing.T) { + t.Run("should generate a character with random ability scores", func(t *testing.T) { + character := GenerateCharacter() assertAbilityScoreInRange(t, "Charisma", character.Charisma) assertAbilityScoreInRange(t, "Strength", character.Strength) @@ -49,7 +49,7 @@ func BenchmarkAbility(b *testing.B) { func BenchmarkCharacter(b *testing.B) { for i := 0; i < b.N; i++ { - Character() + GenerateCharacter() } } From 26c33b2475ba7ff69bf315c3d6debdcb57468e70 Mon Sep 17 00:00:00 2001 From: Jesse Kroon Date: Mon, 29 Jan 2024 19:11:39 +0100 Subject: [PATCH 12/24] add andre to contributors array --- exercises/practice/dnd-character/.meta/config.json | 1 + 1 file changed, 1 insertion(+) diff --git a/exercises/practice/dnd-character/.meta/config.json b/exercises/practice/dnd-character/.meta/config.json index 3fe331c9a..959efc87d 100644 --- a/exercises/practice/dnd-character/.meta/config.json +++ b/exercises/practice/dnd-character/.meta/config.json @@ -1,5 +1,6 @@ { "authors": ["jesse-kroon"], + "contributors": ["andrerfcsantos"], "files": { "solution": [ "dnd_character.go" From f44625c5d9f3c8335b397cad4d4b3d7a725f3691 Mon Sep 17 00:00:00 2001 From: Jesse Kroon Date: Mon, 29 Jan 2024 19:34:36 +0100 Subject: [PATCH 13/24] update function description --- exercises/practice/dnd-character/dnd_character.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/practice/dnd-character/dnd_character.go b/exercises/practice/dnd-character/dnd_character.go index 69c1e1cfa..02531495e 100644 --- a/exercises/practice/dnd-character/dnd_character.go +++ b/exercises/practice/dnd-character/dnd_character.go @@ -25,7 +25,7 @@ func GenerateCharacter() Character { panic("Please implement the 'GenerateCharacter' function") } -// CalculateAbilityScore expects an array of 4 dice scores and returns the sum of the 3 highest numbers +// CalculateAbilityScore expects an array of 4 dice-roll scores and should return the sum of the 3 highest numbers func CalculateAbilityScore(scores []int) int { panic("Please implement the 'CalculateAbilityScore' function") } From c285406b059f35fc21afa7426fc02acda5ad418a Mon Sep 17 00:00:00 2001 From: Jesse Kroon Date: Mon, 29 Jan 2024 19:39:47 +0100 Subject: [PATCH 14/24] change typo and update subtest description --- exercises/practice/dnd-character/dnd_character_test.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/exercises/practice/dnd-character/dnd_character_test.go b/exercises/practice/dnd-character/dnd_character_test.go index 13866b735..a910c5a27 100644 --- a/exercises/practice/dnd-character/dnd_character_test.go +++ b/exercises/practice/dnd-character/dnd_character_test.go @@ -15,11 +15,9 @@ func TestModifier(t *testing.T) { func TestAbility(t *testing.T) { for i := 0; i < 10; i++ { - t.Run("", func(t *testing.T) { + t.Run("should generate ability score within accepted range", func(t *testing.T) { got := Ability() - if !inAcceptedRange(got) { - t.Fatal("Ability score is not within accepted range (3-18)") - } + assertAbilityScoreInRange(t, "random", got) }) } } @@ -67,6 +65,6 @@ 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) + t.Fatalf("%s score is not within accepted range. Got %d", ability, score) } } From 9058fa30e8da26680307f09b94db5d8920ea89d0 Mon Sep 17 00:00:00 2001 From: Jesse Kroon Date: Tue, 30 Jan 2024 06:37:18 +0100 Subject: [PATCH 15/24] increase dnd-character's difficulty Also made sure topics is the final key, as per convention --- config.json | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/config.json b/config.json index 8acb5eae6..916433034 100644 --- a/config.json +++ b/config.json @@ -581,18 +581,6 @@ "time" ] }, - { - "slug": "dnd-character", - "name": "D&D Character", - "uuid": "fb42541e-6334-495f-b63b-e3c3d4ac1ed6", - "topics": [ - "structs", - "randomness" - ], - "practices": [], - "prerequisites": [], - "difficulty": 2 - }, { "slug": "hamming", "name": "Hamming", @@ -765,6 +753,18 @@ "math" ] }, + { + "slug": "dnd-character", + "name": "D&D Character", + "uuid": "fb42541e-6334-495f-b63b-e3c3d4ac1ed6", + "practices": [], + "prerequisites": [], + "difficulty": 3, + "topics": [ + "structs", + "randomness" + ] + }, { "slug": "etl", "name": "ETL", From bbdec12d4eba4f593436f9fdbec5240f500758fd Mon Sep 17 00:00:00 2001 From: Jesse Kroon <156132898+jesse-kroon@users.noreply.github.com> Date: Tue, 30 Jan 2024 06:38:55 +0100 Subject: [PATCH 16/24] Update exercises/practice/dnd-character/.meta/config.json MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit added cases_test.go under the editor key Co-authored-by: André Santos --- exercises/practice/dnd-character/.meta/config.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/exercises/practice/dnd-character/.meta/config.json b/exercises/practice/dnd-character/.meta/config.json index 959efc87d..f266fae11 100644 --- a/exercises/practice/dnd-character/.meta/config.json +++ b/exercises/practice/dnd-character/.meta/config.json @@ -8,6 +8,9 @@ "test": [ "dnd_character_test.go" ], + "editor": [ + "cases_test.go" + ], "example": [ ".meta/example.go" ] From 3855546a8545b9c3d13c666c0a074e08352505f6 Mon Sep 17 00:00:00 2001 From: Jesse Kroon Date: Tue, 30 Jan 2024 06:39:36 +0100 Subject: [PATCH 17/24] make sure the config.json ends with a newline --- config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.json b/config.json index 916433034..bbf538156 100644 --- a/config.json +++ b/config.json @@ -2270,4 +2270,4 @@ "used_for/cross_platform_development", "used_for/web_development" ] -} \ No newline at end of file +} From 8a97121c4390a4eeddfe53fc33687b23210b2779 Mon Sep 17 00:00:00 2001 From: Jesse Kroon Date: Tue, 30 Jan 2024 06:43:48 +0100 Subject: [PATCH 18/24] update function comments --- exercises/practice/dnd-character/.meta/example.go | 6 +++--- exercises/practice/dnd-character/dnd_character.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/exercises/practice/dnd-character/.meta/example.go b/exercises/practice/dnd-character/.meta/example.go index 60b0ce9e8..a4bc2d8cb 100644 --- a/exercises/practice/dnd-character/.meta/example.go +++ b/exercises/practice/dnd-character/.meta/example.go @@ -16,12 +16,12 @@ type Character struct { Hitpoints int } -// Modifier should calculate the correct modifier for a given score +// Modifier calculates the ability modifier for a given ability score func Modifier(score int) int { return int(math.Floor(float64(score-10) / 2.0)) } -// Ability should generate the score for a random ability +// Ability uses randomness to generate the score for an ability func Ability() int { var scores []int @@ -33,7 +33,7 @@ func Ability() int { return CalculateAbilityScore(scores) } -// GenerateCharacter should return a Character with valid ability scores +// GenerateCharacter creates a new Character with random scores for abilities func GenerateCharacter() Character { character := Character{ Strength: Ability(), diff --git a/exercises/practice/dnd-character/dnd_character.go b/exercises/practice/dnd-character/dnd_character.go index 02531495e..418947811 100644 --- a/exercises/practice/dnd-character/dnd_character.go +++ b/exercises/practice/dnd-character/dnd_character.go @@ -10,17 +10,17 @@ type Character struct { Hitpoints int } -// Modifier should calculate the correct modifier for a given score +// Modifier calculates the ability modifier for a given ability score func Modifier(score int) int { panic("Please implement the 'Modifier' function") } -// Ability should generate the score for a random ability +// Ability uses randomness to generate the score for an ability func Ability() int { panic("Please implement the 'Ability' function") } -// GenerateCharacter should return a Character with valid ability scores +// GenerateCharacter creates a new Character with random scores for abilities func GenerateCharacter() Character { panic("Please implement the 'GenerateCharacter' function") } From fa7de0f216b0f2c5beb6e4994396093b5820189a Mon Sep 17 00:00:00 2001 From: Jesse Kroon Date: Tue, 30 Jan 2024 07:15:56 +0100 Subject: [PATCH 19/24] remove the CalculateAbilityScore function --- exercises/practice/dnd-character/.meta/example.go | 15 +++------------ exercises/practice/dnd-character/dnd_character.go | 5 ----- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/exercises/practice/dnd-character/.meta/example.go b/exercises/practice/dnd-character/.meta/example.go index a4bc2d8cb..bea460efd 100644 --- a/exercises/practice/dnd-character/.meta/example.go +++ b/exercises/practice/dnd-character/.meta/example.go @@ -24,13 +24,15 @@ func Modifier(score int) int { // Ability uses randomness to generate the score for an ability func Ability() int { var scores []int + var sum int for i := 0; i < 4; i++ { roll := RollDice() + sum += roll scores = append(scores, roll) } - return CalculateAbilityScore(scores) + return sum - slices.Min(scores) } // GenerateCharacter creates a new Character with random scores for abilities @@ -49,17 +51,6 @@ func GenerateCharacter() Character { return character } -// 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 } diff --git a/exercises/practice/dnd-character/dnd_character.go b/exercises/practice/dnd-character/dnd_character.go index 418947811..d9915354d 100644 --- a/exercises/practice/dnd-character/dnd_character.go +++ b/exercises/practice/dnd-character/dnd_character.go @@ -24,8 +24,3 @@ func Ability() int { func GenerateCharacter() Character { panic("Please implement the 'GenerateCharacter' function") } - -// CalculateAbilityScore expects an array of 4 dice-roll scores and should return the sum of the 3 highest numbers -func CalculateAbilityScore(scores []int) int { - panic("Please implement the 'CalculateAbilityScore' function") -} From e26ca9d28991757b7a3681c77a6c56e79d7248b9 Mon Sep 17 00:00:00 2001 From: Jesse Kroon <156132898+jesse-kroon@users.noreply.github.com> Date: Tue, 30 Jan 2024 07:18:26 +0100 Subject: [PATCH 20/24] update comment explaning the emptyTestCase struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: André Santos --- exercises/practice/dnd-character/.meta/gen.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/exercises/practice/dnd-character/.meta/gen.go b/exercises/practice/dnd-character/.meta/gen.go index 2a61e09e7..06c6346f7 100644 --- a/exercises/practice/dnd-character/.meta/gen.go +++ b/exercises/practice/dnd-character/.meta/gen.go @@ -22,10 +22,13 @@ func main() { } } -// The problem specifications expect properties "Ability" and "Character" to be present -// but, we don't want to generate test cases for these as they don't have any input. To -// circumvent the test generator failing on missing properties, we've introduced -// the emptyTestCase struct. +// Problem specifications have the 'ability' and 'character' properties, +// and the test generator expects them to be present. +// However, for these properties, generating test cases automatically +// from the 'input' and the 'expected' objects is not trivial. +// To satisfy the test generator, we create an emptyTestCase for these properties +// and implement the tests manually. +// In the future we might adapt the test generator to also cover this exercise. type emptyTestCase struct{} type modifierTestInput struct { From fc7c71b32ea350d8ad4f38820b7ce91ad3ba76d4 Mon Sep 17 00:00:00 2001 From: Jesse Kroon Date: Tue, 30 Jan 2024 07:19:20 +0100 Subject: [PATCH 21/24] update panic messages --- exercises/practice/dnd-character/dnd_character.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/exercises/practice/dnd-character/dnd_character.go b/exercises/practice/dnd-character/dnd_character.go index d9915354d..5c048c3f6 100644 --- a/exercises/practice/dnd-character/dnd_character.go +++ b/exercises/practice/dnd-character/dnd_character.go @@ -12,15 +12,15 @@ type Character struct { // Modifier calculates the ability modifier for a given ability score func Modifier(score int) int { - panic("Please implement the 'Modifier' function") + panic("Please implement the Modifier() function") } // Ability uses randomness to generate the score for an ability func Ability() int { - panic("Please implement the 'Ability' function") + panic("Please implement the Ability() function") } // GenerateCharacter creates a new Character with random scores for abilities func GenerateCharacter() Character { - panic("Please implement the 'GenerateCharacter' function") + panic("Please implement the GenerateCharacter() function") } From 593c831fdbbed09c554b06ad09903860faf4d5b2 Mon Sep 17 00:00:00 2001 From: Jesse Kroon Date: Tue, 30 Jan 2024 07:31:36 +0100 Subject: [PATCH 22/24] refactor tests --- .../dnd-character/dnd_character_test.go | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/exercises/practice/dnd-character/dnd_character_test.go b/exercises/practice/dnd-character/dnd_character_test.go index a910c5a27..88d4225b1 100644 --- a/exercises/practice/dnd-character/dnd_character_test.go +++ b/exercises/practice/dnd-character/dnd_character_test.go @@ -7,34 +7,39 @@ func TestModifier(t *testing.T) { t.Run(tc.description, func(t *testing.T) { actual := Modifier(tc.input.Score) if actual != tc.expected { - t.Fatalf("Modifier(%#v) = %#v, want %#v", tc.input, actual, tc.expected) + t.Fatalf("Modifier(%d) = %d, want %d", tc.input, actual, tc.expected) } }) } } func TestAbility(t *testing.T) { - for i := 0; i < 10; i++ { - t.Run("should generate ability score within accepted range", func(t *testing.T) { + t.Run("should generate ability score within accepted range", func(t *testing.T) { + for i := 0; i < 100; i++ { got := Ability() - assertAbilityScoreInRange(t, "random", got) - }) - } + if !inAcceptedRange(got) { + t.Fatalf("Ability() returned a score for an ability outside the accepted range. Got %d, expected a value between 3 and 18 inclusive.", got) + } + } + }) } func TestGenerateCharacter(t *testing.T) { t.Run("should generate a character with random ability scores", func(t *testing.T) { - character := GenerateCharacter() + for i := 0; i < 100; i++ { + character := GenerateCharacter() - 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) + assertCharacterAbilityScoreInRange(t, "Charisma", character.Charisma) + assertCharacterAbilityScoreInRange(t, "Strength", character.Strength) + assertCharacterAbilityScoreInRange(t, "Dexterity", character.Dexterity) + assertCharacterAbilityScoreInRange(t, "Wisdom", character.Wisdom) + assertCharacterAbilityScoreInRange(t, "Intelligence", character.Intelligence) + assertCharacterAbilityScoreInRange(t, "Constitution", character.Constitution) - if character.Hitpoints < 10 { - t.Fatalf("Character's base hitpoints are incorrect. Got %d", character.Hitpoints) + expectedHitpoints := 10 + Modifier(character.Constitution) + if character.Hitpoints != expectedHitpoints { + t.Fatalf("Got %d hitpoints for a character with %d constitution, expected %d hitpoints", character.Hitpoints, character.Constitution, expectedHitpoints) + } } }) } @@ -61,10 +66,10 @@ func inAcceptedRange(score int) bool { return score >= 3 && score <= 18 } -func assertAbilityScoreInRange(t testing.TB, ability string, score int) { +func assertCharacterAbilityScoreInRange(t *testing.T, ability string, score int) { t.Helper() if !inAcceptedRange(score) { - t.Fatalf("%s score is not within accepted range. Got %d", ability, score) + t.Fatalf("GenerateCharacter() created a character with a %s score of %d, but the score for an ability is expected to be between 3 and 18 inclusive", ability, score) } } From bd130a43845e7c25f635fad365b07d7a260df13b Mon Sep 17 00:00:00 2001 From: Jesse Kroon Date: Tue, 30 Jan 2024 07:31:48 +0100 Subject: [PATCH 23/24] use correct calculation for character hitpoints --- exercises/practice/dnd-character/.meta/example.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/practice/dnd-character/.meta/example.go b/exercises/practice/dnd-character/.meta/example.go index bea460efd..34812f9a2 100644 --- a/exercises/practice/dnd-character/.meta/example.go +++ b/exercises/practice/dnd-character/.meta/example.go @@ -46,7 +46,7 @@ func GenerateCharacter() Character { Charisma: Ability(), } - character.Hitpoints = 10 + character.Constitution + character.Hitpoints = 10 + Modifier(character.Constitution) return character } From d8f8a5a91f4af5d4c95beaff8da231d60cc8c168 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Santos?= Date: Tue, 30 Jan 2024 23:05:33 +0000 Subject: [PATCH 24/24] Small fixes to the tests --- .../dnd-character/dnd_character_test.go | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/exercises/practice/dnd-character/dnd_character_test.go b/exercises/practice/dnd-character/dnd_character_test.go index 88d4225b1..a4fb06f09 100644 --- a/exercises/practice/dnd-character/dnd_character_test.go +++ b/exercises/practice/dnd-character/dnd_character_test.go @@ -7,7 +7,7 @@ func TestModifier(t *testing.T) { t.Run(tc.description, func(t *testing.T) { actual := Modifier(tc.input.Score) if actual != tc.expected { - t.Fatalf("Modifier(%d) = %d, want %d", tc.input, actual, tc.expected) + t.Fatalf("Modifier(%d) = %d, want %d", tc.input.Score, actual, tc.expected) } }) } @@ -15,7 +15,7 @@ func TestModifier(t *testing.T) { func TestAbility(t *testing.T) { t.Run("should generate ability score within accepted range", func(t *testing.T) { - for i := 0; i < 100; i++ { + for i := 0; i < 1000; i++ { got := Ability() if !inAcceptedRange(got) { t.Fatalf("Ability() returned a score for an ability outside the accepted range. Got %d, expected a value between 3 and 18 inclusive.", got) @@ -26,7 +26,7 @@ func TestAbility(t *testing.T) { func TestGenerateCharacter(t *testing.T) { t.Run("should generate a character with random ability scores", func(t *testing.T) { - for i := 0; i < 100; i++ { + for i := 0; i < 1000; i++ { character := GenerateCharacter() assertCharacterAbilityScoreInRange(t, "Charisma", character.Charisma) @@ -44,15 +44,15 @@ func TestGenerateCharacter(t *testing.T) { }) } -func BenchmarkAbility(b *testing.B) { - for i := 0; i < b.N; i++ { - Ability() - } +func inAcceptedRange(score int) bool { + return score >= 3 && score <= 18 } -func BenchmarkCharacter(b *testing.B) { - for i := 0; i < b.N; i++ { - GenerateCharacter() +func assertCharacterAbilityScoreInRange(t *testing.T, ability string, score int) { + t.Helper() + + if !inAcceptedRange(score) { + t.Fatalf("GenerateCharacter() created a character with a %s score of %d, but the score for an ability is expected to be between 3 and 18 inclusive", ability, score) } } @@ -62,14 +62,14 @@ func BenchmarkModifier(b *testing.B) { } } -func inAcceptedRange(score int) bool { - return score >= 3 && score <= 18 +func BenchmarkAbility(b *testing.B) { + for i := 0; i < b.N; i++ { + Ability() + } } -func assertCharacterAbilityScoreInRange(t *testing.T, ability string, score int) { - t.Helper() - - if !inAcceptedRange(score) { - t.Fatalf("GenerateCharacter() created a character with a %s score of %d, but the score for an ability is expected to be between 3 and 18 inclusive", ability, score) +func BenchmarkCharacter(b *testing.B) { + for i := 0; i < b.N; i++ { + GenerateCharacter() } }