Thanks for the reply. So this is kinda where I keep banging my head against the wall. I’ve read all of these and followed the examples and just cannot seem to get anything to register or make that connection. My GenServer is a process that I start via a module by calling start_link(), and that GenServer does the countdown. I did make it to the PubSub direction too (out of desperation) and ran into similar issues, which always seems to be I cannot get handle_info callback to receive anything. I have a handle_info() in my module (LiveComponent) but am not even sure if that is a thing (is that only for GenServer). I’m pretty sure I just read a whole thing stating that it wasn’t, but not sure anymore
I can seem to get process to process working, GenServer to process okay, but just the LiveComponent and the socket is escaping me.
defmodule SurfaceApp.Game.TimerServer do
use GenServer
require Kernel
alias SurfaceAppWeb.Components.{McCard, Timer}
alias Phoenix.PubSub
# alias ExTyperacer.Logic.{Game, Player}
@impl true
def start_link() do
GenServer.start_link(__MODULE__, %{})
end
@impl true
def init(state) do
IO.puts "Init timer"
counter = 15
uuid = "1111"
timer = Process.send_after(self(), {:work, counter, uuid}, 1_000)
{:ok, state}
end
@impl true
def handle_call({:reset_timer, counter, uuid}, _from, %{timer: timer}) do
:timer.cancel(timer)
timer = Process.send_after(self(), {:work, counter, uuid}, 1_000)
{:reply, :ok, %{timer: timer}}
end
@impl true
def handle_info({:work, 0, uuid}, state) do
IO.puts "Finished proccess"
{:noreply, state}
end
@impl true
def handle_info({:work, counter, uuid}, state) do
IO.puts "Counting..."
IO.inspect counter
counter = counter - 1
timer = Process.send_after(self(), {:work, counter, uuid},1_000)
{:noreply, %{timer: timer}}
end
@impl true
def handle_cast(:start_timer) do
IO.puts "Hi"
end
@impl true
def handle_info({:start_timer, counter, uuid}, state) do
timer = Process.send_after(self(), {:work, counter, uuid}, 1_000)
{:noreply, %{timer: timer}}
end
# So that unhanded messages don't error
def handle_info(_, state) do
{:ok, state}
end
end
This is my GenServer. Pretty simple and similar to what is below. It works and I get the count but just need a way to send it back to my module. Here that is. It is really messy probably just because I’ve been throwing the kitchen sink at it, so I apologize for that. But again, thanks for your time and effort.
defmodule SurfaceAppWeb.Components.McCard do
# This component will have some state. So use the stateful component.
use Surface.LiveComponent
alias Phoenix.PubSub
alias SurfaceApp.Game
alias SurfaceAppWeb.Components.{Button, Timer, GenTimer, Receiver}
alias Surface.Components.Form.RadioButton
alias SurfaceApp.Game.TimerServer
data question_id, :string
data socket_a, :string
data seconds, :integer
data submission_result, :string, default: ""
data correct_answer, :string
data category, :string
data points_worth, :integer
data question_text, :string
data answer, :string
data choice_one, :string
data choice_two, :string
data choice_three, :string
data choice_four, :string
data answered, :boolean, default: false
data receiver_pid, :string
data self_pid, :string
# Use this to store our trivia card
data trivia_card, :any
# Can omit mount callback if using deault values in data assigns
def mount(socket) do
subscribe_timer()
card = random_card()
correct_answer = correct_answer(card)
pid = self()
Process.send_after(self(), :hi, 1_000)
receiver_pid = spawn(Receiver, :awaiting_for_receive_messages, [])
counter = 18
uuid = "1111"
timer = Process.send_after(self(), {:work, counter, uuid}, 1_000)
IO.inspect Process.monitor(pid)
IO.inspect Process.alive?(pid)
{:ok,
socket
|> assign(seconds: 0)
|> assign(socket_a: socket)
|> assign(self_pid: pid)
|> assign(receiver_pid: receiver_pid)
|> assign(correct_answer: correct_answer)
|> assign(question_id: card.id)
|> assign(category: card.category)
|> assign(points_worth: card.points_worth)
|> assign(question_text: card.question_text)
|> assign(answer: card.answer)
|> assign(choice_one: card.choice_one)
|> assign(choice_two: card.choice_two)
|> assign(choice_three: card.choice_three)
|> assign(choice_four: card.choice_four)
|> assign(trivia_card: card)}
end
defp correct_answer(card) do
cond do
card.answer == card.choice_one -> "1"
card.answer == card.choice_two -> "2"
card.answer == card.choice_three -> "3"
card.answer == card.choice_four -> "4"
end
end
# defp subscribe_timer do
# IO.puts "subscribing to ..."
# PubSub.subscribe(SurfaceApp.PubSub, "timer_topic")
# end
# defp recv() do
# receive do
# :hi -> IO.puts "Chihi."
# :hi_from_timer -> IO.puts "Good Lord"
# end
# end
def handle_event("start_clock", _params, socket) do
:timer.send_interval(1000, self(), :hi_from_timer)
{:noreply, socket |> assign(:seconds, 15)}
end
def handle_info({:work, counter, uuid}, state) do
IO.puts "F this"
IO.inspect counter
end
def handle_info(:tick, %{assigns: %{seconds: seconds}} = socket) do
IO.puts "handle info"
{:noreply, socket |> assign(:seconds, seconds - 1)}
end
def handle_info({:seconds, count}, socket) do
IO.puts "handle info"
socket =
socket
|> assign(:seconds, 7)
{:noreply, socket}
end
defp random_card do
Game.list_mc_cards |> Enum.random()
end
defp add_points() do
IO.puts "add+points"
end
def render(assigns) do
~F"""
<div class="grid items-center justify-center">
<div class="flex justify-center">
<div class="block rounded-lg shadow-lg bg-white max-w-sm text-center">
<h3>
{ @question_text }
</h3>
</div>
</div>
<Timer id="timer" />
{ @seconds }
<div class="grid grid-cols-2 gap-4">
<div class="w-full p-2 lg:w-80">
<div class="p-8 bg-white rounded shadow-md">
<Button label={ @choice_one } value="1" click={"answer"} />
</div>
</div>
<div class="w-full p-2 lg:w-80">
<div class="p-8 bg-white rounded shadow-md">
<Button label={ @choice_two } value="2" click={"answer"} />
</div>
</div>
<div class="w-full p-2 lg:w-80">
<div class="p-8 bg-white rounded shadow-md">
<Button label={ @choice_three } value="3" click={"answer"} />
</div>
</div>
<div class="w-full p-2 lg:w-80">
<div class="p-8 bg-white rounded shadow-md">
<Button label={ @choice_four } value="4" click={"answer"} />
</div>
</div>
</div>
<div :if={@answered} class="submiss-result">{ @submission_result }</div>
<div :if={@answered} class="answer-reveal">Correct Answer: { @answer }</div>
<button :on-click="answer">Submit</button>
<button :if={@answered} :on-click="new">New Question</button>
<Button label="Start Clock" click={"start_clock"} />
<button :on-click="start_clock">Start Clock</button>
</div>
"""
end
# def update(assigns, socket) do
# IO.puts "update"
# {:ok,
# socket
# |> assign(seconds: @seconds)}
# end
def handle_event("answer", value, socket) do
choice = value["value"]
# Process.send(socket.assigns.receiver_pid, "Hi", [])
recv()
card = socket.assigns.trivia_card
correct_answer = socket.assigns.correct_answer
if choice == correct_answer do add_points() else nil end
result = if choice == correct_answer do "Correct" else "Incorrect" end
{:noreply,
socket
|> assign(answer: card.answer)
|> assign(submission_result: result)
|> assign(answered: true)}
end
def handle_event("new", _value, socket) do
card = random_card()
correct_answer = correct_answer(card)
{:noreply,
socket
|> assign(correct_answer: correct_answer)
|> assign(category: card.category)
|> assign(points_worth: card.points_worth)
|> assign(question_text: card.question_text)
|> assign(answer: "")
|> assign(choice_one: card.choice_one)
|> assign(choice_two: card.choice_two)
|> assign(choice_three: card.choice_three)
|> assign(choice_four: card.choice_four)
|> assign(trivia_card: card)
|> assign(answered: false)}
end
# def decrement(counter, state) do
# update(%{seconds: counter}, state)
# end
end