diff --git a/src/CyberSecurityManager/CyberSecurityManager.py b/src/CyberSecurityManager/CyberSecurityManager.py index f943407..6018317 100644 --- a/src/CyberSecurityManager/CyberSecurityManager.py +++ b/src/CyberSecurityManager/CyberSecurityManager.py @@ -24,7 +24,7 @@ logger = logging.getLogger(__name__) -def _set_scenarios() -> list[dict[str, Any]]: +def _set_scenarios() -> list[dict[str, str|Any]]: scenario0 = {"id": "0", "name": "normal", "description": "no hacking", @@ -46,8 +46,8 @@ def _set_scenarios() -> list[dict[str, Any]]: "effect": HackedNoSafetyModule} scenario5 = {"id": "5", - "name": "U-turn", - "description": "the car perfoms a U-turn", + "name": "O-turn", + "description": "the car perfoms a O-turn", "effect": HackedSporadicOTurn} scenario6 = {"id": "6", diff --git a/src/DataModel/Effects/HackingEffects/CleanHackedEffect.py b/src/DataModel/Effects/HackingEffects/CleanHackedEffect.py index 71d60cb..5ddf2dd 100644 --- a/src/DataModel/Effects/HackingEffects/CleanHackedEffect.py +++ b/src/DataModel/Effects/HackingEffects/CleanHackedEffect.py @@ -36,5 +36,6 @@ def on_start(self, vehicle: Vehicle) -> bool: vehicle.hacking_scenario = self._scenario return True - def on_end(self, vehicle: 'Vehicle') -> None: - return + def on_end(self, vehicle: 'Vehicle') -> bool: + vehicle.hacking_scenario = "0" + return True diff --git a/src/DataModel/Effects/HackingEffects/HackedEffect.py b/src/DataModel/Effects/HackingEffects/HackedEffect.py index f60cb3d..24e3836 100644 --- a/src/DataModel/Effects/HackingEffects/HackedEffect.py +++ b/src/DataModel/Effects/HackingEffects/HackedEffect.py @@ -10,17 +10,27 @@ def __init__(self, scenario: str): super().__init__() self._scenario = scenario + def identify(self) -> VehicleEffectIdentification: + return VehicleEffectIdentification.NO_EFFECT + + def can_be_applied(self, vehicle: 'Vehicle') -> bool: + return False + def on_start(self, vehicle: Vehicle) -> bool: vehicle.hacking_scenario = self._scenario return True + def on_end(self, vehicle: 'Vehicle') -> bool: + vehicle.hacking_scenario = "0" + return True + def effect_should_end(self, vehicle: Vehicle) -> bool: return False def conflicts_with(self) -> list[VehicleEffectIdentification]: return [VehicleEffectIdentification.HACKING_PROTECTION] - def remove_other_hacking_effects(self, vehicle: Vehicle): + def remove_other_hacking_effects(self, vehicle: Vehicle) -> None: """ Removes all hacking effects so a new one can be applied without problems """ @@ -30,5 +40,8 @@ def remove_other_hacking_effects(self, vehicle: Vehicle): effect_type = effect.identify() if effect_type == VehicleEffectIdentification.HACKED_NO_SAFETY_MODULE or \ effect_type == VehicleEffectIdentification.HACKED_NO_DRIVING or \ - effect_type == VehicleEffectIdentification.HACKED_REDUCED_SPEED: + effect_type == VehicleEffectIdentification.HACKED_REDUCED_SPEED or \ + effect_type == VehicleEffectIdentification.HACKED_SPORADIC_O_TURNS or \ + effect_type == VehicleEffectIdentification.HACKED_INVERTED_USER_INPUT: vehicle.remove_effect(effect) + return diff --git a/src/DataModel/Effects/HackingEffects/HackedInvertedUserInput.py b/src/DataModel/Effects/HackingEffects/HackedInvertedUserInput.py index 9a9df49..9062589 100644 --- a/src/DataModel/Effects/HackingEffects/HackedInvertedUserInput.py +++ b/src/DataModel/Effects/HackingEffects/HackedInvertedUserInput.py @@ -7,16 +7,28 @@ class HackedInvertedUserInput(HackedEffect): def identify(self) -> VehicleEffectIdentification: return VehicleEffectIdentification.HACKED_INVERTED_USER_INPUT - def on_start(self, vehicle: 'Vehicle') -> None: + def can_be_applied(self, vehicle: Vehicle) -> bool: + _ = vehicle + return True + + def conflicts_with(self) -> list[VehicleEffectIdentification]: + conflict_list: list[VehicleEffectIdentification] = super().conflicts_with() + conflict_list.append(VehicleEffectIdentification.HACKED_NO_DRIVING) + return conflict_list + + def on_start(self, vehicle: 'Vehicle') -> bool: super().on_start(vehicle) self.remove_other_hacking_effects(vehicle) vehicle.speed_factor = -1 vehicle.speed_offset = 119 vehicle.lange_change_inverted = True vehicle.turn_blocked = True + return True - def on_end(self, vehicle: 'Vehicle') -> None: + def on_end(self, vehicle: 'Vehicle') -> bool: + super().on_end(vehicle) vehicle.speed_factor = 1 vehicle.speed_offset = 0 vehicle.lange_change_inverted = False vehicle.turn_blocked = False + return True diff --git a/src/DataModel/Effects/HackingEffects/HackedNoDriving.py b/src/DataModel/Effects/HackingEffects/HackedNoDriving.py index 735dccc..a8dc3bd 100644 --- a/src/DataModel/Effects/HackingEffects/HackedNoDriving.py +++ b/src/DataModel/Effects/HackingEffects/HackedNoDriving.py @@ -11,11 +11,17 @@ def can_be_applied(self, vehicle: Vehicle) -> bool: _ = vehicle return True + def conflicts_with(self) -> list[VehicleEffectIdentification]: + conflict_list: list[VehicleEffectIdentification] = super().conflicts_with() + return conflict_list + def on_start(self, vehicle: 'Vehicle') -> bool: super().on_start(vehicle) self.remove_other_hacking_effects(vehicle) vehicle.speed_factor = 0.0 return True - def on_end(self, vehicle: 'Vehicle') -> None: + def on_end(self, vehicle: 'Vehicle') -> bool: + super().on_end(vehicle) vehicle.speed_factor = 1 + return True diff --git a/src/DataModel/Effects/HackingEffects/HackedNoSafetyModule.py b/src/DataModel/Effects/HackingEffects/HackedNoSafetyModule.py index 20095b9..e2a8510 100644 --- a/src/DataModel/Effects/HackingEffects/HackedNoSafetyModule.py +++ b/src/DataModel/Effects/HackingEffects/HackedNoSafetyModule.py @@ -11,6 +11,10 @@ def can_be_applied(self, vehicle: Vehicle) -> bool: _ = vehicle return True + def conflicts_with(self) -> list[VehicleEffectIdentification]: + conflict_list: list[VehicleEffectIdentification] = super().conflicts_with() + return conflict_list + def on_start(self, vehicle: Vehicle) -> bool: super().on_start(vehicle) self.remove_other_hacking_effects(vehicle) @@ -18,6 +22,8 @@ def on_start(self, vehicle: Vehicle) -> bool: vehicle.set_safemode(False) return True - def on_end(self, vehicle: Vehicle) -> None: + def on_end(self, vehicle: Vehicle) -> bool: + super().on_end(vehicle) vehicle.speed_factor = 1 vehicle.set_safemode(True) + return True diff --git a/src/DataModel/Effects/HackingEffects/HackedReducedSpeed.py b/src/DataModel/Effects/HackingEffects/HackedReducedSpeed.py index 75e570c..2a99e67 100644 --- a/src/DataModel/Effects/HackingEffects/HackedReducedSpeed.py +++ b/src/DataModel/Effects/HackingEffects/HackedReducedSpeed.py @@ -10,6 +10,11 @@ def identify(self) -> VehicleEffectIdentification: def can_be_applied(self, vehicle: Vehicle) -> bool: _ = vehicle return True + + def conflicts_with(self) -> list[VehicleEffectIdentification]: + conflict_list: list[VehicleEffectIdentification] = super().conflicts_with() + conflict_list.append(VehicleEffectIdentification.HACKED_NO_DRIVING) + return conflict_list def on_start(self, vehicle: Vehicle) -> bool: super().on_start(vehicle) @@ -17,6 +22,7 @@ def on_start(self, vehicle: Vehicle) -> bool: vehicle.speed_factor = 0.3 return True - def on_end(self, vehicle: 'Vehicle') -> None: + def on_end(self, vehicle: 'Vehicle') -> bool: + super().on_end(vehicle) vehicle.speed_factor = 1 - return + return True diff --git a/src/DataModel/Effects/HackingEffects/HackedSporadicOTurn.py b/src/DataModel/Effects/HackingEffects/HackedSporadicOTurn.py index 35d98f9..839ab20 100644 --- a/src/DataModel/Effects/HackingEffects/HackedSporadicOTurn.py +++ b/src/DataModel/Effects/HackingEffects/HackedSporadicOTurn.py @@ -9,10 +9,25 @@ class HackedSporadicOTurn(HackedEffect): def identify(self) -> VehicleEffectIdentification: return VehicleEffectIdentification.HACKED_SPORADIC_O_TURNS - def on_start(self, vehicle: 'Vehicle') -> None: + def can_be_applied(self, vehicle: Vehicle) -> bool: + _ = vehicle + return True + + def conflicts_with(self) -> list[VehicleEffectIdentification]: + conflict_list: list[VehicleEffectIdentification] = super().conflicts_with() + conflict_list.append(VehicleEffectIdentification.HACKED_NO_DRIVING) + return conflict_list + + def on_start(self, vehicle: 'Vehicle') -> bool: super().on_start(vehicle) self.remove_other_hacking_effects(vehicle) self.task = asyncio.create_task(self.perform_uturns(vehicle)) # create an async task + return True + + def on_end(self, vehicle: 'Vehicle') -> bool: + super().on_end(vehicle) + self.task.cancel() # cancel the task + return True async def perform_uturns(self, vehicle: 'Vehicle') -> None: while True: @@ -20,6 +35,3 @@ async def perform_uturns(self, vehicle: 'Vehicle') -> None: await asyncio.sleep(2) # delay 2 seconds vehicle.request_uturn() # second u-turn of the pair await asyncio.sleep(random.uniform(4, 12)) # random delay before the next pair - - def on_end(self, vehicle: 'Vehicle') -> None: - self.task.cancel() # cancel the task diff --git a/src/DataModel/Effects/VehicleEffect.py b/src/DataModel/Effects/VehicleEffect.py index 791d864..8c0ac9e 100644 --- a/src/DataModel/Effects/VehicleEffect.py +++ b/src/DataModel/Effects/VehicleEffect.py @@ -38,7 +38,7 @@ def on_start(self, vehicle: 'Vehicle') -> bool: raise NotImplementedError @abstractmethod - def on_end(self, vehicle: 'Vehicle') -> None: + def on_end(self, vehicle: 'Vehicle') -> bool: """ Runs when removed from a vehicle. Should be used for cleaning up """ diff --git a/src/DataModel/Effects/VehicleEffectList.py b/src/DataModel/Effects/VehicleEffectList.py index dd9abc9..8eab007 100644 --- a/src/DataModel/Effects/VehicleEffectList.py +++ b/src/DataModel/Effects/VehicleEffectList.py @@ -3,6 +3,7 @@ class VehicleEffectIdentification(Enum): # todo this list should be resorted + NO_EFFECT = 0, HACKING_PROTECTION = 1, HACKED_REDUCED_SPEED = 2, HACKED_NO_DRIVING = 3, diff --git a/src/DataModel/Vehicle.py b/src/DataModel/Vehicle.py index f9762a8..e738729 100644 --- a/src/DataModel/Vehicle.py +++ b/src/DataModel/Vehicle.py @@ -167,6 +167,9 @@ def hacking_scenario(self, value: str) -> None: self._active_hacking_scenario = value self._on_driving_data_change() + def remove_hacking_scenario(self) -> None: + self._active_hacking_scenario = "0" + @property def speed_factor(self) -> float: return self._speed_factor @@ -332,19 +335,19 @@ def apply_effect(self, new_effect: VehicleEffect) -> None: if effect.identify() == new_effect.identify() or effect.identify() in new_effect.conflicts_with(): return - if not new_effect.can_be_applied(self): - return - - logger.info("Car %s now has the effect %s", self.vehicle_id, str(new_effect.identify())) - self._effects.append(new_effect) - if new_effect.on_start(self) is True: - self._on_item_data_change('hacking_protection') + if new_effect.can_be_applied(self): + self.hacking_scenario = str(new_effect.identify()) + self._effects.append(new_effect) + logger.info("Car %s now has the effect %s", self.vehicle_id, str(new_effect.identify())) + if new_effect.on_start(self) is True: + self._on_item_data_change('hacking_protection') return def remove_effect(self, effect: VehicleEffect): - effect.on_end(self) - self._effects.remove(effect) + if effect.on_end(self) is True: + self.hacking_scenario = "0" + self._effects.remove(effect) async def _check_effect_removal(self): while True: