Skip to content

Commit a14203f

Browse files
committed
FIx
1 parent 3157768 commit a14203f

4 files changed

Lines changed: 88 additions & 22 deletions

File tree

apps/codebattle/assets/js/widgets/middlewares/GroupTournament.js

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ export const connectToTournament = (_currentUserId) => (dispatch) => {
9292
platformError,
9393
code,
9494
langSlug,
95+
snapshot,
9596
} = normalizedResponse;
9697

9798
dispatch(
@@ -109,6 +110,10 @@ export const connectToTournament = (_currentUserId) => (dispatch) => {
109110
langSlug,
110111
}),
111112
);
113+
114+
if (snapshot) {
115+
dispatch(actions.setData(snapshot));
116+
}
112117
};
113118

114119
channel.join().receive("ok", onJoinSuccess).receive("error", onJoinFailure);
@@ -188,13 +193,16 @@ const requestJson = async (url, options = {}) => {
188193
};
189194

190195
export const load = (groupTournamentId) => async (dispatch) => {
191-
const response = await requestJson(`/api/v1/group_tournaments/${groupTournamentId}`, {
192-
headers: {
193-
"Content-Type": "application/json",
194-
"x-csrf-token": window.csrf_token,
195-
},
196-
});
197-
console.log(response);
196+
try {
197+
const response = await requestJson(`/api/v1/group_tournaments/${groupTournamentId}`, {
198+
headers: {
199+
"Content-Type": "application/json",
200+
"x-csrf-token": window.csrf_token || "",
201+
},
202+
});
198203

199-
dispatch(actions.setData(response));
204+
dispatch(actions.setData(response));
205+
} catch (error) {
206+
console.error("group_tournament:load failed", error);
207+
}
200208
};

apps/codebattle/assets/js/widgets/pages/groupTournament/EvolutionPanel.jsx

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,24 @@ import dayjs from "../../../i18n/dayjs";
33
import i18n from "../../../i18n";
44

55
const getExternalUrl = (url) => {
6-
const externalUrl = new URL(`${url.replace(/\/$/, "")}/browse/README.md`);
6+
if (!url) {
7+
return null;
8+
}
79

8-
externalUrl.searchParams.set("rev", "main");
9-
externalUrl.searchParams.set(
10-
"chatMessage",
11-
"Это ИИ-ассистент, который поможет тебе решить задачу.",
12-
);
10+
try {
11+
const externalUrl = new URL(`${url.replace(/\/$/, "")}/browse/README.md`);
1312

14-
return externalUrl.toString();
13+
externalUrl.searchParams.set("rev", "main");
14+
externalUrl.searchParams.set(
15+
"chatMessage",
16+
"Это ИИ-ассистент, который поможет тебе решить задачу.",
17+
);
18+
19+
return externalUrl.toString();
20+
} catch (error) {
21+
console.error("group_tournament: invalid repo url", url, error);
22+
return null;
23+
}
1524
};
1625

