Add reply_chance to markov chains and markov commands
Every time a user sends a message, there is now a chance that markov will reply with a random message based on what they said. !markov chance allows lookups and setting of the chance that a user may receive a message. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -3,7 +3,7 @@ defmodule Omnibot.Contrib.Markov.Chain do
|
|||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
@enforce_keys [:order]
|
@enforce_keys [:order]
|
||||||
defstruct order: 2, chain: %{}
|
defstruct order: 2, chain: %{}, reply_chance: 0.01
|
||||||
|
|
||||||
def train(chain, line) when is_binary(line) do
|
def train(chain, line) when is_binary(line) do
|
||||||
train(chain, line |> String.split(~r/\s+/))
|
train(chain, line |> String.split(~r/\s+/))
|
||||||
|
|||||||
@@ -51,6 +51,14 @@ defmodule Omnibot.Contrib.Markov.ChainServer do
|
|||||||
GenServer.call(server, :chain_sum)
|
GenServer.call(server, :chain_sum)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def reply_chance(server) do
|
||||||
|
GenServer.call(server, :reply_chance)
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_reply_chance(server, chance) do
|
||||||
|
GenServer.cast(server, {:set_reply_chance, chance})
|
||||||
|
end
|
||||||
|
|
||||||
## Server callbacks
|
## Server callbacks
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
@@ -122,4 +130,14 @@ defmodule Omnibot.Contrib.Markov.ChainServer do
|
|||||||
def handle_call(:chain_sum, _from, state = {chain, _channel, _user}) do
|
def handle_call(:chain_sum, _from, state = {chain, _channel, _user}) do
|
||||||
{:reply, Markov.Chain.chain_sum(chain), state}
|
{:reply, Markov.Chain.chain_sum(chain), state}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def handle_call(:reply_chance, _from, state = {chain, _channel, _user}) do
|
||||||
|
{:reply, chain.reply_chance, state}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def handle_cast({:set_reply_chance, chance}, {chain, channel, user}) when is_float(chance) or chance == 0 do
|
||||||
|
{:noreply, {%Markov.Chain{chain | reply_chance: chance}, channel, user}}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ defmodule Omnibot.Contrib.Markov do
|
|||||||
alias Omnibot.{Contrib.Markov.ChainServer, Util}
|
alias Omnibot.{Contrib.Markov.ChainServer, Util}
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
@default_config save_dir: "markov", order: 2, save_every: 5 * 60, ignore: []
|
@default_config save_dir: "markov", order: 2, save_every: 5 * 60, ignore: [], max_reply_chance: 0.01
|
||||||
|
|
||||||
@registry __MODULE__.Registry
|
@registry __MODULE__.Registry
|
||||||
@supervisor __MODULE__.ChainSupervisor
|
@supervisor __MODULE__.ChainSupervisor
|
||||||
@@ -22,18 +22,20 @@ defmodule Omnibot.Contrib.Markov do
|
|||||||
end
|
end
|
||||||
|
|
||||||
command "!markov", ["force"] do
|
command "!markov", ["force"] do
|
||||||
reply = chain_server(channel, nick) |> ChainServer.generate()
|
do_markov_message(irc, channel, nick, nick)
|
||||||
Irc.send_to(irc, channel, "#{nick}: #{reply}")
|
end
|
||||||
|
|
||||||
|
# !markov emulate <name>, except it's !markov force <name>
|
||||||
|
command "!markov", ["force", emulate] do
|
||||||
|
do_markov_message(irc, channel, nick, emulate)
|
||||||
end
|
end
|
||||||
|
|
||||||
command "!markov", ["emulate", emulate] do
|
command "!markov", ["emulate", emulate] do
|
||||||
reply = chain_server(channel, emulate) |> ChainServer.generate()
|
do_markov_message(irc, channel, nick, emulate)
|
||||||
Irc.send_to(irc, channel, "#{nick}: #{reply}")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
command "!markov", ["all"] do
|
command "!markov", ["all"] do
|
||||||
reply = chain_server(channel, :all) |> ChainServer.generate()
|
do_markov_message(irc, channel, nick, :all)
|
||||||
Irc.send_to(irc, channel, "#{nick}: #{reply}")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
command "!markov", ["status"] do
|
command "!markov", ["status"] do
|
||||||
@@ -43,6 +45,23 @@ defmodule Omnibot.Contrib.Markov do
|
|||||||
Irc.send_to(irc, channel, "#{nick}: You are worth #{ratio |> Float.round(4)}% of the channel")
|
Irc.send_to(irc, channel, "#{nick}: You are worth #{ratio |> Float.round(4)}% of the channel")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
command "!markov", ["chance"] do
|
||||||
|
chance = reply_chance(channel, nick)
|
||||||
|
Irc.send_to(irc, channel, "#{nick}: Your reply chance is #{chance}")
|
||||||
|
end
|
||||||
|
|
||||||
|
command "!markov", ["chance", chance] do
|
||||||
|
{chance, ""} = Float.parse(chance)
|
||||||
|
chance = min(chance, cfg()[:max_reply_chance]) |> max(0)
|
||||||
|
chain_server(channel, nick) |> ChainServer.set_reply_chance(chance)
|
||||||
|
Irc.send_to(irc, channel, "#{nick}: Your reply chance is now #{chance}")
|
||||||
|
end
|
||||||
|
|
||||||
|
defp do_markov_message(irc, channel, sender, user) do
|
||||||
|
reply = chain_server(channel, user) |> ChainServer.generate()
|
||||||
|
Irc.send_to(irc, channel, "#{sender}: #{reply}")
|
||||||
|
end
|
||||||
|
|
||||||
def save_dir() do
|
def save_dir() do
|
||||||
cfg()[:save_dir]
|
cfg()[:save_dir]
|
||||||
end
|
end
|
||||||
@@ -88,13 +107,22 @@ defmodule Omnibot.Contrib.Markov do
|
|||||||
Logger.info("Saved markov chains in #{stop - start} seconds")
|
Logger.info("Saved markov chains in #{stop - start} seconds")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp reply_chance(channel, user) do
|
||||||
|
chain_server(channel, user) |> ChainServer.reply_chance()
|
||||||
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def on_channel_msg(_irc, channel, nick, msg) do
|
def on_channel_msg(irc, channel, nick, msg) do
|
||||||
# self-messages are already ignored, so just check the configured ignore-list
|
# self-messages are already ignored, so just check the configured ignore-list
|
||||||
filter = nick in cfg()[:ignore]
|
filter = nick in cfg()[:ignore]
|
||||||
|| (String.trim(msg) |> String.starts_with?("!"))
|
|| (String.trim(msg) |> String.starts_with?("!"))
|
||||||
if !filter do
|
if !filter do
|
||||||
train(channel, nick, msg)
|
train(channel, nick, msg)
|
||||||
|
|
||||||
|
# Maybe send user a message
|
||||||
|
if IO.inspect(:rand.uniform()) < IO.inspect(reply_chance(channel, nick)) do
|
||||||
|
do_markov_message(irc, channel, nick, nick)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user