///- --package .

adjacency (test)

test adjacency: prelude
///- --test static --symbol

:< testing
:< sm'_operators
:== meter =
    {
        enabled : bool
        adjacent_ms : mut i32
        hits : mut i32
        last_tick : mut i32
        ms_by_count : array i32
    }

:= empty_counts () : array i32 = ;[ 0i32; 0i32; 0i32; 0i32 ]

:= from_environment () : meter =
    {
        enabled = client::env_is "TIBIA_ARENA_ADJACENCY" "1"
        adjacent_ms = mut 0
        hits = mut 0
        last_tick = mut (0 - 1)
        ms_by_count = empty_counts ()
    }

:= adjacent_live (here : client::spot) (c : client::creature) : bool =
    client::live_monster c && probe::chebyshev (client::creature_spot c) here <= 1

:~ ^ adjacent_from (here : client::spot) (people : client::crowd) (index : i32) (n : i32) : i32 =
    ? index > client::crowd_size people ?> n
    |: adjacent_from here people (index + 1) (? adjacent_live here (client::member people index) ?> n + 1 |: n)

:= adjacent_monsters (here : client::spot) (people : client::crowd) : i32 = adjacent_from here people 1 0

:= joined (text : string) (item : string) : string = ? text = "" ?> item |: text ++# " " ++# item

:= with_position (text : string) (c : client::creature) : string =
    ? client::positioned_monster c ?> joined text (probe::described (client::creature_spot c)) |: text

:~ ^ positions_from (people : client::crowd) (index : i32) (text : string) : string =
    ? index > client::crowd_size people ?> text
    |: positions_from people (index + 1) (with_position text (client::member people index))

:= start_positions (here : client::spot) (people : client::crowd) : string =
    "start positions: knight " ++# probe::described here ++# " monsters " ++# positions_from people 1 ""

:= per_second (adjacent_ms : i32) (hits : i32) : f64 =
    (conv hits : f64) * 1000.0 / (conv (? adjacent_ms > 1 ?> adjacent_ms |: 1) : f64)

:= rate_line (adjacent_ms : i32) (hits : i32) : string =
    := head = "adjacency: " ++#? adjacent_ms ++# " monster-ms adjacent, " ++#? hits ++# " landed hits, "
    head ++# sm'::format_fixed 3 (per_second adjacent_ms hits) ++# " landed hits per adjacent monster-second"

:= count_line (none : i32) (one : i32) (two : i32) (three : i32) : string =
    "adjacent time by count: 0 " ++#? none ++# " 1 " ++#? one ++# " 2 " ++#? two ++# " 3 " ++#? three ++# " ms"

:= hit_line (elapsed : i32) (adjacent : i32) : string =
    "hit at " ++#? elapsed ++# " ms with " ++#? adjacent ++# " adjacent"

:= time_by_count (m : meter) (adjacent : i32) (elapsed : i32) : () =
    := slot = ? adjacent > 3 ?> 3 |: adjacent
    set m::ms_by_count slot (index m::ms_by_count slot + elapsed)

:= tick_counted (m : meter) (elapsed : i32) (here : client::spot) (people : client::crowd) : () =
    := adjacent = adjacent_monsters here people
    probe::stored m::adjacent_ms (*m::adjacent_ms + adjacent * elapsed)
    time_by_count m adjacent elapsed

:= ticked_since (m : meter) (last : i32) (now : i32) (here : client::spot) (people : client::crowd) : () =
    ? last < 0 ?> probe::note (start_positions here people) |: tick_counted m (now - last) here people

:= on_tick (m : meter) (now : i32) (here : client::spot) (people : client::crowd) : () =
    ? m::enabled ?>
        ticked_since m (*m::last_tick) now here people
        probe::stored m::last_tick now

:= hit_noted (elapsed : i32) : () =
    := here = client::player_spot ()
    probe::note (hit_line elapsed (adjacent_monsters here (client::spectators here)))

:= on_text (m : meter) (elapsed : i32) (text : string) : () =
    ? m::enabled && sm'::contains "due to an attack" text ?>
        probe::stored m::hits (*m::hits + 1)
        ? client::player_present () ?> hit_noted elapsed

:= counts_noted (m : meter) : () =
    := none, one, two, three =
        index m::ms_by_count 0, index m::ms_by_count 1, index m::ms_by_count 2, index m::ms_by_count 3
    probe::note (count_line none one two three)

:= on_cleared (m : meter) () : () =
    ? m::enabled ?>
        probe::note (rate_line (*m::adjacent_ms) (*m::hits))
        counts_noted m

rate_line_divides_landed_hits_by_adjacent_seconds (test)

test rate_line_divides_landed_hits_by_adjacent_seconds: passed
///- --test --symbol
///> lua
///> c

rate_line 2000 3
|> _assert_eq "adjacency: 2000 monster-ms adjacent, 3 landed hits, 1.500 landed hits per adjacent monster-second"
__assert_eq { expected = adjacency: 2000 monster-ms adjacent, 3 landed hits, 1.500 landed hits per adjacent monster-second }
lua: unavailable on this machine (`spiral lua --lua-path /tmp/spiral_cells/1793692028694-964/main.lua` was not found)

rate_line_rounds_to_three_decimals (test)

test rate_line_rounds_to_three_decimals: passed
///- --test --symbol
///> lua
///> c

rate_line 3000 2
|> _assert_eq "adjacency: 3000 monster-ms adjacent, 2 landed hits, 0.667 landed hits per adjacent monster-second"
__assert_eq { expected = adjacency: 3000 monster-ms adjacent, 2 landed hits, 0.667 landed hits per adjacent monster-second }
lua: unavailable on this machine (`spiral lua --lua-path /tmp/spiral_cells/1793692028756-7394/main.lua` was not found)

rate_line_is_zero_without_adjacency (test)

test rate_line_is_zero_without_adjacency: passed
///- --test --symbol
///> lua
///> c

rate_line 0 0
|> _assert_eq "adjacency: 0 monster-ms adjacent, 0 landed hits, 0.000 landed hits per adjacent monster-second"
__assert_eq { expected = adjacency: 0 monster-ms adjacent, 0 landed hits, 0.000 landed hits per adjacent monster-second }
lua: unavailable on this machine (`spiral lua --lua-path /tmp/spiral_cells/1793692028806-7426/main.lua` was not found)

count_line_and_hit_line_keep_the_probe_wording (test)

test count_line_and_hit_line_keep_the_probe_wording: passed
///- --test --symbol
///> lua
///> c

count_line 1200 3400 500 0 |> _assert_eq "adjacent time by count: 0 1200 1 3400 2 500 3 0 ms"
hit_line 8125 2 |> _assert_eq "hit at 8125 ms with 2 adjacent"
__assert_eq { expected = adjacent time by count: 0 1200 1 3400 2 500 3 0 ms }
__assert_eq { expected = hit at 8125 ms with 2 adjacent }
lua: unavailable on this machine (`spiral lua --lua-path /tmp/spiral_cells/1793692039534-7554/main.lua` was not found)