1726
const formatInsertedAtTooltip = (insertedAt) => {
@@ -48,6 +57,7 @@ const findBestRunId = (items) => {
4857
function EvolutionPanel({ items, tournamentStatus, runId, setRunId, repoUrl }) {
4958
const bestRunId = findBestRunId(items);
5059
const [hoverTooltip, setHoverTooltip] = useState(null);
60+
const externalUrl = tournamentStatus !== "finished" ? getExternalUrl(repoUrl) : null;
5161

5262
return (
5363
<>
@@ -73,9 +83,9 @@ function EvolutionPanel({ items, tournamentStatus, runId, setRunId, repoUrl }) {
7383
scrollbarGutter: "stable",
7484
}}
7585
>
76-
{tournamentStatus !== "finished" && repoUrl && (
86+
{externalUrl && (
7787
<a
78-
href={getExternalUrl(repoUrl)}
88+
href={externalUrl}
7989
target="_blank"
8090
rel="noopener noreferrer"
8191
className="d-block text-decoration-none mb-3"

apps/codebattle/assets/js/widgets/pages/groupTournament/Header.jsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ const statusBadge = {
1010
};
1111

1212
function TournamentTimer({ groupTournament }) {
13-
const startedAt = groupTournament?.startedAt;
13+
const roundStartedAt = groupTournament?.lastRoundStartedAt || groupTournament?.startedAt;
1414
const timeoutSeconds = groupTournament?.roundTimeoutSeconds;
1515
const endsAt =
16-
startedAt && Number.isInteger(timeoutSeconds)
17-
? moment.utc(startedAt).add(timeoutSeconds, "seconds")
16+
roundStartedAt && Number.isInteger(timeoutSeconds)
17+
? moment.utc(roundStartedAt).add(timeoutSeconds, "seconds")
1818
: null;
1919

2020
const [time, seconds] = useTimer(endsAt);

apps/codebattle/lib/codebattle_web/channels/group_tournament_channel.ex

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ defmodule CodebattleWeb.GroupTournamentChannel do
33
use CodebattleWeb, :channel
44

55
alias Codebattle.ExternalPlatformInvite.Context, as: InviteContext
6+
alias Codebattle.GroupTask.Context, as: GroupTaskContext
67
alias Codebattle.GroupTournament.Context, as: GroupTournamentContext
78
alias Codebattle.GroupTournament.Server, as: GroupTournamentServer
89
alias Codebattle.PubSub.Message
910
alias Codebattle.UserGroupTournament.Context, as: UserGroupTournamentContext
1011
alias Codebattle.Workers.PlatformInviteAdvancerWorker
12+
alias Runner.Languages
1113

1214
def join("group_tournament:" <> tournament_id, _payload, socket) do
1315
case parse_tournament_id(tournament_id) do
@@ -58,7 +60,8 @@ defmodule CodebattleWeb.GroupTournamentChannel do
5860
require_invitation: true,
5961
run_on_external_platform: group_tournament.run_on_external_platform,
6062
platform_error: platform_error,
61-
external_setup: serialize_external_setup(external_setup, user, group_tournament)
63+
external_setup: serialize_external_setup(external_setup, user, group_tournament),
64+
snapshot: build_snapshot(group_tournament, user)
6265
}, socket}
6366
end
6467

@@ -71,10 +74,55 @@ defmodule CodebattleWeb.GroupTournamentChannel do
7174
invite: %{state: "accepted"},
7275
require_invitation: false,
7376
run_on_external_platform: group_tournament.run_on_external_platform,
74-
external_setup: serialize_external_setup(external_setup, current_user, group_tournament)
77+
external_setup: serialize_external_setup(external_setup, current_user, group_tournament),
78+
snapshot: build_snapshot(group_tournament, current_user)
7579
}, socket}
7680
end
7781

82+
defp build_snapshot(group_tournament, current_user) do
83+
player_ids = Enum.map(group_tournament.players, & &1.user_id)
84+
85+
latest_solutions =
86+
GroupTaskContext.list_latest_solutions(group_tournament.group_task_id, player_ids,
87+
group_tournament_id: group_tournament.id
88+
)
89+
90+
current_user_solutions =
91+
GroupTaskContext.list_user_solutions(group_tournament.group_task_id, current_user.id,
92+
group_tournament_id: group_tournament.id
93+
)
94+
95+
current_player = Enum.find(group_tournament.players, &(&1.user_id == current_user.id))
96+
97+
%{
98+
group_tournament: GroupTournamentContext.serialize_group_tournament(group_tournament),
99+
current_player: serialize_player(current_player),
100+
players: Enum.map(group_tournament.players, &serialize_player/1),
101+
latest_solutions: Map.new(latest_solutions, &{&1.user_id, serialize_solution(&1)}),
102+
solution_history: Enum.map(current_user_solutions, &serialize_solution/1),
103+
latest_solution: current_user_solutions |> List.first() |> serialize_solution(),
104+
runs:
105+
group_tournament
106+
|> GroupTournamentContext.list_runs(limit: :infinity)
107+
|> Enum.map(&GroupTournamentContext.serialize_run/1),
108+
langs: Languages.get_langs()
109+
}
110+
end
111+
112+
defp serialize_player(nil), do: nil
113+
114+
defp serialize_player(player) do
115+
%{
116+
id: player.id,
117+
user_id: player.user_id,
118+
name: player.user && player.user.name,
119+
lang: player.lang,
120+
state: player.state,
121+
last_setup_at: player.last_setup_at,
122+
inserted_at: player.inserted_at
123+
}
124+
end
125+
78126
def handle_in("request_invite_update", _, socket) do
79127
current_user = socket.assigns.current_user
80128

0 commit comments

Comments
 (0)