From 08714c597b44fb64aea4dfbd7bf9496ab8977773 Mon Sep 17 00:00:00 2001 From: Quigley Malcolm Date: Wed, 4 Dec 2024 22:20:54 -0600 Subject: [PATCH 1/8] Move character metadata to lib/characters/metadata.ex --- lib/characters/metadata.ex | 6 ++++++ lib/rule_systems/characters.ex | 13 +++---------- lib/rule_systems/rule_system.ex | 2 +- 3 files changed, 10 insertions(+), 11 deletions(-) create mode 100644 lib/characters/metadata.ex diff --git a/lib/characters/metadata.ex b/lib/characters/metadata.ex new file mode 100644 index 0000000..69958f0 --- /dev/null +++ b/lib/characters/metadata.ex @@ -0,0 +1,6 @@ +defmodule ExTTRPGDev.Characters.Metadata do + @moduledoc """ + Metadata for an individual charater + """ + defstruct [:slug, :rule_system] +end diff --git a/lib/rule_systems/characters.ex b/lib/rule_systems/characters.ex index 33f7e71..6d03749 100644 --- a/lib/rule_systems/characters.ex +++ b/lib/rule_systems/characters.ex @@ -4,13 +4,6 @@ defmodule ExTTRPGDev.RuleSystems.Characters do """ alias ExTTRPGDev.Globals - defmodule CharacterMetadata do - @moduledoc """ - Metadata for an individual charater - """ - defstruct [:slug, :rule_system] - end - defmodule Character do @moduledoc """ Definition of an individual character @@ -22,7 +15,7 @@ defmodule ExTTRPGDev.RuleSystems.Characters do character_json |> Poison.decode!( as: %Character{ - metadata: %CharacterMetadata{ + metadata: %ExTTRPGDev.Characters.Metadata{ rule_system: %ExTTRPGDev.RuleSystems.Metadata{} } } @@ -34,10 +27,10 @@ defmodule ExTTRPGDev.RuleSystems.Characters do ## Examples - iex> Characters.character_file_path!(%Character{metadata: %CharacterMetadata{slug: "mr_whiskers"}}) + iex> Characters.character_file_path!(%Character{metadata: %Characters.Metadata{slug: "mr_whiskers"}}) "mr_whiskers.json" """ - def character_file_path!(%Character{metadata: %CharacterMetadata{slug: slug}}), + def character_file_path!(%Character{metadata: %ExTTRPGDev.Characters.Metadata{slug: slug}}), do: character_file_path!(slug) def character_file_path!(character_slug) when is_bitstring(character_slug) do diff --git a/lib/rule_systems/rule_system.ex b/lib/rule_systems/rule_system.ex index fb4ddc1..cc7c1d5 100644 --- a/lib/rule_systems/rule_system.ex +++ b/lib/rule_systems/rule_system.ex @@ -106,7 +106,7 @@ defmodule ExTTRPGDev.RuleSystems.RuleSystem do %Characters.Character{ name: name, ability_scores: Abilities.gen_scores(abilities), - metadata: %Characters.CharacterMetadata{ + metadata: %ExTTRPGDev.Characters.Metadata{ slug: name |> String.downcase() From 2ca3be78e805baa1b4de223e1aeae40a9fa2070f Mon Sep 17 00:00:00 2001 From: Quigley Malcolm Date: Wed, 4 Dec 2024 22:47:04 -0600 Subject: [PATCH 2/8] Move character struct to lib/characters/character.ex --- lib/characters/character.ex | 21 +++++++++++++++++++++ lib/rule_systems/characters.ex | 30 +++++++----------------------- lib/rule_systems/rule_system.ex | 3 +-- test/characters_test.exs | 3 ++- 4 files changed, 31 insertions(+), 26 deletions(-) create mode 100644 lib/characters/character.ex diff --git a/lib/characters/character.ex b/lib/characters/character.ex new file mode 100644 index 0000000..e153bf2 --- /dev/null +++ b/lib/characters/character.ex @@ -0,0 +1,21 @@ +defmodule ExTTRPGDev.Characters.Character do + alias __MODULE__ + alias ExTTRPGDev.Characters.Metadata + alias ExTTRPGDev.RuleSystems + + @moduledoc """ + Definition of an individual character + """ + defstruct [:name, :ability_scores, :metadata] + + def from_json!(character_json) when is_bitstring(character_json) do + character_json + |> Poison.decode!( + as: %Character{ + metadata: %Metadata{ + rule_system: %RuleSystems.Metadata{} + } + } + ) + end +end diff --git a/lib/rule_systems/characters.ex b/lib/rule_systems/characters.ex index 6d03749..6bb1f19 100644 --- a/lib/rule_systems/characters.ex +++ b/lib/rule_systems/characters.ex @@ -4,24 +4,6 @@ defmodule ExTTRPGDev.RuleSystems.Characters do """ alias ExTTRPGDev.Globals - defmodule Character do - @moduledoc """ - Definition of an individual character - """ - defstruct [:name, :ability_scores, :metadata] - end - - def from_json!(character_json) when is_bitstring(character_json) do - character_json - |> Poison.decode!( - as: %Character{ - metadata: %ExTTRPGDev.Characters.Metadata{ - rule_system: %ExTTRPGDev.RuleSystems.Metadata{} - } - } - ) - end - @doc """ Get the file path for a character @@ -30,8 +12,10 @@ defmodule ExTTRPGDev.RuleSystems.Characters do iex> Characters.character_file_path!(%Character{metadata: %Characters.Metadata{slug: "mr_whiskers"}}) "mr_whiskers.json" """ - def character_file_path!(%Character{metadata: %ExTTRPGDev.Characters.Metadata{slug: slug}}), - do: character_file_path!(slug) + def character_file_path!(%ExTTRPGDev.Characters.Character{ + metadata: %ExTTRPGDev.Characters.Metadata{slug: slug} + }), + do: character_file_path!(slug) def character_file_path!(character_slug) when is_bitstring(character_slug) do Path.join(Globals.characters_path(), "#{character_slug}.json") @@ -48,7 +32,7 @@ defmodule ExTTRPGDev.RuleSystems.Characters do iex> Characters.Character_exists?(%Characters.Character{name: "This character doesn't exist}) false """ - def character_exists?(%Character{} = character) do + def character_exists?(%ExTTRPGDev.Characters.Character{} = character) do character |> character_file_path! |> File.exists?() @@ -69,7 +53,7 @@ defmodule ExTTRPGDev.RuleSystems.Characters do :ok """ def save_character!( - %Character{} = character, + %ExTTRPGDev.Characters.Character{} = character, overwrite \\ false ) do if character_exists?(character) and not overwrite do @@ -105,6 +89,6 @@ defmodule ExTTRPGDev.RuleSystems.Characters do def load_character!(character_slug) do character_file_path!(character_slug) |> File.read!() - |> from_json!() + |> ExTTRPGDev.Characters.Character.from_json!() end end diff --git a/lib/rule_systems/rule_system.ex b/lib/rule_systems/rule_system.ex index cc7c1d5..165a090 100644 --- a/lib/rule_systems/rule_system.ex +++ b/lib/rule_systems/rule_system.ex @@ -4,7 +4,6 @@ defmodule ExTTRPGDev.RuleSystems.RuleSystem do alias ExTTRPGDev.RuleSystems.Abilities alias ExTTRPGDev.RuleSystems.Skills alias ExTTRPGDev.RuleSystems.Languages - alias ExTTRPGDev.RuleSystems.Characters @moduledoc """ Module for handling a specific Rule System @@ -103,7 +102,7 @@ defmodule ExTTRPGDev.RuleSystems.RuleSystem do }) do name = Faker.Person.name() - %Characters.Character{ + %ExTTRPGDev.Characters.Character{ name: name, ability_scores: Abilities.gen_scores(abilities), metadata: %ExTTRPGDev.Characters.Metadata{ diff --git a/test/characters_test.exs b/test/characters_test.exs index 3d4b02b..0ccd1df 100644 --- a/test/characters_test.exs +++ b/test/characters_test.exs @@ -1,5 +1,6 @@ defmodule ExTTRPGDevTest.Characters do use ExUnit.Case + alias ExTTRPGDev.Characters.Character alias ExTTRPGDev.RuleSystems.Characters alias ExTTRPGDev.RuleSystems.RuleSystem alias ExTTRPGDev.RuleSystems @@ -27,7 +28,7 @@ defmodule ExTTRPGDevTest.Characters do character end - def delete_test_character(%Characters.Character{} = character) do + def delete_test_character(%Character{} = character) do File.rm(Characters.character_file_path!(character)) end From 3094409982422285b505dcae79d21e1e549adcaa Mon Sep 17 00:00:00 2001 From: Quigley Malcolm Date: Wed, 4 Dec 2024 22:53:05 -0600 Subject: [PATCH 3/8] Move `lib/rule_systems/characters.ex` to `lib/characters.ex` --- lib/{rule_systems => }/characters.ex | 19 ++++++++++--------- test/characters_test.exs | 6 +++--- 2 files changed, 13 insertions(+), 12 deletions(-) rename lib/{rule_systems => }/characters.ex (81%) diff --git a/lib/rule_systems/characters.ex b/lib/characters.ex similarity index 81% rename from lib/rule_systems/characters.ex rename to lib/characters.ex index 6bb1f19..f2d496a 100644 --- a/lib/rule_systems/characters.ex +++ b/lib/characters.ex @@ -1,7 +1,9 @@ -defmodule ExTTRPGDev.RuleSystems.Characters do +defmodule ExTTRPGDev.Characters do @moduledoc """ - This module handles the definition of rule system characters, and what they do + This module handles handles character operations """ + alias ExTTRPGDev.Characters.Character + alias ExTTRPGDev.Characters.Metadata alias ExTTRPGDev.Globals @doc """ @@ -12,10 +14,9 @@ defmodule ExTTRPGDev.RuleSystems.Characters do iex> Characters.character_file_path!(%Character{metadata: %Characters.Metadata{slug: "mr_whiskers"}}) "mr_whiskers.json" """ - def character_file_path!(%ExTTRPGDev.Characters.Character{ - metadata: %ExTTRPGDev.Characters.Metadata{slug: slug} - }), - do: character_file_path!(slug) + def character_file_path!(%Character{metadata: %Metadata{slug: slug}}) do + character_file_path!(slug) + end def character_file_path!(character_slug) when is_bitstring(character_slug) do Path.join(Globals.characters_path(), "#{character_slug}.json") @@ -32,7 +33,7 @@ defmodule ExTTRPGDev.RuleSystems.Characters do iex> Characters.Character_exists?(%Characters.Character{name: "This character doesn't exist}) false """ - def character_exists?(%ExTTRPGDev.Characters.Character{} = character) do + def character_exists?(%Character{} = character) do character |> character_file_path! |> File.exists?() @@ -53,7 +54,7 @@ defmodule ExTTRPGDev.RuleSystems.Characters do :ok """ def save_character!( - %ExTTRPGDev.Characters.Character{} = character, + %Character{} = character, overwrite \\ false ) do if character_exists?(character) and not overwrite do @@ -89,6 +90,6 @@ defmodule ExTTRPGDev.RuleSystems.Characters do def load_character!(character_slug) do character_file_path!(character_slug) |> File.read!() - |> ExTTRPGDev.Characters.Character.from_json!() + |> Character.from_json!() end end diff --git a/test/characters_test.exs b/test/characters_test.exs index 0ccd1df..ca03a7d 100644 --- a/test/characters_test.exs +++ b/test/characters_test.exs @@ -1,11 +1,11 @@ defmodule ExTTRPGDevTest.Characters do use ExUnit.Case + alias ExTTRPGDev.Characters alias ExTTRPGDev.Characters.Character - alias ExTTRPGDev.RuleSystems.Characters - alias ExTTRPGDev.RuleSystems.RuleSystem alias ExTTRPGDev.RuleSystems + alias ExTTRPGDev.RuleSystems.RuleSystem - doctest ExTTRPGDev.RuleSystems.Characters, + doctest ExTTRPGDev.Characters, except: [ character_file_path!: 1, character_exists?: 1, From f33d3110d4fbfed45876028be5f9fd00958de0ab Mon Sep 17 00:00:00 2001 From: Quigley Malcolm Date: Thu, 5 Dec 2024 00:18:31 -0600 Subject: [PATCH 4/8] Move `gen_character` to `ExTTRPGDev.Characters.Character` --- lib/characters/character.ex | 30 ++++++++++++++++++++++++++++++ lib/cli.ex | 3 ++- lib/rule_systems/rule_system.ex | 27 --------------------------- test/characters/character_test.exs | 28 ++++++++++++++++++++++++++++ test/characters_test.exs | 3 +-- test/rule_systems_test.exs | 20 +------------------- 6 files changed, 62 insertions(+), 49 deletions(-) create mode 100644 test/characters/character_test.exs diff --git a/lib/characters/character.ex b/lib/characters/character.ex index e153bf2..6c3e779 100644 --- a/lib/characters/character.ex +++ b/lib/characters/character.ex @@ -8,6 +8,9 @@ defmodule ExTTRPGDev.Characters.Character do """ defstruct [:name, :ability_scores, :metadata] + @doc """ + Load a character from json representation + """ def from_json!(character_json) when is_bitstring(character_json) do character_json |> Poison.decode!( @@ -18,4 +21,31 @@ defmodule ExTTRPGDev.Characters.Character do } ) end + + @doc """ + Returns an auto generated character for the system + + ## Examples + iex> Character.gen_character(rule_system) + %Character{} + """ + def gen_character!(%RuleSystems.RuleSystem{ + abilities: %RuleSystems.Abilities{} = abilities, + metadata: %RuleSystems.Metadata{} = rule_system_metadata + }) do + character_name = Faker.Person.name() + + %Character{ + name: character_name, + ability_scores: RuleSystems.Abilities.gen_scores(abilities), + metadata: %ExTTRPGDev.Characters.Metadata{ + slug: + character_name + |> String.downcase() + |> String.replace(~r/[!#$%&()*+,.:;<=>?@\^_`'{|}~-]/, "") + |> String.replace(" ", "_"), + rule_system: rule_system_metadata + } + } + end end diff --git a/lib/cli.ex b/lib/cli.ex index d17123b..a1ba76c 100644 --- a/lib/cli.ex +++ b/lib/cli.ex @@ -1,6 +1,7 @@ # credo:disable-for-this-file Credo.Check.Warning.IoInspect defmodule ExTTRPGDev.CLI do alias ExTTRPGDev.Dice + alias ExTTRPGDev.Characters.Character alias ExTTRPGDev.RuleSystems alias ExTTRPGDev.RuleSystems.Abilities alias ExTTRPGDev.RuleSystems.Languages @@ -205,7 +206,7 @@ defmodule ExTTRPGDev.CLI do |> IO.inspect() :character -> - character = RuleSystems.RuleSystem.gen_character!(system) + character = Character.gen_character!(system) IO.puts("-- Name: #{character.name}") Enum.each(character.ability_scores, fn {ability, scores} -> diff --git a/lib/rule_systems/rule_system.ex b/lib/rule_systems/rule_system.ex index 165a090..c358001 100644 --- a/lib/rule_systems/rule_system.ex +++ b/lib/rule_systems/rule_system.ex @@ -88,31 +88,4 @@ defmodule ExTTRPGDev.RuleSystems.RuleSystem do when is_bitstring(spec_name) do Abilities.get_spec_by_name(abilities, spec_name) end - - @doc """ - Returns an auto generated character for the system - - ## Examples - iex> ExTTRPGDev.RuleSystems.gen_character(rule_system) - %Characters.Character{} - """ - def gen_character!(%RuleSystem{ - abilities: %Abilities{} = abilities, - metadata: %Metadata{} = metadata - }) do - name = Faker.Person.name() - - %ExTTRPGDev.Characters.Character{ - name: name, - ability_scores: Abilities.gen_scores(abilities), - metadata: %ExTTRPGDev.Characters.Metadata{ - slug: - name - |> String.downcase() - |> String.replace(~r/[!#$%&()*+,.:;<=>?@\^_`'{|}~-]/, "") - |> String.replace(" ", "_"), - rule_system: metadata - } - } - end end diff --git a/test/characters/character_test.exs b/test/characters/character_test.exs new file mode 100644 index 0000000..fc89fde --- /dev/null +++ b/test/characters/character_test.exs @@ -0,0 +1,28 @@ +defmodule ExTTRPGDevTest.Characters.Character do + use ExUnit.Case + alias ExTTRPGDev.Characters.Character + alias ExTTRPGDev.RuleSystems + + doctest ExTTRPGDev.Characters.Character, + except: [ + to_json!: 1, + gen_character!: 1 + ] + + test "gen_character!/1" do + dnd_5e_srd = RuleSystems.load_system!("dnd_5e_srd") + generated_character = Character.gen_character!(dnd_5e_srd) + + assert generated_character.name != nil + assert generated_character.metadata.slug != nil + assert not String.contains?(generated_character.metadata.slug, " ") + assert generated_character.metadata.rule_system == dnd_5e_srd.metadata + + # Assert that each ability spec is found within the generated character's ability_scores + dnd_5e_srd.abilities.specs + |> Enum.each(fn spec -> + score = Map.get(generated_character.ability_scores, spec.name) + assert score != nil, "Could not find ability #{spec.name} on generated character" + end) + end +end diff --git a/test/characters_test.exs b/test/characters_test.exs index ca03a7d..fec850d 100644 --- a/test/characters_test.exs +++ b/test/characters_test.exs @@ -3,7 +3,6 @@ defmodule ExTTRPGDevTest.Characters do alias ExTTRPGDev.Characters alias ExTTRPGDev.Characters.Character alias ExTTRPGDev.RuleSystems - alias ExTTRPGDev.RuleSystems.RuleSystem doctest ExTTRPGDev.Characters, except: [ @@ -19,7 +18,7 @@ defmodule ExTTRPGDevTest.Characters do RuleSystems.list_systems() |> List.first() |> RuleSystems.load_system!() - |> RuleSystem.gen_character!() + |> Character.gen_character!() end def save_test_character do diff --git a/test/rule_systems_test.exs b/test/rule_systems_test.exs index 138fc60..ba532be 100644 --- a/test/rule_systems_test.exs +++ b/test/rule_systems_test.exs @@ -9,8 +9,7 @@ defmodule ExTTRPGDevTest.RuleSystems do system_path!: 1, load_system!: 1, save_system!: 1, - save_system!: 2, - gen_character!: 1 + save_system!: 2 ] def build_test_system do @@ -135,21 +134,4 @@ defmodule ExTTRPGDevTest.RuleSystems do bundled_system = RuleSystems.load_system!(bundled_system_slug) assert_raise RuntimeError, fn -> RuleSystems.save_system!(bundled_system) end end - - test "gen_character!/1" do - dnd_5e_srd = RuleSystems.load_system!("dnd_5e_srd") - generated_character = RuleSystems.RuleSystem.gen_character!(dnd_5e_srd) - - assert generated_character.name != nil - assert generated_character.metadata.slug != nil - assert not String.contains?(generated_character.metadata.slug, " ") - assert generated_character.metadata.rule_system == dnd_5e_srd.metadata - - # Assert that each ability spec is found within the generated character's ability_scores - dnd_5e_srd.abilities.specs - |> Enum.each(fn spec -> - score = Map.get(generated_character.ability_scores, spec.name) - assert score != nil, "Could not find ability #{spec.name} on generated character" - end) - end end From dc9135a6be0486ea64f383bf5c8c9fd9909d750f Mon Sep 17 00:00:00 2001 From: Quigley Malcolm Date: Sat, 7 Dec 2024 23:13:03 -0600 Subject: [PATCH 5/8] Move CLI implementations for `roll` command to ExTTRPGDev.CLI.Roll --- lib/cli.ex | 212 ++++++++++++++++++++++-------------------------- lib/cli/roll.ex | 40 +++++++++ 2 files changed, 136 insertions(+), 116 deletions(-) create mode 100644 lib/cli/roll.ex diff --git a/lib/cli.ex b/lib/cli.ex index a1ba76c..dc6ccb5 100644 --- a/lib/cli.ex +++ b/lib/cli.ex @@ -1,12 +1,11 @@ # credo:disable-for-this-file Credo.Check.Warning.IoInspect defmodule ExTTRPGDev.CLI do - alias ExTTRPGDev.Dice alias ExTTRPGDev.Characters.Character alias ExTTRPGDev.RuleSystems alias ExTTRPGDev.RuleSystems.Abilities alias ExTTRPGDev.RuleSystems.Languages alias ExTTRPGDev.RuleSystems.Skills - alias ExTTRPGDev.CustomParsers + alias ExTTRPGDev.CLI.Roll @moduledoc """ The CLI for the project @@ -22,125 +21,114 @@ defmodule ExTTRPGDev.CLI do about: "Utility for playing tabletop role-playing games.", allow_unknown_args: false, parse_double_dash: true, - subcommands: [ - roll: [ - name: "roll", - about: "Roll some dice", - args: [ - dice: [ - value_name: "DICE", - help: - "Dice in the format of xdy wherein x is the number of dice, y is the number of sides the dice should have", - required: true, - parser: &CustomParsers.dice_parser(&1) - ] - ] - ], - list_systems: [ - name: "list-systems", - about: "List systems that are setup to be used with ExTTRPGDev" - ], - system: [ - name: "system", - about: "Top level command fo systems", - subcommands: [ - gen: [ - name: "gen", - about: "Used for generating things for the system", + subcommands: + Roll.commands() ++ + [ + list_systems: [ + name: "list-systems", + about: "List systems that are setup to be used with ExTTRPGDev" + ], + system: [ + name: "system", + about: "Top level command fo systems", subcommands: [ - stat_block: [ - name: "stat-block", - about: "Generate stat blocks for characters of the system", - args: [ - system: [ - value_name: "SYSTEM", - help: "A supported system, e.g. dnd5e", - required: true, - parser: :string + gen: [ + name: "gen", + about: "Used for generating things for the system", + subcommands: [ + stat_block: [ + name: "stat-block", + about: "Generate stat blocks for characters of the system", + args: [ + system: [ + value_name: "SYSTEM", + help: "A supported system, e.g. dnd5e", + required: true, + parser: :string + ] + ] + ], + character: [ + name: "character", + about: "Generate characters for system", + args: [ + system: [ + value_name: "SYSTEM", + help: "A supported system, e.g. dnd5e", + required: true, + parser: :string + ] + ] ] ] ], - character: [ - name: "character", - about: "Generate characters for system", - args: [ - system: [ - value_name: "SYSTEM", - help: "A supported system, e.g. dnd5e", - required: true, - parser: :string + show: [ + name: "show", + about: "Used for showing information about the rule system", + subcommands: [ + abilities: [ + name: "abilities", + about: "Show the rule systems character abilities", + args: [ + system: [ + value_name: "SYSTEM", + help: "A supported system, e.g. dnd5e", + required: true, + parser: :string + ] + ] + ], + languages: [ + name: "languages", + about: "Show the rule systems languages", + args: [ + system: [ + value_name: "SYSTEM", + help: "A supported system, e.g. dnd5e", + required: true, + parser: :string + ] + ] + ], + metadata: [ + name: "metadata", + about: "Show system metadata", + args: [ + system: [ + value_name: "SYSTEM", + help: "A supported system, e.g. dnd5e", + required: true, + parser: :string + ] + ] + ], + skills: [ + name: "skills", + about: "Show rule system skills", + args: [ + system: [ + value_name: "SYSTEM", + help: "A supported system, e.g. dnd5e", + required: true, + parser: :string + ] + ] ] ] ] ] ], - show: [ - name: "show", - about: "Used for showing information about the rule system", + gen: [ + name: "gen", + about: "system agnostic generation helpers", subcommands: [ - abilities: [ - name: "abilities", - about: "Show the rule systems character abilities", - args: [ - system: [ - value_name: "SYSTEM", - help: "A supported system, e.g. dnd5e", - required: true, - parser: :string - ] - ] - ], - languages: [ - name: "languages", - about: "Show the rule systems languages", - args: [ - system: [ - value_name: "SYSTEM", - help: "A supported system, e.g. dnd5e", - required: true, - parser: :string - ] - ] - ], - metadata: [ - name: "metadata", - about: "Show system metadata", - args: [ - system: [ - value_name: "SYSTEM", - help: "A supported system, e.g. dnd5e", - required: true, - parser: :string - ] - ] - ], - skills: [ - name: "skills", - about: "Show rule system skills", - args: [ - system: [ - value_name: "SYSTEM", - help: "A supported system, e.g. dnd5e", - required: true, - parser: :string - ] - ] + name: [ + name: "name", + about: "Generate a random name" ] ] ] ] - ], - gen: [ - name: "gen", - about: "system agnostic generation helpers", - subcommands: [ - name: [ - name: "name", - about: "Generate a random name" - ] - ] - ] - ] ) case Optimus.parse!(optimus, argv) do @@ -148,7 +136,7 @@ defmodule ExTTRPGDev.CLI do Optimus.parse!(optimus, ["--help"]) {[:roll], parse_result} -> - handle_roll(parse_result) + Roll.handle(parse_result) {[:list_systems], _} -> RuleSystems.list_systems() @@ -171,14 +159,6 @@ defmodule ExTTRPGDev.CLI do end end - def handle_roll(%Optimus.ParseResult{args: %{dice: dice}}) do - dice - |> Dice.multi_roll!() - |> Enum.each(fn {dice_spec, results} -> - IO.inspect(results, label: dice_spec, charlists: :as_lists) - end) - end - def handle_system_subcommands([command | subcommands], %Optimus.ParseResult{ args: %{system: system} }) do diff --git a/lib/cli/roll.ex b/lib/cli/roll.ex new file mode 100644 index 0000000..8722d92 --- /dev/null +++ b/lib/cli/roll.ex @@ -0,0 +1,40 @@ +# credo:disable-for-this-file Credo.Check.Warning.IoInspect +defmodule ExTTRPGDev.CLI.Roll do + @moduledoc """ + Defintions for dealing with the CLI `roll` commond + """ + alias ExTTRPGDev.Dice + alias ExTTRPGDev.CustomParsers + + @doc """ + Command specifications for CLI `roll` command + """ + def commands do + [ + roll: [ + name: "roll", + about: "Roll some dice", + args: [ + dice: [ + value_name: "DICE", + help: + "Dice in the format of xdy wherein x is the number of dice, y is the number of sides the dice should have", + required: true, + parser: &CustomParsers.dice_parser(&1) + ] + ] + ] + ] + end + + @doc """ + Handles CLI `roll` command + """ + def handle(%Optimus.ParseResult{args: %{dice: dice}}) do + dice + |> Dice.multi_roll!() + |> Enum.each(fn {dice_spec, results} -> + IO.inspect(results, label: dice_spec, charlists: :as_lists) + end) + end +end From 72ef83208f2eac8ed836973c6e7d6e0054c6c951 Mon Sep 17 00:00:00 2001 From: Quigley Malcolm Date: Sat, 7 Dec 2024 23:50:37 -0600 Subject: [PATCH 6/8] Move CLI logic for rule systems to ExTTRPGDev.CLI.RuleSystems --- lib/cli.ex | 183 +-------------------------------------- lib/cli/system.ex | 216 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 220 insertions(+), 179 deletions(-) create mode 100644 lib/cli/system.ex diff --git a/lib/cli.ex b/lib/cli.ex index dc6ccb5..edfefd1 100644 --- a/lib/cli.ex +++ b/lib/cli.ex @@ -1,11 +1,7 @@ # credo:disable-for-this-file Credo.Check.Warning.IoInspect defmodule ExTTRPGDev.CLI do - alias ExTTRPGDev.Characters.Character - alias ExTTRPGDev.RuleSystems - alias ExTTRPGDev.RuleSystems.Abilities - alias ExTTRPGDev.RuleSystems.Languages - alias ExTTRPGDev.RuleSystems.Skills alias ExTTRPGDev.CLI.Roll + alias ExTTRPGDev.CLI.RuleSystems @moduledoc """ The CLI for the project @@ -23,101 +19,8 @@ defmodule ExTTRPGDev.CLI do parse_double_dash: true, subcommands: Roll.commands() ++ + RuleSystems.commands() ++ [ - list_systems: [ - name: "list-systems", - about: "List systems that are setup to be used with ExTTRPGDev" - ], - system: [ - name: "system", - about: "Top level command fo systems", - subcommands: [ - gen: [ - name: "gen", - about: "Used for generating things for the system", - subcommands: [ - stat_block: [ - name: "stat-block", - about: "Generate stat blocks for characters of the system", - args: [ - system: [ - value_name: "SYSTEM", - help: "A supported system, e.g. dnd5e", - required: true, - parser: :string - ] - ] - ], - character: [ - name: "character", - about: "Generate characters for system", - args: [ - system: [ - value_name: "SYSTEM", - help: "A supported system, e.g. dnd5e", - required: true, - parser: :string - ] - ] - ] - ] - ], - show: [ - name: "show", - about: "Used for showing information about the rule system", - subcommands: [ - abilities: [ - name: "abilities", - about: "Show the rule systems character abilities", - args: [ - system: [ - value_name: "SYSTEM", - help: "A supported system, e.g. dnd5e", - required: true, - parser: :string - ] - ] - ], - languages: [ - name: "languages", - about: "Show the rule systems languages", - args: [ - system: [ - value_name: "SYSTEM", - help: "A supported system, e.g. dnd5e", - required: true, - parser: :string - ] - ] - ], - metadata: [ - name: "metadata", - about: "Show system metadata", - args: [ - system: [ - value_name: "SYSTEM", - help: "A supported system, e.g. dnd5e", - required: true, - parser: :string - ] - ] - ], - skills: [ - name: "skills", - about: "Show rule system skills", - args: [ - system: [ - value_name: "SYSTEM", - help: "A supported system, e.g. dnd5e", - required: true, - parser: :string - ] - ] - ] - ] - ] - ] - ], gen: [ name: "gen", about: "system agnostic generation helpers", @@ -139,11 +42,10 @@ defmodule ExTTRPGDev.CLI do Roll.handle(parse_result) {[:list_systems], _} -> - RuleSystems.list_systems() - |> IO.inspect(label: "Configured Systems") + RuleSystems.handle_list_systems() {[:system | sub_commands], parse_result} -> - handle_system_subcommands(sub_commands, parse_result) + RuleSystems.handle_system_subcommands(sub_commands, parse_result) {[:gen | sub_commands], _} -> handle_generate_subcommands(sub_commands) @@ -159,87 +61,10 @@ defmodule ExTTRPGDev.CLI do end end - def handle_system_subcommands([command | subcommands], %Optimus.ParseResult{ - args: %{system: system} - }) do - loaded_system = - system - |> RuleSystems.assert_configured!() - |> RuleSystems.load_system!() - - case command do - :gen -> - handle_system_generation_subcommands(subcommands, loaded_system) - - :show -> - handle_system_show_subcommands(subcommands, loaded_system) - end - end - - def handle_system_generation_subcommands( - [command | _subcommands], - %RuleSystems.RuleSystem{} = system - ) do - case command do - :stat_block -> - RuleSystems.RuleSystem.gen_ability_scores_assigned(system) - |> IO.inspect() - - :character -> - character = Character.gen_character!(system) - IO.puts("-- Name: #{character.name}") - - Enum.each(character.ability_scores, fn {ability, scores} -> - IO.puts("#{ability}: #{Enum.sum(scores)}") - end) - end - end - - def handle_system_show_subcommands( - [command | _subcommands], - %RuleSystems.RuleSystem{} = system - ) do - case command do - :abilities -> - show_abilities(system) - - :languages -> - show_languages(system) - - :metadata -> - Map.get(system, :metadata) - |> IO.inspect() - - :skills -> - show_skills(system) - end - end - def handle_generate_subcommands([command | _subcommands]) do case command do :name -> IO.inspect(Faker.Person.name()) end end - - def show_abilities(%RuleSystems.RuleSystem{abilities: %Abilities{specs: specs}}) do - Enum.each(specs, fn %Abilities.Spec{name: name, abbreviation: abbr} -> - IO.puts("(#{abbr}) #{name}") - end) - end - - def show_languages(%RuleSystems.RuleSystem{languages: languages}) do - Enum.each(languages, fn %Languages.Language{name: name, script: script} -> - IO.puts("Name: #{name}, Script: #{script}") - end) - end - - def show_skills(%RuleSystems.RuleSystem{skills: skills} = system) do - Enum.each(skills, fn %Skills.Skill{name: name, modifying_stat: mod_stat} -> - %Abilities.Spec{abbreviation: abbr} = - RuleSystems.RuleSystem.get_spec_by_name(system, mod_stat) - - IO.puts("(#{abbr}) #{name}") - end) - end end diff --git a/lib/cli/system.ex b/lib/cli/system.ex new file mode 100644 index 0000000..adeabd5 --- /dev/null +++ b/lib/cli/system.ex @@ -0,0 +1,216 @@ +# credo:disable-for-this-file Credo.Check.Warning.IoInspect +defmodule ExTTRPGDev.CLI.RuleSystems do + @moduledoc """ + Defintions for dealing with rule system CLI commands + """ + alias ExTTRPGDev.Characters.Character + alias ExTTRPGDev.RuleSystems.Abilities + alias ExTTRPGDev.RuleSystems.Languages + alias ExTTRPGDev.RuleSystems.RuleSystem + alias ExTTRPGDev.RuleSystems.Skills + + @doc """ + Command specifications for rule system CLI commands + """ + def commands do + [ + list_systems: [ + name: "list-systems", + about: "List systems that are setup to be used with ExTTRPGDev" + ], + system: [ + name: "system", + about: "Top level command fo systems", + subcommands: [ + gen: [ + name: "gen", + about: "Used for generating things for the system", + subcommands: [ + stat_block: [ + name: "stat-block", + about: "Generate stat blocks for characters of the system", + args: [ + system: [ + value_name: "SYSTEM", + help: "A supported system, e.g. dnd5e", + required: true, + parser: :string + ] + ] + ], + character: [ + name: "character", + about: "Generate characters for system", + args: [ + system: [ + value_name: "SYSTEM", + help: "A supported system, e.g. dnd5e", + required: true, + parser: :string + ] + ] + ] + ] + ], + show: [ + name: "show", + about: "Used for showing information about the rule system", + subcommands: [ + abilities: [ + name: "abilities", + about: "Show the rule systems character abilities", + args: [ + system: [ + value_name: "SYSTEM", + help: "A supported system, e.g. dnd5e", + required: true, + parser: :string + ] + ] + ], + languages: [ + name: "languages", + about: "Show the rule systems languages", + args: [ + system: [ + value_name: "SYSTEM", + help: "A supported system, e.g. dnd5e", + required: true, + parser: :string + ] + ] + ], + metadata: [ + name: "metadata", + about: "Show system metadata", + args: [ + system: [ + value_name: "SYSTEM", + help: "A supported system, e.g. dnd5e", + required: true, + parser: :string + ] + ] + ], + skills: [ + name: "skills", + about: "Show rule system skills", + args: [ + system: [ + value_name: "SYSTEM", + help: "A supported system, e.g. dnd5e", + required: true, + parser: :string + ] + ] + ] + ] + ] + ] + ] + ] + end + + @doc """ + Handle list-systems CLI command + """ + def handle_list_systems() do + ExTTRPGDev.RuleSystems.list_systems() + |> IO.inspect(label: "Configured Systems") + end + + @doc """ + Handle `system` CLI command and sub commands + """ + def handle_system_subcommands([command | subcommands], %Optimus.ParseResult{ + args: %{system: system} + }) do + loaded_system = + system + |> ExTTRPGDev.RuleSystems.assert_configured!() + |> ExTTRPGDev.RuleSystems.load_system!() + + case command do + :gen -> + handle_system_generation_subcommands(subcommands, loaded_system) + + :show -> + handle_system_show_subcommands(subcommands, loaded_system) + end + end + + @doc """ + Handle generation commands for a rule system + """ + def handle_system_generation_subcommands( + [command | _subcommands], + %RuleSystem{} = system + ) do + case command do + :stat_block -> + RuleSystem.gen_ability_scores_assigned(system) + |> IO.inspect() + + :character -> + character = Character.gen_character!(system) + IO.puts("-- Name: #{character.name}") + + Enum.each(character.ability_scores, fn {ability, scores} -> + IO.puts("#{ability}: #{Enum.sum(scores)}") + end) + end + end + + @doc """ + Hand showing a rule system's components + """ + def handle_system_show_subcommands( + [command | _subcommands], + %RuleSystem{} = system + ) do + case command do + :abilities -> + show_abilities(system) + + :languages -> + show_languages(system) + + :metadata -> + Map.get(system, :metadata) + |> IO.inspect() + + :skills -> + show_skills(system) + end + end + + @doc """ + Show a rule system's abilities + """ + def show_abilities(%RuleSystem{abilities: %Abilities{specs: specs}}) do + Enum.each(specs, fn %Abilities.Spec{name: name, abbreviation: abbr} -> + IO.puts("(#{abbr}) #{name}") + end) + end + + @doc """ + Show a rule system's languages + """ + def show_languages(%RuleSystem{languages: languages}) do + Enum.each(languages, fn %Languages.Language{name: name, script: script} -> + IO.puts("Name: #{name}, Script: #{script}") + end) + end + + @doc """ + Show a rule system's skills + """ + def show_skills(%RuleSystem{skills: skills} = system) do + Enum.each(skills, fn %Skills.Skill{name: name, modifying_stat: mod_stat} -> + %Abilities.Spec{abbreviation: abbr} = + RuleSystem.get_spec_by_name(system, mod_stat) + + IO.puts("(#{abbr}) #{name}") + end) + end +end From 587ca23e548e35d510a65cc9a8c938a6ad3657a4 Mon Sep 17 00:00:00 2001 From: Quigley Malcolm Date: Sun, 8 Dec 2024 00:00:26 -0600 Subject: [PATCH 7/8] Move `generate` CLI command logic to ExTTRPGDev.CLI.Generate --- lib/cli.ex | 23 +++-------------------- lib/cli/generate.ex | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 20 deletions(-) create mode 100644 lib/cli/generate.ex diff --git a/lib/cli.ex b/lib/cli.ex index edfefd1..b718173 100644 --- a/lib/cli.ex +++ b/lib/cli.ex @@ -1,5 +1,6 @@ # credo:disable-for-this-file Credo.Check.Warning.IoInspect defmodule ExTTRPGDev.CLI do + alias ExTTRPGDev.CLI.Generate alias ExTTRPGDev.CLI.Roll alias ExTTRPGDev.CLI.RuleSystems @@ -20,18 +21,7 @@ defmodule ExTTRPGDev.CLI do subcommands: Roll.commands() ++ RuleSystems.commands() ++ - [ - gen: [ - name: "gen", - about: "system agnostic generation helpers", - subcommands: [ - name: [ - name: "name", - about: "Generate a random name" - ] - ] - ] - ] + Generate.commands() ) case Optimus.parse!(optimus, argv) do @@ -48,7 +38,7 @@ defmodule ExTTRPGDev.CLI do RuleSystems.handle_system_subcommands(sub_commands, parse_result) {[:gen | sub_commands], _} -> - handle_generate_subcommands(sub_commands) + Generate.handle_generate_subcommands(sub_commands) {unhandled, _parse_result} -> str_command = @@ -60,11 +50,4 @@ defmodule ExTTRPGDev.CLI do raise "Unhandled CLI command `#{str_command}`, if you are seeing this error please report the issue" end end - - def handle_generate_subcommands([command | _subcommands]) do - case command do - :name -> - IO.inspect(Faker.Person.name()) - end - end end diff --git a/lib/cli/generate.ex b/lib/cli/generate.ex new file mode 100644 index 0000000..14eecb3 --- /dev/null +++ b/lib/cli/generate.ex @@ -0,0 +1,34 @@ +# credo:disable-for-this-file Credo.Check.Warning.IoInspect +defmodule ExTTRPGDev.CLI.Generate do + @moduledoc """ + Definitions for dealing with genenerate CLI commands + """ + + @doc """ + Command specifications for generate commands + """ + def commands do + [ + gen: [ + name: "gen", + about: "system agnostic generation helpers", + subcommands: [ + name: [ + name: "name", + about: "Generate a random name" + ] + ] + ] + ] + end + + @doc """ + Handles generate sub commands + """ + def handle_generate_subcommands([command | _subcommands]) do + case command do + :name -> + IO.inspect(Faker.Person.name()) + end + end +end From 83e02dfc10f6077f0f9ae24f8927e086cea7bb8b Mon Sep 17 00:00:00 2001 From: Quigley Malcolm Date: Sun, 8 Dec 2024 00:03:53 -0600 Subject: [PATCH 8/8] Move CustomParsers to live in the CLI module --- lib/{ => cli}/custom_parsers.ex | 4 ++-- lib/cli/roll.ex | 2 +- test/custom_parsers_test.exs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) rename lib/{ => cli}/custom_parsers.ex (77%) diff --git a/lib/custom_parsers.ex b/lib/cli/custom_parsers.ex similarity index 77% rename from lib/custom_parsers.ex rename to lib/cli/custom_parsers.ex index 08b5e0b..7e2bb23 100644 --- a/lib/custom_parsers.ex +++ b/lib/cli/custom_parsers.ex @@ -1,4 +1,4 @@ -defmodule ExTTRPGDev.CustomParsers do +defmodule ExTTRPGDev.CLI.CustomParsers do @moduledoc """ Custom parsers to be used with Optimus args :parse """ @@ -8,7 +8,7 @@ defmodule ExTTRPGDev.CustomParsers do ## Examples - iex> ExTTRPGDev.CustomParsers.dice_parser("3d4, 1d10,2d20") + iex> ExTTRPGDev.CLI.CustomParsers.dice_parser("3d4, 1d10,2d20") {:ok, ["3d4", "1d10", "2d20"]} """ def dice_parser(arg) when is_bitstring(arg) do diff --git a/lib/cli/roll.ex b/lib/cli/roll.ex index 8722d92..5ee6e60 100644 --- a/lib/cli/roll.ex +++ b/lib/cli/roll.ex @@ -4,7 +4,7 @@ defmodule ExTTRPGDev.CLI.Roll do Defintions for dealing with the CLI `roll` commond """ alias ExTTRPGDev.Dice - alias ExTTRPGDev.CustomParsers + alias ExTTRPGDev.CLI.CustomParsers @doc """ Command specifications for CLI `roll` command diff --git a/test/custom_parsers_test.exs b/test/custom_parsers_test.exs index d16849f..4312f13 100644 --- a/test/custom_parsers_test.exs +++ b/test/custom_parsers_test.exs @@ -1,5 +1,5 @@ -defmodule ExTTRPGDevTest.CustomParsers do +defmodule ExTTRPGDevTest.CLI.CustomParsers do use ExUnit.Case - doctest ExTTRPGDev.CustomParsers + doctest ExTTRPGDev.CLI.CustomParsers end