From ab81a5351c79f25a4716a6442a87e86fb52f4aad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Rivi=C3=A8re?= Date: Fri, 20 Jun 2025 00:21:16 +0200 Subject: [PATCH] =?UTF-8?q?Modification=20des=20param=C3=A8tres=20en=20cou?= =?UTF-8?q?rs=20de=20jeu=20+=20UI=20+=20corrections?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- traque-back/admin_socket.js | 6 +++-- traque-back/game.js | 26 ++++++++++++------- traque-back/photo.js | 4 +-- traque-front/app/admin/layout.js | 1 + traque-front/app/admin/page.js | 17 ++++-------- traque-front/app/admin/parameters/page.js | 22 ++++++++++++++++ traque-front/components/admin/mapPicker.jsx | 11 ++++---- .../components/admin/penaltySettings.jsx | 9 ++++++- traque-front/components/admin/teamEdit.jsx | 8 +++--- traque-front/components/admin/teamList.jsx | 13 +++------- traque-front/components/admin/teamReady.jsx | 2 +- .../components/admin/zoneSelector.jsx | 13 +++++++--- 12 files changed, 81 insertions(+), 51 deletions(-) create mode 100644 traque-front/app/admin/parameters/page.js diff --git a/traque-back/admin_socket.js b/traque-back/admin_socket.js index 595ee89..4976cf2 100644 --- a/traque-back/admin_socket.js +++ b/traque-back/admin_socket.js @@ -76,9 +76,11 @@ export function initAdminSocketHandler() { } if (!game.changeSettings(settings)) { socket.emit("error", "Invalid settings"); + socket.emit("game_settings", penaltyController.settings) + } else { + secureAdminBroadcast("game_settings", game.settings); + playersBroadcast("game_settings", game.settings); } - secureAdminBroadcast("game_settings", game.settings); - playersBroadcast("game_settings", game.settings); }) socket.on("set_zone_settings", (settings) => { diff --git a/traque-back/game.js b/traque-back/game.js index 4dafe42..bc6a6af 100644 --- a/traque-back/game.js +++ b/traque-back/game.js @@ -297,7 +297,7 @@ export default { } this.teams = this.teams.filter(t => t.id !== teamId); this.updateTeamChasing(); - timeoutHandler.endSendPositionTimeout(team.id); + timeoutHandler.endSendPositionTimeout(teamId); return true; }, @@ -342,17 +342,23 @@ export default { * @returns false if failed */ setZoneSettings(newSettings) { - //cannot change zones while playing + if ('min' in newSettings || 'max' in newSettings) { + const min = newSettings.min ?? zoneManager.zoneSettings.min; + const max = newSettings.max ?? zoneManager.zoneSettings.max; + // The end zone must be included in the start zone + if (!isInCircle(min.center, max.center, max.radius-min.radius)) { + return false; + } + } + zoneManager.udpateSettings(newSettings); if (this.state == GameState.PLAYING || this.state == GameState.FINISHED) { - return false; + zoneManager.reset() + if (!zoneManager.start()) { + this.setState(GameState.SETUP); + return false; + } } - var min = newSettings.min; - var max = newSettings.max; - // The end zone must be included in the start zone - if (!isInCircle(min.center, max.center, max.radius-min.radius)) { - return false; - } - return zoneManager.udpateSettings(newSettings); + return true; }, /** diff --git a/traque-back/photo.js b/traque-back/photo.js index c02df53..d26c20b 100644 --- a/traque-back/photo.js +++ b/traque-back/photo.js @@ -59,8 +59,8 @@ export function initPhotoUpload() { //App handler for serving the photo of a team given its secret ID app.get("/photo/my", (req, res) => { let team = game.getTeam(Number(req.query.team)); - const imagePath = path.join(process.cwd(), UPLOAD_DIR, team.id.toString()); if (team) { + const imagePath = path.join(process.cwd(), UPLOAD_DIR, team.id.toString()); res.set("Content-Type", "image/png") res.set("Access-Control-Allow-Origin", "*"); res.sendFile(fs.existsSync(imagePath) ? imagePath : path.join(process.cwd(), "images", "missing_image.jpg")); @@ -71,8 +71,8 @@ export function initPhotoUpload() { //App handler for serving the photo of the team chased by the team given by its secret ID app.get("/photo/enemy", (req, res) => { let team = game.getTeam(Number(req.query.team)); - const imagePath = path.join(process.cwd(), UPLOAD_DIR, team.chasing.toString()); if (team) { + const imagePath = path.join(process.cwd(), UPLOAD_DIR, team.chasing.toString()); res.set("Content-Type", "image/png") res.set("Access-Control-Allow-Origin", "*"); res.sendFile(fs.existsSync(imagePath) ? imagePath : path.join(process.cwd(), "images", "missing_image.jpg")); diff --git a/traque-front/app/admin/layout.js b/traque-front/app/admin/layout.js index 9ff7fa6..b2097d4 100644 --- a/traque-front/app/admin/layout.js +++ b/traque-front/app/admin/layout.js @@ -11,6 +11,7 @@ export default function AdminLayout({ children}) {
diff --git a/traque-front/app/admin/page.js b/traque-front/app/admin/page.js index a12197e..5cab131 100644 --- a/traque-front/app/admin/page.js +++ b/traque-front/app/admin/page.js @@ -1,16 +1,12 @@ "use client"; -import { GameSettings } from "@/components/admin/gameSettings"; -import { PenaltySettings } from "@/components/admin/penaltySettings"; import { TeamReady } from "@/components/admin/teamReady"; import BlueButton, { GreenButton, RedButton } from "@/components/util/button"; import { useAdminConnexion } from "@/context/adminConnexionContext"; import useAdmin from "@/hook/useAdmin"; import { GameState } from "@/util/gameState"; import dynamic from "next/dynamic"; +import { TeamListFixed } from '@/components/admin/teamList'; -const ZoneSelector = dynamic(() => import('@/components/admin/zoneSelector').then((mod) => mod.ZoneSelector), { - ssr: false -}); const LiveMap = dynamic(() => import('@/components/admin/mapPicker').then((mod) => mod.LiveMap), { ssr: false }); @@ -22,7 +18,7 @@ export default function AdminPage() {
-

Game state

+

Game state

Current : {gameState}
changeState(GameState.SETUP)}>Reset game @@ -30,14 +26,11 @@ export default function AdminPage() { changeState(GameState.PLAYING)}>Start game
- + {gameState == GameState.PLACEMENT && }
- {gameState == GameState.PLACEMENT &&
} - {(gameState == GameState.SETUP || gameState == GameState.PLACEMENT) && } - {(gameState == GameState.SETUP || gameState == GameState.PLACEMENT) && } - {gameState == GameState.PLAYING &&
+
-
} +
) } \ No newline at end of file diff --git a/traque-front/app/admin/parameters/page.js b/traque-front/app/admin/parameters/page.js new file mode 100644 index 0000000..3d5f318 --- /dev/null +++ b/traque-front/app/admin/parameters/page.js @@ -0,0 +1,22 @@ +"use client"; +import { GameSettings } from "@/components/admin/gameSettings"; +import { PenaltySettings } from "@/components/admin/penaltySettings"; +import { useAdminConnexion } from "@/context/adminConnexionContext"; +import dynamic from "next/dynamic"; + +const ZoneSelector = dynamic(() => import('@/components/admin/zoneSelector').then((mod) => mod.ZoneSelector), { + ssr: false +}); +export default function AdminPage() { + const { useProtect } = useAdminConnexion(); + useProtect(); + return ( +
+
+ +
+ + +
+ ) +} \ No newline at end of file diff --git a/traque-front/components/admin/mapPicker.jsx b/traque-front/components/admin/mapPicker.jsx index f2af583..31ce085 100644 --- a/traque-front/components/admin/mapPicker.jsx +++ b/traque-front/components/admin/mapPicker.jsx @@ -5,6 +5,7 @@ import "leaflet/dist/leaflet.css"; import { Circle, MapContainer, Marker, TileLayer, useMap, Tooltip, Polyline } from "react-leaflet"; import { useMapCircleDraw } from "@/hook/mapDrawing"; import useAdmin from "@/hook/useAdmin"; +import { GameState } from "@/util/gameState"; const positionIcon = new L.Icon({ iconUrl: '/icons/location.png', @@ -109,7 +110,7 @@ export function ZonePicker({ minZone, setMinZone, maxZone, setMaxZone, editMode, export function LiveMap() { const location = useLocation(Infinity); const [timeLeftNextZone, setTimeLeftNextZone] = useState(null); - const { zone, zoneExtremities, teams, nextZoneDate, isShrinking , getTeam} = useAdmin(); + const { zone, zoneExtremities, teams, nextZoneDate, isShrinking , getTeam, gameState } = useAdmin(); // Remaining time before sending position useEffect(() => { @@ -143,16 +144,16 @@ export function LiveMap() { return (
-

{`${isShrinking ? "Fin" : "Début"} du rétrécissement de la zone dans : ${formatTime(timeLeftNextZone)}`}

+ {gameState == GameState.PLAYING &&

{`${isShrinking ? "Fin" : "Début"} du rétrécissement de la zone dans : ${formatTime(timeLeftNextZone)}`}

} - {zone && } - {zoneExtremities && } - {zoneExtremities && } + {gameState == GameState.PLAYING && zone && } + {gameState == GameState.PLAYING && zoneExtremities && } + {gameState == GameState.PLAYING && zoneExtremities && } {teams.map((team) => team.currentLocation && !team.captured && {team.name} diff --git a/traque-front/components/admin/penaltySettings.jsx b/traque-front/components/admin/penaltySettings.jsx index f7b832a..b7a8d59 100644 --- a/traque-front/components/admin/penaltySettings.jsx +++ b/traque-front/components/admin/penaltySettings.jsx @@ -18,7 +18,14 @@ export const PenaltySettings = () => { }, [penaltySettings]); function applySettings() { - changePenaltySettings({maxPenalties: Number(maxPenalties), allowedTimeOutOfZone: Number(allowedTimeOutOfZone), allowedTimeBetweenPositionUpdate: Number(allowedTimeBetweenUpdates)}); + const newSettings = {maxPenalties: Number(maxPenalties), allowedTimeOutOfZone: Number(allowedTimeOutOfZone), allowedTimeBetweenPositionUpdate: Number(allowedTimeBetweenUpdates)}; + const changingSettings = {}; + for (const key in newSettings) { + if (newSettings[key] != penaltySettings[key]) { + changingSettings[key] = newSettings[key]; + } + } + changePenaltySettings(changingSettings); } return ( diff --git a/traque-front/components/admin/teamEdit.jsx b/traque-front/components/admin/teamEdit.jsx index 0829c88..43ed926 100644 --- a/traque-front/components/admin/teamEdit.jsx +++ b/traque-front/components/admin/teamEdit.jsx @@ -70,19 +70,17 @@ export default function TeamEdit({ selectedTeamId, setSelectedTeamId }) {

Team details

-

Secret : {String(team.id).padStart(6, '0')}

-

Name : {team.name}

+

Secret : {String(team.id).padStart(6, '0').replace(/(\d{3})(\d{3})/, '$1 $2')}

+

Capture code : {String(team.captureCode).padStart(4, '0')}

Chasing : {getTeamName(team.chasing)}

Chased by : {getTeamName(team.chased)}

-

Capture code : {String(team.captureCode).padStart(4, '0')}

-

Captured : {team.captured ? "Yes" : "No"}

-

Has to send location before {new Date(team.locationSendDeadline).toTimeString()}

Penalties :

{team.penalties}

+
diff --git a/traque-front/components/admin/teamList.jsx b/traque-front/components/admin/teamList.jsx index ee6ee41..80c7024 100644 --- a/traque-front/components/admin/teamList.jsx +++ b/traque-front/components/admin/teamList.jsx @@ -12,16 +12,9 @@ const reorder = (list, startIndex, endIndex) => { }; function TeamListItem({ team, index, onSelected, itemSelected }) { - let bgColor; - if(itemSelected) { - bgColor = "bg-blue-400"; - }else if(team.captured) { - bgColor = "bg-red-400"; - } - else { - bgColor = "bg-gray-100"; - } - const classNames = 'w-full p-3 my-3 shadow ' + (bgColor); + const bgColor = team.captured ? " bg-red-400" : " bg-gray-300"; + const border = " border border-4 " + (itemSelected ? "border-black" : team.captured ? "border-red-400" : "border-gray-300"); + const classNames = 'w-full p-3 my-3' + (bgColor) + (border); return ( onSelected(team.id)}> {provided => ( diff --git a/traque-front/components/admin/teamReady.jsx b/traque-front/components/admin/teamReady.jsx index 504ed79..ea5cd60 100644 --- a/traque-front/components/admin/teamReady.jsx +++ b/traque-front/components/admin/teamReady.jsx @@ -2,7 +2,7 @@ import useAdmin from "@/hook/useAdmin" export function TeamReady() { const {teams} = useAdmin(); - return
+ return

Teams ready status

{teams.map((team) => team.ready ? (
diff --git a/traque-front/components/admin/zoneSelector.jsx b/traque-front/components/admin/zoneSelector.jsx index 5b00205..9c770e7 100644 --- a/traque-front/components/admin/zoneSelector.jsx +++ b/traque-front/components/admin/zoneSelector.jsx @@ -24,7 +24,14 @@ export function ZoneSelector() { }, [zoneSettings]); function handleSettingsSubmit() { - changeZoneSettings({min:minZone, max:maxZone, reductionCount: Number(reductionCount), reductionDuration: Number(reductionDuration), reductionInterval: Number(reductionInterval)}); + const newSettings = {min:minZone, max:maxZone, reductionCount: Number(reductionCount), reductionDuration: Number(reductionDuration), reductionInterval: Number(reductionInterval)}; + const changingSettings = {}; + for (const key in newSettings) { + if (newSettings[key] != zoneSettings[key]) { + changingSettings[key] = newSettings[key]; + } + } + changeZoneSettings(changingSettings); } //When the user set one zone, switch to the other @@ -39,8 +46,8 @@ export function ZoneSelector() { return

Edit zones

- {editMode == EditMode.MIN && setEditMode(EditMode.MAX)}>Edit end zone} - {editMode == EditMode.MAX && setEditMode(EditMode.MIN)}>Edit start zone} + {editMode == EditMode.MIN && setEditMode(EditMode.MAX)}>Click to edit first zone} + {editMode == EditMode.MAX && setEditMode(EditMode.MIN)}>Click to edit last zone}

Number of reductions