///- --package .

scenario (test)

test scenario: prelude
///- --test static --symbol

:< testing
:< sm'_operators

:== order = { name : string; count : i32 }

:| mix =
    | Mix : list order
    | BadOrder : string

:= named_count (name : string) (count : string) : option order =
    ?= convert::try_convert (sm'::trim count) ?|
    | Some n => Some { name = sm'::trim name; count = n }
    | None => None

:= order_of (part : string) : option order =
    := fields = part |> sm'::split ":" |> array
    ? am'::length fields <> 2 ?> None |: named_count (am'::index 0 fields) (am'::index 1 fields)

:~ ^ collected (parts : array string) (i : i32) (orders : list order) : mix =
    ? i < 0 ?> Mix orders
    |:
        := part = am'::index i parts
        ?= order_of part ?|
        | Some o => collected parts (i - 1) (o :: orders)
        | None => BadOrder part

:= mix_of (monster : string) (count : i32) : mix =
    ? sm'::contains ":" monster ?>
        := parts = monster |> sm'::split "," |> array
        collected parts (am'::length parts - 1) []
    |: Mix [ { name = monster; count = count } ]

:= order_entry (radius : i32) (o : order) : string = o::name ++# "," ++#? o::count ++# ",," ++#? radius

:= summon_orders (orders : list order) (radius : i32) : string =
    ?= orders ?|
    | head :: tail => listm::fold (\ text o => text ++# ";" ++# order_entry radius o) (order_entry radius head) tail
    | [] => ""

:= total_count (orders : list order) : i32 = listm::fold (\ total (o : order) => total + o::count) 0 orders

:= camp_orders (m : mix) (radius : i32) : string * i32 =
    ?= m ?|
    | Mix orders => summon_orders orders radius, total_count orders
    | BadOrder part => failwith part

a_single_monster_gives_the_harness_order (test)

test a_single_monster_gives_the_harness_order: passed
///- --test --symbol
///> lua
///> gleam

:= ~radius = 2i32
camp_orders (mix_of "troll" 3) radius |> _assert_eq ("troll,3,,2", 3i32)
__assert_eq { expected = (troll,3,,2, 3) }
lua: unavailable on this machine (`spiral lua --lua-path /tmp/spiral_cells/1793692836616-36/main.lua` was not found)

a_mixed_camp_gives_one_order_per_monster (test)

test a_mixed_camp_gives_one_order_per_monster: passed
///- --test --symbol
///> lua
///> gleam

:= ~radius = 2i32
camp_orders (mix_of "troll:2, cyclops:1" 0) radius |> _assert_eq ("troll,2,,2;cyclops,1,,2", 3i32)
__assert_eq { expected = (troll,2,,2;cyclops,1,,2, 3) }
lua: unavailable on this machine (`spiral lua --lua-path /tmp/spiral_cells/1793692836638-68/main.lua` was not found)

a_count_that_is_not_a_number_names_its_part (test)

test a_count_that_is_not_a_number_names_its_part: passed
///- --test --symbol
///> lua
///> gleam

:= ~monster = "troll:2,cyclops:x"
mix_of monster 0 |> _assert_eq (BadOrder "cyclops:x")
__assert_eq { expected = BadOrder(cyclops:x) }
lua: unavailable on this machine (`spiral lua --lua-path /tmp/spiral_cells/1793692836676-7138/main.lua` was not found)