SquadJS/squad-server/utils/squad-layers.js
2020-10-05 18:56:45 +01:00

275 lines
9.0 KiB
JavaScript

import axios from 'axios';
import didYouMean from 'didyoumean';
import fs from 'fs';
class SquadLayersBase {
get layerNames() {
return this.layers.map((layer) => layer.name);
}
getLayerByCondition(condition) {
const results = this.layers.filter(condition);
return results.length === 1 ? results[0] : null;
}
getLayerByLayerName(layerName) {
return this.getLayerByCondition((layer) => layer.layer === layerName);
}
getLayerByLayerClassname(layerClassname) {
return this.getLayerByCondition((layer) => layer.layerClassname === layerClassname);
}
getLayerByLayerNameAutoCorrection(layerName) {
return this.getLayerByLayerName(didYouMean(layerName, this.layerNames()));
}
getLayerByNumber(layerNumber) {
return this.getLayerByCondition((layer) => layer.layerNumber === layerNumber);
}
}
class SquadLayers extends SquadLayersBase {
constructor(source) {
super();
this.source =
source || 'https://raw.githubusercontent.com/Thomas-Smyth/squad-layers/master/layers.json';
this.pulled = false;
}
async pull(force = false) {
if (this.pulled && !force) return;
this.layers = (await axios.get(this.source)).data;
for (let i = 0; i < this.layers.length; i++) this.layers[i].layerNumber = i + 1;
}
buildPoolFromLayerNames(layerNames, activeFilter) {
return new SquadLayersPool(
this.layers.filter((layer) => layerNames.includes(layer.layer)),
activeFilter
);
}
buildPoolFromLayerNamesAutoCorrection(layerNames, activeFilter) {
return this.buildPoolFromLayerNames(
layerNames.map((layerName) => this.getLayerByLayerNameAutoCorrection(layerName)),
activeFilter
);
}
buildPoolFromFile(path, activeFilter, delimiter = '\n') {
return this.buildPoolFromLayerNames(
fs.readFileSync(path, 'utf8').split(delimiter),
activeFilter
);
}
buildPoolFromFilter(filter, activeFilter) {
const whitelistedLayers = filter.whitelistedLayers || null;
const blacklistedLayers = filter.blacklistedLayers || null;
const whitelistedMaps = filter.whitelistedMaps || null;
const blacklistedMaps = filter.blacklistedMaps || null;
const whitelistedGamemodes = filter.whitelistedGamemodes || null;
const blacklistedGamemodes = filter.blacklistedGamemodes || ['Training'];
const flagCountMin = filter.flagCountMin || null;
const flagCountMax = filter.flagCountMax || null;
const hasCommander = filter.hasCommander || null;
const hasTanks = filter.hasTanks || null;
const hasHelicopters = filter.hasHelicopters || null;
const layers = [];
for (const layer of this.layers) {
// Whitelist / Blacklist Layers
if (whitelistedLayers !== null && !whitelistedLayers.includes(layer.layer)) continue;
if (blacklistedLayers !== null && blacklistedLayers.includes(layer.layer)) continue;
// Whitelist / Blacklist Maps
if (whitelistedMaps !== null && !whitelistedMaps.includes(layer.map)) continue;
if (blacklistedMaps !== null && blacklistedMaps.includes(layer.map)) continue;
// Whitelist / Blacklist Gamemodes
if (whitelistedGamemodes !== null && !whitelistedGamemodes.includes(layer.gamemode)) continue;
if (blacklistedGamemodes !== null && blacklistedGamemodes.includes(layer.gamemode)) continue;
// Flag Count
if (flagCountMin !== null && layer.flagCount < flagCountMin) continue;
if (flagCountMax !== null && layer.flagCount > flagCountMax) continue;
// Other Properties
if (hasCommander !== null && layer.commander !== hasCommander) continue;
if (hasTanks !== null && (layer.tanks !== 'N/A') !== hasTanks) continue;
if (hasHelicopters !== null && (layer.helicopters !== 'N/A') !== hasHelicopters) continue;
layers.push(layer);
}
return new SquadLayersPool(layers, activeFilter);
}
}
class SquadLayersPool extends SquadLayersBase {
constructor(layers, activeFilter = null) {
super();
this.layers = layers;
for (let i = 0; i < this.layers.length; i++) this.layers[i].layerNumber = i + 1;
this.activeFilter = activeFilter;
}
inPool(layer) {
if (typeof layer === 'object') layer = layer.layer;
return super.layerNames.includes(layer);
}
isHistoryCompliant(layerHistory, layer) {
if (this.activeFilter === null) return true;
if (typeof layer === 'object') layer = layer.layer;
for (
let i = 0;
i < Math.min(layerHistory.length, this.activeFilter.layerHistoryTolerance);
i++
) {
if (new Date() - layerHistory[i].time > this.activeFilter.historyResetTime) return true;
if (layerHistory[i].layer === layer) return false;
}
return true;
}
isMapHistoryCompliant(layerHistory, layer) {
if (this.activeFilter === null) return true;
if (typeof layer === 'string') layer = this.getLayerByLayerName(layer);
for (let i = 0; i < Math.min(layerHistory.length, this.activeFilter.mapHistoryTolerance); i++) {
if (new Date() - layerHistory[i].time > this.activeFilter.historyResetTime) return true;
if (layerHistory[i].map === layer.map) return false;
}
return true;
}
isGamemodeHistoryCompliant(layerHistory, layer) {
if (this.activeFilter === null) return true;
if (typeof layer === 'string') layer = this.getLayerByLayerName(layer);
const gamemodeHistoryTolerance = this.activeFilter.gamemodeHistoryTolerance[layer.gamemode];
if (!gamemodeHistoryTolerance) return true;
for (let i = 0; i < Math.min(layerHistory.length, gamemodeHistoryTolerance); i++) {
if (new Date() - layerHistory[i].time > this.activeFilter.historyResetTime) return true;
if (layerHistory[i].gamemode === layer.gamemode) return false;
}
return true;
}
isGamemodeRepetitiveCompliant(layerHistory, layer) {
if (this.activeFilter === null) return true;
if (typeof layer === 'string') layer = this.getLayerByLayerName(layer);
const gamemodeRepetitiveTolerance = this.activeFilter.gamemodeRepetitiveTolerance[
layer.gamemode
];
if (!gamemodeRepetitiveTolerance) return true;
for (let i = 0; i < Math.min(layerHistory.length, gamemodeRepetitiveTolerance); i++) {
if (new Date() - layerHistory[i].time > this.activeFilter.historyResetTime) return true;
if (layerHistory[i].gamemode.gamemode !== layer.gamemode) return true;
}
return false;
}
isFactionCompliant(layerHistory, layer) {
if (this.activeFilter === null || this.activeFilter.factionComplianceEnabled === false)
return true;
if (layerHistory.length === 0) return true;
if (typeof layer === 'string') layer = this.getLayerByLayerName(layer);
return (
!layerHistory[0] ||
(layerHistory[0].teamOne.faction !== layer.teamTwo.faction &&
layerHistory[0].teamTwo.faction !== layer.teamOne.faction)
);
}
isFactionHistoryCompliant(layerHistory, layer, faction = null) {
if (this.activeFilter === null) return true;
if (typeof layer === 'string') layer = SquadLayers.getLayerByLayerName(layer);
if (faction === null) {
return (
this.isFactionHistoryCompliant(layerHistory, layer, layer.teamOne.faction) &&
this.isFactionHistoryCompliant(layerHistory, layer, layer.teamTwo.faction)
);
} else {
const factionThreshold = this.activeFilter.factionHistoryTolerance[faction];
if (!factionThreshold) return true;
for (let i = 0; i < Math.min(layerHistory.length, factionThreshold); i++) {
if (new Date() - layerHistory[i].time > this.activeFilter.historyResetTime) return true;
if (
layerHistory[i].teamOne.faction === faction ||
layerHistory[i].teamTwo.faction === faction
)
return false;
}
return true;
}
}
isFactionRepetitiveCompliant(layerHistory, layer, faction = null) {
if (this.activeFilter === null) return true;
if (typeof layer === 'string') layer = SquadLayers.getLayerByLayerName(layer);
if (faction === null) {
return (
this.isFactionRepetitiveCompliant(layerHistory, layer, layer.teamOne.faction) &&
this.isFactionRepetitiveCompliant(layerHistory, layer, layer.teamTwo.faction)
);
} else {
const factionThreshold = this.activeFilter.factionRepetitiveTolerance[faction];
if (!factionThreshold) return true;
for (let i = 0; i < Math.min(layerHistory.length, factionThreshold); i++) {
if (new Date() - layerHistory[i].time > this.activeFilter.historyResetTime) return true;
if (
layerHistory[i].teamOne.faction !== faction &&
layerHistory[i].teamTwo.faction !== faction
)
return true;
}
return false;
}
}
isPlayerCountCompliant(server, layer) {
if (this.activeFilter === null || this.activeFilter.playerCountComplianceEnabled === false)
return true;
if (typeof layer === 'string') layer = this.getLayerByLayerName(layer);
return !(
server.players.length > layer.estimatedSuitablePlayerCount.max ||
server.players.length < layer.estimatedSuitablePlayerCount.min
);
}
}
export { SquadLayers, SquadLayersPool };