+
{showTaskBuilder && (
<>
@@ -158,6 +115,18 @@ function RoomWidget({
{showReplayer &&
}
+
+
+
diff --git a/services/app/apps/codebattle/assets/js/widgets/pages/game/GameRoomLockPanel.jsx b/services/app/apps/codebattle/assets/js/widgets/pages/game/GameRoomLockPanel.jsx
new file mode 100644
index 000000000..cafea69fb
--- /dev/null
+++ b/services/app/apps/codebattle/assets/js/widgets/pages/game/GameRoomLockPanel.jsx
@@ -0,0 +1,69 @@
+import React, { useState, useRef, useCallback } from 'react';
+
+import cn from 'classnames';
+import { useDispatch } from 'react-redux';
+
+import { sendPassCode } from '../../middlewares/Room';
+
+const passCodeLength = 8;
+
+function GameRoomLockPanel() {
+ const dispatch = useDispatch();
+
+ const inputRef = useRef(null);
+
+ const [error, setError] = useState(null);
+
+ const onChangePassCode = useCallback(() => {
+ if (error) {
+ setError(null);
+ }
+ }, [error, setError]);
+ const onSubmitCode = useCallback(() => {
+ const value = (inputRef.current.value || '').replaceAll(' ', '');
+ const onError = err => setError(err);
+
+ if (passCodeLength === value.length) {
+ onError({
+ message: `Only ${passCodeLength} character pass code (now ${value.length})`,
+ });
+ return;
+ }
+
+ dispatch(sendPassCode(value, onError));
+ }, [inputRef, setError, dispatch]);
+
+ const inputClassName = cn('form-control', {
+ 'is-invalid': !!error,
+ });
+
+ return (
+
+
Game is Locked
+
+
+
+ Submit
+
+
+
+ Example: 12345678
+ {error && {error.message} }
+
+
+ );
+}
+
+export default GameRoomLockPanel;
diff --git a/services/app/apps/codebattle/assets/js/widgets/pages/tournament/CustomTournamentInfoPanel.jsx b/services/app/apps/codebattle/assets/js/widgets/pages/tournament/CustomTournamentInfoPanel.jsx
index de6fa33b0..314d47b25 100644
--- a/services/app/apps/codebattle/assets/js/widgets/pages/tournament/CustomTournamentInfoPanel.jsx
+++ b/services/app/apps/codebattle/assets/js/widgets/pages/tournament/CustomTournamentInfoPanel.jsx
@@ -14,6 +14,7 @@ function CustomTournamentInfoPanel({
currentRoundPosition = 0,
matches,
players,
+ taskList,
topPlayerIds,
currentUserId,
pageNumber,
@@ -57,10 +58,11 @@ function CustomTournamentInfoPanel({
}
disabledSearch={!isAdmin && !isOwner}
/>
- {!hideCustomGameConsole && (
+ {!hideCustomGameConsole && (isOwner || isAdmin) && (
)}
diff --git a/services/app/apps/codebattle/assets/js/widgets/pages/tournament/PlayersPanel.jsx b/services/app/apps/codebattle/assets/js/widgets/pages/tournament/PlayersPanel.jsx
index e0a622434..55095e2a3 100644
--- a/services/app/apps/codebattle/assets/js/widgets/pages/tournament/PlayersPanel.jsx
+++ b/services/app/apps/codebattle/assets/js/widgets/pages/tournament/PlayersPanel.jsx
@@ -8,6 +8,7 @@ const Players = ({
playersCount,
players,
canBan,
+ showBots,
handleKick,
}) => (
@@ -27,23 +28,25 @@ const Players = ({
{playersCount === 0 ? (
NO_PARTICIPANTS_YET
) : (
- Object.values(players).slice(0, 30).map(player => (
-
-
-
+ Object.values(players)
+ .filter(player => (showBots ? true : !player.isBot))
+ .slice(0, 30).map(player => (
+
+
+
+
+ {canBan && (
+
+ Kick
+
+ )}
- {canBan && (
-
- Kick
-
- )}
-
- ))
+ ))
)}
diff --git a/services/app/apps/codebattle/assets/js/widgets/pages/tournament/Tournament.jsx b/services/app/apps/codebattle/assets/js/widgets/pages/tournament/Tournament.jsx
index 879a14f97..2caf09387 100644
--- a/services/app/apps/codebattle/assets/js/widgets/pages/tournament/Tournament.jsx
+++ b/services/app/apps/codebattle/assets/js/widgets/pages/tournament/Tournament.jsx
@@ -17,6 +17,7 @@ import {
kickFromTournament,
} from '../../middlewares/Tournament';
import * as selectors from '../../selectors';
+import { actions } from '../../slices';
import CustomTournamentInfoPanel from './CustomTournamentInfoPanel';
import DetailsModal from './DetailsModal';
@@ -68,6 +69,7 @@ function InfoPanel({
return (
@@ -113,8 +119,10 @@ function Tournament() {
] = useState(false);
const playersCount = useMemo(
- () => Object.keys(tournament.players).length,
- [tournament.players],
+ () => Object.values(tournament.players)
+ .filter(player => (tournament.showBots ? true : !player.isBot))
+ .length,
+ [tournament.players, tournament.showBots],
);
const isOver = useMemo(
() => [TournamentStates.finished, TournamentStates.cancelled].includes(
@@ -133,6 +141,9 @@ function Tournament() {
const onCloseRoundConfirmationModal = useCallback(() => {
setStartRoundConfirmationModalShowing(false);
}, [setStartRoundConfirmationModalShowing]);
+ const toggleShowBots = useCallback(() => {
+ dispatch(actions.toggleShowBots());
+ }, [dispatch]);
const handleKick = useCallback(event => {
const { playerId } = event.currentTarget.dataset;
if (playerId) {
@@ -243,12 +254,14 @@ function Tournament() {
players={tournament.players}
playersCount={playersCount}
playersLimit={tournament.playersLimit}
+ showBots={tournament.showBots}
hideResults={hideResults}
startsAt={tournament.startsAt}
state={tournament.state}
type={tournament.type}
handleStartRound={handleStartRound}
handleOpenDetails={handleOpenDetails}
+ toggleShowBots={toggleShowBots}
/>
{tournament.useChat && (
)}
diff --git a/services/app/apps/codebattle/assets/js/widgets/pages/tournament/TournamentGameCreatePanel.jsx b/services/app/apps/codebattle/assets/js/widgets/pages/tournament/TournamentGameCreatePanel.jsx
index 5339d7985..935e51c52 100644
--- a/services/app/apps/codebattle/assets/js/widgets/pages/tournament/TournamentGameCreatePanel.jsx
+++ b/services/app/apps/codebattle/assets/js/widgets/pages/tournament/TournamentGameCreatePanel.jsx
@@ -4,6 +4,7 @@ import React, {
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import MatchStates from '../../config/matchStates';
import { createCustomGame } from '../../middlewares/Tournament';
import { tournamentEmptyPlayerUrl } from '../../utils/urlBuilders';
@@ -12,23 +13,44 @@ const emptyPlayer = {};
function TournamentGameCreatePanel({
players,
matches,
+ taskList = [],
currentRoundPosition,
}) {
const [selectedPlayer, setSelectedPlayer] = useState(emptyPlayer);
const [selectedTaskLevel, setSelectedTaskLevel] = useState();
- const alreadyHaveActiveMatch = useMemo(() => {
- if (!selectedPlayer) return false;
+ const activeMatch = useMemo(() => {
+ if (!selectedPlayer) return null;
const activeMatches = Object.values(matches)
.filter(match => (
match.roundPosition === currentRoundPosition
&& match.playerIds.includes(selectedPlayer.id)
- && match.state === 'playing'
+ && match.state === MatchStates.playing
));
- return activeMatches.length !== 0;
+ if (activeMatches.length === 0) {
+ return null;
+ }
+ return activeMatches[0];
}, [selectedPlayer, matches, currentRoundPosition]);
+ const availableTasks = useMemo(() => (
+ taskList.reduce((acc, task) => {
+ if (selectedPlayer && players[selectedPlayer.id]?.taskIds?.includes(task.id)) {
+ return acc;
+ }
+
+ acc[task.level].push(task);
+
+ return acc;
+ }, {
+ elementary: [],
+ easy: [],
+ medium: [],
+ hard: [],
+ })
+ ), [selectedPlayer, players, taskList]);
+
const clearSelectedPlayer = useCallback(() => {
setSelectedPlayer();
setSelectedTaskLevel();
@@ -40,7 +62,7 @@ function TournamentGameCreatePanel({
useEffect(() => {
if (selectedPlayer === emptyPlayer) {
const playersListWithoutBots = Object.values(players)
- .filter(player => !player.isBot);
+ .filter(player => !player.isBot);
if (playersListWithoutBots.length === 1) {
setSelectedPlayer(playersListWithoutBots[0]);
@@ -78,29 +100,54 @@ function TournamentGameCreatePanel({
)}
{selectedPlayer && !selectedTaskLevel && (
<>
-
-
{`Choose task level for player ${selectedPlayer.name}: `}
-
+
+
+ {'Choose task level for player '}
+ {selectedPlayer.name}
+ :
+
+
+ setSelectedTaskLevel('elementary')}
+ disabled={availableTasks.elementary.length < 1}
+ >
+ Elementary
+ {' '}
+
+ {`(${availableTasks.elementary.length} available)`}
+
+
setSelectedTaskLevel('easy')}
+ disabled={availableTasks.easy.length < 1}
>
Easy
+ {' '}
+ {availableTasks.easy.length}
setSelectedTaskLevel('medium')}
+ disabled={availableTasks.medium.length < 1}
>
Medium
+ {' '}
+ {availableTasks.medium.length}
setSelectedTaskLevel('hard')}
+ disabled={availableTasks.hard.length < 1}
>
Hard
+ {' '}
+ {availableTasks.hard.length}
@@ -123,7 +170,7 @@ function TournamentGameCreatePanel({
{`Player: ${selectedPlayer.name}`}
- {`Level: ${selectedTaskLevel}`}
+ {`Level: ${selectedTaskLevel} (${availableTasks[selectedTaskLevel].length} available)`}
- {alreadyHaveActiveMatch ? (
+ {activeMatch ? (
Start match
diff --git a/services/app/apps/codebattle/assets/js/widgets/pages/tournament/TournamentHeader.jsx b/services/app/apps/codebattle/assets/js/widgets/pages/tournament/TournamentHeader.jsx
index 1c06df7e3..6d3c89488 100644
--- a/services/app/apps/codebattle/assets/js/widgets/pages/tournament/TournamentHeader.jsx
+++ b/services/app/apps/codebattle/assets/js/widgets/pages/tournament/TournamentHeader.jsx
@@ -9,6 +9,7 @@ import GameLevelBadge from '../../components/GameLevelBadge';
import Loading from '../../components/Loading';
import TournamentType from '../../components/TournamentType';
import TournamentStates from '../../config/tournament';
+import TournamentTypes from '../../config/tournamentTypes';
import useTimer from '../../utils/useTimer';
import JoinButton from './JoinButton';
@@ -134,11 +135,13 @@ function TournamentHeader({
playersCount,
playersLimit,
currentUserId,
+ showBots = true,
hideResults = true,
level,
isOnline,
isOver,
canModerate,
+ toggleShowBots,
handleStartRound,
handleOpenDetails,
}) {
@@ -169,6 +172,7 @@ function TournamentHeader({
|| state === TournamentStates.active
|| state === TournamentStates.finished
|| state === TournamentStates.cancelled;
+ const canToggleShowBots = type === TournamentTypes.show;
return (
<>
@@ -250,10 +254,13 @@ function TournamentHeader({
canStartRound={canStartRound}
canFinishRound={canFinishRound}
canRestart={canRestart}
+ canToggleShowBots={canToggleShowBots}
+ showBots={showBots}
hideResults={hideResults}
disabled={!isOnline}
handleStartRound={handleStartRound}
handleOpenDetails={handleOpenDetails}
+ toggleShowBots={toggleShowBots}
/>
)}
diff --git a/services/app/apps/codebattle/assets/js/widgets/pages/tournament/TournamentMainControlButtons.jsx b/services/app/apps/codebattle/assets/js/widgets/pages/tournament/TournamentMainControlButtons.jsx
index 0dbbe95e3..25dfe0e0f 100644
--- a/services/app/apps/codebattle/assets/js/widgets/pages/tournament/TournamentMainControlButtons.jsx
+++ b/services/app/apps/codebattle/assets/js/widgets/pages/tournament/TournamentMainControlButtons.jsx
@@ -29,9 +29,12 @@ const TournamentMainControlButtons = ({
canStart,
canStartRound,
canFinishRound,
+ canToggleShowBots,
canRestart,
- disabled = true,
+ showBots,
hideResults,
+ disabled = true,
+ toggleShowBots,
handleStartRound,
handleOpenDetails,
}) => {
@@ -115,6 +118,14 @@ const TournamentMainControlButtons = ({
Show Results
+
+
+ {showBots ? 'Hide bots' : 'Show bots'}
+
,
* tournamentsInfo: {?Object},
@@ -364,6 +367,11 @@ const defaultTournamentPlayerParams = {
* alerts: Object,
* }} GameState
* @typedef {{
+ * id: number,
+ * level: @type {import("../config/levels.js").default},
+ * name: string,
+ * }} TaskInfo
+ * @typedef {{
* accessToken: string,
* accessType: string,
* breakDurationSeconds: number,
@@ -371,7 +379,7 @@ const defaultTournamentPlayerParams = {
* currentRoundPosition: number,
* defaultLanguage: string,
* description: string,
- * level: string,
+ * level: @type {import("../config/levels.js").default},
* matchTimeoutSeconds: number,
* matches: Object,
* lastRoundStartedAt: string,
@@ -380,6 +388,7 @@ const defaultTournamentPlayerParams = {
* name: string,
* playedPairIds: number[],
* players: Object,
+ * taskList: TaskInfo[],
* playersCount: number,
* playersLimit: number,
* startsAt: string,
@@ -387,6 +396,8 @@ const defaultTournamentPlayerParams = {
* taskStrategy: string,
* type: string,
* useChat: boolean,
+ * showBots: boolean,
+ * showResults: boolean,
* }} TournamentState
*
* @typedef {{
@@ -415,6 +426,8 @@ const defaultTournamentPlayerParams = {
export default {
game: {
gameStatus: initialGameStatus,
+ award: null,
+ awardStatus: 'idle',
task: initialGameTask,
players: initialPlayers,
tournamentsInfo: null,
diff --git a/services/app/apps/codebattle/assets/js/widgets/slices/tournament.js b/services/app/apps/codebattle/assets/js/widgets/slices/tournament.js
index 2ee132c90..16eca57b2 100644
--- a/services/app/apps/codebattle/assets/js/widgets/slices/tournament.js
+++ b/services/app/apps/codebattle/assets/js/widgets/slices/tournament.js
@@ -1,6 +1,8 @@
import { createSlice } from '@reduxjs/toolkit';
import omit from 'lodash/omit';
+import TournamentTypes from '../config/tournamentTypes';
+
import initial from './initial';
const initialState = initial.tournament;
@@ -14,7 +16,12 @@ const tournament = createSlice({
}),
updateTournamentData: (state, { payload }) => ({
...state,
- ...(['swiss', 'ladder', 'stairway'].includes(payload.type) ? omit(payload, ['matches', 'players']) : payload),
+ ...(
+ [TournamentTypes.swiss, TournamentTypes.ladder, TournamentTypes.stairway, TournamentTypes.show]
+ .includes(payload.type)
+ ? omit(payload, ['matches', 'players'])
+ : payload
+ ),
}),
updateTournamentMatches: (state, { payload }) => {
const newMatches = payload.reduce((acc, match) => ({
@@ -30,6 +37,9 @@ const tournament = createSlice({
...newMatches,
};
},
+ setTournamentTaskList: (state, { payload }) => {
+ state.taskList = payload;
+ },
addTournamentPlayer: (state, { payload }) => {
state.players = { ...state.players, [payload.player.id]: payload.player };
},
@@ -74,6 +84,11 @@ const tournament = createSlice({
setTournamentPlayersPageNumber: (state, { payload }) => {
state.playersPageNumber = payload;
},
+ toggleShowBots: state => {
+ if (state.type === TournamentTypes.show) {
+ state.showBots = !state.showBots;
+ }
+ },
},
});
diff --git a/services/app/apps/codebattle/assets/js/widgets/utils/useGameRoomSocketChannel.js b/services/app/apps/codebattle/assets/js/widgets/utils/useGameRoomSocketChannel.js
new file mode 100644
index 000000000..d14898c52
--- /dev/null
+++ b/services/app/apps/codebattle/assets/js/widgets/utils/useGameRoomSocketChannel.js
@@ -0,0 +1,40 @@
+import { useEffect } from 'react';
+
+import { useDispatch, useSelector } from 'react-redux';
+
+import PageNames from '../config/pageNames';
+import * as ChatActions from '../middlewares/Chat';
+import * as GameRoomActions from '../middlewares/Room';
+import * as selectors from '../selectors';
+
+const useGameRoomSocketChannel = (pageName, machines) => {
+ const dispatch = useDispatch();
+
+ const useChat = useSelector(selectors.gameUseChatSelector);
+
+ useEffect(() => {
+ if (pageName === PageNames.builder) {
+ const clearTask = GameRoomActions.connectToTask(
+ machines.mainService,
+ machines.taskService,
+ )(dispatch);
+
+ return clearTask;
+ }
+
+ const options = { cancelRedirect: false };
+
+ const clearGame = GameRoomActions.connectToGame(machines.mainService, options)(
+ dispatch,
+ );
+ const clearChat = ChatActions.connectToChat(useChat)(dispatch);
+
+ return () => {
+ clearGame();
+ clearChat();
+ };
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+};
+
+export default useGameRoomSocketChannel;
diff --git a/services/app/apps/codebattle/assets/js/widgets/utils/useGameRoomSoundSettings.js b/services/app/apps/codebattle/assets/js/widgets/utils/useGameRoomSoundSettings.js
new file mode 100644
index 000000000..3c4b593de
--- /dev/null
+++ b/services/app/apps/codebattle/assets/js/widgets/utils/useGameRoomSoundSettings.js
@@ -0,0 +1,38 @@
+import { useEffect } from 'react';
+
+import { useDispatch, useSelector } from 'react-redux';
+
+import sound from '../lib/sound';
+import { actions } from '../slices';
+
+const useGameRoomSoundSettings = () => {
+ const dispatch = useDispatch();
+
+ const mute = useSelector(state => state.user.settings.mute);
+
+ useEffect(() => {
+ const muteSound = e => {
+ if ((e.ctrlKey || e.metaKey) && e.key === 'm') {
+ e.preventDefault();
+
+ if (mute) {
+ sound.toggle();
+ } else {
+ sound.toggle(0);
+ }
+
+ dispatch(actions.toggleMuteSound());
+ }
+ };
+
+ window.addEventListener('keydown', muteSound);
+
+ return () => {
+ window.removeEventListener('keydown', muteSound);
+ };
+ }, [dispatch, mute]);
+
+ return mute;
+};
+
+export default useGameRoomSoundSettings;
diff --git a/services/app/apps/codebattle/assets/js/widgets/utils/useRoomSettings.js b/services/app/apps/codebattle/assets/js/widgets/utils/useRoomSettings.js
index 8d51ceee6..fefd1b3c7 100644
--- a/services/app/apps/codebattle/assets/js/widgets/utils/useRoomSettings.js
+++ b/services/app/apps/codebattle/assets/js/widgets/utils/useRoomSettings.js
@@ -30,10 +30,9 @@ const useRoomSettings = (pageName, roomMachineState) => {
const showBattleRoom = !showTaskBuilder;
const showTimeoutMessage = gameStatus.state === GameStateCodes.timeout && !(firstPlayer && secondPlayer);
- console.log(gameStatus);
-
return {
tournamentId,
+ // viewMode: BattleRoomViewModesCodes.single,
viewMode: mapGameTypeOnViewMode[gameStatus.type] || BattleRoomViewModesCodes.duel,
showWaitingRoom,
showBattleRoom,
diff --git a/services/app/apps/codebattle/lib/codebattle/game/auth.ex b/services/app/apps/codebattle/lib/codebattle/game/auth.ex
index d54c8832f..78d67e593 100644
--- a/services/app/apps/codebattle/lib/codebattle/game/auth.ex
+++ b/services/app/apps/codebattle/lib/codebattle/game/auth.ex
@@ -17,7 +17,7 @@ defmodule Codebattle.Game.Auth do
is_player =
Game.Context.get_active_games()
|> Enum.any?(fn game ->
- Game.Helpers.is_player?(game, player.id)
+ Game.Helpers.player?(game, player.id)
end)
case is_player do
@@ -27,7 +27,7 @@ defmodule Codebattle.Game.Auth do
end
def player_can_cancel_game?(game, player) do
- case {Game.Helpers.is_player?(game, player.id), game.state} do
+ case {Game.Helpers.player?(game, player.id), game.state} do
{true, "waiting_opponent"} -> :ok
{false, _} -> {:error, :not_authorized}
{_, _} -> {:error, :only_waiting_opponent}
@@ -35,7 +35,7 @@ defmodule Codebattle.Game.Auth do
end
def player_can_rematch?(game, player_id) do
- case Game.Helpers.is_player?(game, player_id) do
+ case Game.Helpers.player?(game, player_id) do
true -> :ok
false -> {:error, :not_authorized}
end
diff --git a/services/app/apps/codebattle/lib/codebattle/game/helpers.ex b/services/app/apps/codebattle/lib/codebattle/game/helpers.ex
index d373263a1..1490ae87d 100644
--- a/services/app/apps/codebattle/lib/codebattle/game/helpers.ex
+++ b/services/app/apps/codebattle/lib/codebattle/game/helpers.ex
@@ -38,7 +38,7 @@ defmodule Codebattle.Game.Helpers do
|> Enum.find(fn player -> player.id == id end)
end
- def is_player?(game, player_id) do
+ def player?(game, player_id) do
game
|> get_players
|> Enum.any?(&(&1.id == player_id))
@@ -75,10 +75,10 @@ defmodule Codebattle.Game.Helpers do
|> Enum.into(%{})
end
- def winner?(game, player_id), do: is_player_result?(game, player_id, "won")
+ def winner?(game, player_id), do: player_result?(game, player_id, "won")
- def lost?(game, player_id), do: is_player_result?(game, player_id, "lost")
- def gave_up?(game, player_id), do: is_player_result?(game, player_id, "gave_up")
+ def lost?(game, player_id), do: player_result?(game, player_id, "lost")
+ def gave_up?(game, player_id), do: player_result?(game, player_id, "gave_up")
def update_player(game, player_id, params) do
new_players =
@@ -126,7 +126,7 @@ defmodule Codebattle.Game.Helpers do
}
end
- defp is_player_result?(game, player_id, result) do
+ defp player_result?(game, player_id, result) do
game
|> get_players
|> Enum.find_value(fn p -> p.id == player_id && p.result == result end)
diff --git a/services/app/apps/codebattle/lib/codebattle/tournament/helpers.ex b/services/app/apps/codebattle/lib/codebattle/tournament/helpers.ex
index 5bab67d62..f80f42dff 100644
--- a/services/app/apps/codebattle/lib/codebattle/tournament/helpers.ex
+++ b/services/app/apps/codebattle/lib/codebattle/tournament/helpers.ex
@@ -15,6 +15,7 @@ defmodule Codebattle.Tournament.Helpers do
def get_players(tournament, ids), do: Tournament.Players.get_players(tournament, ids)
+ def get_tasks(tournament = %{tasks_table: nil}), do: []
def get_tasks(tournament), do: Tournament.Tasks.get_tasks(tournament)
def players_count(tournament = %{players_table: nil}) do
@@ -135,7 +136,7 @@ defmodule Codebattle.Tournament.Helpers do
)
end
- def is_match_player?(match, player_id), do: Enum.any?(match.player_ids, &(&1 == player_id))
+ def match_player?(match, player_id), do: Enum.any?(match.player_ids, &(&1 == player_id))
def get_player_ids(tournament), do: tournament |> get_players |> Enum.map(& &1.id)
@@ -150,37 +151,37 @@ defmodule Codebattle.Tournament.Helpers do
def can_be_started?(_t), do: false
def can_moderate?(tournament, user) do
- is_creator?(tournament, user) || User.admin?(user)
+ creator?(tournament, user) || User.admin?(user)
end
def can_access?(tournament = %{access_type: "token"}, user, params) do
can_moderate?(tournament, user) ||
- is_player?(tournament, user.id) ||
+ player?(tournament, user.id) ||
params["access_token"] == tournament.access_token
end
# default public or null for old tournaments
def can_access?(_tournament, _user, _params), do: true
- def is_active?(tournament), do: tournament.state == "active"
- def is_waiting_participants?(tournament), do: tournament.state == "waiting_participants"
- def is_canceled?(tournament), do: tournament.state == "canceled"
- def is_finished?(tournament), do: tournament.state == "finished"
- def is_individual?(tournament), do: tournament.type == "individual"
- def is_stairway?(tournament), do: tournament.type == "stairway"
- def is_team?(tournament), do: tournament.type == "team"
- def is_public?(tournament), do: tournament.access_type == "public"
- def is_visible_by_token?(tournament), do: tournament.access_type == "token"
+ def active?(tournament), do: tournament.state == "active"
+ def waiting_participants?(tournament), do: tournament.state == "waiting_participants"
+ def canceled?(tournament), do: tournament.state == "canceled"
+ def finished?(tournament), do: tournament.state == "finished"
+ def individual?(tournament), do: tournament.type == "individual"
+ def stairway?(tournament), do: tournament.type == "stairway"
+ def team?(tournament), do: tournament.type == "team"
+ def public?(tournament), do: tournament.access_type == "public"
+ def visible_by_token?(tournament), do: tournament.access_type == "token"
def in_break?(tournament), do: tournament.break_state == "on"
- def is_player?(tournament, player_id) do
+ def player?(tournament, player_id) do
tournament
|> get_player(player_id)
|> Kernel.!()
|> Kernel.!()
end
- def is_player?(tournament, player_id, team_id) do
+ def player?(tournament, player_id, team_id) do
tournament
|> get_player(player_id)
|> case do
@@ -189,7 +190,7 @@ defmodule Codebattle.Tournament.Helpers do
end
end
- def is_creator?(tournament, user) do
+ def creator?(tournament, user) do
tournament.creator_id == user.id
end
diff --git a/services/app/apps/codebattle/lib/codebattle/tournament/server.ex b/services/app/apps/codebattle/lib/codebattle/tournament/server.ex
index 21e9f9d9b..9a83865d3 100644
--- a/services/app/apps/codebattle/lib/codebattle/tournament/server.ex
+++ b/services/app/apps/codebattle/lib/codebattle/tournament/server.ex
@@ -144,7 +144,7 @@ defmodule Codebattle.Tournament.Server do
def handle_info({:stop_round_break, round_position}, %{tournament: tournament}) do
if tournament.current_round_position == round_position and
in_break?(tournament) and
- not is_finished?(tournament) do
+ not finished?(tournament) do
new_tournament = tournament.module.stop_round_break(tournament)
{:noreply, %{tournament: new_tournament}}
@@ -156,7 +156,7 @@ defmodule Codebattle.Tournament.Server do
def handle_info({:finish_round_force, round_position}, %{tournament: tournament}) do
if tournament.current_round_position == round_position and
not in_break?(tournament) and
- not is_finished?(tournament) do
+ not finished?(tournament) do
new_tournament = tournament.module.finish_round(tournament)
{:noreply, %{tournament: new_tournament}}
@@ -168,7 +168,7 @@ defmodule Codebattle.Tournament.Server do
def handle_info({:start_rematch, match_ref, round_position}, %{tournament: tournament}) do
if tournament.current_round_position == round_position and
not in_break?(tournament) and
- not is_finished?(tournament) do
+ not finished?(tournament) do
new_tournament = tournament.module.start_rematch(tournament, match_ref)
broadcast_tournament_update(new_tournament)
@@ -191,7 +191,7 @@ defmodule Codebattle.Tournament.Server do
if tournament.current_round_position == match.round_position and
not in_break?(tournament) and
- not is_finished?(tournament) do
+ not finished?(tournament) do
new_tournament =
tournament.module.finish_match(tournament, Map.put(payload, :game_id, match.game_id))
diff --git a/services/app/apps/codebattle/lib/codebattle/tournament/strategy/base.ex b/services/app/apps/codebattle/lib/codebattle/tournament/strategy/base.ex
index ef766a415..522905811 100644
--- a/services/app/apps/codebattle/lib/codebattle/tournament/strategy/base.ex
+++ b/services/app/apps/codebattle/lib/codebattle/tournament/strategy/base.ex
@@ -575,6 +575,7 @@ defmodule Codebattle.Tournament.Base do
defp broadcast_round_created(tournament) do
Codebattle.PubSub.broadcast("tournament:round_created", %{tournament: tournament})
+
tournament
end
diff --git a/services/app/apps/codebattle/lib/codebattle/tournament/tournament.ex b/services/app/apps/codebattle/lib/codebattle/tournament/tournament.ex
index 398ecbfab..314d0d48d 100644
--- a/services/app/apps/codebattle/lib/codebattle/tournament/tournament.ex
+++ b/services/app/apps/codebattle/lib/codebattle/tournament/tournament.ex
@@ -126,6 +126,7 @@ defmodule Codebattle.Tournament do
:task_pack_name,
:task_provider,
:task_strategy,
+ :task_pack_name,
:type,
:use_chat,
:use_infinite_break,
diff --git a/services/app/apps/codebattle/lib/codebattle_web/channels/lobby_channel.ex b/services/app/apps/codebattle/lib/codebattle_web/channels/lobby_channel.ex
index 0a177828a..7d7353388 100644
--- a/services/app/apps/codebattle/lib/codebattle_web/channels/lobby_channel.ex
+++ b/services/app/apps/codebattle/lib/codebattle_web/channels/lobby_channel.ex
@@ -102,7 +102,7 @@ defmodule CodebattleWeb.LobbyChannel do
def handle_info(_, socket), do: {:noreply, socket}
defp can_user_see_game?(game, user) do
- game.visibility_type == "public" || Game.Helpers.is_player?(game, user)
+ game.visibility_type == "public" || Game.Helpers.player?(game, user)
end
defp add_players(acc, %{"opponent_type" => "bot"}, user),
diff --git a/services/app/apps/codebattle/lib/codebattle_web/channels/tournament_channel.ex b/services/app/apps/codebattle/lib/codebattle_web/channels/tournament_channel.ex
index 633abe1bb..7b78535bd 100644
--- a/services/app/apps/codebattle/lib/codebattle_web/channels/tournament_channel.ex
+++ b/services/app/apps/codebattle/lib/codebattle_web/channels/tournament_channel.ex
@@ -253,12 +253,19 @@ defmodule CodebattleWeb.TournamentChannel do
def handle_info(%{event: "tournament:updated", payload: payload}, socket) do
matches =
- if payload.tournament.type in ["swiss", "ladder"] do
+ if payload.tournament.type in ["swiss", "ladder", "show"] do
[]
else
Helpers.get_matches(payload.tournament)
end
+ tasks_info =
+ if payload.tournament.type == "show" do
+ Helpers.get_tasks(payload.tournament)
+ else
+ []
+ end
+
push(socket, "tournament:update", %{
tournament:
Map.drop(payload.tournament, [
@@ -274,7 +281,8 @@ defmodule CodebattleWeb.TournamentChannel do
:played_pair_ids
]),
players: Helpers.get_top_players(payload.tournament),
- matches: matches
+ matches: matches,
+ tasks_info: tasks_info
})
{:noreply, socket}
@@ -287,7 +295,10 @@ defmodule CodebattleWeb.TournamentChannel do
end
def handle_info(%{event: "tournament:round_created", payload: payload}, socket) do
- push(socket, "tournament:round_created", %{tournament: payload.tournament})
+ push(socket, "tournament:round_created", %{
+ tournament: payload.tournament,
+ tasks_info: payload.tasks_info
+ })
{:noreply, socket}
end
@@ -341,7 +352,7 @@ defmodule CodebattleWeb.TournamentChannel do
tournament
end
- defp get_tournament_join_payload(%{type: type} = tournament, socket)
+ defp get_tournament_join_payload(tournament = %{type: type}, socket)
when type in ["swiss", "ladder", "stairway"] do
current_user = socket.assigns.current_user
@@ -387,7 +398,7 @@ defmodule CodebattleWeb.TournamentChannel do
}
end
- defp get_tournament_join_payload(%{type: "show"} = tournament, _socket) do
+ defp get_tournament_join_payload(tournament = %{type: "show"}, _socket) do
%{
tournament: Map.drop(tournament, [:players_table, :matches_table, :tasks_table]),
matches: Helpers.get_matches(tournament),
diff --git a/services/app/apps/codebattle/lib/codebattle_web/controllers/api/v1/user_game_report_controller.ex b/services/app/apps/codebattle/lib/codebattle_web/controllers/api/v1/user_game_report_controller.ex
index e5b6a8265..e452a8619 100644
--- a/services/app/apps/codebattle/lib/codebattle_web/controllers/api/v1/user_game_report_controller.ex
+++ b/services/app/apps/codebattle/lib/codebattle_web/controllers/api/v1/user_game_report_controller.ex
@@ -13,8 +13,8 @@ defmodule CodebattleWeb.Api.V1.UserGameReportController do
reporter = conn.assigns.current_user
game = Game.Context.get_game!(game_id)
- is_reporter_player = Game.Helpers.is_player?(game, reporter.id)
- is_reported_user_player = Game.Helpers.is_player?(game, reported_user_id)
+ is_reporter_player = Game.Helpers.player?(game, reporter.id)
+ is_reported_user_player = Game.Helpers.player?(game, reported_user_id)
is_reported_himself = reporter.id == reported_user_id
case {is_reporter_player, is_reported_himself, is_reported_user_player} do
diff --git a/services/app/apps/codebattle/lib/codebattle_web/controllers/game_controller.ex b/services/app/apps/codebattle/lib/codebattle_web/controllers/game_controller.ex
index 6589507ed..0f2535f9f 100644
--- a/services/app/apps/codebattle/lib/codebattle_web/controllers/game_controller.ex
+++ b/services/app/apps/codebattle/lib/codebattle_web/controllers/game_controller.ex
@@ -33,7 +33,7 @@ defmodule CodebattleWeb.GameController do
players: present_users_for_gon(Helpers.get_players(game))
)
- is_player = Helpers.is_player?(game, user.id)
+ is_player = Helpers.player?(game, user.id)
case {game.state, is_player} do
{"waiting_opponent", false} ->
diff --git a/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/edit_form.ex b/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/edit_form.ex
index b1269e0a2..a7f1bd570 100644
--- a/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/edit_form.ex
+++ b/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/edit_form.ex
@@ -108,14 +108,14 @@ defmodule CodebattleWeb.Live.Tournament.EditFormComponent do
) %>
<%= error_tag(f, :task_provider) %>
- <%= if (f.params["task_provider"] == "level" || is_nil(f.params["task_provider"])) do %>
+ <%= if (f.params["task_provider"] == "level" || f.data.task_provider == "level") do %>
<%= label(f, :level) %>
<%= select(f, :level, Codebattle.Tournament.levels(), class: "custom-select") %>
<%= error_tag(f, :level) %>
<% end %>
- <%= if (f.params["task_provider"] == "task_pack") do %>
+ <%= if (f.params["task_provider"] == "task_pack" || f.data.task_provider == "task_pack") do %>
<%= label(f, :task_pack_name) %>
<%= select(f, :task_pack_name, @task_pack_names,
@@ -125,7 +125,7 @@ defmodule CodebattleWeb.Live.Tournament.EditFormComponent do
<%= error_tag(f, :task_pack_name) %>
<% end %>
- <%= if (f.params["task_provider"] == "tags") do %>
+ <%= if (f.params["task_provider"] == "tags" || f.data.task_provider == "tags") do %>
<%= label(f, :tags) %>
<%= text_input(f, :tags,
diff --git a/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/header.ex b/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/header.ex
index 7676a0d6a..831dda9a3 100644
--- a/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/header.ex
+++ b/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/header.ex
@@ -12,10 +12,10 @@ defmodule CodebattleWeb.Live.Tournament.HeaderComponent do
- <%= if is_waiting_participants?(@tournament) do %>
+ <%= if waiting_participants?(@tournament) do %>
- <%= if is_individual?(@tournament) do %>
- <%= if is_player?(@tournament, @current_user.id) do %>
+ <%= if individual?(@tournament) do %>
+ <%= if player?(@tournament, @current_user.id) do %>
Leave
@@ -24,8 +24,8 @@ defmodule CodebattleWeb.Live.Tournament.HeaderComponent do
<% end %>
<% end %>
- <%= if is_stairway?(@tournament) do %>
- <%= if is_player?(@tournament, @current_user.id) do %>
+ <%= if stairway?(@tournament) do %>
+ <%= if player?(@tournament, @current_user.id) do %>
Leave
<% else %>
Join
@@ -44,29 +44,29 @@ defmodule CodebattleWeb.Live.Tournament.HeaderComponent do
Restart
Cancel
- <%= if !is_public?(@tournament) do %>
+ <%= if !public?(@tournament) do %>
Open Up
<% end %>
<% end %>
<% end %>
- <%= if is_active?(@tournament) do %>
+ <%= if active?(@tournament) do %>
<%= if can_moderate?(@tournament, @current_user) do %>
Restart
Cancel
- <%= if !is_public?(@tournament) do %>
+ <%= if !public?(@tournament) do %>
Open Up
<% end %>
<% end %>
<% end %>
- <%= if is_finished?(@tournament) do %>
+ <%= if finished?(@tournament) do %>
<%= if can_moderate?(@tournament, @current_user) do %>
Restart
- <%= if !is_public?(@tournament) do %>
+ <%= if !public?(@tournament) do %>
Open Up
<% end %>
<% end %>
@@ -81,7 +81,7 @@ defmodule CodebattleWeb.Live.Tournament.HeaderComponent do
Access: <%= @tournament.access_type %>
<% end %>
PlayersLimit: <%= @tournament.players_limit %>
- <%= if is_visible_by_token?(@tournament) && can_moderate?(@tournament, @current_user) do %>
+ <%= if visible_by_token?(@tournament) && can_moderate?(@tournament, @current_user) do %>
Private url: <%= Routes.tournament_url(@socket, :show, @tournament.id,
access_token: @tournament.access_token
diff --git a/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/individual.ex b/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/individual.ex
index a816df7b4..e92f4b39a 100644
--- a/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/individual.ex
+++ b/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/individual.ex
@@ -34,11 +34,11 @@ defmodule CodebattleWeb.Live.Tournament.IndividualComponent do
- <%= if is_active?(@tournament) || is_finished?(@tournament) do %>
+ <%= if active?(@tournament) || finished?(@tournament) do %>
<% end %>
- <%= if is_waiting_participants?(@tournament) do %>
- <%= if is_player?(@tournament, @current_user.id) do %>
+ <%= if waiting_participants?(@tournament) do %>
+ <%= if player?(@tournament, @current_user.id) do %>
Leave
diff --git a/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/ladder.ex b/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/ladder.ex
index 40609d24a..23a698f0b 100644
--- a/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/ladder.ex
+++ b/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/ladder.ex
@@ -26,7 +26,7 @@ defmodule CodebattleWeb.Live.Tournament.LadderComponent do
current_user={@current_user}
messages={@messages}
/>
- <%= if is_waiting_participants?(@tournament) do %>
+ <%= if waiting_participants?(@tournament) do %>
- <%= if !is_waiting_participants?(@tournament) do %>
+ <%= if !waiting_participants?(@tournament) do %>
<% end %>
- <%= if is_waiting_participants?(@tournament) do %>
- <%= if is_player?(@tournament, @current_user.id) do %>
+ <%= if waiting_participants?(@tournament) do %>
+ <%= if player?(@tournament, @current_user.id) do %>
Leave
diff --git a/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/match.ex b/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/match.ex
index 103ae0cb0..af76960e9 100644
--- a/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/match.ex
+++ b/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/match.ex
@@ -38,7 +38,7 @@ defmodule CodebattleWeb.Live.Tournament.MatchComponent do
end
def get_match_bg_class(match, player_id) do
- if is_match_player?(match, player_id) do
+ if match_player?(match, player_id) do
"p-1 border border-success bg-winner"
else
"p-1 border border-success"
@@ -46,7 +46,7 @@ defmodule CodebattleWeb.Live.Tournament.MatchComponent do
end
def get_game_link_name(match, player_id) do
- case {match.state, is_match_player?(match, player_id)} do
+ case {match.state, match_player?(match, player_id)} do
{"pending", true} -> "Pending"
{"playing", true} -> "Join"
_ -> "Show"
diff --git a/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/players.ex b/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/players.ex
index 6ef632c30..dc934a2a2 100644
--- a/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/players.ex
+++ b/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/players.ex
@@ -19,7 +19,7 @@ defmodule CodebattleWeb.Live.Tournament.PlayersComponent do
- <%= if can_moderate?(@tournament, @current_user) and is_waiting_participants?(@tournament) do %>
+ <%= if can_moderate?(@tournament, @current_user) and waiting_participants?(@tournament) do %>
- <%= if is_waiting_participants?(@tournament) do %>
+ <%= if waiting_participants?(@tournament) do %>
- <%= if !is_waiting_participants?(@tournament) do %>
+ <%= if !waiting_participants?(@tournament) do %>
<% end %>
- <%= if is_waiting_participants?(@tournament) do %>
- <%= if is_player?(@tournament, @current_user.id) do %>
+ <%= if waiting_participants?(@tournament) do %>
+ <%= if player?(@tournament, @current_user.id) do %>
Leave
diff --git a/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/stairway_round.ex b/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/stairway_round.ex
index d85eda285..81c40f4ec 100644
--- a/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/stairway_round.ex
+++ b/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/stairway_round.ex
@@ -68,7 +68,7 @@ defmodule CodebattleWeb.Live.Tournament.StairwayRoundComponent do
end
defp get_game_link_name(match, player_id) do
- case {match.state, is_match_player?(match, player_id)} do
+ case {match.state, match_player?(match, player_id)} do
{"pending", true} -> "Pending"
{"playing", true} -> "Join"
_ -> "Show"
@@ -76,7 +76,7 @@ defmodule CodebattleWeb.Live.Tournament.StairwayRoundComponent do
end
defp get_match_bg_class(match, player_id) do
- if is_match_player?(match, player_id) do
+ if match_player?(match, player_id) do
"p-1 border bg-winner"
else
"p-1 border"
diff --git a/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/swiss.ex b/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/swiss.ex
index 226c31094..5412e9efb 100644
--- a/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/swiss.ex
+++ b/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/swiss.ex
@@ -26,7 +26,7 @@ defmodule CodebattleWeb.Live.Tournament.SwissComponent do
current_user={@current_user}
messages={@messages}
/>
- <%= if is_waiting_participants?(@tournament) do %>
+ <%= if waiting_participants?(@tournament) do %>
- <%= if !is_waiting_participants?(@tournament) do %>
+ <%= if !waiting_participants?(@tournament) do %>
<% end %>
- <%= if is_waiting_participants?(@tournament) do %>
- <%= if is_player?(@tournament, @current_user.id) do %>
+ <%= if waiting_participants?(@tournament) do %>
+ <%= if player?(@tournament, @current_user.id) do %>
Leave
diff --git a/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/team_round.ex b/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/team_round.ex
index da0b8ac10..9a26520ba 100644
--- a/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/team_round.ex
+++ b/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/team_round.ex
@@ -39,7 +39,7 @@ defmodule CodebattleWeb.Live.Tournament.TeamRoundComponent do
end
def get_game_link_name(match, player_id) do
- case {match.state, is_match_player?(match, player_id)} do
+ case {match.state, match_player?(match, player_id)} do
{"pending", true} -> "Pending"
{"playing", true} -> "Join"
_ -> "Show"
@@ -47,7 +47,7 @@ defmodule CodebattleWeb.Live.Tournament.TeamRoundComponent do
end
def get_match_bg_class(match, player_id) do
- if is_match_player?(match, player_id) do
+ if match_player?(match, player_id) do
"row align-items-center py-2 bg-light"
else
"row align-items-center py-2"
diff --git a/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/team_tab.ex b/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/team_tab.ex
index a286c0f88..2a121c11c 100644
--- a/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/team_tab.ex
+++ b/services/app/apps/codebattle/lib/codebattle_web/live/components/tournament/team_tab.ex
@@ -22,8 +22,8 @@ defmodule CodebattleWeb.Live.Tournament.TeamTabComponent do
<%= for team <- @teams do %>
- <%= if is_waiting_participants?(@tournament) do %>
- <%= if is_player?(@tournament, @current_user.id, team.id) do %>
+ <%= if waiting_participants?(@tournament) do %>
+ <%= if player?(@tournament, @current_user.id, team.id) do %>
Leave
<% else %>
diff --git a/services/app/apps/codebattle/lib/codebattle_web/views/api/lobby_view.ex b/services/app/apps/codebattle/lib/codebattle_web/views/api/lobby_view.ex
index fe744b834..565fae285 100644
--- a/services/app/apps/codebattle/lib/codebattle_web/views/api/lobby_view.ex
+++ b/services/app/apps/codebattle/lib/codebattle_web/views/api/lobby_view.ex
@@ -29,6 +29,6 @@ defmodule CodebattleWeb.Api.LobbyView do
end
def can_user_see_game?(game, user) do
- game.visibility_type == "public" || Game.Helpers.is_player?(game, user)
+ game.visibility_type == "public" || Game.Helpers.player?(game, user)
end
end