From 47c040e75fdc65de97bfd29e023df4fb0ba5d93d Mon Sep 17 00:00:00 2001 From: Andre Henriques Date: Tue, 16 Jan 2024 23:46:30 +0000 Subject: [PATCH] more work on the server --- lib/paxos.ex | 5 +- lib/server.ex | 156 ++++++++++++++++++++++++++++++++++++++++++-------- lib/test.ex | 12 ++++ 3 files changed, 144 insertions(+), 29 deletions(-) diff --git a/lib/paxos.ex b/lib/paxos.ex index 8bf9474..b69b994 100644 --- a/lib/paxos.ex +++ b/lib/paxos.ex @@ -1,7 +1,6 @@ defmodule Utils do @min_print_level 1 - def safecast(p, m) when p == nil, do: IO.puts('Trying to safecast #{m} with p as nil') def safecast(p, m) when is_pid(p), do: send(p, m) @@ -47,8 +46,7 @@ defmodule Utils do IO.puts(msg) end end - - + defmacro or_state(val, do: expr) do quote do case unquote(val) do @@ -91,7 +89,6 @@ defmodule Paxos do end end - # Starts the Paxos replica with a specific name and some processes def start(name, processes, link \\ false) do log("Starting paxos for #{name}") diff --git a/lib/server.ex b/lib/server.ex index d7c5d94..92e257d 100644 --- a/lib/server.ex +++ b/lib/server.ex @@ -15,28 +15,22 @@ defmodule ServerMacros do ast3 = ast1 ++ match_exp ++ ast2 - if after_exp != nil do + after_exp = if after_exp == nil do quote do - def unquote(function_name)(v, t) do - var!(v) = v - unquote(process_exp) - receive do - unquote(ast3) - after - unquote(after_exp) - end - end + t -> :timeout end else - quote do - def unquote(function_name)(v, t) do - var!(v) = v - unquote(process_exp) - receive do - unquote(ast3) - after - t -> :timeout - end + after_exp + end + + quote do + def unquote(function_name)(v, t) do + var!(v) = v + unquote(process_exp) + receive do + unquote(ast3) + after + unquote(after_exp) end end end @@ -115,11 +109,82 @@ defmodule Server do runfn do {:start_game, participants, pid_to_inform} -> {state, game_id} = try_to_create_game(state, participants) + state = set_modifed(state, game_id) safecast(pid_to_inform, {:start_game_ans, game_id}) state {:get_game_state, game_id, pid_to_inform} -> get_game_state(state, game_id, pid_to_inform) + + {:make_move, game_id, move, pid_to_inform} -> + state = try_to_play_checks(state, game_id, move, pid_to_inform) + + end + + def try_to_play_checks(state, game_id, move, pid_to_inform, repeat \\ false) do + cond do + state.games[game_id] == :not_playing_in_game -> + safecast(pid_to_inform, {:make_move, game_id, :not_playing}) + state + + state.games[game_id] == nil -> + if repeat do + safecast(pid_to_inform, {:make_move, game_id, :game_does_not_exist}) + state + else + state = qurey_status(state) + try_to_play_checks(state, game_id, move, pid_to_inform, true) + end + + true -> + state = qurey_status(state) + game = state.games[game_id] + cond do + game.modified -> + safecast(pid_to_inform, {:make_move, game_id, :player_moved_before, game.game_state, game.hand}) + set_modifed(state, game_id) + is_finished(game, game_id) -> + {_, score} = state.games[game_id] + safecast(pid_to_inform, {:make_move, game_id, :game_finished, score}) + state + true -> + try_to_play(state, game_id, move, pid_to_inform) + end + end + end + + def try_to_play(state, game_id, move, pid_to_inform) do + name = state.name + try_propose {:make_move, game_id, name, move} + do + {:decision, {:make_move, ^game_id, ^name, ^move}} -> + state = apply_game(state, {:make_move, game_id, name, move}) + + if is_finished(state, game_id) do + {_, score} = state.games[game_id] + safecast(pid_to_inform, {:make_move, game_id, :game_finished, score}) + else + game = state.games[game_id] + safecast(pid_to_inform, {:make_move, game_id, game.game_state, game.hand[state.name]}) + end + + set_modifed(state, game_id) + + {:decision, {:make_move, ^game_id, new_name, new_move}} -> + state = apply_game(state, {:make_move, game_id, new_name, new_move}) + + if is_finished(state, game_id) do + {_, score} = state.games[game_id] + safecast(pid_to_inform, {:make_move, game_id, :game_finished, score}) + else + game = state.games[game_id] + safecast(pid_to_inform, {:make_move, game_id, :player_moved_before, game.game_state, game.hand}) + end + + set_modifed(state, game_id) + else + try_to_play(state, game_id, move, pid_to_inform) + end end def get_game_state(state, game_id, pid_to_inform, repeat \\ false) do @@ -139,12 +204,11 @@ defmodule Server do true -> state = qurey_status(state) - safecast(pid_to_inform, {:game_state, game_id, state.games[game_id].game_state, state.games[game_id].hand}) + safecast(pid_to_inform, {:game_state, game_id, state.games[game_id].game_state, state.games[game_id].hand[state.name]}) state end end - def try_to_create_game(state, participants) do game_ids = Map.keys(state.games) latest = Enum.at(Enum.sort(game_ids), length(game_ids) - 1) @@ -169,6 +233,13 @@ defmodule Server do # Utils # + def is_finished(state, game) do + case state.games[game] do + {:finished, _} -> true + _ -> false + end + end + def qurey_status(state) do v = Paxos.get_decision(state.paxos, state.instance, 100) or_state v != nil do @@ -177,9 +248,20 @@ defmodule Server do end end + def set_modifed(state, game, val \\ false) do + or_state not is_finished(state, game) do + %{state | games: Map.put(state.games, game, %{state.games | modified: val})} + end + end + # # Apply Game States # + + def apply_game(state, {:make_move, game_id, new_name, new_move}) do + raise :todo + end + def apply_game(state, {:start_game, game_id, participants, new_game_state, hand}) do cond do state.games[game_id] -> @@ -189,7 +271,8 @@ defmodule Server do games: Map.put(state.games, game_id, %{ game_state: new_game_state, participants: participants, - hand: hand[state.name], + hand: hand, + modified: true, }), instance: state.instance + 1 } @@ -221,13 +304,13 @@ defmodule Server do create_loop :get_game_state do {:game_state, ^v, :not_playing} -> IO.puts("Not Playing in that game") - :not_playing + {:not_playing} {:game_state, ^v, game_state, hand} -> IO.puts("Got game state, #{inspect(game_state)}, hand: #{inspect(hand)}") - {game_state, hand} + {:state, game_state, hand} {:game_state, ^v, :game_does_not_exist} -> IO.puts("Got game does not exist") - nil + {:not_exists} end def get_game_state(name, game_id) do @@ -235,6 +318,29 @@ defmodule Server do get_game_state_loop(game_id, 1000) end + create_loop :make_move do + {:make_move, ^v, :game_does_not_exist} -> + IO.puts("Got game does not exist") + {:not_exists} + {:make_move, ^v, :not_playing} -> + IO.puts("Not Playing in that game") + {:not_playing} + {:make_move, ^v, :game_finished, score} -> + IO.puts("Game finsihed, #{score}") + {:game_finished, score} + {:make_move, ^v, :player_moved_before, game_state, hand} -> + IO.puts("Player moved_before, #{inspect(game_state)} #{inspect(hand)}") + {:player_moved_before, game_state, hand} + {:make_move, ^v, game_state, hand} -> + IO.puts("Got game state, #{inspect(game_state)}, hand: #{inspect(hand)}") + {:state, game_state, hand} + end + + def make_move(name, game_id, move) do + safecast(name, {:make_move, game_id, move, self()}) + make_move_loop(game_id, 1000) + end + ############ # Debug diff --git a/lib/test.ex b/lib/test.ex index e86b94f..a62097a 100644 --- a/lib/test.ex +++ b/lib/test.ex @@ -1,5 +1,11 @@ defmodule Test do + defmacro test() do + quote do + a = 1 + end + end + defmacro createfuncBase(name, do: do_exp, else: else_exp) do b1 = quote do false -> unquote(else_exp) @@ -25,6 +31,12 @@ end defmodule Test2 do require Test + def test2() do + a = 2 + test + IO.puts("#{a}") + end + Test.createfuncBase :lol do true -> :test else :test1 end