Commit 4a673030 authored by Ahmad Reza's avatar Ahmad Reza
Browse files

Again a lot of changes have been done:

- For the reading the data of the config the classe ConfigData is created
in a seperated file called config.py

- For the visualization a bug is fixed. The bug was that whenever
the vis.py goes into a sleep it is not possible to zoom or to create
tiles. !This bus has been fixed by Karol Actun!

- Three methods sim_to_coords, coords_to_sim, check_coords are moved
from the world.py to the header.py. Because those methods are
independent from the world.py. Based on these change some changes
have to been made on the other files.

- The particle counter has been removed from particle.py. The counting
of the particle and given the particle a number based on the counting
is happening now in world.py.

- Some unnecessary variables have been deleted from the matters.
parent 9eb54fc1
import configparser
from datetime import datetime
class ConfigData:
def __init__(self):
config = configparser.ConfigParser(allow_no_value=True)
config.read("config.ini")
self.seed_value = config.getint("Simulator", "seedvalue")
self.max_round = config.getint("Simulator", "max_round")
self.random_order = config.getboolean("Simulator", "random_order")
self.visualization = config.getint("Simulator", "visualization")
try:
self.scenario = config.get("File", "scenario")
except configparser.NoOptionError as noe:
self.scenario = "init_scenario.py"
try:
self.solution = config.get("File", "solution")
except configparser.NoOptionError as noe:
self.solution = "solution.py"
self.size_x = config.getfloat("Simulator", "size_x")
self.size_y = config.getfloat("Simulator", "size_y")
self.window_size_x = config.getint("Simulator", "window_size_x")
self.window_size_y = config.getint("Simulator", "window_size_y")
self.border = config.getfloat("Simulator", "border")
self.max_particles = config.getint("Simulator", "max_particles")
self.mm_limitation = config.getboolean("Matter", "mm_limitation")
self.particle_mm_size = config.getint("Matter", "particle_mm_size")
self.tile_mm_size = config.getint("Matter", "tile_mm_size")
self.marker_mm_size = config.getint("Matter", "marker_mm_size")
self.local_time = datetime.now().strftime('%Y-%m-%d_%H-%M-%S')[:-1]
self.multiple_sim = 0
...@@ -109,27 +109,26 @@ class CsvParticleData: ...@@ -109,27 +109,26 @@ class CsvParticleData:
class CsvRoundData: class CsvRoundData:
def __init__(self, task=0, scenario=0, solution=0, seed=20, particle_num=0, tiles_num=0, markers_num=0, def __init__(self, task=0, scenario=0, solution=0, seed=20, directory="outputs/"):
steps=0, directory="outputs/"):
self.task = task self.task = task
self.scenario = scenario self.scenario = scenario
self.solution = solution self.solution = solution
self.actual_round= 1 self.actual_round= 1
self.seed = seed self.seed = seed
self.steps = steps self.steps = 0
self.steps_sum = steps self.steps_sum = 0
self.particle_created=0 self.particle_created=0
self.particle_deleted=0 self.particle_deleted=0
self.particle_num = particle_num self.particle_num = 0
self.particle_read = 0 self.particle_read = 0
self.particle_write = 0 self.particle_write = 0
self.tile_created = 0 self.tile_created = 0
self.tile_deleted = 0 self.tile_deleted = 0
self.tile_num = tiles_num self.tile_num = 0
self.tile_read = 0 self.tile_read = 0
self.tile_write = 0 self.tile_write = 0
self.markers_num = markers_num self.markers_num = 0
self.marker_read = 0 self.marker_read = 0
self.marker_write = 0 self.marker_write = 0
self.marker_created = 0 self.marker_created = 0
......
import math
from enum import Enum from enum import Enum
...@@ -79,3 +80,32 @@ def get_the_invert(dir): ...@@ -79,3 +80,32 @@ def get_the_invert(dir):
def dir_in_range(dir): def dir_in_range(dir):
return dir % 6 return dir % 6
def check_coords( coords_x, coords_y):
"""
Checks if the given coordinates are matching the
hexagon coordinates
:param coords_x: proposed x coordinate
:param coords_y: proposed y coordinate
:return: True: Correct x and y coordinates; False: Incorrect coordinates
"""
if (coords_x / 0.5) % 2 == 0:
if coords_y % 2 != 0:
return False
else:
return True
else:
if coords_y % 2 == 0:
return False
else:
return True
def coords_to_sim(coords):
return coords[0], coords[1] * math.sqrt(3 / 4)
def sim_to_coords(x, y):
return x, round(y / math.sqrt(3 / 4), 0)
\ No newline at end of file
...@@ -24,6 +24,7 @@ class Matter: ...@@ -24,6 +24,7 @@ class Matter:
self.mm_limit = world.config_data.mm_limitation self.mm_limit = world.config_data.mm_limitation
self.mm_size = mm_size self.mm_size = mm_size
self.modified = False self.modified = False
self.created = False
def set_alpha(self, alpha): def set_alpha(self, alpha):
""" """
......
...@@ -18,27 +18,17 @@ particle_counter=0 ...@@ -18,27 +18,17 @@ particle_counter=0
class Particle(matter.Matter): class Particle(matter.Matter):
"""In the classe marker all the methods for the characterstic of a marker is included""" """In the classe marker all the methods for the characterstic of a marker is included"""
def __init__(self, world, x, y, color=black, alpha=1): def __init__(self, world, x, y, color=black, alpha=1, particle_counter = particle_counter):
"""Initializing the marker constructor""" """Initializing the marker constructor"""
super().__init__( world, (x, y), color, alpha, type="particle", mm_size=world.config_data.particle_mm_size) super().__init__( world, (x, y), color, alpha,
global particle_counter type="particle", mm_size=world.config_data.particle_mm_size)
particle_counter+=1 self.number = particle_counter
self.number=particle_counter
self.__isCarried = False self.__isCarried = False
self.created = False
self.carried_tile = None self.carried_tile = None
self.carried_particle = None self.carried_particle = None
self.__isCarried = False
self.steps = 0 self.steps = 0
self.created = False
self.csv_particle_writer = csv_generator.CsvParticleData( self.get_id(), self.number) self.csv_particle_writer = csv_generator.CsvParticleData( self.get_id(), self.number)
def coords_to_sim(self, coords):
return coords[0], coords[1] * math.sqrt(3 / 4)
def sim_to_coords(self, x, y):
return x, round(y / math.sqrt(3 / 4), 0)
def has_tile(self): def has_tile(self):
if self.carried_tile == None: if self.carried_tile == None:
return False return False
...@@ -51,7 +41,6 @@ class Particle(matter.Matter): ...@@ -51,7 +41,6 @@ class Particle(matter.Matter):
else: else:
return True return True
def get_carried_status(self): def get_carried_status(self):
""" """
Get the status if it is taken or not Get the status if it is taken or not
...@@ -71,7 +60,6 @@ class Particle(matter.Matter): ...@@ -71,7 +60,6 @@ class Particle(matter.Matter):
else: else:
return False return False
def check_on_particle(self): def check_on_particle(self):
""" """
Checks if the particle is on a particle Checks if the particle is on a particle
...@@ -103,7 +91,7 @@ class Particle(matter.Matter): ...@@ -103,7 +91,7 @@ class Particle(matter.Matter):
""" """
dir_coord = self.world.get_coords_in_dir(self.coords, dir) dir_coord = self.world.get_coords_in_dir(self.coords, dir)
dir, dir_coord = self.check_within_border(dir, dir_coord) dir, dir_coord = self.check_within_border(dir, dir_coord)
if self.world.check_coords(dir_coord[0], dir_coord[1]): if check_coords(dir_coord[0], dir_coord[1]):
if self.coords in self.world.particle_map_coords: if self.coords in self.world.particle_map_coords:
del self.world.particle_map_coords[self.coords] del self.world.particle_map_coords[self.coords]
...@@ -142,7 +130,7 @@ class Particle(matter.Matter): ...@@ -142,7 +130,7 @@ class Particle(matter.Matter):
:return: True: Success Moving; False: Non moving :return: True: Success Moving; False: Non moving
""" """
dir_coord = self.world.get_coords_in_dir(self.coords, dir) dir_coord = self.world.get_coords_in_dir(self.coords, dir)
sim_coord = self.coords_to_sim(dir_coord) sim_coord = coords_to_sim(dir_coord)
if self.world.get_sim_x_size() >= abs(sim_coord[0]) and \ if self.world.get_sim_x_size() >= abs(sim_coord[0]) and \
self.world.get_sim_y_size() >= abs(sim_coord[1]): self.world.get_sim_y_size() >= abs(sim_coord[1]):
return self.move_to(dir) return self.move_to(dir)
...@@ -799,7 +787,7 @@ class Particle(matter.Matter): ...@@ -799,7 +787,7 @@ class Particle(matter.Matter):
logging.info("particle with id %s is", self.get_id()) logging.info("particle with id %s is", self.get_id())
if x is not None and y is not None: if x is not None and y is not None:
coords = (x, y) coords = (x, y)
if self.world.check_coords(x,y): if check_coords(x,y):
logging.info("Going to create a tile on position \(%i , %i\)", x,y ) logging.info("Going to create a tile on position \(%i , %i\)", x,y )
if self.world.add_tile(coords[0], coords[1], color, alpha) == True: if self.world.add_tile(coords[0], coords[1], color, alpha) == True:
self.world.tile_map_coords[coords[0], coords[1]].created = True self.world.tile_map_coords[coords[0], coords[1]].created = True
...@@ -980,7 +968,7 @@ class Particle(matter.Matter): ...@@ -980,7 +968,7 @@ class Particle(matter.Matter):
:return: True: successful taken; False: unsuccessful taken :return: True: successful taken; False: unsuccessful taken
""" """
if self.carried_particle is None and self.carried_tile is None: if self.carried_particle is None and self.carried_tile is None:
if self.world.check_coords(x, y): if check_coords(x, y):
coords = (x, y) coords = (x, y)
if coords in self.world.tile_map_coords: if coords in self.world.tile_map_coords:
self.carried_tile = self.world.tile_map_coords[coords] self.carried_tile = self.world.tile_map_coords[coords]
...@@ -1060,7 +1048,7 @@ class Particle(matter.Matter): ...@@ -1060,7 +1048,7 @@ class Particle(matter.Matter):
:param y: y coordinate :param y: y coordinate
""" """
if self.carried_tile is not None: if self.carried_tile is not None:
if self.world.check_coords(x, y): if check_coords(x, y):
coords = (x, y) coords = (x, y)
if coords not in self.world.get_tile_map_coords(): if coords not in self.world.get_tile_map_coords():
try: # cher: insert so to overcome the AttributeError try: # cher: insert so to overcome the AttributeError
...@@ -1138,7 +1126,7 @@ class Particle(matter.Matter): ...@@ -1138,7 +1126,7 @@ class Particle(matter.Matter):
""" """
coords = (0, 0) coords = (0, 0)
if x is not None and y is not None: if x is not None and y is not None:
if self.world.check_coords(x, y): if check_coords(x, y):
coords = (x, y) coords = (x, y)
logging.info("Going to create a particle on position %s", str(coords)) logging.info("Going to create a particle on position %s", str(coords))
new_particle = self.world.add_particle(coords[0], coords[1], color, alpha) new_particle = self.world.add_particle(coords[0], coords[1], color, alpha)
...@@ -1213,7 +1201,7 @@ class Particle(matter.Matter): ...@@ -1213,7 +1201,7 @@ class Particle(matter.Matter):
:return: True: Deleting successful; False: Deleting unsuccessful :return: True: Deleting successful; False: Deleting unsuccessful
""" """
if x is not None and y is not None: if x is not None and y is not None:
if self.world.check_coords(x, y): if check_coords(x, y):
coords = (x, y) coords = (x, y)
if self.world.remove_particle_on(coords): if self.world.remove_particle_on(coords):
logging.info("Deleted particle with particle on coords %s", str(coords)) logging.info("Deleted particle with particle on coords %s", str(coords))
...@@ -1313,7 +1301,7 @@ class Particle(matter.Matter): ...@@ -1313,7 +1301,7 @@ class Particle(matter.Matter):
:return: True: Successful taken; False: Cannot be taken or wrong Coordinates :return: True: Successful taken; False: Cannot be taken or wrong Coordinates
""" """
if self.carried_particle is None and self.carried_tile is None: if self.carried_particle is None and self.carried_tile is None:
if self.world.check_coords(x, y): if check_coords(x, y):
coords = (x, y) coords = (x, y)
if coords in self.world.particle_map_coords: if coords in self.world.particle_map_coords:
self.carried_particle = self.world.particle_map_coords[coords] self.carried_particle = self.world.particle_map_coords[coords]
...@@ -1394,7 +1382,7 @@ class Particle(matter.Matter): ...@@ -1394,7 +1382,7 @@ class Particle(matter.Matter):
""" """
if self.carried_particle is not None: if self.carried_particle is not None:
if x is not None and y is not None: if x is not None and y is not None:
if self.world.check_coords(x, y): if check_coords(x, y):
coords = (x, y) coords = (x, y)
if coords not in self.world.particle_map_coords: if coords not in self.world.particle_map_coords:
try: # cher: insert so to overcome the AttributeError try: # cher: insert so to overcome the AttributeError
...@@ -1483,7 +1471,7 @@ class Particle(matter.Matter): ...@@ -1483,7 +1471,7 @@ class Particle(matter.Matter):
""" """
coords = (0, 0) coords = (0, 0)
if x is not None and y is not None: if x is not None and y is not None:
if self.world.check_coords(x, y): if check_coords(x, y):
coords = (x, y) coords = (x, y)
logging.info("Going to create a marker on position %s", str(coords)) logging.info("Going to create a marker on position %s", str(coords))
new_marker = self.world.add_marker(coords[0], coords[1], color, alpha) new_marker = self.world.add_marker(coords[0], coords[1], color, alpha)
...@@ -1558,7 +1546,7 @@ class Particle(matter.Matter): ...@@ -1558,7 +1546,7 @@ class Particle(matter.Matter):
:return: True: Deleting successful; False: Deleting unsuccessful :return: True: Deleting successful; False: Deleting unsuccessful
""" """
if x is not None and y is not None: if x is not None and y is not None:
if self.world.check_coords(x, y): if check_coords(x, y):
coords = (x, y) coords = (x, y)
if self.world.remove_marker_on(coords): if self.world.remove_marker_on(coords):
logging.info("Deleted marker oords %s", str(coords)) logging.info("Deleted marker oords %s", str(coords))
......
...@@ -10,7 +10,6 @@ class Tile(matter.Matter): ...@@ -10,7 +10,6 @@ class Tile(matter.Matter):
"""Initializing the marker constructor""" """Initializing the marker constructor"""
super().__init__( world, (x, y), color, alpha, type="tile", mm_size=world.config_data.tile_mm_size) super().__init__( world, (x, y), color, alpha, type="tile", mm_size=world.config_data.tile_mm_size)
self.__isCarried = False self.__isCarried = False
self.created = False
def get_tile_status(self): def get_tile_status(self):
""" """
......
...@@ -30,7 +30,7 @@ busy_waiting_time = 1 ...@@ -30,7 +30,7 @@ busy_waiting_time = 1
print_frame_stats = False print_frame_stats = False
# simulation parameters # simulation parameters
rounds_per_second = 1 rounds_per_second = 10
# tile_alpha = 0.6 # tile_alpha = 0.6
particle_alpha = 1 particle_alpha = 1
...@@ -417,16 +417,25 @@ class VisWindow(pyglet.window.Window): ...@@ -417,16 +417,25 @@ class VisWindow(pyglet.window.Window):
self.marker_vertex_list.colors[16 * i: 16 * i + 16] = (marker.color + [marker.get_alpha()]) * 4 self.marker_vertex_list.colors[16 * i: 16 * i + 16] = (marker.color + [marker.get_alpha()]) * 4
def draw_world(self): def draw_world(self, round_start_timestamp):
while not self.simulation_running: while not self.simulation_running:
self.dispatch_events() self.dispatch_events()
self.draw() self.draw()
if self.simulation_running or self.window_active is False: if self.simulation_running or self.window_active is False:
return return
self.dispatch_events()
#while actual simulation round is below max round
time.sleep(1/rounds_per_second)
self.draw() self.draw()
# waiting until enough time passed to do the next simulation round.
time_elapsed = time.perf_counter() - round_start_timestamp
while time_elapsed < 1 / rounds_per_second:
# waiting for 1/100 of the round_time
waiting_time = (1 / rounds_per_second) / 100
time.sleep(waiting_time)
self.dispatch_events()
self.draw()
time_elapsed = time.perf_counter() - round_start_timestamp
return return
def finished(self): def finished(self):
......
...@@ -17,11 +17,11 @@ class World: ...@@ -17,11 +17,11 @@ class World:
""" """
Initializing the world constructor Initializing the world constructor
:param seed: seed number for new random numbers :param seed: seed number for new random numbers
:param max_round: the max round number for terminating the simulator :param max_round: the max round number for terminating the worldulator
:param solution: The name of the solution that is going to be used :param solution: The name of the solution that is going to be used
:param size_x: the maximal size of the x axes :param size_x: the maximal size of the x axes
:param size_y: the maximal size of the y axes :param size_y: the maximal size of the y axes
:param sim_name: the name of the world file that is used to build up the world :param world_name: the name of the world file that is used to build up the world
:param solution_name: the name of the solution file that is only used for the csv file :param solution_name: the name of the solution file that is only used for the csv file
:param seed: the seed number it is only used here for the csv file :param seed: the seed number it is only used here for the csv file
:param max_particles: the maximal number of particles that are allowed to be or created in this world :param max_particles: the maximal number of particles that are allowed to be or created in this world
...@@ -31,7 +31,7 @@ class World: ...@@ -31,7 +31,7 @@ class World:
self.__end = False self.__end = False
self.init_particles=[] self.init_particles=[]
self.particle_num=0 self.particle_id_counter = 0
self.particles = [] self.particles = []
self.particles_created = [] self.particles_created = []
self.particle_rm = [] self.particle_rm = []
...@@ -39,7 +39,6 @@ class World: ...@@ -39,7 +39,6 @@ class World:
self.particle_map_id = {} self.particle_map_id = {}
self.__particle_deleted=False self.__particle_deleted=False
self.tiles_num = 0
self.tiles = [] self.tiles = []
self.tiles_created = [] self.tiles_created = []
self.tiles_rm = [] self.tiles_rm = []
...@@ -48,7 +47,6 @@ class World: ...@@ -48,7 +47,6 @@ class World:
self.__tile_deleted=False self.__tile_deleted=False
self.new_tile = None self.new_tile = None
self.markers_num=0
self.markers = [] self.markers = []
self.markers_created = [] self.markers_created = []
self.marker_map_coords = {} self.marker_map_coords = {}
...@@ -56,14 +54,12 @@ class World: ...@@ -56,14 +54,12 @@ class World:
self.markers_rm = [] self.markers_rm = []
self.__marker_deleted = False self.__marker_deleted = False
self.directory = config_data.dir_name
self.config_data = config_data self.config_data = config_data
self.csv_round = csv_generator.CsvRoundData(scenario=config_data.scenario, self.csv_round = csv_generator.CsvRoundData(scenario=config_data.scenario,
solution=config_data.solution, solution=config_data.solution,
seed=config_data.seed_value, seed=config_data.seed_value,
tiles_num=0, particle_num=0, directory=config_data.dir_name)
steps=0, directory=config_data.dir_name)
mod = importlib.import_module('scenario.' + self.config_data.scenario) mod = importlib.import_module('scenario.' + self.config_data.scenario)
mod.scenario(self) mod.scenario(self)
...@@ -76,7 +72,7 @@ class World: ...@@ -76,7 +72,7 @@ class World:
def csv_aggregator(self): def csv_aggregator(self):
self.csv_round.aggregate_metrics() self.csv_round.aggregate_metrics()
particle_csv = csv_generator.CsvParticleFile(self.directory) particle_csv = csv_generator.CsvParticleFile(self.config_data.dir_name)
for particle in self.particles: for particle in self.particles:
particle_csv.write_particle(particle) particle_csv.write_particle(particle)
particle_csv.csv_file.close() particle_csv.csv_file.close()
...@@ -129,14 +125,13 @@ class World: ...@@ -129,14 +125,13 @@ class World:
""" """
return self.__solution return self.__solution
def get_amount_of_particles(self):
def get_particles_num(self):
""" """
Returns the actual number of particles in the world Returns the actual number of particles in the world
:return: The actual number of Particles :return: The actual number of Particles
""" """
return self.tiles_num return len(self.particles)
def get_particle_list(self): def get_particle_list(self):
""" """
...@@ -162,14 +157,13 @@ class World: ...@@ -162,14 +157,13 @@ class World:
""" """
return self.particle_map_id return self.particle_map_id
def get_amount_of_tiles(self):
def get_tiles_num(self):
""" """
Returns the actual number of particles in the world Returns the actual number of particles in the world
:return: The actual number of Particles :return: The actual number of Particles
""" """
return self.tiles_num return len(self.tiles)
def get_tiles_list(self): def get_tiles_list(self):
""" """
...@@ -195,13 +189,13 @@ class World: ...@@ -195,13 +189,13 @@ class World:
""" """
return self.tile_map_id return self.tile_map_id
def get_marker_num(self): def get_amount_of_markers(self):
""" """
Returns the actual number of markers in the world Returns the actual number of markers in the world
:return: The actual number of markers :return: The actual number of markers
""" """
return self.markers_num return len(self.markers)
def get_marker_list(self): def get_marker_list(self):
""" """
...@@ -227,7 +221,6 @@ class World: ...@@ -227,7 +221,6 @@ class World:
""" """
return self.marker_map_id return self.marker_map_id
def get_coords_in_dir(self, coords, dir): def get_coords_in_dir(self, coords, dir):
""" """
Returns the coordination data of the pointed directions Returns the coordination data of the pointed directions
...@@ -238,14 +231,14 @@ class World: ...@@ -238,14 +231,14 @@ class World:
""" """
return coords[0] + x_offset[dir], coords[1] + y_offset[dir] return coords[0] + x_offset[dir], coords[1] + y_offset[dir]
def get_sim_x_size(self): def get_world_x_size(self):
"""