Advertisement
Guest User

Untitled

a guest
May 22nd, 2018
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 27.04 KB | None | 0 0
  1. from kivy.app import App
  2. from kivy.uix.gridlayout import GridLayout
  3. from kivy.uix.relativelayout import RelativeLayout
  4. from kivy.uix.button import Button
  5. from kivy.uix.label import Label
  6. from kivy.uix.widget import Widget
  7.  
  8. from kivy.graphics import Ellipse, Color
  9.  
  10. from simulations import Simulation, FailureSimulation
  11.  
  12. # # activate FPS counter
  13. # from kivy.config import Config
  14. # Config.set('modules', 'monitor', '')
  15.  
  16.  
  17. def update_preview(preview, simulation):
  18.     try:
  19.         for widget in simulation.node_widgets + simulation.target_widgets:
  20.             clear_map_widget(preview=preview, widget=widget)
  21.     except AttributeError:
  22.         pass
  23.  
  24.     targets = [(target.name, target.position) for target in simulation.targets.active]
  25.     nodes = [(node.name, node.position) for node in simulation.nodes.active]
  26.  
  27.     width = preview.width
  28.     height = preview.height
  29.  
  30.     mapped_targets = [
  31.         (name, (position.x * width / 100, position.y * height / 100))
  32.         for name, position in targets
  33.     ]
  34.     mapped_nodes = [
  35.         (name, (position.x * width / 100, position.y * height / 100))
  36.         for name, position in nodes
  37.     ]
  38.  
  39.     # TODO: Change adding new Widgets to getting old widgets
  40.     simulation.node_widgets = [NodeWidget(pos=position, id=name)
  41.                                for name, position in mapped_nodes]
  42.     for node_widget in simulation.node_widgets:
  43.         preview.add_widget(node_widget)
  44.  
  45.     # TODO: Change removing and adding widgets for stationary targets.
  46.     simulation.target_widgets = [TargetWidget(pos=position, id=name)
  47.                                  for name, position in mapped_targets]
  48.     for target_widget in simulation.target_widgets:
  49.         preview.add_widget(target_widget)
  50.  
  51.  
  52. def clear_map_widget(preview, widget):
  53.     preview.remove_widget(widget)
  54.     widget.canvas.clear()
  55.     del widget
  56.  
  57.  
  58. def move_map_widget(widget, position):
  59.     widget.pos = position
  60.     widget.ellipse.pos = position
  61.  
  62.  
  63. class NodeWidget(Widget):
  64.  
  65.     def __init__(self, **kwargs):
  66.         super().__init__(**kwargs)
  67.         self.canvas.clear()
  68.  
  69.         self.ellipse_color = Color(1., 1., 1.)
  70.         self.canvas.add(self.ellipse_color)
  71.  
  72.         self.ellipse = Ellipse(size=(5, 5), pos=self.pos)
  73.         self.canvas.add(self.ellipse)
  74.  
  75.  
  76. class TargetWidget(Widget):
  77.  
  78.     def __init__(self, **kwargs):
  79.         super().__init__(**kwargs)
  80.         self.canvas.clear()
  81.  
  82.         self.ellipse_color = Color(1., 0, 0)
  83.         self.canvas.add(self.ellipse_color)
  84.  
  85.         self.ellipse = Ellipse(size=(5, 5), pos=self.pos)
  86.         self.canvas.add(self.ellipse)
  87.  
  88.  
  89. class SimulationPreviewLayout(RelativeLayout):
  90.  
  91.     def __init__(self, **kwargs):
  92.         super().__init__(**kwargs)
  93.  
  94.  
  95. class SimulationMenuLayout(GridLayout):
  96.  
  97.     def __init__(self, **kwargs):
  98.         super().__init__(**kwargs)
  99.         self.cols = 1
  100.         self.rows = 4
  101.         self.padding = 10
  102.         self.spacing = 10
  103.  
  104.         self.name_label = Label(text='Menu', size_hint_y=0.1)
  105.         self.add_widget(self.name_label)
  106.  
  107.         self.restart_button = Button(text='Start simulation', size_hint_y=0.1)
  108.         self.restart_button.on_press = self.restart_simulation
  109.         self.add_widget(self.restart_button)
  110.  
  111.         self.step_button = Button(text='Step', size_hint_y=0.1)
  112.         self.step_button.on_press = self.step_simulation
  113.         self.step_button.disabled = True
  114.         self.add_widget(self.step_button)
  115.  
  116.         self.empty_space = Label(size_hint_y=0.7)
  117.         self.add_widget(self.empty_space)
  118.  
  119.     def step_simulation(self, steps=1):
  120.         simulation = self.parent.simulation
  121.  
  122.         for _ in range(steps):
  123.             if simulation.ended is not True:
  124.                 simulation.run_next_turn(spawn=True)
  125.  
  126.         preview = self.parent.preview
  127.         update_preview(preview=preview, simulation=simulation)
  128.  
  129.     def restart_simulation(self):
  130.         self.restart_button.text = 'Restart simulation'
  131.         self.step_button.disabled = False
  132.  
  133.         self.parent.simulation = FailureSimulation(nodes=100,
  134.                                                    target_spawn_rate=18,
  135.                                                    targets=200,
  136.                                                    node_load=10)
  137.  
  138.         self.simulation = self.parent.simulation
  139.         self.simulation.setup()
  140.         self.simulation.target_widgets = []
  141.         self.simulation.node_widgets = []
  142.         self.simulation.run_next_turn(spawn=False)
  143.  
  144.         preview = self.parent.preview
  145.         update_preview(preview=preview, simulation=self.simulation)
  146.  
  147.  
  148. class StepSimulationScreen(GridLayout):
  149.  
  150.     def __init__(self, **kwargs):
  151.         super().__init__(**kwargs)
  152.         self.cols = 2
  153.         self.rows = 1
  154.         self.padding = 10
  155.  
  156.         self.menu = SimulationMenuLayout(size_hint_x=1/4)
  157.         self.add_widget(self.menu)
  158.  
  159.         self.preview = SimulationPreviewLayout(size_hint_x=3/4)
  160.         self.add_widget(self.preview)
  161.  
  162.  
  163. class StepSimulationApp(App):
  164.     title = 'Basic Simulation'
  165.  
  166.     def build(self):
  167.         return StepSimulationScreen()
  168.  
  169.  
  170. if __name__ == '__main__':
  171.     StepSimulationApp().run()
  172.  
  173.  
  174.  
  175.  
  176.  
  177.  
  178.  
  179.  
  180.  
  181.  
  182. import random
  183.  
  184. from nodes import Node
  185. from targets import Target
  186.  
  187.  
  188. class NodeManager:
  189.     def __init__(self):
  190.         self._objects = []
  191.         self._active_objects = []
  192.  
  193.     @property
  194.     def active(self):
  195.         return self._active_objects
  196.  
  197.     @property
  198.     def all(self):
  199.         return self._objects
  200.  
  201.     @property
  202.     def active_count(self):
  203.         return len(self.active)
  204.  
  205.     @property
  206.     def count(self):
  207.         return len(self.all)
  208.  
  209.     # def activate(self, node):
  210.     #     if node.is_active is False:
  211.     #         node.is_active = True
  212.     #         self._active_objects.append(node)
  213.  
  214.     def deactivate(self, node):
  215.         if node.is_active is True:
  216.             node.is_active = False
  217.             self._active_objects.remove(node)
  218.  
  219.     def create(self, *args, **kwargs):
  220.         new_node = Node(*args, **kwargs, name=f'Node{self.active_count + 1}')
  221.         self._objects.append(new_node)
  222.         if new_node.is_active:
  223.             self._active_objects.append(new_node)
  224.  
  225.         return new_node
  226.  
  227.     def random(self, number=1, active=True):
  228.         if active is True:
  229.             node_pool = self._active_objects
  230.         else:
  231.             node_pool = self._objects
  232.  
  233.         if number > self.count:
  234.             return self._objects
  235.  
  236.         return [random.choice(node_pool) for _ in range(number)]
  237.  
  238.     # def delete(self, node):
  239.     #     if node in self._objects:
  240.     #         self._objects.remove(node)
  241.     #
  242.     #     if node in self._active_objects:
  243.     #         self._active_objects.remove(node)
  244.  
  245.     def closest(self, position):
  246.         nodes = {
  247.             node: node.distance(position)
  248.             for node in self.active
  249.             if node.target_position is None
  250.             and node.is_in_range(position)
  251.         }
  252.  
  253.         sorted_nodes = sorted(nodes, key=nodes.get)
  254.  
  255.         return sorted_nodes
  256.  
  257.     def nodes_in_range(self, position, exclude=True):
  258.         nodes = [node for node in self.active if node.is_in_range(position)]
  259.         if exclude is True:
  260.             for node in nodes:
  261.                 if node.position == position:
  262.                     nodes.remove(node)
  263.  
  264.         return nodes
  265.  
  266.  
  267. class TargetManager:
  268.     def __init__(self):
  269.         self._objects = []
  270.         self._active_objects = []
  271.  
  272.     @property
  273.     def active(self):
  274.         return self._active_objects
  275.  
  276.     @property
  277.     def all(self):
  278.         return self._objects
  279.  
  280.     @property
  281.     def active_count(self):
  282.         return len(self.active)
  283.  
  284.     @property
  285.     def count(self):
  286.         return len(self.all)
  287.  
  288.     # def activate(self, target):
  289.     #     if target.is_active is False:
  290.     #         target.is_active = True
  291.     #         self._active_objects.append(target)
  292.  
  293.     def deactivate(self, target, caught=True):
  294.         if target.is_active is True:
  295.             target.is_active = False
  296.             target.caught = caught
  297.             self._active_objects.remove(target)
  298.  
  299.     def create(self, *args, **kwargs):
  300.         new_target = Target(*args, **kwargs, name=f'Target{self.active_count}')
  301.         self._objects.append(new_target)
  302.         if new_target.is_active:
  303.             self._active_objects.append(new_target)
  304.  
  305.         return new_target
  306.  
  307.     def delete(self, target):
  308.         if target in self._objects:
  309.             self._objects.remove(target)
  310.  
  311.         if target in self._active_objects:
  312.             self._active_objects.remove(target)
  313.  
  314.  
  315.  
  316.  
  317.  
  318.  
  319.  
  320.  
  321.  
  322.  
  323. from environments import Environment
  324. from helpers import random_position
  325. from managers import NodeManager, TargetManager
  326.  
  327.  
  328. class Simulation:
  329.     """
  330.    Simulations are being run as a part of the study.
  331.    """
  332.     environment = None
  333.     ended = False
  334.     environment_model = Environment
  335.  
  336.     def __init__(self, nodes=20, node_load=10,
  337.                  targets=30, target_spawn_rate=4):
  338.         # Nodes
  339.         self.node_load = node_load
  340.         self.node_number = nodes
  341.  
  342.         # Targets
  343.         self.target_spawn_rate = target_spawn_rate
  344.         self.target_number = targets
  345.         self.targets_to_spawn = targets
  346.         self.max_lifetime = 300
  347.  
  348.         # Managers
  349.         self.nodes = NodeManager()
  350.         self.targets = TargetManager()
  351.  
  352.         # Environment
  353.         self.create_environment(nodes=self.nodes, targets=self.targets)
  354.         self.turn = 0
  355.  
  356.     def create_environment(self, nodes, targets):
  357.         self.environment = self.environment_model(nodes=nodes, targets=targets)
  358.  
  359.     def run(self):  # pragma: no cover
  360.         self.setup()
  361.  
  362.         while not self.ended:
  363.             self.run_next_turn()
  364.             if self.turn % 100 == 0:
  365.                 print(f'Simulation turn: {self.turn}.')
  366.  
  367.         self.save_results()
  368.         print(f'Simulation ran successfully! Results has been saved.')
  369.  
  370.     def run_next_turn(self, spawn=True):
  371.         if spawn is True:
  372.             self.spawn_target()
  373.  
  374.         self.nodes_pursue()
  375.         self.move_nodes()
  376.         self.age_targets()
  377.  
  378.         self.end_simulation_if_no_more_targets()
  379.         self.turn += 1
  380.  
  381.     def nodes_pursue(self):
  382.         """
  383.        For every target that is not being pursued node if searched.
  384.        If node if found- pursuit is established. If target is within
  385.        reach of node, it is deactivated, node is moved and pursuit
  386.        is ended. Node later on will be normally moved by loads.
  387.        """
  388.         for target in self.targets.active:
  389.             # set pursuits for active targets if not set already
  390.             if target.pursued_by is None:
  391.                 # check all nodes in range, is any is found- stop searching
  392.                 for node in self.nodes.closest(target.position):
  393.                     if node.target_position is None:
  394.                         target.pursued_by = node
  395.                         node.target_position = target.position
  396.                         break
  397.  
  398.     def move_nodes(self):
  399.         """
  400.        After nodes start pursuits, if they have a target they are moved
  401.        towards the target. Otherwise they are moved by loads(forces).
  402.        """
  403.         nodes_with_forces = dict()
  404.         for node in self.nodes.active:
  405.             # calculate forces by loads if node has no target
  406.             if node.target_position is None:
  407.                 force = self.environment.calculate_force(node)
  408.                 nodes_with_forces[node] = force
  409.  
  410.             # move targets towards target position if it is set
  411.             else:
  412.                 target = self.environment.get_target_by_position(node.target_position)
  413.                 node.move_to_position(target.position)
  414.                 if node.distance(target.position) < node.speed:
  415.                     self.targets.deactivate(target)
  416.                     node.target_position = None
  417.  
  418.         # apply calculated forces
  419.         for node, force in nodes_with_forces.items():
  420.             node.move_by_force(force, map_size=self.environment.map_size)
  421.  
  422.     def setup(self):
  423.         map_size = self.environment.map_size
  424.         for _ in range(self.node_number):
  425.             self.nodes.create(load=self.node_load,
  426.                               sight_range=self.environment.range,
  427.                               position=random_position(1, map_size - 1),
  428.                               speed=0.2)
  429.  
  430.     def spawn_target(self):
  431.         """
  432.        Spawns target if there are still targets to be spawned and if spawn
  433.        rate aligns with current turn.
  434.        """
  435.         map_size = self.environment.map_size
  436.         if self.turn % self.target_spawn_rate == 0 and self.targets_to_spawn > 0:
  437.             target_position = random_position(1, map_size - 1)
  438.  
  439.             self.targets.create(position=target_position)
  440.             self.targets_to_spawn -= 1
  441.  
  442.     def age_targets(self):
  443.         for target in self.targets.active:
  444.             target.age(1)
  445.             if target.lifetime == self.max_lifetime:
  446.                 self.targets.deactivate(target, caught=False)
  447.  
  448.                 # remove pursuer's target_position if given target is too old
  449.                 if target.pursued_by is not None:
  450.                     node = target.pursued_by
  451.                     target.pursued_by = None
  452.                     node.target_position = None
  453.  
  454.     def end_simulation_if_no_more_targets(self):
  455.         if self.targets_to_spawn == 0 and self.targets.active_count == 0:
  456.             self.ended = True
  457.  
  458.     def save_results(self):  # pragma: no cover
  459.         file_name = 'results.txt'
  460.         with open(file_name, 'w+') as results:
  461.  
  462.             cumulative_lifespan = sum([target.lifetime for target in self.targets.all])
  463.             average_lifespan = cumulative_lifespan / self.targets.count
  464.             uncaught_targets = len([target for target in self.targets.all
  465.                                     if target.caught is False])
  466.  
  467.             results.write(f'Simulation ended in turn {self.turn}.\n')
  468.             results.write(f'Cumulative target lifespan was: {cumulative_lifespan}.\n')
  469.             results.write(f'Average target lifespan was: {average_lifespan}.\n')
  470.             results.write(f'Uncaught targets: {uncaught_targets}.\n')
  471.  
  472.             for node in self.nodes.all:
  473.                 results.write(str(node) + '\n')
  474.  
  475.             for target in self.targets.all:
  476.                 results.write(str(target) + '\n')
  477.  
  478.  
  479. class FailureSimulation(Simulation):
  480.  
  481.     def setup(self, number=0.5):
  482.         super().setup()
  483.         self.partial_failure(number=number)
  484.  
  485.     def partial_failure(self, number=None):
  486.         if number is None:
  487.             failing_nodes = self.nodes.random(number=int(0.5 * self.nodes.active_count),
  488.                                               active=True)
  489.         elif number < 1:
  490.             failing_nodes = self.nodes.random(number=int(number * self.nodes.active_count),
  491.                                               active=True)
  492.         else:
  493.             failing_nodes = self.nodes.random(number=number,
  494.                                               active=True)
  495.  
  496.         # Call deactivate for all nodes
  497.         return [self.nodes.deactivate(node) for node in failing_nodes]
  498.  
  499.  
  500.  
  501.  
  502.  
  503.  
  504.  
  505.  
  506.  
  507.  
  508.  
  509.  
  510. import random
  511. import pytest
  512.  
  513. from simulations import Simulation, FailureSimulation
  514.  
  515. from helpers import random_position, Position
  516.  
  517.  
  518. class TestSimulation:
  519.     def test_creating_simulation(self):
  520.         simulation = Simulation()
  521.  
  522.         assert simulation is not None
  523.         assert simulation.environment is not None
  524.         assert simulation.ended is False
  525.  
  526.     def test_end_simulation(self):
  527.         simulation = Simulation(targets=0)
  528.         simulation.end_simulation_if_no_more_targets()
  529.  
  530.         assert simulation.ended is True
  531.  
  532.     def test_setup(self):
  533.         node_number = 10
  534.         simulation = Simulation(nodes=node_number)
  535.         simulation.setup()
  536.  
  537.         assert simulation.node_number == node_number
  538.         assert simulation.nodes.count == node_number
  539.  
  540.     def test_spawn_target_on_starting_turn(self):
  541.         simulation = Simulation(target_spawn_rate=10)
  542.         simulation.spawn_target()
  543.  
  544.         assert simulation.targets.count == 1
  545.         assert simulation.targets.active_count == 1
  546.  
  547.     def test_spawn_target_with_not_aligned_turn(self):
  548.         simulation = Simulation(target_spawn_rate=10)
  549.         simulation.turn = 5
  550.         simulation.spawn_target()
  551.  
  552.         assert simulation.targets.count == 0
  553.         assert simulation.targets.active_count == 0
  554.  
  555.     def test_spawn_target_with_aligned_turn(self):
  556.         simulation = Simulation(target_spawn_rate=1)
  557.         simulation.turn = 5
  558.         simulation.spawn_target()
  559.  
  560.         assert simulation.targets.active_count == 1
  561.         assert simulation.targets.count == 1
  562.  
  563.     def test_spawn_target_random_positions(self):
  564.         # set seed for random position function
  565.         random.seed(123)
  566.  
  567.         simulation = Simulation(target_spawn_rate=10)
  568.         simulation.spawn_target()
  569.         simulation.spawn_target()
  570.  
  571.         map_size = simulation.environment.map_size
  572.         # restart seed to get the same values
  573.         random.seed(123)
  574.  
  575.         position1 = random_position(1, map_size - 1)
  576.         position2 = random_position(1, map_size - 1)
  577.  
  578.         targets = simulation.targets.active
  579.         target1, target2 = targets
  580.  
  581.         assert target1.position == position1
  582.         assert target2.position == position2
  583.         assert target1.position != target2.position
  584.  
  585.     def test_nodes_pursue_when_node_is_close(self):
  586.         simulation = Simulation()
  587.  
  588.         node = simulation.nodes.create(position=(50, 51))
  589.         target = simulation.targets.create(position=(50, 50))
  590.  
  591.         node_target_before = node.target_position
  592.  
  593.         simulation.nodes_pursue()
  594.  
  595.         node_target_after = node.target_position
  596.  
  597.         assert target in simulation.targets.all
  598.         assert target in simulation.targets.active
  599.         assert node_target_before is None
  600.         assert node_target_after == target.position
  601.         assert target.pursued_by is node
  602.  
  603.     def test_nodes_pursue_when_node_is_away(self):
  604.         simulation = Simulation()
  605.  
  606.         node = simulation.nodes.create(position=(90, 90))
  607.         target = simulation.targets.create(position=(50, 50))
  608.  
  609.         node_target_before = node.target_position
  610.  
  611.         simulation.nodes_pursue()
  612.  
  613.         node_target_after = node.target_position
  614.  
  615.         assert target in simulation.targets.active
  616.         assert node_target_before is None
  617.         assert node_target_after is None
  618.         assert target.pursued_by is None
  619.  
  620.     def test_nodes_pursue_when_target_is_pursued(self):
  621.         simulation = Simulation()
  622.  
  623.         node = simulation.nodes.create(position=(50, 51))
  624.         pursuer = simulation.nodes.create(position=(52, 52))
  625.         target = simulation.targets.create(position=(50, 50))
  626.         target.pursued_by = pursuer
  627.  
  628.         node_target_before = node.target_position
  629.  
  630.         simulation.nodes_pursue()
  631.  
  632.         node_target_after = node.target_position
  633.  
  634.         assert target in simulation.targets.active
  635.         assert node_target_before is None
  636.         assert node_target_after is None
  637.         assert target.pursued_by is pursuer
  638.  
  639.     def test_age_targets(self):
  640.         simulation = Simulation()
  641.  
  642.         target1 = simulation.targets.create(position=(50, 50))
  643.         simulation.age_targets()
  644.  
  645.         target2 = simulation.targets.create(position=(50, 50))
  646.  
  647.         simulation.age_targets()
  648.  
  649.         assert target1.lifetime == 2
  650.         assert target2.lifetime == 1
  651.  
  652.     def test_age_targets_deactivate_target_without_pursuer(self):
  653.         simulation = Simulation()
  654.  
  655.         target_old = simulation.targets.create(position=(50, 50))
  656.         target_old.lifetime = simulation.max_lifetime - 1
  657.  
  658.         simulation.age_targets()
  659.  
  660.         assert target_old.caught is False
  661.         assert target_old in simulation.targets.all
  662.         assert target_old not in simulation.targets.active
  663.         assert target_old.lifetime == simulation.max_lifetime
  664.  
  665.     def test_age_targets_deactivate_target_with_pursuer(self):
  666.         simulation = Simulation()
  667.         pursuer = simulation.nodes.create(position=(50, 50))
  668.  
  669.         target_old_pursued = simulation.targets.create(position=(50, 50))
  670.         target_old_pursued.lifetime = simulation.max_lifetime - 1
  671.         pursuer.target_position = target_old_pursued.position
  672.         target_old_pursued.pursued_by = pursuer
  673.  
  674.         simulation.age_targets()
  675.  
  676.         assert target_old_pursued.caught is False
  677.         assert target_old_pursued in simulation.targets.all
  678.         assert target_old_pursued not in simulation.targets.active
  679.         assert target_old_pursued.lifetime == simulation.max_lifetime
  680.         assert target_old_pursued.pursued_by is None
  681.         assert pursuer.target_position is None
  682.  
  683.     def test_move_nodes_by_loads(self):
  684.         simulation = Simulation()
  685.         node = simulation.nodes.create(position=(60, 60))
  686.  
  687.         node_position_before_x = node.position.x
  688.         node_position_before_y = node.position.y
  689.         simulation.move_nodes()
  690.  
  691.         assert node.position.x < node_position_before_x
  692.         assert node.position.y < node_position_before_y
  693.  
  694.     def test_move_nodes_by_loads_equilibrium(self):
  695.         simulation = Simulation()
  696.  
  697.         position1 = (simulation.environment.map_size / 3,
  698.                      50)
  699.         position2 = (simulation.environment.map_size * 2 / 3,
  700.                      50)
  701.  
  702.         node1 = simulation.nodes.create(position=position1)
  703.         node2 = simulation.nodes.create(position=position2)
  704.  
  705.         simulation.move_nodes()
  706.  
  707.         assert node1.position.y == Position(*position1).y
  708.         assert node2.position.y == Position(*position2).y
  709.  
  710.     def test_move_nodes_by_loads_with_moving_nodes(self):
  711.         simulation = Simulation()
  712.         node = simulation.nodes.create(position=(50, 50))
  713.         target = simulation.targets.create(position=(90, 90))
  714.  
  715.         node_moving = simulation.nodes.create(position=(45, 45))
  716.         node_moving.target_position = target.position
  717.  
  718.         node_position_before = Position(*node.position)
  719.         simulation.move_nodes()
  720.  
  721.         assert node.position != node_position_before
  722.  
  723.     def test_move_nodes_deactivate_target(self):
  724.         simulation = Simulation()
  725.         node = simulation.nodes.create(position=(50, 50))
  726.         target = simulation.targets.create(position=(51, 51))
  727.  
  728.         node.target_position = target.position
  729.  
  730.         simulation.move_nodes()
  731.  
  732.         assert node.position == target.position
  733.         assert node.target_position is None
  734.  
  735.     def test_move_nodes_move_towards_target(self):
  736.         simulation = Simulation()
  737.         node = simulation.nodes.create(position=(50, 50))
  738.         target = simulation.targets.create(position=(90, 90))
  739.  
  740.         node.target_position = target.position
  741.         node_position_before = Position(node.position.x, node.position.y)
  742.  
  743.         simulation.move_nodes()
  744.  
  745.         assert node.position.x > node_position_before.x
  746.         assert node.position.y > node_position_before.y
  747.         assert node.target_position is target.position
  748.  
  749.     def test_run_next_turn(self):
  750.         simulation = Simulation()
  751.  
  752.         node1 = simulation.nodes.create(position=(50, 50),
  753.                                         sight_range=20,
  754.                                         speed=2)
  755.         node2 = simulation.nodes.create(position=(49, 49),
  756.                                         sight_range=20,
  757.                                         speed=2)
  758.         target = simulation.targets.create(position=(55, 55))
  759.  
  760.         turn_before = simulation.turn
  761.         target_age_before = target.lifetime
  762.         node1_position_before = Position(*node1.position)
  763.         node2_position_before = Position(*node2.position)
  764.  
  765.         simulation.run_next_turn()
  766.  
  767.         assert simulation.turn == turn_before + 1
  768.         assert simulation.ended is False
  769.         assert target.lifetime == target_age_before + 1
  770.         assert node1.position != node1_position_before
  771.         assert node1.target_position == target.position
  772.         assert node2.position != node2_position_before
  773.         assert node2.target_position is None
  774.  
  775.     def test_run_next_turn_if_no_more_targets(self):
  776.         simulation = Simulation(targets=0)
  777.  
  778.         simulation.nodes.create(position=(50, 50), sight_range=20, speed=2)
  779.  
  780.         simulation.run_next_turn()
  781.  
  782.         assert simulation.ended is True
  783.  
  784.     def test_run_next_turn_if_0_targets_but_more_to_spawn(self):
  785.         simulation = Simulation(targets=2, target_spawn_rate=200)
  786.  
  787.         simulation.nodes.create(position=(50, 50), sight_range=20, speed=2)
  788.  
  789.         simulation.run_next_turn()
  790.         simulation.run_next_turn()
  791.  
  792.         target = simulation.targets.all[0]
  793.         simulation.targets.delete(target)
  794.  
  795.         assert simulation.ended is False
  796.  
  797.     def test_run_next_turn_with_spawn_false(self):
  798.         simulation = Simulation(targets=1, target_spawn_rate=1)
  799.  
  800.         simulation.nodes.create(position=(50, 50), sight_range=20, speed=2)
  801.  
  802.         simulation.run_next_turn(spawn=False)
  803.         simulation.run_next_turn(spawn=False)
  804.         simulation.run_next_turn(spawn=False)
  805.  
  806.         assert simulation.ended is False
  807.  
  808.  
  809. class TestFailureSimulation:
  810.  
  811.     def test_setup_without_percentage(self):
  812.         simulation = FailureSimulation(target_spawn_rate=200, nodes=10)
  813.  
  814.         simulation.setup()
  815.  
  816.         inactive_nodes = [node for node in simulation.nodes.all if
  817.                           node.is_active is False]
  818.  
  819.         assert len(inactive_nodes) == 5
  820.         assert simulation.nodes.active_count == 5
  821.  
  822.     def test_setup_with_percentage(self):
  823.         simulation = FailureSimulation(target_spawn_rate=200, nodes=10)
  824.  
  825.         simulation.setup(number=0.3)
  826.  
  827.         inactive_nodes = [node for node in simulation.nodes.all if
  828.                           node.is_active is False]
  829.  
  830.         assert len(inactive_nodes) == 3
  831.         assert simulation.nodes.active_count == 7
  832.  
  833.     def test_partial_failure(self):
  834.         simulation = FailureSimulation(target_spawn_rate=200, nodes=10)
  835.  
  836.         simulation.partial_failure()
  837.  
  838.         inactive_nodes = [node for node in simulation.nodes.all if
  839.                           node.is_active is False]
  840.  
  841.         assert len(inactive_nodes) == 5
  842.         assert simulation.nodes.active_count == 5
  843.  
  844.     def test_partial_failure_with_percentage(self):
  845.         simulation = FailureSimulation(target_spawn_rate=200, nodes=10)
  846.  
  847.         simulation.partial_failure(number=0.3)
  848.  
  849.         inactive_nodes = [node for node in simulation.nodes.all if
  850.                           node.is_active is False]
  851.  
  852.         assert len(inactive_nodes) == 3
  853.         assert simulation.nodes.active_count == 7
  854.  
  855.     def test_partial_failure_with_number(self):
  856.         simulation = FailureSimulation(target_spawn_rate=200, nodes=10)
  857.  
  858.         simulation.partial_failure(3)
  859.  
  860.         inactive_nodes = [node for node in simulation.nodes.all if
  861.                           node.is_active is False]
  862.  
  863.         assert len(inactive_nodes) == 3
  864.         assert simulation.nodes.active_count == 7
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement