Files
traque/traque-back/zoneManager.js

92 lines
3.8 KiB
JavaScript

import randomLocation, { randomCirclePoint } from 'random-location'
import { isInCircle } from './map_utils';
class ZoneManager {
constructor(onZoneUpdate, onNextZoneUpdate) {
//Setings storing where the zone will start, end and how it should evolve
//The zone will start by staying at its mzx value for reductionInterval minutes
//and then reduce during reductionDuration minutes, then wait again...
//The reduction factor is such that after reductionCount the zone will be the min zone
//a call to onZoneUpdate will be made every updateIntervalSeconds when the zone is changing
//a call to onNextZoneUpdate will be made when the zone reduction ends and a new next zone is announced
this.zoneSettings = {
min: {center: null, radius: null},
max: {center: null, radius: null},
reductionCount: 2,
reductionDuration: 10,
reductionInterval: 10,
updateIntervalSeconds: 10,
}
this.shrinkFactor = null;
//Live location of the zone
this.currentZone = null;
this.currentDecrement = null;
//If the zone is shrinking, this is the target of the current shrinking
//If the zone is not shrinking, this will be the target of the next shrinking
this.nextZone = null;
this.startDate = null;
this.zoneSettings = zoneSettings;
this.started = false;
this.timeoutId = null;
this.onZoneUpdate = onZoneUpdate;
this.onNextZoneUpdate = onNextZoneUpdate
}
udpateSettings(newSettings) {
this.zoneSettings = {newSettings, ...this.zoneSettings};
this.shrinkFactor = Math.pow(this.zoneSettings.min.radius / this.zoneSettings.max.radius, 1/this.zoneSettings.reductionCount)
}
reset() {
this.currentZoneCount = 0;
}
start() {
this.started = true;
this.startDate = new Date();
requestAnimationFrame(tick);
}
/**
* Get the center of the next zone, this center need to satisfy two properties
* - it needs to be included in the current zone, this means that this new point should lie in the circle of center currentZone.center and radius currentZone.radius - newRadius
* - it needs to include the last zone, which means that the center must lie in the center of center min.center and of radius newRadius - min.radius
* @param newRadius the radius that the new zone will have
* @returns the coordinates of the new center as an object with lat and long fields
*/
getRandomNextCenter(newRadius) {
let ok = false;
let res = null
while(!ok) {
res = randomCirclePoint({latitude: this.currentZone.lat, longitude: this.currentZone.long}, this.currentZone.radius - newRadius);
ok = (isInCircle({lat: res.latitude, long: res.longitude}, this.zoneSettings.min.center, newRadius - this.zoneSettings.min.radius))
}
return {
lat: res.latitude,
long: res.longitude
}
}
setNextZone() {
//At this point, nextZone == currentZone, we need to update the next zone, the raidus decrement, and start a timer before the next shrink
//last zone
if(this.currentZoneCount == this.zoneSettings.currentZoneCount - 1) {
//Copy values
this.nextZone = {center: [...this.zoneSettings.min.center],...this.zoneSettings.min}
}else {
//TODO : compute next zone
this.nextZone.center = this.getRandomNextCenter(this.nextZone.radius * this.shrinkFactor)
this.nextZone.radius *= this.shrinkFactor;
this.timeoutId = setTimeout(() => this.startShrinking(), 1000 * 60 * this.zoneSettings.reductionIntervalMinutes)
}
}
startShrinking() {
}
}