Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions services/app/apps/codebattle/assets/js/socket.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export const channelTopics = {
tournamentPlayerFinishedRoundTopic: 'tournament:player:finished_round',
tournamentPlayerFinishedTopic: 'tournament:player:finished',
tournamentActivated: 'tournament:activated',
tournamentCanceled: 'tournament:canceled',

roundCreatedTopic: 'round:created',

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ const initPresence = followId => dispatch => {
data => {
camelizeKeysAndDispatch(dispatch, actions.changeTournamentState)(data);
},
).addListener(
channelTopics.tournamentCanceled,
data => {
camelizeKeysAndDispatch(dispatch, actions.changeTournamentState)(data);
},
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const renderUser = (page, pageSize, user, index) => (
<UserInfo user={user} truncate />
</td>
<td className="p-3 align-middle text-nowrap text-white cb-border-color">{user.rank}</td>
<td className="p-3 align-middle text-nowrap text-white cb-border-color">{user.points}</td>
<td className="p-3 align-middle text-nowrap text-white cb-border-color">{user.rating}</td>
<td className="p-3 align-middle text-nowrap text-white cb-border-color">{user.gamesPlayed}</td>
<td className="p-3 align-middle text-nowrap text-white cb-border-color">
Expand Down Expand Up @@ -235,6 +236,13 @@ function UsersRating() {
Rank &nbsp;
{renderSortArrow('rank', sortParams)}
</th>
<th
className="p-3 border-0 text-nowrap cursor-pointer"
onClick={() => triggerSort('points')}
>
Points &nbsp;
{renderSortArrow('points', sortParams)}
</th>
<th
className="p-3 text-nowrap border-0 cursor-pointer"
onClick={() => triggerSort('rating')}
Expand Down
27 changes: 18 additions & 9 deletions services/app/apps/codebattle/assets/js/widgets/slices/lobby.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ const lobby = createSlice({
state.activeGames = state.activeGames.map(game => {
if (game.id === payload.gameId) {
const newPlayers = game.players.map(player => (player.id === payload.userId
? { ...player, editorLang: payload.editorLang }
: player));
? { ...player, editorLang: payload.editorLang }
: player));

return { ...game, players: newPlayers };
}
Expand All @@ -71,8 +71,8 @@ const lobby = createSlice({
state.activeGames = state.activeGames.map(game => {
if (game.id === payload.gameId) {
const newPlayers = game.players.map(player => (player.id === payload.userId
? { ...player, checkResult: payload.checkResult }
: player));
? { ...player, checkResult: payload.checkResult }
: player));

return { ...game, players: newPlayers };
}
Expand Down Expand Up @@ -131,16 +131,25 @@ const lobby = createSlice({
},
extraReducers: {
[tournamentActions.changeTournamentState]: (state, { payload }) => {
const seasonTournament = state.seasonTournaments.find(t => t.id === payload.id);
const liveTournament = state.liveTournaments.find(t => t.id === payload.id);
const seasonTournament = state.seasonTournaments.find(
t => t.id === payload.id,
);
const liveTournament = state.liveTournaments.find(
t => t.id === payload.id,
);

if (seasonTournament) {
state.upcomingTournaments = state.upcomingTournaments.filter(t => t.id !== payload.id);
state.liveTournaments = [...state.liveTournaments, seasonTournament].sort(sortByStartsAt);
state.seasonTournaments = state.seasonTournaments.filter(
t => t.id !== payload.id,
);
state.liveTournaments = [
...state.liveTournaments,
{ ...seasonTournament, state: payload.state },
].sort(sortByStartsAt);
}

if (liveTournament) {
state.liveTournaments = state.liveTournaments.map(t => (t.id === payload.id ? ({ ...t, state: payload.state }) : t));
state.liveTournaments = state.liveTournaments.map(t => (t.id === payload.id ? { ...t, state: payload.state } : t));
}
},
},
Expand Down
10 changes: 10 additions & 0 deletions services/app/apps/codebattle/lib/codebattle/pub_sub/events.ex
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ defmodule Codebattle.PubSub.Events do
]
end

def get_messages("tournament:canceled", params) do
[
%Message{
topic: "season",
event: "tournament:canceled",
payload: %{tournament: params.tournament}
}
]
end

def get_messages("tournament:activated", params) do
[
%Message{
Expand Down
25 changes: 7 additions & 18 deletions services/app/apps/codebattle/lib/codebattle/tournament/context.ex
Original file line number Diff line number Diff line change
Expand Up @@ -109,18 +109,6 @@ defmodule Codebattle.Tournament.Context do
)
end

@spec get_waiting_participants_to_start_candidates() :: list(Tournament.t())
def get_waiting_participants_to_start_candidates do
Enum.filter(get_live_tournaments(), fn tournament ->
tournament.state == "waiting_participants" &&
tournament.grade != "open" &&
tournament.starts_at

# &&
# DateTime.compare(tournament.starts_at, DateTime.utc_now()) == :lt
end)
end

@spec get_upcoming_to_live_candidate(non_neg_integer()) :: Tournament.t() | nil
def get_upcoming_to_live_candidate(starts_at_delay_mins) do
now = DateTime.utc_now()
Expand All @@ -133,8 +121,8 @@ defmodule Codebattle.Tournament.Context do
where:
t.state == "upcoming" and
t.grade != "open" and
t.starts_at > ^now and
t.starts_at < ^delay_time
t.starts_at >= ^now and
t.starts_at <= ^delay_time
)
)
end
Expand Down Expand Up @@ -341,11 +329,12 @@ defmodule Codebattle.Tournament.Context do

@spec move_upcoming_to_live(Tournament.t()) :: :ok
def move_upcoming_to_live(tournament) do
tournament
|> Tournament.changeset(%{state: "waiting_participants"})
|> Repo.update!()
tournament =
tournament
|> Tournament.changeset(%{state: "waiting_participants"})
|> Repo.update!()

:timer.sleep(1000)
:timer.sleep(100)

Tournament.GlobalSupervisor.start_tournament(tournament)
Codebattle.PubSub.broadcast("tournament:activated", %{tournament: tournament})
Expand Down
34 changes: 28 additions & 6 deletions services/app/apps/codebattle/lib/codebattle/tournament/server.ex
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,14 @@ defmodule Codebattle.Tournament.Server do
{:error, :not_found}
end

def cast_event(tournament_id, event_type, params) do
GenServer.cast(server_name(tournament_id), {:fire_event, event_type, params})
catch
:exit, reason ->
Logger.warning("Error to send tournament update: #{inspect(reason)}")
{:error, :not_found}
end

# SERVER
def init(tournament_id) do
# Create tournament_info_cache table if it doesn't exist
Expand All @@ -120,6 +128,11 @@ defmodule Codebattle.Tournament.Server do
|> Map.put(:tasks_table, tasks_table)
|> Map.put(:clans_table, clans_table)

if tournament.grade != "open" do
time_diff_ms = DateTime.diff(tournament.starts_at, DateTime.utc_now()) * 1000
Process.send_after(self(), :start_grade_tournament, time_diff_ms)
end

{:ok, %{tournament: tournament}}
end

Expand All @@ -130,6 +143,12 @@ defmodule Codebattle.Tournament.Server do
end
end

def handle_cast({:fire_event, event_type, params}, state) do
{:reply, _tournament, state} = handle_call({:fire_event, event_type, params}, nil, state)

{:noreply, state}
end

def handle_cast(:match_waiting_room_players, state) do
handle_info(:match_waiting_room_players, state)
{:noreply, state}
Expand Down Expand Up @@ -243,6 +262,15 @@ defmodule Codebattle.Tournament.Server do
{:reply, tournament, Map.put(state, :tournament, new_tournament)}
end

def handle_info(:start_grade_tournament, %{tournament: tournament}) do
case tournament do
%{players_count: pc} = t when pc > 0 -> cast_event(t.id, :start, %{})
%{players_count: 0} = t -> cast_event(t.id, :cancel, %{})
end

{:noreply, %{tournament: tournament}}
end

def handle_info({:stop_round_break, round_position}, %{tournament: tournament}) do
if tournament.current_round_position == round_position and
in_break?(tournament) and
Expand Down Expand Up @@ -422,10 +450,4 @@ defmodule Codebattle.Tournament.Server do
end

defp server_name(id), do: {:via, Registry, {Codebattle.Registry, "tournament_srv::#{id}"}}

# defp prepare_wr_player(player) do
# player
# |> Map.take([:id, :clan_id, :score, :wr_joined_at])
# |> Map.put(:tasks, Enum.count(player.task_ids))
# end
end
Original file line number Diff line number Diff line change
Expand Up @@ -260,21 +260,21 @@ defmodule Codebattle.Tournament.Base do

def cancel(tournament, params \\ %{})

def cancel(tournament, %{user: user}) do
def cancel(tournament, %{user: user} = params) do
if can_moderate?(tournament, user) do
new_tournament = tournament |> update_struct(%{state: "canceled"}) |> db_save!()

Game.Context.terminate_tournament_games(tournament.id)
Tournament.GlobalSupervisor.terminate_tournament(tournament.id)

new_tournament
cancel_tournament(tournament, params)
else
tournament
end
end

def cancel(tournament, _params) do
cancel_tournament(tournament)
end

defp cancel_tournament(tournament, params \\ %{}) do
new_tournament = tournament |> update_struct(%{state: "canceled"}) |> db_save!()
broadcast_tournament_canceled(new_tournament)

Game.Context.terminate_tournament_games(tournament.id)
Tournament.GlobalSupervisor.terminate_tournament(tournament.id)
Expand Down Expand Up @@ -917,6 +917,11 @@ defmodule Codebattle.Tournament.Base do
tournament
end

defp broadcast_tournament_canceled(tournament) do
Codebattle.PubSub.broadcast("tournament:canceled", %{tournament: tournament})
tournament
end

defp broadcast_tournament_finished(tournament) do
Codebattle.PubSub.broadcast("tournament:finished", %{tournament: tournament})
tournament
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ defmodule Codebattle.Tournament.UpcomingRunner do
require Logger

@tournament_run_upcoming Application.compile_env(:codebattle, :tournament_run_upcoming)
@worker_timeout to_timeout(second: 30)
@worker_timeout to_timeout(second: 3)

@upcoming_time_before_live_mins 7

Expand All @@ -30,7 +30,6 @@ defmodule Codebattle.Tournament.UpcomingRunner do
@impl GenServer
def handle_info(:run_upcoming, state) do
run_upcoming()
start_or_cancel_waiting_participants()

Process.send_after(self(), :run_upcoming, @worker_timeout)

Expand All @@ -50,22 +49,4 @@ defmodule Codebattle.Tournament.UpcomingRunner do
:noop
end
end

def start_or_cancel_waiting_participants do
case Tournament.Context.get_waiting_participants_to_start_candidates() do
tournaments when is_list(tournaments) ->
Enum.each(
tournaments,
fn
%{players_count: pc} = t when pc > 0 ->
Tournament.Context.handle_event(t.id, :start, %{})

%{players_count: 0} = t ->
Tournament.Context.handle_event(t.id, :cancel, %{})
end
)

:ok
end
end
end
5 changes: 5 additions & 0 deletions services/app/apps/codebattle/lib/codebattle/user/scope.ex
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ defmodule Codebattle.User.Scope do
lang: u.lang,
name: u.name,
rank: u.rank,
points: u.points,
rating: u.rating
})
end
Expand Down Expand Up @@ -80,6 +81,10 @@ defmodule Codebattle.User.Scope do
order_by(query, {^direction, :rank})
end

defp apply_sort(query, "points", direction) do
order_by(query, {^direction, :points})
end

defp apply_sort(query, "rating", direction) do
order_by(query, {^direction, :rating})
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ defmodule Codebattle.UsersPointsAndRankUpdateServer do

# SERVER
def init(_) do
Process.send_after(self(), :subscribe, 0)
Process.send_after(self(), :subscribe, 200)
Process.send_after(self(), :work, to_timeout(minute: 5))

Logger.debug("Start UsersPointsServer")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,15 @@ defmodule CodebattleWeb.MainChannel do
{:noreply, socket}
end

def handle_info(%{event: "tournament:canceled", payload: %{tournament: tournament}}, socket) do
push(socket, "tournament:canceled", %{
id: tournament.id,
state: tournament.state
})

{:noreply, socket}
end

def handle_info({:after_join, state}, socket) do
{:ok, _} =
Presence.track(socket, socket.assigns.current_user.id, %{
Expand Down
Loading
Loading