diff --git a/lib/paxos.ex b/lib/paxos.ex index ec001a8..1abec82 100644 --- a/lib/paxos.ex +++ b/lib/paxos.ex @@ -1,6 +1,6 @@ defmodule Utils do - @min_print_level 1 + @min_print_level 2 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) diff --git a/lib/server.ex b/lib/server.ex index c29b901..1f6f1cb 100644 --- a/lib/server.ex +++ b/lib/server.ex @@ -137,7 +137,16 @@ defmodule Server do safecast(pid_to_inform, {:make_move, game_id, :player_moved_before, game.game_state, game.hand}) set_modifed(state, game_id) true -> - try_to_play(state, game_id, move, pid_to_inform) + cond do + not is_number(move) -> + safecast(pid_to_inform, {:make_move, game_id, :invalid_move}) + state + move >= length(game.game_state) -> + safecast(pid_to_inform, {:make_move, game_id, :invalid_move}) + state + true -> + try_to_play(state, game_id, move, pid_to_inform) + end end end end @@ -207,7 +216,7 @@ defmodule Server do defp get_hand_for_game_state(game_state) do r1 = Enum.random(0..100) - if r1 <= 10 do + if r1 <= 20 do :+ else mx = game_state |> Enum.filter(fn m -> m != :+ end) |> Enum.max() @@ -255,7 +264,7 @@ defmodule Server do end defp set_modifed(state, game, val \\ false) do - or_state not is_finished(state, game) do + or_state not is_finished(state, game) and state.games[game] != :not_playing_in_game do %{state | games: Map.put(state.games, game, %{state.games[game] | modified: val})} end end @@ -332,7 +341,7 @@ defmodule Server do {:merged, _} -> indexed_game_state _ -> indexed_game_state |> - Enum.map(fn {x, ti} -> if ti == i, do: {{:merged, n + 1}, i}, else: {x, ti} end) |> + Enum.map(fn {x, ti} -> if ti == i, do: {{:merged, max(n, a) + 1}, i}, else: {x, ti} end) |> Enum.filter(fn {x, ti} -> cond do b_i == ti -> false a_i == ti -> false @@ -362,24 +371,16 @@ defmodule Server do defp remove_merged([], rec, _), do: rec - defp remove_merged([{:merged, n} | tl], rec, add) do - if add do - remove_merged(tl, rec ++ [n], false) - else - remove_merged(tl, rec, false) - end - end + defp remove_merged([{:merged, n} | tl], rec, add), + do: if add, do: remove_merged(tl, rec ++ [n], false), + else: remove_merged(tl, rec, false) defp remove_merged([n | tl], rec, add), do: remove_merged(tl, rec ++ [n], add) - defp remove_merged(list) do - log("#{inspect(list)}") - remove_merged(list, [], true) - end + defp remove_merged(list), do: remove_merged(list, [], true) defp simplify_game_state(game_state) do - log("game_state: #{inspect(game_state)}") indexed_game_state = game_state |> reindex(false) @@ -393,8 +394,6 @@ defmodule Server do end) |> simplify_game_state_pluses(indexed_game_state) - log("game_state2: #{inspect(indexed_game_state)}") - if repeat do indexed_game_state |> Enum.map(fn {v, _} -> v end) |> @@ -418,10 +417,15 @@ defmodule Server do game_state = b ++ [ game.hand[player_name] ] ++ e game_state = simplify_game_state(game_state) hand = Map.put(game.hand, player_name, new_hand) - game = %{game| hand: hand, game_state: game_state } + game = %{game| hand: hand, game_state: game_state, modified: true } - if length(game.game_state) > 15 do - %{state| games: Map.put(state.games, game_id, {:finished, Enum.sum(game.game_state)}), instance: state.instance + 1} + if length(game.game_state) > 16 do + %{state| games: Map.put(state.games, game_id, { + :finished, + game.game_state |> + Enum.filter(fn x -> not is_atom(x) end) |> + Enum.sum()}), instance: state.instance + 1 + } else %{state| games: Map.put(state.games, game_id, game), instance: state.instance + 1} end @@ -468,18 +472,15 @@ defmodule Server do end create_loop :get_game_state do - {:game_state, ^v, :not_playing} -> - log("Not Playing in that game") - {:not_playing} - {:game_state, ^v, game_state, hand} -> - log("Got game state, #{inspect(game_state)}, hand: #{inspect(hand)}") - {:state, game_state, hand} {:game_state, ^v, :not_playing} -> log("Not Playing in that game") {:not_playing} {:game_state, ^v, :game_finished, score} -> log("Game finsihed, #{score}") {:game_finished, score} + {:game_state, ^v, game_state, hand} -> + log("Got game state, #{inspect(game_state)}, hand: #{inspect(hand)}") + {:state, game_state, hand} {:game_state, ^v, :game_does_not_exist} -> log("Got game does not exist") {:not_exists} @@ -503,6 +504,9 @@ defmodule Server do {:make_move, ^v, :player_moved_before, game_state, hand} -> log("Player moved_before, #{inspect(game_state)} #{inspect(hand)}") {:player_moved_before, game_state, hand} + {:make_move, ^v, :invalid_move} -> + log("Invalid Move") + {:invalid_move} {:make_move, ^v, game_state, hand} -> log("Got game state, #{inspect(game_state)}, hand: #{inspect(hand)}") {:state, game_state, hand} @@ -534,87 +538,231 @@ defmodule Client do create_log 3 def play_game(process, game_id) do - + game = Server.get_game_state(process, game_id) + + cont = case game do + :timeout -> + log("Could to not comunicate with the server") + true + {:not_exists} -> + log("Game does not exist") + true + {:not_playing} -> + log("Not Playing in that game") + true + {:game_finished, score} -> + log("Game finsihed, #{score}") + true + {:game_does_not_exist} -> + log("Got game does not exist") + true + {:state, game_state, hand} -> + game_state |> + to_name() |> + interpolate() |> + fill() |> + printpt(pad(to_name(hand))) + false + end + + if not cont do + to_play = IO.gets("Type the number you want to play or q to exit: ") + to_play = to_play |> String.trim("\"") |> String.trim() + + case to_play do + "q" -> + log("Bye Bye") + v -> + try do + {n, _} = Integer.parse(v) + + res = Server.make_move(process, game_id, n) + case res do + :timeout -> + log("Could to not comunicate with the server") + {:not_exists} -> play_game(process, game_id) + {:not_playing} -> play_game(process, game_id) + {:game_finished, _} -> play_game(process, game_id) + {:player_moved_before, _, _} -> + log("Player Moved before you did please check the map and try again") + play_game(process, game_id) + {:invalid_move} -> raise "Invalid Move" + {:state, _, _} -> play_game(process, game_id) + end + rescue + _ -> + log("Please provide a valid number") + play_game(process, game_id) + end + end + end + end + + + def control_game(process, game_id) do + to_play = IO.gets("Type the number you want to play or q to exit: ") + to_play = to_play |> String.trim("\"") |> String.trim() + + case to_play do + "q" -> + log("Bye Bye") + v -> + try do + {n, _} = Integer.parse(v) + + res = Server.make_move(process, game_id, n) + case res do + :timeout -> log("Could to not comunicate with the server") + {:not_exists} -> play_game(process, game_id) + {:not_playing} -> play_game(process, game_id) + {:game_finished, _} -> play_game(process, game_id) + {:player_moved_before, _, _} -> + log("Player Moved before you did please check the map and try again") + play_game(process, game_id) + {:invalid_move} -> raise "Invalid Move" + {:state, _, _} -> control_game(process, game_id) + end + rescue + _ -> + log("Please provide a valid number") + control_game(process, game_id) + end + end + end + + + def display_game(process, game_id) do + game = Server.get_game_state(process, game_id) + + cont = case game do + :timeout -> log("Could to not comunicate with the server") + {:not_exists} -> log("Game does not exist") + {:not_playing} -> log("Not Playing in that game") + {:game_finished, score} -> log("Game finsihed, #{score}") + {:game_does_not_exist} -> log("Got game does not exist") + {:state, game_state, hand} -> + IO.ANSI.clear() + game_state |> + to_name() |> + interpolate() |> + fill() |> + printpt(pad(to_name(hand))) + Process.sleep(1000) + display_game(process, game_id) + end end def to_name(list) when is_list(list), do: list |> Enum.map(fn x -> to_name(x) end) + def to_name(atom) when atom == :+, do: IO.ANSI.color_background(9) <> IO.ANSI.color(15) <> "#{:atom}" <> IO.ANSI.reset() def to_name(atom) when is_atom(atom), do: atom def to_name(i) do - [ "H", "He", "Li", "Be", "B", "C", "N", "O", "F", "Ne", "Na", "Mg", "Al", "Si", "P", "S", "Cl", "Ar", "K", "Ca", "Sc", "Ti", "V", "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn", "Ga", "Ge", "As", "Se", "Br", "Kr", "Rb", "Sr", "Y", "Zr", "Nb", "Mo", "Tc", "Ru", "Rh", "Pd", "Ag", "Cd", "In", "Sn", "Sb", "Te", "I", "Xe", "Cs", "Ba", "La", "Ce", "Pr", "Nd", "Pm", "Sm", "Eu", "Gd", "Tb", "Dy", "Ho", "Er", "Tm", "Yb", "Lu", "Hf", "Ta", "W", "Re", "Os", "Ir", "Pt", "Au", "Hg", "Tl", "Pb", "Bi", "Po", "At", "Rn", "Fr", "Ra", "Ac", "Th", "Pa", "U", "Np", "Pu", "Am", "Cm", "Bk", "Cf", "Es", "Fm", "Md", "No", "Lr", "Rf", "Db", "Sg", "Bh", "Hs", "Mt", "Ds", "Rg", "Cn", "Nh", "Fl", "Mc", "Lv", "Ts", "Og" ] |> - Enum.at(i - 1) + letter = [ "H", "He", "Li", "Be", "B", "C", "N", "O", "F", "Ne", "Na", "Mg", "Al", "Si", "P", "S", "Cl", "Ar", "K", "Ca", "Sc", "Ti", "V", "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn", "Ga", "Ge", "As", "Se", "Br", "Kr", "Rb", "Sr", "Y", "Zr", "Nb", "Mo", "Tc", "Ru", "Rh", "Pd", "Ag", "Cd", "In", "Sn", "Sb", "Te", "I", "Xe", "Cs", "Ba", "La", "Ce", "Pr", "Nd", "Pm", "Sm", "Eu", "Gd", "Tb", "Dy", "Ho", "Er", "Tm", "Yb", "Lu", "Hf", "Ta", "W", "Re", "Os", "Ir", "Pt", "Au", "Hg", "Tl", "Pb", "Bi", "Po", "At", "Rn", "Fr", "Ra", "Ac", "Th", "Pa", "U", "Np", "Pu", "Am", "Cm", "Bk", "Cf", "Es", "Fm", "Md", "No", "Lr", "Rf", "Db", "Sg", "Bh", "Hs", "Mt", "Ds", "Rg", "Cn", "Nh", "Fl", "Mc", "Lv", "Ts", "Og" ] |> Enum.at(i - 1) + color = [46,45,138,19,11,140,8,47,57,159,72,48,55,35,251,188,107,110,21,11,156,134,128,179,140,234,14,90,206,7,249,209,253,123,192,165,234,136,198,208,43,34,215,127,23,250,177,237,124,202,229, +63,206,220,224,109,202,113,253,7,243,26,160,65,39,112,57,75, 252,82,213,186,68,243,134,100,226,48,90,134,208,102,25,106,72, 242,26,59,166,26,187,54,194,165,97,219,186,130,7,154,233,85, 130,67,43,200,90,60,148,49,161,110,247,116,223,159,132,132] |> Enum.at(i - 1) |> IO.ANSI.color() + color <> letter <> IO.ANSI.reset() end def interpolate(list) do [list, 0..length(list) - 1] |> Enum.zip() |> Enum.reduce([], fn {v, i}, acc -> acc ++ [i, v] end) |> - Enum.map(fn x -> String.pad_leading("#{x}", 2, " ") end) + Enum.map(fn x -> pad(x) end) end - def printpt(game_state) do - rad = 8; - printpt1(game_state, 0, rad) + def pad(elem) do + String.pad_leading("#{elem}", 3, " ") end - defp count_char(str, char) do - String.split(str, "") |> Enum.reduce(0, fn x, acc -> if x == char do acc + 1 else acc end end) + def grow_empty_list(t, i, acc) when i == 0, do: t ++ acc + def grow_empty_list([], i, acc), do: grow_empty_list(acc, i, []) + def grow_empty_list([h | tl], i, acc), do: + grow_empty_list(tl, i - 1, acc ++ [ h ++ [" "] ]) + + def fill(list) do + to_fill = 32 - length(list) + to_add = grow_empty_list(Enum.map(list, fn _ -> [] end), to_fill, []) + fill(list, to_add, []) end - def printpt1(_, i, rad) when i > rad * 2, do: nil - def printpt1(game_state, i, rad) do - res = printpt2(game_state, i, -5, rad, "") + def fill([], _, acc), do: acc + def fill([hd | tail], [add_hd | add_tail], acc) do + fill(tail, add_tail ,acc ++ [hd] ++ add_hd) + end - " xxx \n" - " xxx yyy \n" - " xxx yyy \n" - " xxx yyy \n" - " xxx yyy \n" - " xxx yyy \n" - " xxx yyy \n" - " xxx yyy \n" - " xxx yyy \n" - " xxx yyy \n" - " xxx yyy \n" - " xxx yyy \n" - " xxx yyy \n" - " xxx yyy \n" - " xxx yyy \n" - " xxx \n" - - - - - if i != 15 do - res = case i do - 0 -> - x = count_char(res, "x") - log("#{x}") - #TODO - res - 16 -> - #TODO - res - v -> - #TODO - res - end - IO.write(" #{res} \n") + def printpt(game_state, hand), do: printpt(game_state, hand, 0) + def printpt(_, _, i) when i > 16, do: nil + def printpt(game_state, hand, i) do + res = case i do + 0 -> + " xxx \n" |> + String.replace("xxx", Enum.at(game_state, 1)) + 1 -> + " xxx yyy \n" |> + String.replace("xxx", Enum.at(game_state, 0)) |> + String.replace("yyy", Enum.at(game_state, 2)) + 2 -> + " xxx yyy \n" |> + String.replace("xxx", Enum.at(game_state, 31)) |> + String.replace("yyy", Enum.at(game_state, 3)) + 3 -> + " xxx yyy \n" |> + String.replace("xxx", Enum.at(game_state, 30)) |> + String.replace("yyy", Enum.at(game_state, 4)) + 4 -> + " xxx yyy \n" |> + String.replace("xxx", Enum.at(game_state, 29)) |> + String.replace("yyy", Enum.at(game_state, 5)) + 5 -> + " xxx yyy \n" |> + String.replace("xxx", Enum.at(game_state, 28)) |> + String.replace("yyy", Enum.at(game_state, 6)) + 6 -> + " xxx yyy \n" |> + String.replace("xxx", Enum.at(game_state, 27)) |> + String.replace("yyy", Enum.at(game_state, 7)) + 7 -> + " xxx yyy \n" |> + String.replace("xxx", Enum.at(game_state, 26)) |> + String.replace("yyy", Enum.at(game_state, 8)) + 8 -> + " xxx zzz yyy \n" |> + String.replace("xxx", Enum.at(game_state, 25)) |> + String.replace("yyy", Enum.at(game_state, 9)) |> + String.replace("zzz", hand) + 9 -> + " xxx yyy \n" |> + String.replace("xxx", Enum.at(game_state, 24)) |> + String.replace("yyy", Enum.at(game_state, 10)) + 10 -> + " xxx yyy \n" |> + String.replace("xxx", Enum.at(game_state, 23)) |> + String.replace("yyy", Enum.at(game_state, 11)) + 11 -> + " xxx yyy \n" |> + String.replace("xxx", Enum.at(game_state, 22)) |> + String.replace("yyy", Enum.at(game_state, 12)) + 12 -> + " xxx yyy \n" |> + String.replace("xxx", Enum.at(game_state, 21)) |> + String.replace("yyy", Enum.at(game_state, 13)) + 13 -> + " xxx yyy \n" |> + String.replace("xxx", Enum.at(game_state, 20)) |> + String.replace("yyy", Enum.at(game_state, 14)) + 14 -> + " xxx yyy \n" |> + String.replace("xxx", Enum.at(game_state, 19)) |> + String.replace("yyy", Enum.at(game_state, 15)) + 15 -> + " xxx yyy \n" |> + String.replace("xxx", Enum.at(game_state, 18)) |> + String.replace("yyy", Enum.at(game_state, 16)) + 16 -> + " xxx \n" |> + String.replace("xxx", Enum.at(game_state, 17)) end - printpt1(game_state, i + 1, rad) - end - def printpt2(_, _, j, rad, res) when j > rad * 4 + 10, do: res - def printpt2(game_state, i, j, rad, res) do - dist = :math.sqrt((i - rad)*(i - rad) + (j / 2 - rad)*(j / 2 - rad)); - v = if (dist > rad - 1 and dist < rad + 1) do - case i do - 0 -> "x" - 16 -> "x" - _ -> if j < rad * 2 do "x" else "y" end - end - else - " " - end - printpt2(game_state, i, j + 1, rad, res <> v) + IO.write("#{res}") + printpt(game_state, hand, i + 1) end end