diff --git a/2024-04-08-Note-11-05.xopp b/2024-04-08-Note-11-05.xopp new file mode 100644 index 0000000..3583cae Binary files /dev/null and b/2024-04-08-Note-11-05.xopp differ diff --git a/traque-front/app/admin/page.js b/traque-front/app/admin/page.js index dbb81a6..c36c8bc 100644 --- a/traque-front/app/admin/page.js +++ b/traque-front/app/admin/page.js @@ -4,7 +4,11 @@ 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"; +const ZoneSelector = dynamic(() => import('@/components/admin/zoneSelector').then((mod) => mod.ZoneSelector), { + ssr: false +}); export default function AdminPage() { const { useProtect } = useAdminConnexion(); const { gameState, changeState } = useAdmin(); @@ -19,6 +23,7 @@ export default function AdminPage() { changeState(GameState.PLAYING)}>Start game {gameState == GameState.PLACEMENT &&
} + {gameState == GameState.SETUP && } ) } \ No newline at end of file diff --git a/traque-front/components/admin/mapPicker.jsx b/traque-front/components/admin/mapPicker.jsx index a265f1d..65b5e96 100644 --- a/traque-front/components/admin/mapPicker.jsx +++ b/traque-front/components/admin/mapPicker.jsx @@ -1,6 +1,6 @@ "use client"; import { useLocation } from "@/hook/useLocation"; -import { use, useEffect, useState } from "react"; +import { useEffect, useState } from "react"; import "leaflet/dist/leaflet.css"; import { Circle, MapContainer, TileLayer, useMap } from "react-leaflet"; import { useMapCircleDraw } from "@/hook/mapDrawing"; @@ -18,7 +18,7 @@ function MapPan(props) { return null; } -function MapEventListener({onClick, onMouseMove}) { +function MapEventListener({ onClick, onMouseMove }) { const map = useMap(); useEffect(() => { map.on('click', onClick); @@ -36,33 +36,52 @@ function MapEventListener({onClick, onMouseMove}) { } const DEFAULT_ZOOM = 17; -export function CircularAreaPicker({area, setArea, ...props}) { +export function CircularAreaPicker({ area, setArea, ...props }) { const location = useLocation(Infinity); - const {handleClick, handleMouseMove, center, radius} = useMapCircleDraw(area, setArea); + const { handleClick, handleMouseMove, center, radius } = useMapCircleDraw(area, setArea); return ( - {center && radius && } + {center && radius && } ) } - -export function ZonePicker({minArea, setMinArea, maxArea, setMaxArea, ...props}) { +export const EditMode = { + MIN: 0, + MAX: 1 +} +export function ZonePicker({ minZone, setMinZone, maxZone, setMaxZone, editMode, ...props }) { const location = useLocation(Infinity); - const {handleClick: maxClick, handleMouseMove: maxHover, center: maxCenter, radius: maxRadius} = useMapCircleDraw(minArea, setMinArea); - const {handleClick: minClick, handleMouseMove: minHover, center: minCenter, radius: minRadius} = useMapCircleDraw(maxArea, setMaxArea); + const { handleClick: maxClick, handleMouseMove: maxHover, center: maxCenter, radius: maxRadius } = useMapCircleDraw(minZone, setMinZone); + const { handleClick: minClick, handleMouseMove: minHover, center: minCenter, radius: minRadius } = useMapCircleDraw(maxZone, setMaxZone); + function handleClick(e) { + if (editMode == EditMode.MAX) { + maxClick(e); + } else { + minClick(e); + } + } + function handleMouseMove(e) { + if (editMode == EditMode.MAX) { + maxHover(e); + } else { + minHover(e); + } + } return ( - {center && radius && } + {minCenter && minRadius && } + {maxCenter && maxRadius && } - ) + + ) } \ No newline at end of file diff --git a/traque-front/components/admin/zoneSelector.jsx b/traque-front/components/admin/zoneSelector.jsx new file mode 100644 index 0000000..c572c75 --- /dev/null +++ b/traque-front/components/admin/zoneSelector.jsx @@ -0,0 +1,51 @@ +import { useEffect, useState } from "react"; +import BlueButton, { GreenButton, RedButton } from "../util/button"; +import { EditMode, ZonePicker } from "./mapPicker"; +import TextInput from "../util/textInput"; +import useAdmin from "@/hook/useAdmin"; + +export function ZoneSelector() { + const [editMode, setEditMode] = useState(EditMode.MIN); + const [minZone, setMinZone] = useState(null); + const [maxZone, setMaxZone] = useState(null); + const [reductionCount, setReductionCount] = useState(""); + const [reductionDuration, setReductionDuration] = useState(""); + const [reductionInterval, setReductionInterval] = useState(""); + const {zoneSettings, changeZoneSettings} = useAdmin(); + + useEffect(() => { + if (zoneSettings) { + setMinZone(zoneSettings.min); + setMaxZone(zoneSettings.max); + setReductionCount(zoneSettings.reductionCount.toString()); + setReductionDuration(zoneSettings.reductionDuration.toString()); + setReductionInterval(zoneSettings.reductionInterval.toString()); + } + }, [zoneSettings]); + + function handleSettingsSubmit() { + changeZoneSettings({min:minZone, max:maxZone, reductionCount: Number(reductionCount), reductionDuration: Number(reductionDuration), reductionInterval: Number(reductionInterval)}); + } + + return
+

Edit zones

+ {editMode == EditMode.MIN && setEditMode(EditMode.MAX)}>Edit end zone} + {editMode == EditMode.MAX && setEditMode(EditMode.MIN)}>Edit start zone} +
+ +
+
+

Number of reductions

+ setReductionCount(e.target.value)}> +
+
+

Duration of each reduction

+ setReductionDuration(e.target.value)}> +
+
+

Interval between reductions

+ setReductionInterval(e.target.value)}> +
+ Save +
+} \ No newline at end of file diff --git a/traque-front/components/team/map.jsx b/traque-front/components/team/map.jsx index 725e5d5..9c897d4 100644 --- a/traque-front/components/team/map.jsx +++ b/traque-front/components/team/map.jsx @@ -5,32 +5,49 @@ import 'leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility import "leaflet-defaulticon-compatibility"; import "leaflet/dist/leaflet.css"; import useGame from '@/hook/useGame'; +import { useTeamContext } from '@/context/teamContext'; const DEFAULT_ZOOM = 17; // Pan to the center of the map when the position of the user is updated for the first time function MapPan(props) { - const map = useMap(); - const [initialized, setInitialized] = useState(false); + const map = useMap(); + const [initialized, setInitialized] = useState(false); - useEffect(() => { - if(!initialized && props.center) { - map.flyTo(props.center, DEFAULT_ZOOM, {animate: false}); - setInitialized(true) - } - },[props.center]); + useEffect(() => { + if (!initialized && props.center) { + map.flyTo(props.center, DEFAULT_ZOOM, { animate: false }); + setInitialized(true) + } + }, [props.center]); - return null; + return null; } -export function LiveMap({ ...props}) { - const {currentPosition, enemyPosition} = useGame(); +function LiveZone() { + const { zone } = useTeamContext(); + console.log('Zone', zone); + return zone && +} + +function ZoneExtremities() { + const { zoneExtremities } = useTeamContext(); + console.log('Zone extremities', zoneExtremities); + return zoneExtremities && zoneExtremities.begin && zoneExtremities.end && <> + + + + +} + +export function LiveMap({ ...props }) { + const { currentPosition, enemyPosition } = useGame(); useEffect(() => { console.log('Current position', currentPosition); }, [currentPosition]); return ( - + } - {enemyPosition && } - + + + ) } -export function PlacementMap({ ...props}) { - const {currentPosition, startingArea} = useGame(); +export function PlacementMap({ ...props }) { + const { currentPosition, startingArea } = useGame(); return ( } - + {startingArea && } ) diff --git a/traque-front/context/adminContext.jsx b/traque-front/context/adminContext.jsx index 0f3cdd4..3f1e9d4 100644 --- a/traque-front/context/adminContext.jsx +++ b/traque-front/context/adminContext.jsx @@ -7,10 +7,11 @@ import { GameState } from "@/util/gameState"; const adminContext = createContext(); -function AdminProvider({children}) { +function AdminProvider({ children }) { const [teams, setTeams] = useState([]); + const [zoneSettings, setZoneSettings] = useState(null) const { adminSocket } = useSocket(); - const {loggedIn} = useAdminConnexion(); + const { loggedIn } = useAdminConnexion(); const [gameState, setGameState] = useState(GameState.SETUP); useSocketListener(adminSocket, "game_state", setGameState); @@ -21,8 +22,9 @@ function AdminProvider({children}) { //Bind listeners to update the team list and the game status on socket message useSocketListener(adminSocket, "teams", setTeams); + useSocketListener(adminSocket, "zone_settings", setZoneSettings); - const value = useMemo(() => ({teams, setTeams, gameState}), [teams, gameState]); + const value = useMemo(() => ({ teams, zoneSettings, setZoneSettings, setTeams, gameState }), [zoneSettings, teams, gameState]); return ( {children} diff --git a/traque-front/context/teamContext.jsx b/traque-front/context/teamContext.jsx index cf5a9c7..fb1b70e 100644 --- a/traque-front/context/teamContext.jsx +++ b/traque-front/context/teamContext.jsx @@ -1,7 +1,7 @@ "use client"; import { useLocation } from "@/hook/useLocation"; import { useSocketListener } from "@/hook/useSocketListener"; -import { createContext, useContext, useEffect, useMemo, useRef, useState } from "react"; +import { createContext, use, useContext, useEffect, useMemo, useRef, useState } from "react"; import { useSocket } from "./socketContext"; import { useTeamConnexion } from "./teamConnexionContext"; import { GameState } from "@/util/gameState"; @@ -11,6 +11,8 @@ const teamContext = createContext() function TeamProvider({children}) { const [teamInfos, setTeamInfos] = useState({}); const [gameState, setGameState] = useState(GameState.SETUP); + const [zone, setZone] = useState(null); + const [zoneExtremities, setZoneExtremities] = useState(null); const measuredLocation = useLocation(10000); const {teamSocket} = useSocket(); const {loggedIn} = useTeamConnexion(); @@ -23,6 +25,9 @@ function TeamProvider({children}) { }); useSocketListener(teamSocket, "game_state", setGameState); + useSocketListener(teamSocket, "zone", setZone); + useSocketListener(teamSocket, "new_zone", setZoneExtremities); + //Send the current position to the server when the user is logged in useEffect(() => { @@ -32,7 +37,7 @@ function TeamProvider({children}) { } }, [loggedIn, measuredLocation]); - const value = useMemo(() => ({teamInfos, gameState}), [teamInfos, gameState]); + const value = useMemo(() => ({teamInfos, gameState, zone, zoneExtremities}), [teamInfos, gameState, zone, zoneExtremities]); return ( {children} diff --git a/traque-front/hook/mapDrawing.jsx b/traque-front/hook/mapDrawing.jsx index f354905..804a99a 100644 --- a/traque-front/hook/mapDrawing.jsx +++ b/traque-front/hook/mapDrawing.jsx @@ -1,5 +1,4 @@ import { useEffect, useState } from "react"; -import { useLocation } from "./useLocation"; export function useMapCircleDraw(area, setArea) { const [drawing, setDrawing] = useState(false); diff --git a/traque-front/hook/useAdmin.jsx b/traque-front/hook/useAdmin.jsx index 56c566e..6c25284 100644 --- a/traque-front/hook/useAdmin.jsx +++ b/traque-front/hook/useAdmin.jsx @@ -2,7 +2,7 @@ import { useAdminContext } from "@/context/adminContext"; import { useSocket } from "@/context/socketContext"; export default function useAdmin(){ - const {teams, gameState } = useAdminContext(); + const {teams, gameState, zoneSettings } = useAdminContext(); const {adminSocket} = useSocket(); function pollTeams() { @@ -38,6 +38,10 @@ export default function useAdmin(){ adminSocket.emit("change_state", state); } - return {teams, gameState, pollTeams, getTeam, getTeamName, reorderTeams, addTeam, removeTeam, changeState, updateTeam }; + function changeZoneSettings(zone) { + adminSocket.emit("set_zone_settings", zone); + } + + return {teams, zoneSettings, gameState,changeZoneSettings, pollTeams, getTeam, getTeamName, reorderTeams, addTeam, removeTeam, changeState, updateTeam }; } \ No newline at end of file