From 0de79417a9a13580ca880c718d658ebc76dbd65a Mon Sep 17 00:00:00 2001 From: "Jimmy Ghaderi (jigh01)" Date: Mon, 12 May 2025 20:54:45 +0200 Subject: [PATCH] handle issues with rule checking, log warnings --- src/rule/index.ts | 26 ++++----- src/rule/rules/isOverlappingOrContained.ts | 64 +++++++++++++--------- 2 files changed, 49 insertions(+), 41 deletions(-) diff --git a/src/rule/index.ts b/src/rule/index.ts index 540e7b3e..5e6b4821 100644 --- a/src/rule/index.ts +++ b/src/rule/index.ts @@ -4,9 +4,7 @@ import CheapRuler from 'cheap-ruler'; import type { MapEntity } from '../entities/entity'; import { ClusterCache } from '../entities/ClusterCache'; import * as Rules from './rules'; -import { - FIRE_BUFFER_IN_METER -} from '../../SETTINGS'; +import { FIRE_BUFFER_IN_METER } from '../../SETTINGS'; export const clusterCache = new ClusterCache(); // instantiate here and use it as a global cache when calculating clusters export const ruler = new CheapRuler(57.5, 'meters'); @@ -14,14 +12,17 @@ export enum Severity { None = 0, Low = 1, Medium = 2, - High = 3 + High = 3, } export class Rule { private _severity: Severity; private _triggered: boolean; - private _callback: (entity: MapEntity) => { triggered: boolean; shortMessage?: string; message?: string }; - + private _callback: ( + entity: MapEntity, + ruleMessage: string, + ) => { triggered: boolean; shortMessage?: string; message?: string }; + public message: string; public shortMessage: string; @@ -34,7 +35,7 @@ export class Rule { } public checkRule(entity: MapEntity) { - const result = this._callback(entity); + const result = this._callback(entity, this.message); this._triggered = result.triggered; if (result.shortMessage) this.shortMessage = result.shortMessage; if (result.message) this.message = result.message; @@ -97,7 +98,9 @@ export function generateRulesForEditor(groups: any, placementLayers: any): () => placementLayers, Severity.High, 'Too large/close to others!', - 'For fire safety, we need to add a bit of open space (' + FIRE_BUFFER_IN_METER + 'm2) between these camps (or if not next to any camps, this camp simply too big)', + 'For fire safety, we need to add a bit of open space (' + + FIRE_BUFFER_IN_METER + + 'm2) between these camps (or if not next to any camps, this camp simply too big)', ), Rules.isNotInsideBoundaries( groups.area, @@ -131,13 +134,6 @@ export function generateRulesForEditor(groups: any, placementLayers: any): () => 'Close to the sanctuary', 'This area is in the viscinity of the sanctuary, please be mindful of what energy your camp is releasing and how it may effect the santuarcy', ), - // Special notification when on the western meadow - Rules.isOverlappingOrContained( - groups.redsoundzone, - Severity.Low, - 'In the western meadow', - "You're in the western meadow, please be extra careful of keeping the land in good condition and do not put your overnight camp here unless necessary, public dreams are prefered", - ), ]; } diff --git a/src/rule/rules/isOverlappingOrContained.ts b/src/rule/rules/isOverlappingOrContained.ts index 0aad1a5b..2cd552ff 100644 --- a/src/rule/rules/isOverlappingOrContained.ts +++ b/src/rule/rules/isOverlappingOrContained.ts @@ -1,36 +1,48 @@ import * as Turf from '@turf/turf'; import { Severity, Rule } from '../index'; -export const isOverlappingOrContained = ( - layerGroup: any, - severity: Severity, - shortMsg: string, - message: string -) => new Rule(severity, shortMsg, message, (entity) => { - let geoJson = entity.toGeoJSON(); - let overlap = false; +export const isOverlappingOrContained = (layerGroup: any, severity: Severity, shortMsg: string, message: string) => + new Rule(severity, shortMsg, message, (entity, ruleMessage) => { + let geoJson = entity.toGeoJSON(); + let overlap = false; - layerGroup.eachLayer((layer) => { - //@ts-ignore - let otherGeoJson = layer.toGeoJSON(); + if (!layerGroup) { + console.warn('No layer group provided in isOverlappingOrContained:', { ruleMessage, entity }); + return { triggered: false }; + } + + layerGroup.eachLayer((layer) => { + //@ts-ignore + let otherGeoJson = layer.toGeoJSON(); - //Loop through all features if it is a feature collection - if (otherGeoJson.features) { - for (let i = 0; i < otherGeoJson.features.length; i++) { - if (Turf.booleanOverlap(geoJson, otherGeoJson.features[i]) || - Turf.booleanContains(otherGeoJson.features[i], geoJson)) { + //Loop through all features if it is a feature collection + if (otherGeoJson.features) { + for (let i = 0; i < otherGeoJson.features.length; i++) { + if ( + Turf.booleanOverlap(geoJson, otherGeoJson.features[i]) || + Turf.booleanContains(otherGeoJson.features[i], geoJson) + ) { + overlap = true; + return; // Break out of the inner loop + } + } + } else if (geoJson.geometry.type === otherGeoJson.geometry.type) { + if (Turf.booleanOverlap(geoJson, otherGeoJson) || Turf.booleanContains(otherGeoJson, geoJson)) { overlap = true; - return; // Break out of the inner loop + return; // Break out of the loop once an overlap is found } + } else { + console.warn('Mismatched types in isOverlappingOrContained:', { + ruleMessage, + geoJson, + otherGeoJson, + }); } - } else if (Turf.booleanOverlap(geoJson, otherGeoJson) || Turf.booleanContains(otherGeoJson, geoJson)) { - overlap = true; - } - if (overlap) { - return; // Break out of the loop once an overlap is found - } - }); + if (overlap) { + return; // Break out of the loop once an overlap is found + } + }); - return { triggered: overlap }; -}); + return { triggered: overlap }; + });