summaryrefslogtreecommitdiff
path: root/lib/lsg_irc/alcolog_plugin.ex
diff options
context:
space:
mode:
authorhref <href@random.sh>2021-09-01 10:30:18 +0200
committerhref <href@random.sh>2021-09-01 10:30:18 +0200
commit75687711f35355bc30e4829439384aab28fcac6d (patch)
tree8f3256f472893c39720a684d390e890a152f7303 /lib/lsg_irc/alcolog_plugin.ex
parentlink: post_* callbacks; html & pdftitle. (diff)
Commit all the changes that hasn't been committed + updates.
Diffstat (limited to 'lib/lsg_irc/alcolog_plugin.ex')
-rw-r--r--lib/lsg_irc/alcolog_plugin.ex358
1 files changed, 245 insertions, 113 deletions
diff --git a/lib/lsg_irc/alcolog_plugin.ex b/lib/lsg_irc/alcolog_plugin.ex
index 600dc1a..c758117 100644
--- a/lib/lsg_irc/alcolog_plugin.ex
+++ b/lib/lsg_irc/alcolog_plugin.ex
@@ -6,6 +6,7 @@ defmodule LSG.IRC.AlcoologPlugin do
* **!santai `<cl | (calc)>` `<degrés d'alcool> [annotation]`**: enregistre un nouveau verre de `montant` d'une boisson à `degrés d'alcool`.
* **!santai `<cl | (calc)>` `<beer name>`**: enregistre un nouveau verre de `cl` de la bière `beer name`, et checkin sur Untappd.com.
+ * **!moar `[cl]` : enregistre un verre équivalent au dernier !santai.
* **-santai**: annule la dernière entrée d'alcoolisme.
* **.alcoolisme**: état du channel en temps réel.
* **.alcoolisme `<semaine | Xj>`**: points par jour, sur X j.
@@ -139,7 +140,7 @@ defmodule LSG.IRC.AlcoologPlugin do
"attention... l'alcool permet de rendre l'eau potable",
"{{'QUOI ?' | bold}}",
"QUO{{'I' | rrepeat}}?",
- "{{'COMMENT ÇA DE L'EAU ?' | red}}",
+ "{{\"COMMENT ÇA DE L'EAU ?\" | red}}",
"resaisis toi et va ouvrir une bonne teille de rouge...",
"bwais tu veux pas un \"petit\" rhum plutôt ?"
]
@@ -163,16 +164,20 @@ defmodule LSG.IRC.AlcoologPlugin do
end
def init(_) do
- {:ok, _} = Registry.register(IRC.PubSub, "account", [])
- {:ok, _} = Registry.register(IRC.PubSub, "trigger:santai", [])
- {:ok, _} = Registry.register(IRC.PubSub, "trigger:santo", [])
- {:ok, _} = Registry.register(IRC.PubSub, "trigger:santeau", [])
- {:ok, _} = Registry.register(IRC.PubSub, "trigger:alcoolog", [])
- {:ok, _} = Registry.register(IRC.PubSub, "trigger:sobre", [])
- {:ok, _} = Registry.register(IRC.PubSub, "trigger:sobrepour", [])
- {:ok, _} = Registry.register(IRC.PubSub, "trigger:soif", [])
- {:ok, _} = Registry.register(IRC.PubSub, "trigger:alcoolisme", [])
- {:ok, _} = Registry.register(IRC.PubSub, "trigger:alcool", [])
+ regopts = [plugin: __MODULE__]
+ {:ok, _} = Registry.register(IRC.PubSub, "account", regopts)
+ {:ok, _} = Registry.register(IRC.PubSub, "trigger:santai", regopts)
+ {:ok, _} = Registry.register(IRC.PubSub, "trigger:moar", regopts)
+ {:ok, _} = Registry.register(IRC.PubSub, "trigger:again", regopts)
+ {:ok, _} = Registry.register(IRC.PubSub, "trigger:bis", regopts)
+ {:ok, _} = Registry.register(IRC.PubSub, "trigger:santo", regopts)
+ {:ok, _} = Registry.register(IRC.PubSub, "trigger:santeau", regopts)
+ {:ok, _} = Registry.register(IRC.PubSub, "trigger:alcoolog", regopts)
+ {:ok, _} = Registry.register(IRC.PubSub, "trigger:sobre", regopts)
+ {:ok, _} = Registry.register(IRC.PubSub, "trigger:sobrepour", regopts)
+ {:ok, _} = Registry.register(IRC.PubSub, "trigger:soif", regopts)
+ {:ok, _} = Registry.register(IRC.PubSub, "trigger:alcoolisme", regopts)
+ {:ok, _} = Registry.register(IRC.PubSub, "trigger:alcool", regopts)
dets_filename = (LSG.data_path() <> "/" <> "alcoolisme.dets") |> String.to_charlist
{:ok, dets} = :dets.open_file(dets_filename, [{:type,:bag}])
ets = :ets.new(__MODULE__.ETS, [:ordered_set, :named_table, :protected, {:read_concurrency, true}])
@@ -182,8 +187,25 @@ defmodule LSG.IRC.AlcoologPlugin do
traverse_fun = fn(obj, dets) ->
case obj do
+ object = {nick, date, volumes, active, cl, deg, name, comment, meta} ->
+ :ets.insert(ets, {{nick, date}, volumes, active, cl, deg, name, comment, meta})
+ dets
object = {nick, date, volumes, active, name, comment} ->
- :ets.insert(ets, {{nick, date}, volumes, active, name, comment})
+ IO.puts("Migrating object #{inspect object}")
+ {cl, deg} = with \
+ %{"cl" => cl, "deg" => deg} <- Regex.named_captures(~r/^(?<cl>\d+[.]\d+)cl\s+(?<deg>\d+[.]\d+)°$/, name),
+ {cl, _} <- Util.float_paparse(cl),
+ {deg, _} <- Util.float_paparse(deg)
+ do
+ {cl, deg}
+ else
+ _ -> {nil, nil}
+ end
+ new = {nick, date, volumes, active, cl, deg, name, comment, Map.new()}
+ :dets.delete_object(dets, obj)
+ :dets.insert(dets, new)
+
+ :ets.insert(ets, {{nick, date}, volumes, active, cl, deg, name, comment, Map.new()})
dets
_ ->
dets
@@ -206,40 +228,40 @@ defmodule LSG.IRC.AlcoologPlugin do
|> Timex.Timezone.convert("Europe/Paris")
apero = format_duration_from_now(%DateTime{now | hour: 18, minute: 0, second: 0}, false)
day_of_week = Date.day_of_week(now)
- txt = cond do
+ {txt, apero?} = cond do
now.hour >= 0 && now.hour < 6 ->
- ["apéro tardif ? Je dis OUI ! SANTAI !"]
+ {["apéro tardif ? Je dis OUI ! SANTAI !"], true}
now.hour >= 6 && now.hour < 12 ->
if day_of_week >= 6 do
- ["C'est quand même un peu tôt non ? Prochain apéro #{apero}"]
+ {["de l'alcool pour le petit dej ? le week-end, pas de problème !"], true}
else
- ["de l'alcool pour le petit dej ? le week-end, pas de problème !"]
+ {["C'est quand même un peu tôt non ? Prochain apéro #{apero}"], false}
end
now.hour >= 12 && (now.hour < 14) ->
- ["oui! c'est l'apéro de midi! (et apéro #{apero})",
+ {["oui! c'est l'apéro de midi! (et apéro #{apero})",
"tu peux attendre #{apero} ou y aller, il est midi !"
- ]
+ ], true}
now.hour == 17 ->
- [
+ {[
"ÇA APPROCHE !!! Apéro #{apero}",
"BIENTÔT !!! Apéro #{apero}",
"achetez vite les teilles, apéro dans #{apero}!",
"préparez les teilles, apéro dans #{apero}!"
- ]
+ ], false}
now.hour >= 14 && now.hour < 18 ->
weekend = if day_of_week >= 6 do
" ... ou maintenant en fait, c'est le week-end!"
else
""
end
- ["tiens bon! apéro #{apero}#{weekend}",
+ {["tiens bon! apéro #{apero}#{weekend}",
"courage... apéro dans #{apero}#{weekend}",
"pas encore :'( apéro dans #{apero}#{weekend}"
- ]
+ ], false}
true ->
- [
+ {[
"C'EST L'HEURE DE L'APÉRO !!! SANTAIIIIIIIIIIII !!!!"
- ]
+ ], true}
end
txt = txt
@@ -248,6 +270,11 @@ defmodule LSG.IRC.AlcoologPlugin do
m.replyfun.(txt)
+ stats = get_full_statistics(state, m.account.id)
+ if !apero? && stats.active > 0.1 do
+ m.replyfun.("(... ou continue en fait, je suis pas ta mère !)")
+ end
+
{:noreply, state}
end
@@ -344,15 +371,58 @@ defmodule LSG.IRC.AlcoologPlugin do
end
def handle_info({:irc, :trigger, "santai", m = %IRC.Message{trigger: %IRC.Trigger{args: [cl, deg | comment], type: :bang}}}, state) do
- comment = if comment == [] do
- nil
- else
- Enum.join(comment, " ")
+ santai(m, state, cl, deg, comment)
+ {:noreply, state}
+ end
+
+ @moar [
+ "{{message.sender.nick}}: la même donc ?",
+ "{{message.sender.nick}}: et voilà la petite sœur !"
+ ]
+
+ def handle_info({:irc, :trigger, "bis", m = %IRC.Message{trigger: %IRC.Trigger{args: args, type: :bang}}}, state) do
+ handle_info({:irc, :trigger, "moar", m}, state)
+ end
+ def handle_info({:irc, :trigger, "again", m = %IRC.Message{trigger: %IRC.Trigger{args: args, type: :bang}}}, state) do
+ handle_info({:irc, :trigger, "moar", m}, state)
+ end
+
+ def handle_info({:irc, :trigger, "moar", m = %IRC.Message{trigger: %IRC.Trigger{args: args, type: :bang}}}, state) do
+ case get_statistics_for_nick(state, m.account.id) do
+ {_, obj = {_, _date, _points, _active, cl, deg, _name, comment, _meta}} ->
+ cl = case args do
+ [cls] ->
+ case Util.float_paparse(cls) do
+ {cl, _} -> cl
+ _ -> cl
+ end
+ _ -> cl
+ end
+ moar = @moar |> Enum.shuffle() |> Enum.random() |> Tmpl.render(m) |> m.replyfun.()
+ santai(m, state, cl, deg, comment, auto_set: true)
+ {_, obj = {_, date, points, _last_active, type, descr}} ->
+ case Regex.named_captures(~r/^(?<cl>\d+[.]\d+)cl\s+(?<deg>\d+[.]\d+)°$/, type) do
+ nil -> m.replyfun.("suce")
+ u ->
+ moar = @moar |> Enum.shuffle() |> Enum.random() |> Tmpl.render(m) |> m.replyfun.()
+ santai(m, state, u["cl"], u["deg"], descr, auto_set: true)
+ end
+ _ -> nil
+ end
+ {:noreply, state}
+ end
+
+ defp santai(m, state, cl, deg, comment, options \\ []) do
+ comment = cond do
+ comment == [] -> nil
+ is_binary(comment) -> comment
+ comment == nil -> nil
+ true -> Enum.join(comment, " ")
end
{cl, cl_extra} = case {Util.float_paparse(cl), cl} do
{{cl, extra}, _} -> {cl, extra}
- {:error, "("<>_} ->
+ {:error, "("<>_} ->
try do
{:ok, result} = Abacus.eval(cl)
{result, nil}
@@ -363,7 +433,7 @@ defmodule LSG.IRC.AlcoologPlugin do
end
{deg, comment, auto_set, beer_id} = case Util.float_paparse(deg) do
- {deg, _} -> {deg, comment, false, nil}
+ {deg, _} -> {deg, comment, Keyword.get(options, :auto_set, false), nil}
:error ->
beername = if(comment, do: "#{deg} #{comment}", else: deg)
case Untappd.search_beer(beername, limit: 1) do
@@ -374,7 +444,6 @@ defmodule LSG.IRC.AlcoologPlugin do
end
end
-
cond do
cl == nil -> m.replyfun.(cl_extra)
deg == nil -> m.replyfun.(comment)
@@ -383,16 +452,20 @@ defmodule LSG.IRC.AlcoologPlugin do
cl < 0 || deg < 0 -> m.replyfun.(Tmpl.render(Enum.random(Enum.shuffle(Map.get(@bad_drinks, :negative))), m))
true ->
points = Alcool.units(cl, deg)
- now = DateTime.to_unix(DateTime.utc_now(), :millisecond)
+ now = m.at || DateTime.utc_now()
+ |> DateTime.to_unix(:millisecond)
user_meta = get_user_meta(state, m.account.id)
name = "#{cl}cl #{deg}°"
old_stats = get_full_statistics(state, m.account.id)
- :ok = :dets.insert(state.dets, {m.account.id, now, points, if(old_stats, do: old_stats.active, else: 0), name, comment})
- true = :ets.insert(state.ets, {{m.account.id, now}, points, if(old_stats, do: old_stats.active, else: 0),name, comment})
+ meta = %{}
+ meta = Map.put(meta, "timestamp", now)
+ meta = Map.put(meta, "weight", user_meta.weight)
+ meta = Map.put(meta, "sex", user_meta.sex)
+ :ok = :dets.insert(state.dets, {m.account.id, now, points, if(old_stats, do: old_stats.active, else: 0), cl, deg, name, comment, meta})
+ true = :ets.insert(state.ets, {{m.account.id, now}, points, if(old_stats, do: old_stats.active, else: 0),cl, deg, name, comment, meta})
sante = @santai |> Enum.map(fn(s) -> String.trim(String.upcase(s)) end) |> Enum.shuffle() |> Enum.random()
- meta = get_user_meta(state, m.account.id)
- k = if meta.sex, do: 0.7, else: 0.6
- weight = meta.weight
+ k = if user_meta.sex, do: 0.7, else: 0.6
+ weight = user_meta.weight
peak = Float.round((10*points||0.0)/(k*weight), 4)
stats = get_full_statistics(state, m.account.id)
sober_add = if old_stats && Map.get(old_stats || %{}, :sober_in) do
@@ -418,12 +491,24 @@ defmodule LSG.IRC.AlcoologPlugin do
""
end
+ since_str = if stats.since && stats.since_min > 180 do
+ "(depuis: #{stats.since_s}) "
+ else
+ ""
+ end
+
msg = fn(nick, extra) ->
- "#{sante} #{nick}#{extra}#{up} #{format_points(points)} @#{stats.active}g/l [+#{peak} g/l]"
- <> " (15m: #{stats.active15m}, 30m: #{stats.active30m}, 1h: #{stats.active1h}) (sobriété #{at} (dans #{stats.sober_in_s})#{sober_add}) !"
+ "#{sante} #{nick} #{extra}#{up} #{format_points(points)} @#{stats.active}g/l [+#{peak} g/l]"
+ <> " (15m: #{stats.active15m}, 30m: #{stats.active30m}, 1h: #{stats.active1h}) #{since_str}(sobriété #{at} (dans #{stats.sober_in_s})#{sober_add}) !"
<> " (aujourd'hui #{stats.daily_volumes} points - #{stats.daily_gl} g/l)"
end
+ meta = if beer_id do
+ Map.put(meta, "untappd:beer_id", beer_id)
+ else
+ meta
+ end
+
if beer_id do
spawn(fn() ->
case Untappd.maybe_checkin(m.account, beer_id) do
@@ -434,7 +519,7 @@ defmodule LSG.IRC.AlcoologPlugin do
|> Enum.filter(fn(b) -> b end)
|> Enum.intersperse(", ")
|> Enum.join("")
- badge = if(badges > 1, do: "badges", else: "badge")
+ badge = if(length(badges) > 1, do: "badges", else: "badge")
m.replyfun.("\\O/ Unlocked untappd #{badge}: #{badges_s}")
end
:ok
@@ -445,7 +530,15 @@ defmodule LSG.IRC.AlcoologPlugin do
end)
end
- local_extra = if auto_set, do: " #{comment} (#{deg}°)", else: ""
+ local_extra = if auto_set do
+ if comment do
+ " #{comment} (#{cl}cl @ #{deg}°)"
+ else
+ "#{cl}cl @ #{deg}°"
+ end
+ else
+ ""
+ end
m.replyfun.(msg.(m.sender.nick, local_extra))
notify = IRC.Membership.notify_channels(m.account) -- [{m.network,m.channel}]
for {net, chan} <- notify do
@@ -456,6 +549,7 @@ defmodule LSG.IRC.AlcoologPlugin do
end
miss = cond do
+ points <= 0.6 -> :blague
stats.active30m >= 2.9 && stats.active30m < 3 -> :miss3
stats.active30m >= 1.9 && stats.active30m < 2 -> :miss2
stats.active30m >= 0.9 && stats.active30m < 1 -> :miss1
@@ -471,6 +565,9 @@ defmodule LSG.IRC.AlcoologPlugin do
end
miss = case miss do
+ :blague -> [
+ "c'est une blague ?!"
+ ]
:miss025 -> [
"si peu ?"
]
@@ -518,7 +615,6 @@ defmodule LSG.IRC.AlcoologPlugin do
end
end
- {:noreply, state}
end
def handle_info({:irc, :trigger, "santai", m = %IRC.Message{trigger: %IRC.Trigger{args: _, type: :bang}}}, state) do
@@ -549,13 +645,26 @@ defmodule LSG.IRC.AlcoologPlugin do
|> Enum.sort_by(fn({_, status}) -> status.active end, &>/2)
end
+ @spec since() :: %{IRC.Account.id() => DateTime.t()}
+ @doc "Returns the last time the user was at 0 g/l"
+ def since() do
+ :ets.foldr(fn({{acct, timestamp}, _vol, current, _cl, _deg, _name, _comment, _m}, acc) ->
+ if !Map.get(acc, acct) && current == 0 do
+ date = DateTime.from_unix!(timestamp, :millisecond)
+ Map.put(acc, acct, date)
+ else
+ acc
+ end
+ end, %{}, __MODULE__.ETS)
+ end
+
def get_full_statistics(nick) do
get_full_statistics(data_state(), nick)
end
defp get_full_statistics(state, nick) do
case get_statistics_for_nick(state, nick) do
- {count, {_, last_at, last_points, last_active, last_type, last_descr}} ->
+ {count, {_, last_at, last_points, last_active, last_cl, last_deg, last_type, last_descr, _meta}} ->
{active, active_drinks} = current_alcohol_level(state, nick)
{_, m30} = alcohol_level_rising(state, nick)
{rising, m15} = alcohol_level_rising(state, nick, 15)
@@ -601,20 +710,30 @@ defmodule LSG.IRC.AlcoologPlugin do
nil
end
+ since = if active > 0 do
+ since()
+ |> Map.get(nick)
+ end
+
+ since_diff = if since, do: Timex.diff(DateTime.utc_now(), since, :minutes)
+ since_duration = if since, do: Timex.Duration.from_minutes(since_diff)
+ since_s = if since, do: Timex.Format.Duration.Formatter.lformat(since_duration, "fr", :humanized)
+
user_status = list
|> Enum.shuffle()
|> Enum.random()
{total_volumes, total_gl} = user_stats(state, nick)
- %{active: active, last_at: last_at, last_points: last_points, last_type: last_type, last_descr: last_descr,
+ %{active: active, last_at: last_at, last_cl: last_cl, last_deg: last_deg, last_points: last_points, last_type: last_type, last_descr: last_descr,
trend_symbol: trend,
active5m: m5, active15m: m15, active30m: m30, active1h: h1,
rising: rising,
active_drinks: active_drinks,
user_status: user_status,
daily_gl: total_gl, daily_volumes: total_volumes,
- sober_in: minutes_til_sober, sober_in_s: sober_in_s
+ sober_in: minutes_til_sober, sober_in_s: sober_in_s,
+ since: since, since_min: since_diff, since_s: since_s,
}
_ ->
nil
@@ -660,7 +779,7 @@ defmodule LSG.IRC.AlcoologPlugin do
if account do
user = IRC.UserTrack.find_by_account(m.network, account)
nick = if(user, do: user.nick, else: account.name)
- stats = get_full_statistics(state, nick)
+ stats = get_full_statistics(state, account.id)
if stats && stats.sober_in > 0 do
now = DateTime.utc_now()
sober = now |> DateTime.add(round(stats.sober_in*60), :second)
@@ -693,7 +812,12 @@ defmodule LSG.IRC.AlcoologPlugin do
else
status.trend_symbol
end
- "#{nick} #{status.user_status} #{trend_symbol} #{Float.round(status.active, 4)} g/l"
+ since_str = if status.since_min > 180 do
+ "depuis: #{status.since_s} | "
+ else
+ ""
+ end
+ "#{nick} #{status.user_status} #{trend_symbol} #{Float.round(status.active, 4)} g/l [#{since_str}sobre dans: #{status.sober_in_s}]"
end)
|> Enum.intersperse(", ")
|> Enum.join("")
@@ -732,54 +856,43 @@ defmodule LSG.IRC.AlcoologPlugin do
{:noreply, state}
end
- # TODO Fix with user/channel membership
- def handle_info({:irc, :trigger, "alcoolisme", m = %IRC.Message{trigger: %IRC.Trigger{args: ["semaine"], type: :bang}}}, state) do
- aday = 7*((24 * 60)*60)
- now = DateTime.utc_now()
- before = now
- |> DateTime.add(-aday, :second)
- |> DateTime.to_unix(:millisecond)
- over_time_stats(before, 7, m, state)
- end
-
- def handle_info({:irc, :trigger, "alcoolisme", m = %IRC.Message{trigger: %IRC.Trigger{args: ["30j"], type: :bang}}}, state) do
- aday = 31*((24 * 60)*60)
- now = DateTime.utc_now()
- before = now
- |> DateTime.add(-aday, :second)
- |> DateTime.to_unix(:millisecond)
- over_time_stats(before, 30, m, state)
+ def user_over_time(account, count) do
+ user_over_time(data_state(), account, count)
end
- def handle_info({:irc, :trigger, "alcoolisme", m = %IRC.Message{trigger: %IRC.Trigger{args: ["90j"], type: :bang}}}, state) do
- aday = 91*((24 * 60)*60)
- now = DateTime.utc_now()
- before = now
- |> DateTime.add(-aday, :second)
- |> DateTime.to_unix(:millisecond)
- over_time_stats(before, 90, m, state)
- end
-
- def handle_info({:irc, :trigger, "alcoolisme", m = %IRC.Message{trigger: %IRC.Trigger{args: ["180j"], type: :bang}}}, state) do
- aday = 180*((24 * 60)*60)
+ def user_over_time(state, account, count) do
+ delay = count*((24 * 60)*60)
now = DateTime.utc_now()
- before = now
- |> DateTime.add(-aday, :second)
+ before = DateTime.utc_now()
+ |> DateTime.shift_zone!("Europe/Paris", Tzdata.TimeZoneDatabase)
+ |> DateTime.add(-delay, :second, Tzdata.TimeZoneDatabase)
|> DateTime.to_unix(:millisecond)
- over_time_stats(before, 180, m, state)
- end
+ #[
+# {{{:"$1", :"$2"}, :_, :_, :_, :_, :_, :_, :_},
+# [{:andalso, {:==, :"$1", :"$1"}, {:<, :"$2", {:const, 3000}}}], [:lol]}
+ #]
+ match = [{{{:"$1", :"$2"}, :_, :_, :_, :_, :_, :_, :_},
+ [{:andalso, {:>, :"$2", {:const, before}}, {:==, :"$1", {:const, account.id}}}], [:"$_"]}
+ ]
+ :ets.select(state.ets, match)
+ |> Enum.reduce(Map.new, fn({{_, ts}, vol, _, _, _, _, _, _}, acc) ->
+ date = DateTime.from_unix!(ts, :millisecond)
+ |> DateTime.shift_zone!("Europe/Paris", Tzdata.TimeZoneDatabase)
+ date = if date.hour <= 8 do
+ DateTime.add(date, -(60*(60*(date.hour+1))), :second, Tzdata.TimeZoneDatabase)
+ else
+ date
+ end
+ |> DateTime.to_date()
- def handle_info({:irc, :trigger, "alcoolisme", m = %IRC.Message{trigger: %IRC.Trigger{args: ["365j"], type: :bang}}}, state) do
- aday = 365*((24 * 60)*60)
- now = DateTime.utc_now()
- before = now
- |> DateTime.add(-aday, :second)
- |> DateTime.to_unix(:millisecond)
- over_time_stats(before, 365, m, state)
+ Map.put(acc, date, Map.get(acc, date, 0) + vol)
+ end)
end
- defp user_over_time(state, account, count) do
+ def user_over_time_gl(account, count) do
+ state = data_state()
+ meta = get_user_meta(state, account.id)
delay = count*((24 * 60)*60)
now = DateTime.utc_now()
before = DateTime.utc_now()
@@ -787,14 +900,14 @@ defmodule LSG.IRC.AlcoologPlugin do
|> DateTime.add(-delay, :second, Tzdata.TimeZoneDatabase)
|> DateTime.to_unix(:millisecond)
#[
-# {{{:"$1", :"$2"}, :_, :_, :_, :_},
+# {{{:"$1", :"$2"}, :_, :_, :_, :_, :_, :_, :_},
# [{:andalso, {:==, :"$1", :"$1"}, {:<, :"$2", {:const, 3000}}}], [:lol]}
#]
- match = [{{{:"$1", :"$2"}, :_, :_, :_, :_},
+ match = [{{{:"$1", :"$2"}, :_, :_, :_, :_, :_, :_, :_},
[{:andalso, {:>, :"$2", {:const, before}}, {:==, :"$1", {:const, account.id}}}], [:"$_"]}
]
:ets.select(state.ets, match)
- |> Enum.reduce(Map.new, fn({{_, ts}, vol, _, _, _}, acc) ->
+ |> Enum.reduce(Map.new, fn({{_, ts}, vol, _, _, _, _, _, _}, acc) ->
date = DateTime.from_unix!(ts, :millisecond)
|> DateTime.shift_zone!("Europe/Paris", Tzdata.TimeZoneDatabase)
@@ -804,23 +917,28 @@ defmodule LSG.IRC.AlcoologPlugin do
date
end
|> DateTime.to_date()
+ weight = meta.weight
+ k = if meta.sex, do: 0.7, else: 0.6
+ gl = (10*vol)/(k*weight)
- Map.put(acc, date, Map.get(acc, date, 0) + vol)
+ Map.put(acc, date, Map.get(acc, date, 0) + gl)
end)
end
+
+
defp over_time_stats(before, j, m, state) do
- #match = :ets.fun2ms(fn(obj = {{^nick, date}, _, _, _, _}) when date > before -> obj end)
- match = [{{{:_, :"$1"}, :_, :_, :_, :_},
+ #match = :ets.fun2ms(fn(obj = {{^nick, date}, _, _, _, _, _, _, _}) when date > before -> obj end)
+ match = [{{{:_, :"$1"}, :_, :_, :_, :_, :_, :_, :_},
[{:>, :"$1", {:const, before}}], [:"$_"]}
]
# tuple ets: {{nick, date}, volumes, current, nom, commentaire}
members = IRC.Membership.members_or_friends(m.account, m.network, m.channel)
drinks = :ets.select(state.ets, match)
- |> Enum.filter(fn({{account, _}, _, _, _, _}) -> Enum.member?(members, account) end)
- |> Enum.sort_by(fn({{_, ts}, _, _, _, _}) -> ts end, &>/2)
+ |> Enum.filter(fn({{account, _}, _, _, _, _, _, _, _}) -> Enum.member?(members, account) end)
+ |> Enum.sort_by(fn({{_, ts}, _, _, _, _, _, _, _}) -> ts end, &>/2)
- top = Enum.reduce(drinks, %{}, fn({{nick, _}, vol, _, _, _}, acc) ->
+ top = Enum.reduce(drinks, %{}, fn({{nick, _}, vol, _, _, _, _, _, _}, acc) ->
all = Map.get(acc, nick, 0)
Map.put(acc, nick, all + vol)
end)
@@ -872,7 +990,7 @@ defmodule LSG.IRC.AlcoologPlugin do
meta = Map.merge(@default_user_meta, %{sex: h, weight: weight, loss_factor: factor})
put_user_meta(state, m.account.id, meta)
fat = ["t'as grossi...", "bientôt la tonne ?", "t'as encore abusé du fromage ?"]
- thin = ["en route vers l'anorexie ?", "t'as grossi...", "faut manger plus de fromage!"]
+ thin = ["en route vers l'anorexie ?", "t'as vomi...", "t'as grossi...", "faut manger plus de fromage!"]
msg = cond do
old_meta.weight < meta.weight -> Enum.random(Enum.shuffle(fat))
old_meta.weight == meta.weight -> "ok"
@@ -886,7 +1004,7 @@ defmodule LSG.IRC.AlcoologPlugin do
def handle_info({:irc, :trigger, "santai", m = %IRC.Message{trigger: %IRC.Trigger{args: args, type: :minus}}}, state) do
case get_statistics_for_nick(state, m.account.id) do
- {_, obj = {_, date, points, _last_active, type, descr}} ->
+ {_, obj = {_, date, points, _last_active, _cl, _deg, type, descr, _meta}} ->
:dets.delete_object(state.dets, obj)
:ets.delete(state.ets, {m.account.id, date})
m.replyfun.("supprimé: #{m.sender.nick} #{points} #{type} #{descr}")
@@ -903,6 +1021,7 @@ defmodule LSG.IRC.AlcoologPlugin do
end
end
+
def handle_info({:irc, :trigger, "alcoolisme", m = %IRC.Message{trigger: %IRC.Trigger{args: args, type: :bang}}}, state) do
{account, duration} = case args do
[nick | rest] -> {IRC.Account.find_always_by_nick(m.network, m.channel, nick), rest}
@@ -951,6 +1070,7 @@ defmodule LSG.IRC.AlcoologPlugin do
<> (if stats.active > 0 || stats.active15m > 0 || stats.active30m > 0 || stats.active1h > 0, do: ": #{trend_symbol} #{Float.round(stats.active, 4)}g/l ", else: "")
<> (if stats.active30m > 0 || stats.active1h > 0, do: "(15m: #{stats.active15m}, 30m: #{stats.active30m}, 1h: #{stats.active1h}) ", else: "")
<> (if stats.sober_in > 0, do: "— Sobre dans #{stats.sober_in_s} ", else: "")
+ <> (if stats.since && stats.since_min > 180, do: "— Paitai depuis #{stats.since_s} ", else: "")
<> "— Dernier verre: #{present_type(stats.last_type, stats.last_descr)} [#{Float.round(stats.last_points+0.0, 4)}] "
<> "#{format_duration_from_now(stats.last_at)} "
<> (if stats.daily_volumes > 0, do: "— Aujourd'hui: #{stats.daily_volumes} #{stats.daily_gl}g/l", else: "")
@@ -969,7 +1089,7 @@ defmodule LSG.IRC.AlcoologPlugin do
# Account merge
def handle_info({:account_change, old_id, new_id}, state) do
- spec = [{{:"$1", :_, :_, :_, :_, :_}, [{:==, :"$1", {:const, old_id}}], [:"$_"]}]
+ spec = [{{:"$1", :_, :_, :_, :_, :_, :_, :_, :_}, [{:==, :"$1", {:const, old_id}}], [:"$_"]}]
Util.ets_mutate_select_each(:dets, state.dets, spec, fn(table, obj) ->
Logger.debug("alcolog/account_change:: merging #{old_id} -> #{new_id}")
rename_object_owner(table, state.ets, obj, old_id, new_id)
@@ -991,11 +1111,11 @@ defmodule LSG.IRC.AlcoologPlugin do
end
end
- defp rename_object_owner(table, ets, object = {old_id, date, volume, current, name, comment}, old_id, new_id) do
+ defp rename_object_owner(table, ets, object = {old_id, date, volume, current, cl, deg, name, comment, meta}, old_id, new_id) do
:dets.delete_object(table, object)
:ets.delete(ets, {old_id, date})
- :dets.insert(table, {new_id, date, volume, current, name, comment})
- :ets.insert(ets, {{new_id, date}, volume, current, name, comment})
+ :dets.insert(table, {new_id, date, volume, current, cl, deg, name, comment, meta})
+ :ets.insert(ets, {{new_id, date}, volume, current, cl, deg, name, comment, meta})
end
# Account: move from nick to account id
@@ -1005,9 +1125,9 @@ defmodule LSG.IRC.AlcoologPlugin do
mapping = Enum.reduce(accounts, Map.new, fn({:account, _net, _chan, nick, account_id}, acc) ->
Map.put(acc, String.downcase(nick), account_id)
end)
- spec = [{{:"$1", :_, :_, :_, :_, :_}, [], [:"$_"]}]
+ spec = [{{:"$1", :_, :_, :_, :_, :_, :_, :_, :_}, [], [:"$_"]}]
Logger.debug("accounts:: mappings #{inspect mapping}")
- Util.ets_mutate_select_each(:dets, state.dets, spec, fn(table, obj = {nick, _date, _vol, _cur, _name, _comment}) ->
+ Util.ets_mutate_select_each(:dets, state.dets, spec, fn(table, obj = {nick, _date, _vol, _cur, _cl, _deg, _name, _comment, _meta}) ->
#Logger.debug("accounts:: item #{inspect(obj)}")
if new_id = Map.get(mapping, nick) do
Logger.debug("alcolog/accounts:: merging #{nick} -> #{new_id}")
@@ -1019,7 +1139,7 @@ defmodule LSG.IRC.AlcoologPlugin do
def handle_info({:account, _net, _chan, nick, account_id}, state) do
nick = String.downcase(nick)
- spec = [{{:"$1", :_, :_, :_, :_, :_}, [{:==, :"$1", {:const, nick}}], [:"$_"]}]
+ spec = [{{:"$1", :_, :_, :_, :_, :_, :_, :_, :_}, [{:==, :"$1", {:const, nick}}], [:"$_"]}]
Util.ets_mutate_select_each(:dets, state.dets, spec, fn(table, obj) ->
Logger.debug("alcoolog/account:: merging #{nick} -> #{account_id}")
rename_object_owner(table, state.ets, obj, nick, account_id)
@@ -1039,10 +1159,19 @@ defmodule LSG.IRC.AlcoologPlugin do
{:noreply, state}
end
+ def nick_history(account) do
+ spec = [
+ {{{:"$1", :_}, :_, :_, :_, :_, :_, :_, :_},
+ [{:==, :"$1", {:const, account.id}}],
+ [:"$_"]}
+ ]
+ :ets.select(data_state().ets, spec)
+ end
+
defp get_statistics_for_nick(state, account_id) do
qvc = :dets.lookup(state.dets, account_id)
- |> Enum.sort_by(fn({_, ts, _, _, _, _}) -> ts end, &</2)
- count = Enum.reduce(qvc, 0, fn({_nick, _ts, points, _active, _type, _descr}, acc) -> acc + (points||0) end)
+ |> Enum.sort_by(fn({_, ts, _, _, _, _, _, _, _}) -> ts end, &</2)
+ count = Enum.reduce(qvc, 0, fn({_nick, _ts, points, _active, _cl, _deg, _type, _descr, _meta}, acc) -> acc + (points||0) end)
last = List.last(qvc) || nil
{count, last}
end
@@ -1102,6 +1231,10 @@ defmodule LSG.IRC.AlcoologPlugin do
# stop folding when ?
#
+ def user_stats(account) do
+ user_stats(data_state(), account.id)
+ end
+
defp user_stats(state = %{ets: ets}, account_id) do
meta = get_user_meta(state, account_id)
aday = (10 * 60)*60
@@ -1111,7 +1244,7 @@ defmodule LSG.IRC.AlcoologPlugin do
|> DateTime.to_unix(:millisecond)
#match = :ets.fun2ms(fn(obj = {{^nick, date}, _, _, _, _}) when date > before -> obj end)
match = [
- {{{:"$1", :"$2"}, :_, :_, :_, :_},
+ {{{:"$1", :"$2"}, :_, :_, :_, :_, :_, :_, :_},
[
{:>, :"$2", {:const, before}},
{:"=:=", {:const, account_id}, :"$1"}
@@ -1120,7 +1253,7 @@ defmodule LSG.IRC.AlcoologPlugin do
# tuple ets: {{nick, date}, volumes, current, nom, commentaire}
drinks = :ets.select(ets, match)
# {date, single_peak}
- total_volume = Enum.reduce(drinks, 0.0, fn({{_, date}, volume, _, _, _}, acc) ->
+ total_volume = Enum.reduce(drinks, 0.0, fn({{_, date}, volume, _, _, _, _, _, _}, acc) ->
acc + volume
end)
k = if meta.sex, do: 0.7, else: 0.6
@@ -1155,7 +1288,7 @@ defmodule LSG.IRC.AlcoologPlugin do
|> DateTime.to_unix(:millisecond)
#match = :ets.fun2ms(fn(obj = {{^nick, date}, _, _, _, _}) when date > before -> obj end)
match = [
- {{{:"$1", :"$2"}, :_, :_, :_, :_},
+ {{{:"$1", :"$2"}, :_, :_, :_, :_, :_, :_, :_},
[
{:>, :"$2", {:const, before}},
{:"=:=", {:const, account_id}, :"$1"}
@@ -1163,9 +1296,9 @@ defmodule LSG.IRC.AlcoologPlugin do
]
# tuple ets: {{nick, date}, volumes, current, nom, commentaire}
drinks = :ets.select(ets, match)
- |> Enum.sort_by(fn({{_, date}, _, _, _, _}) -> date end, &</2)
+ |> Enum.sort_by(fn({{_, date}, _, _, _, _, _, _, _}) -> date end, &</2)
# {date, single_peak}
- {all, last_drink_at, gl, active_drinks} = Enum.reduce(drinks, {0.0, nil, [], 0}, fn({{_, date}, volume, _, _, _}, {all, last_at, acc, active_drinks}) ->
+ {all, last_drink_at, gl, active_drinks} = Enum.reduce(drinks, {0.0, nil, [], 0}, fn({{_, date}, volume, _, _, _, _, _, _}, {all, last_at, acc, active_drinks}) ->
k = if meta.sex, do: 0.7, else: 0.6
weight = meta.weight
peak = (10*volume)/(k*weight)
@@ -1249,4 +1382,3 @@ defmodule LSG.IRC.AlcoologPlugin do
end
end
-