Clone
defmodule PiDayWeb.MiniGameChannel do
use PiDayWeb, :channel
alias PiDay.Game
@valid_games ~w(pi_memory monte_carlo slice_the_pi pi_trivia projectile_pi)
@impl true
def join("game:mini:" <> game_type, _payload, socket) when game_type in @valid_games do
socket = assign(socket, :game_type, game_type)
{:ok, socket}
end
def join(_, _, _), do: {:error, %{reason: "invalid game"}}
# --- Pi Memory Sprint ---
@impl true
def handle_in("pi_check_digit", %{"position" => pos, "digit" => digit}, socket) do
correct = Game.check_pi_digit(pos, digit)
if correct do
broadcast!(socket, "pi_progress", %{
player_id: socket.assigns.player.id,
name: socket.assigns.player.name,
position: pos + 1
})
end
{:reply, {:ok, %{correct: correct}}, socket}
end
def handle_in("pi_game_over", %{"score" => score}, socket) do
player = socket.assigns.player
Game.record_score(%{
player_id: player.id,
game_type: "pi_memory",
score: score,
metadata: %{digits: score}
})
broadcast!(socket, "pi_score", %{
player_id: player.id,
name: player.name,
score: score
})
{:reply, {:ok, %{recorded: true}}, socket}
end
# --- Monte Carlo Pi ---
def handle_in("mc_submit", %{"estimate" => estimate, "darts" => darts}, socket) do
player = socket.assigns.player
error = abs(estimate - :math.pi())
score = max(0, round(1000 - error * 1000))
Game.record_score(%{
player_id: player.id,
game_type: "monte_carlo",
score: score,
metadata: %{estimate: estimate, darts: darts, error: Float.round(error, 6)}
})
broadcast!(socket, "mc_result", %{
player_id: player.id,
name: player.name,
estimate: estimate,
score: score
})
{:reply, {:ok, %{score: score, error: Float.round(error, 6)}}, socket}
end
# --- Slice the Pi (speed math) ---
def handle_in("slice_get_problem", _payload, socket) do
problem = Game.generate_math_problem()
{:reply, {:ok, problem}, socket}
end
def handle_in("slice_answer", %{"correct" => correct, "time_ms" => time_ms, "streak" => streak}, socket) do
player = socket.assigns.player
points = if correct, do: max(10, 100 - div(time_ms, 100)) + streak * 10, else: 0
if correct do
broadcast!(socket, "slice_correct", %{
player_id: player.id,
name: player.name,
streak: streak
})
end
{:reply, {:ok, %{points: points}}, socket}
end
def handle_in("slice_game_over", %{"score" => score, "correct" => correct, "total" => total}, socket) do
player = socket.assigns.player
Game.record_score(%{
player_id: player.id,
game_type: "slice_the_pi",
score: score,
metadata: %{correct: correct, total: total}
})
broadcast!(socket, "slice_score", %{
player_id: player.id,
name: player.name,
score: score
})
{:reply, {:ok, %{recorded: true}}, socket}
end
# --- Pi Trivia Blitz ---
def handle_in("trivia_get_question", _payload, socket) do
question = Game.get_trivia_question()
{:reply, {:ok, question}, socket}
end
def handle_in("trivia_answer", %{"correct" => correct, "time_ms" => time_ms, "streak" => streak}, socket) do
player = socket.assigns.player
points = if correct, do: max(10, 150 - div(time_ms, 100)) + streak * 15, else: 0
if correct do
broadcast!(socket, "trivia_correct", %{
player_id: player.id,
name: player.name,
streak: streak
})
end
{:reply, {:ok, %{points: points}}, socket}
end
def handle_in("trivia_game_over", %{"score" => score, "correct" => correct, "total" => total}, socket) do
player = socket.assigns.player
Game.record_score(%{
player_id: player.id,
game_type: "pi_trivia",
score: score,
metadata: %{correct: correct, total: total}
})
broadcast!(socket, "trivia_score", %{
player_id: player.id,
name: player.name,
score: score
})
{:reply, {:ok, %{recorded: true}}, socket}
end
# --- Projectile Pi ---
def handle_in("projectile_get_target", _payload, socket) do
target = Game.generate_projectile_target()
{:reply, {:ok, target}, socket}
end
def handle_in("projectile_submit", %{"score" => score, "target_x" => target_x, "best_error" => best_error}, socket) do
player = socket.assigns.player
Game.record_score(%{
player_id: player.id,
game_type: "projectile_pi",
score: score,
metadata: %{target_x: target_x, best_error: best_error}
})
broadcast!(socket, "projectile_score", %{
player_id: player.id,
name: player.name,
score: score
})
{:reply, {:ok, %{recorded: true}}, socket}
end
end