Update mission_engine.py
Browse files- mission_engine.py +40 -8
mission_engine.py
CHANGED
|
@@ -329,6 +329,35 @@ class MissionEvaluator:
|
|
| 329 |
"""Deterministic logic engine for matching rules against observations."""
|
| 330 |
def __init__(self):
|
| 331 |
self.active_rules: List[MissionRule] = []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 332 |
|
| 333 |
def set_rules(self, rules: List[MissionRule]):
|
| 334 |
self.active_rules = rules
|
|
@@ -477,9 +506,9 @@ class MissionEvaluator:
|
|
| 477 |
# βββββββββββββββββββββββββββββββββββββββββββ
|
| 478 |
# THREAT / DANGER / EMERGENCY
|
| 479 |
# βββββββββββββββββββββββββββββββββββββββββββ
|
| 480 |
-
"danger": ["knife", "gun", "weapon", "fire", "flame", "blood", "fight", "alarm", "scream", "explosion", "threat", "attack", "violence", "aggressive", "sword", "pistol", "rifle", "crash", "collision", "smoke", "broken", "falling", "injured"],
|
| 481 |
-
"threat": ["knife", "gun", "weapon", "fire", "blood", "fight", "alarm", "scream", "explosion", "attack", "violence", "aggressive", "intruder", "suspicious", "trespassing", "masked", "hooded"],
|
| 482 |
-
"emergency": ["fire", "smoke", "alarm", "siren", "scream", "crash", "explosion", "injured", "blood", "ambulance", "fallen", "collapse", "unconscious", "drowning"],
|
| 483 |
"accident": ["crash", "collision", "fall", "fallen", "broken", "blood", "damage", "wreck", "injury", "injured", "ambulance", "fire", "smoke", "shattered", "debris", "impact", "overturned", "dent"],
|
| 484 |
"crime": ["knife", "gun", "weapon", "masked", "hooded", "stealing", "robbery", "intruder", "trespassing", "suspicious", "fight", "assault", "vandalism", "break-in", "threat"],
|
| 485 |
"weapon": ["knife", "gun", "pistol", "rifle", "sword", "blade", "firearm", "machete", "bat", "club", "axe", "hammer"],
|
|
@@ -492,7 +521,7 @@ class MissionEvaluator:
|
|
| 492 |
# βββββββββββββββββββββββββββββββββββββββββββ
|
| 493 |
# HUMAN ACTIVITIES & ACTIONS
|
| 494 |
# βββββββββββββββββββββββββββββββββββββββββββ
|
| 495 |
-
"activity": ["walking", "running", "sitting", "standing", "holding", "moving", "talking", "eating", "drinking", "working", "playing", "reading", "typing", "cooking", "cleaning", "dancing", "exercising", "sleeping", "lying", "writing"],
|
| 496 |
"movement": ["walking", "running", "moving", "jumping", "climbing", "crawling", "dancing", "jogging", "sprinting", "stepping", "marching", "pacing", "sliding"],
|
| 497 |
"interaction": ["talking", "speaking", "shaking hands", "hugging", "fighting", "pointing", "waving", "greeting", "kissing", "arguing", "collaborating"],
|
| 498 |
"working": ["typing", "writing", "computer", "laptop", "desk", "phone", "meeting", "office", "paperwork", "keyboard", "tool", "construction"],
|
|
@@ -524,6 +553,7 @@ class MissionEvaluator:
|
|
| 524 |
# βββββββββββββββββββββββββββββββββββββββββββ
|
| 525 |
# PEOPLE / IDENTITY
|
| 526 |
# βββββββββββββββββββββββββββββββββββββββββββ
|
|
|
|
| 527 |
"person": ["person", "man", "woman", "human", "subject", "individual", "boy", "girl", "child", "people", "face", "standing", "walking", "sitting"],
|
| 528 |
"man": ["man", "male", "guy", "boy", "gentleman", "person"],
|
| 529 |
"woman": ["woman", "female", "lady", "girl", "person"],
|
|
@@ -1028,8 +1058,10 @@ class MissionEvaluator:
|
|
| 1028 |
continue
|
| 1029 |
positive_sentences.append(s)
|
| 1030 |
|
| 1031 |
-
# Combine positive findings
|
|
|
|
| 1032 |
verified_context = " ".join(positive_sentences)
|
|
|
|
| 1033 |
|
| 1034 |
if not verified_context:
|
| 1035 |
continue
|
|
@@ -1047,9 +1079,9 @@ class MissionEvaluator:
|
|
| 1047 |
# Literal check
|
| 1048 |
if re.search(fr"\b{re.escape(word)}\b", verified_context):
|
| 1049 |
word_found = True
|
| 1050 |
-
# Semantic expansion check
|
| 1051 |
-
elif word in self.
|
| 1052 |
-
for kw in self.
|
| 1053 |
if re.search(fr"\b{re.escape(kw)}\b", verified_context):
|
| 1054 |
word_found = True
|
| 1055 |
break
|
|
|
|
| 329 |
"""Deterministic logic engine for matching rules against observations."""
|
| 330 |
def __init__(self):
|
| 331 |
self.active_rules: List[MissionRule] = []
|
| 332 |
+
# Pre-process the concept map to ensure bidirectional matching
|
| 333 |
+
self.concept_mirror = self._mirror_concept_map(self.CONCEPT_MAP)
|
| 334 |
+
|
| 335 |
+
def _mirror_concept_map(self, original_map: Dict[str, List[str]]) -> Dict[str, set]:
|
| 336 |
+
"""
|
| 337 |
+
Hardens the CONCEPT_MAP by making it bidirectional and self-referential.
|
| 338 |
+
If 'person' maps to 'human', then 'human' will now map to 'person'.
|
| 339 |
+
"""
|
| 340 |
+
mirrored = {}
|
| 341 |
+
|
| 342 |
+
# 1. First, ensure every key is in its own list and create initial sets
|
| 343 |
+
for key, synonyms in original_map.items():
|
| 344 |
+
all_words = set(synonyms)
|
| 345 |
+
all_words.add(key)
|
| 346 |
+
|
| 347 |
+
if key not in mirrored:
|
| 348 |
+
mirrored[key] = all_words
|
| 349 |
+
else:
|
| 350 |
+
mirrored[key].update(all_words)
|
| 351 |
+
|
| 352 |
+
# 2. For every synonym, create a key if it doesn't exist and add the whole group
|
| 353 |
+
for syn in synonyms:
|
| 354 |
+
if syn not in mirrored:
|
| 355 |
+
mirrored[syn] = all_words
|
| 356 |
+
else:
|
| 357 |
+
mirrored[syn].update(all_words)
|
| 358 |
+
|
| 359 |
+
logger.info(f"[EVALUATOR] Semantic Mirroring complete. Expanded {len(original_map)} concepts into {len(mirrored)} bidirectional links.")
|
| 360 |
+
return mirrored
|
| 361 |
|
| 362 |
def set_rules(self, rules: List[MissionRule]):
|
| 363 |
self.active_rules = rules
|
|
|
|
| 506 |
# βββββββββββββββββββββββββββββββββββββββββββ
|
| 507 |
# THREAT / DANGER / EMERGENCY
|
| 508 |
# βββββββββββββββββββββββββββββββββββββββββββ
|
| 509 |
+
"danger": ["knife", "gun", "weapon", "fire", "flame", "blood", "fight", "alarm", "scream", "explosion", "threat", "attack", "violence", "aggressive", "sword", "pistol", "rifle", "crash", "collision", "smoke", "broken", "falling", "injured", "hazard", "threat"],
|
| 510 |
+
"threat": ["knife", "gun", "weapon", "fire", "blood", "fight", "alarm", "scream", "explosion", "attack", "violence", "aggressive", "intruder", "suspicious", "trespassing", "masked", "hooded", "danger", "hostile"],
|
| 511 |
+
"emergency": ["fire", "smoke", "alarm", "siren", "scream", "crash", "explosion", "injured", "blood", "ambulance", "fallen", "collapse", "unconscious", "drowning", "critical"],
|
| 512 |
"accident": ["crash", "collision", "fall", "fallen", "broken", "blood", "damage", "wreck", "injury", "injured", "ambulance", "fire", "smoke", "shattered", "debris", "impact", "overturned", "dent"],
|
| 513 |
"crime": ["knife", "gun", "weapon", "masked", "hooded", "stealing", "robbery", "intruder", "trespassing", "suspicious", "fight", "assault", "vandalism", "break-in", "threat"],
|
| 514 |
"weapon": ["knife", "gun", "pistol", "rifle", "sword", "blade", "firearm", "machete", "bat", "club", "axe", "hammer"],
|
|
|
|
| 521 |
# βββββββββββββββββββββββββββββββββββββββββββ
|
| 522 |
# HUMAN ACTIVITIES & ACTIONS
|
| 523 |
# βββββββββββββββββββββββββββββββββββββββββββ
|
| 524 |
+
"activity": ["walking", "running", "sitting", "standing", "holding", "moving", "talking", "eating", "drinking", "working", "playing", "reading", "typing", "cooking", "cleaning", "dancing", "exercising", "sleeping", "lying", "writing", "person", "man", "woman", "human", "subject", "individual", "boy", "girl", "child", "people"],
|
| 525 |
"movement": ["walking", "running", "moving", "jumping", "climbing", "crawling", "dancing", "jogging", "sprinting", "stepping", "marching", "pacing", "sliding"],
|
| 526 |
"interaction": ["talking", "speaking", "shaking hands", "hugging", "fighting", "pointing", "waving", "greeting", "kissing", "arguing", "collaborating"],
|
| 527 |
"working": ["typing", "writing", "computer", "laptop", "desk", "phone", "meeting", "office", "paperwork", "keyboard", "tool", "construction"],
|
|
|
|
| 553 |
# βββββββββββββββββββββββββββββββββββββββββββ
|
| 554 |
# PEOPLE / IDENTITY
|
| 555 |
# βββββββββββββββββββββββββββββββββββββββββββ
|
| 556 |
+
"human": ["human", "person", "man", "woman", "subject", "individual", "boy", "girl", "child", "people"],
|
| 557 |
"person": ["person", "man", "woman", "human", "subject", "individual", "boy", "girl", "child", "people", "face", "standing", "walking", "sitting"],
|
| 558 |
"man": ["man", "male", "guy", "boy", "gentleman", "person"],
|
| 559 |
"woman": ["woman", "female", "lady", "girl", "person"],
|
|
|
|
| 1058 |
continue
|
| 1059 |
positive_sentences.append(s)
|
| 1060 |
|
| 1061 |
+
# Combine positive findings and sanitize special characters (slashes/parentheses)
|
| 1062 |
+
# This allows "standing/active" to match "standing" and "person(s)" to match "person"
|
| 1063 |
verified_context = " ".join(positive_sentences)
|
| 1064 |
+
verified_context = verified_context.replace("/", " ").replace("(", " ").replace(")", " ")
|
| 1065 |
|
| 1066 |
if not verified_context:
|
| 1067 |
continue
|
|
|
|
| 1079 |
# Literal check
|
| 1080 |
if re.search(fr"\b{re.escape(word)}\b", verified_context):
|
| 1081 |
word_found = True
|
| 1082 |
+
# Semantic expansion check (using the new Bidirectional Mirror)
|
| 1083 |
+
elif word in self.concept_mirror:
|
| 1084 |
+
for kw in self.concept_mirror[word]:
|
| 1085 |
if re.search(fr"\b{re.escape(kw)}\b", verified_context):
|
| 1086 |
word_found = True
|
| 1087 |
break
|