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: