diff --git a/proxy/nginx.conf b/proxy/nginx.conf index a9b309a..87672e0 100644 --- a/proxy/nginx.conf +++ b/proxy/nginx.conf @@ -7,6 +7,7 @@ http { server { listen 80; client_max_body_size 15M; + access_log off; location / { proxy_pass http://front:3000/; proxy_set_header Host $host; diff --git a/traque-app/app/display.js b/traque-app/app/display.js index 814e2a4..062cfe7 100644 --- a/traque-app/app/display.js +++ b/traque-app/app/display.js @@ -1,5 +1,5 @@ // React -import { useState, useEffect, useRef } from 'react'; +import { useState, useEffect, useRef, Fragment } from 'react'; import { ScrollView, View, Text, Image, Alert, StyleSheet, TouchableOpacity, TouchableHighlight } from 'react-native'; import MapView, { Marker, Circle, Polygon } from 'react-native-maps'; // Expo @@ -34,7 +34,7 @@ export default function Display() { const {SERVER_URL} = useSocket(); const {messages, zoneType, zoneExtremities, nextZoneDate, isShrinking, location, startLocationTracking, stopLocationTracking, gameState, startDate} = useTeamContext(); const {loggedIn, logout, loading} = useTeamConnexion(); - const {sendCurrentPosition, capture, enemyLocation, enemyName, startingArea, captureCode, name, ready, captured, lastSentLocation, locationSendDeadline, teamId, outOfZone, outOfZoneDeadline, distance, finishDate, nCaptures, nSentLocation} = useGame(); + const {sendCurrentPosition, capture, enemyLocation, enemyName, startingArea, captureCode, name, ready, captured, lastSentLocation, locationSendDeadline, teamId, outOfZone, outOfZoneDeadline, distance, finishDate, nCaptures, nSentLocation, hasHandicap, enemyHasHandicap} = useGame(); const [enemyCaptureCode, setEnemyCaptureCode] = useState(""); const [timeLeftSendLocation] = useTimeDifference(locationSendDeadline, 1000); const [timeLeftNextZone] = useTimeDifference(nextZoneDate, 1000); @@ -175,7 +175,8 @@ export default function Display() { { gameState == GameState.SETUP && Préparation de la partie} { gameState == GameState.PLACEMENT && Phase de placement} { gameState == GameState.PLAYING && !outOfZone && La partie est en cours} - { gameState == GameState.PLAYING && outOfZone && Hors zone (pénalité dans {formatTimeMinutes(-timeLeftOutOfZone)})} + { gameState == GameState.PLAYING && outOfZone && !hasHandicap && Hors zone (handicap dans {formatTimeMinutes(-timeLeftOutOfZone)})} + { gameState == GameState.PLAYING && hasHandicap && Hors zone (position révélée en continue)} { gameState == GameState.FINISHED && La partie est terminée} ); @@ -191,10 +192,10 @@ export default function Display() { } const TimeBeforeNextPosition = () => { - return ( + return ( Position envoyée dans - {formatTimeMinutes(-timeLeftSendLocation)} + { !hasHandicap ? formatTimeMinutes(-timeLeftSendLocation) : "00:00"} ); } @@ -245,17 +246,17 @@ export default function Display() { switch (zoneType) { case zoneTypes.circle: return ( - + { zoneExtremities.begin && } { zoneExtremities.end && } - + ); case zoneTypes.polygon: return ( - + { zoneExtremities.begin && latToLatitude(pos))} strokeColor="red" fillColor="rgba(255,0,0,0.1)" strokeWidth={2} /> } { zoneExtremities.end && latToLatitude(pos))} strokeColor="green" fillColor="rgba(0,255,0,0.1)" strokeWidth={2} /> } - + ); default: return null; @@ -272,12 +273,12 @@ export default function Display() { } - { gameState == GameState.PLAYING && lastSentLocation && + { gameState == GameState.PLAYING && lastSentLocation && !hasHandicap && } - { gameState == GameState.PLAYING && enemyLocation && + { gameState == GameState.PLAYING && enemyLocation && !hasHandicap && @@ -287,7 +288,7 @@ export default function Display() { } const UpdatePositionButton = () => { - return ( + return ( !hasHandicap && @@ -327,8 +328,9 @@ export default function Display() { const ChasedTeamImage = () => { return ( - {"Cible (" + (enemyName ?? "Indisponible") + ")"} - + {{"Cible (" + (enemyName ?? "Indisponible") + ")"}} + {enemyHasHandicap && Position ennemie révélée en continue} + {} ); } @@ -417,11 +419,13 @@ export default function Display() { { TeamCaptureCode() } - { ChasedTeamImage() } - - { CaptureCode() } - { CaptureButton() } - + { !hasHandicap && + { ChasedTeamImage() } + + { CaptureCode() } + { CaptureButton() } + + } { Stats() } @@ -504,7 +508,6 @@ const styles = StyleSheet.create({ }, bottomContainer: { flex: 1, - alignItems: 'center' }, mapContainer: { flex: 1, @@ -518,11 +521,9 @@ const styles = StyleSheet.create({ bottom: 0, left: 0, right: 0, - alignItems: 'center' }, innerDrawerContainer: { width: "100%", - alignItems: 'center', backgroundColor: backgroundColor, borderTopLeftRadius: 30, borderTopRightRadius: 30, @@ -536,13 +537,11 @@ const styles = StyleSheet.create({ }, collapsibleWindow: { width: "100%", - alignItems: 'center', justifyContent: 'center', backgroundColor: backgroundColor, }, collapsibleContent: { paddingHorizontal: 15, - alignItems: 'center' }, centerMapContainer: { position: 'absolute', diff --git a/traque-back/game.js b/traque-back/game.js index ea3e97f..eee69b5 100644 --- a/traque-back/game.js +++ b/traque-back/game.js @@ -106,6 +106,7 @@ export default { // Zone team.outOfZone = false; team.outOfZoneDeadline = null; + team.hasHandicap = false; // Stats team.distance = 0; team.nCaptures = 0; @@ -274,6 +275,7 @@ export default { // Zone outOfZone: false, outOfZoneDeadline: null, + hasHandicap: false, // Stats distance: 0, nCaptures: 0, @@ -362,7 +364,17 @@ export default { }, handicapTeam(teamId) { - // TODO + // Test of parameters + if (!this.hasTeam(teamId)) return false; + // Variables + const team = this.getTeam(teamId); + // Make the capture + team.hasHandicap = true; + sendPositionTimeouts.clear(team.id); + // Broadcast new infos + secureAdminBroadcast("teams", this.teams); + sendUpdatedTeamInformations(team.id); + return true; }, @@ -375,12 +387,20 @@ export default { if (!location) return false; // Variables const team = this.getTeam(teamId); + const enemyTeam = this.getTeam(team.chasing); const dateNow = Date.now(); // Update distance if (team.currentLocation) team.distance += Math.floor(getDistanceFromLatLon({lat: location[0], lng: location[1]}, {lat: team.currentLocation[0], lng: team.currentLocation[1]})); // Update of currentLocation team.currentLocation = location; team.lastCurrentLocationDate = dateNow; + if (team.hasHandicap) { + team.lastSentLocation = team.currentLocation; + } + // Update of enemyLocation + if (enemyTeam.hasHandicap) { + team.enemyLocation = enemyTeam.currentLocation; + } // Update of ready if (this.state == GameState.PLACEMENT && team.startingArea) { team.ready = isInCircle({ lat: location[0], lng: location[1] }, team.startingArea.center, team.startingArea.radius); @@ -394,6 +414,11 @@ export default { } else if (!teamCurrentlyOutOfZone && team.outOfZone) { team.outOfZone = false; team.outOfZoneDeadline = null; + team.hasHandicap = false; + if (!sendPositionTimeouts.has(team.id)) { + team.locationSendDeadline = dateNow + sendPositionTimeouts.delay * 60 * 1000; + sendPositionTimeouts.set(team.id); + } outOfZoneTimeouts.clear(teamId); } // Broadcast new infos diff --git a/traque-back/team_socket.js b/traque-back/team_socket.js index add93b7..bdb2617 100644 --- a/traque-back/team_socket.js +++ b/traque-back/team_socket.js @@ -31,15 +31,18 @@ export function playersBroadcast(event, data) { * @param {String} teamId The team that will receive the message */ export function sendUpdatedTeamInformations(teamId) { + // Test of parameters + if (!game.hasTeam(teamId)) return false; + // Variables const team = game.getTeam(teamId); - if (!team) return; + const enemyTeam = game.getTeam(team.chasing); teamBroadcast(teamId, "update_team", { // Identification name: team.name, captureCode: team.captureCode, // Chasing captured: team.captured, - enemyName: game.getTeam(team.chasing)?.name ?? null, + enemyName: enemyTeam?.name, // Locations lastSentLocation: team.lastSentLocation, enemyLocation: team.enemyLocation, @@ -50,6 +53,8 @@ export function sendUpdatedTeamInformations(teamId) { outOfZone: team.outOfZone, outOfZoneDeadline: team.outOfZoneDeadline, locationSendDeadline: team.locationSendDeadline, + hasHandicap: team.hasHandicap, + enemyHasHandicap: enemyTeam?.hasHandicap, // Stats distance: team.distance, nCaptures: team.nCaptures, diff --git a/traque-back/timeout_handler.js b/traque-back/timeout_handler.js index 9c68059..7b7101c 100644 --- a/traque-back/timeout_handler.js +++ b/traque-back/timeout_handler.js @@ -5,6 +5,10 @@ class TimeoutManager { this.timeouts = new Map(); } + has(key) { + return this.timeouts.has(key); + } + set(key, callback, delay) { const newCallback = () => { this.timeouts.delete(key); @@ -32,6 +36,10 @@ export const sendPositionTimeouts = { timeoutManager: new TimeoutManager(), delay: 10, // Minutes + has(teamID) { + return this.timeoutManager.has(teamID); + }, + set(teamID) { const callback = () => { game.sendLocation(teamID); @@ -58,6 +66,10 @@ export const outOfZoneTimeouts = { timeoutManager: new TimeoutManager(), delay: 10, // Minutes + has(teamID) { + return this.timeoutManager.has(teamID); + }, + set(teamID) { const callback = () => { game.handicapTeam(teamID); diff --git a/traque-front/util/functions.js b/traque-front/util/functions.js index 0f34e14..7223830 100644 --- a/traque-front/util/functions.js +++ b/traque-front/util/functions.js @@ -9,7 +9,7 @@ export function getStatus(team, gamestate) { case GameState.PLACEMENT: return team.ready ? teamStatus.ready : teamStatus.notready; case GameState.PLAYING: - return team.captured ? teamStatus.captured : team.outofzone ? teamStatus.outofzone : teamStatus.playing; + return team.captured ? teamStatus.captured : team.outOfZone ? teamStatus.outofzone : teamStatus.playing; case GameState.FINISHED: return team.captured ? teamStatus.captured : teamStatus.playing; default: