Fix bug in Markov.Chain where reply_chance would get reset, add regression tests for this

* Markov.Chain.add_weight/4 would return a fresh new markov chain,
  instead of using all of the previous values of the chain that was
  being modified. This would result in resetting the reply_chance value
  to the default of 0.01.
* Add tests to make sure this doesn't happen to add_weights in the
  future.

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2020-07-21 14:58:10 -07:00
parent ec1dd42ca1
commit b1461e24db
2 changed files with 22 additions and 5 deletions

View File

@@ -21,17 +21,17 @@ defmodule Omnibot.Contrib.Markov.Chain do
end) end)
end end
def add_weight(%Chain{chain: chain, order: order}, key, word, increment \\ 1) do def add_weight(chain = %Chain{}, key, word, increment \\ 1) do
if length(key) != order do if length(key) != chain.order do
raise(ArgumentError, message: "invalid key (length #{length(key)} vs. order #{order})") raise(ArgumentError, message: "invalid key (length #{length(key)} vs. order #{chain.order})")
end end
# %{ # %{
# ["word1", "word2"] => %{"target" => weight} # ["word1", "word2"] => %{"target" => weight}
# } # }
chain = Map.update(chain, key, %{word => increment}, chain_map = Map.update(chain.chain, key, %{word => increment},
fn weights -> Map.update(weights, word, increment, &(increment + &1)) end) fn weights -> Map.update(weights, word, increment, &(increment + &1)) end)
%Chain{chain: chain, order: order} %Chain{chain | chain: chain_map}
end end
def generate(chain) do def generate(chain) do

View File

@@ -68,6 +68,23 @@ defmodule MarkovChainTest do
} }
end end
test "chain add_weight does not reset reply_chance" do
chain = %Chain {order: 2, reply_chance: 0.0}
|> Chain.add_weight(["foo", "bar"], "baz")
chain = chain |> Chain.add_weight(["foo", "bar"], "baz", 2)
assert chain.reply_chance == 0.0
chain = chain |> Chain.add_weight(["foo", "bar"], "qux")
assert chain.reply_chance == 0.0
chain = chain |> Chain.add_weight(["bar", "baz"], "qux")
assert chain.reply_chance == 0.0
chain = chain |> Chain.add_weight(["bar", "baz"], nil)
assert chain.reply_chance == 0.0
end
test "chain merge works correctly" do test "chain merge works correctly" do
chain1 = %Chain {order: 2} chain1 = %Chain {order: 2}
|> Chain.add_weight(["foo", "bar"], "baz") |> Chain.add_weight(["foo", "bar"], "baz")