def intersection_tick(self, streets): # todo (cleanup): make function similar to functional programming # if this is the first tick if self.cycle_position == -1: self.cycle_position += 1 streets[cl.find( streets, self.schedule.iat[self.cycle_position])].flip_state() return streets previous_position = self.schedule.iat[self.cycle_position] # increment current cycle position if self.cycle_position + 1 == len(self.schedule): # Reset the timer to 1 if it reached the end self.cycle_position = 0 else: self.cycle_position += 1 # print(self.cycle_position) current_position = self.schedule.iat[self.cycle_position] # Check if lights need to change if previous_position != current_position: # Turn off previous position and turn on current position streets[cl.find(streets, previous_position)].flip_state() streets[cl.find(streets, current_position)].flip_state() return streets
def move_queue(self, street): """ Helper function :param street: :return: """ # pop the first member of the queue and have it cross the street car = self.cars[cl.find(self.cars, street.pop_queue())] car.cross_intersection() # Add the car to its new street self.streets[cl.find( self.streets, car.get_current_streetID)].place_car_in_traffic(car)
def print_lights(cls, tick, intersections, streets): print("tick: " + str(tick)) for i in intersections: print("\tintersection: " + str(i.get_id)) for s in i.get_streets: print("\t\t" + s + ": " + streets[cl.find(streets, s)].get_state)
def optimize_lights(cls, intersections, streets): """ run_simulation helper function :return: """ # Find lights that are always set to on/off and mark as such to optimize later ticks remove_list = [] for i in intersections: # A light is always on if only one light is mentioned in a schedule if i.get_schedule is None: # print("Removing intersection " + str(i.get_id) + " because its always red.") remove_list.append(i.get_id) # A light is always off if the intersection is not listed in the schedule elif i.get_schedule.unique().size == 1: # Street to update streets[cl.find(streets, i.get_schedule[0])].flip_state() # print("Removing intersection " + str(i.get_id) + " because its always green.") # Remove light from list of intersections to check each tick remove_list.append(i.get_id) # Remove intersections scheduled for disposal intersections = [ r for r in intersections if r.get_id not in remove_list ] return intersections, streets
def cut_streets(cls, cars, streets, intersections): # Create list of all streets and intersections cars touch all_streets = pd.DataFrame() # todo (optimization): optimize for i in cars: all_street = pd.DataFrame() all_street['streets'] = i.get_path # grab the intersection ids all_street['intersections'] = [ streets[cl.find(streets, j)].get_intersection for j in i.get_path ] all_streets = all_streets.append(all_street) # Convert list into pandas series of unique streets unique_streets = all_streets['streets'].unique() unique_intersections = all_streets['intersections'].unique() # Delete all streets not in unique_streets # Gather list of streets not in unique_streets streets = [ street for street in streets if street.get_id in unique_streets ] # Delete all intersections not in unique_intersections # Gather list of intersections not in unique_intersections intersections = [ it for it in intersections if str(it.get_id) in unique_intersections ] return streets, intersections
def add_delay(self, cars, tick): # Count number of cars in queue array and add 1 delay for each new_row = { 'tick': tick, 'cars': self.queue, 'delay added': len(self.queue) } self.street_delay_df.append(new_row) for i in self.queue: cars[cl.find(cars, i)].add_delay(tick)
def read_input(cls, file): # Read in the first line, which contains the simulation-wide variables f = open(file, 'r') line = f.readline().split(' ') # Instantiate the Simulation class # todo: add documentation on which line part is what sim = Simulation(int(line[0]), int(line[1]), int(line[2]), int(line[3]), int(line[4])) # Create the streets streets = [] intersections = [] for x in range(sim.get_num_streets): line = f.readline().split(' ') streets.append(Street.Street(line[2], line[0], line[1], line[3])) # Add the new intersection to the list, or add new street to existing intersection # Check if current intersection is already in the list # todo: rewrite code to look/add new intersections in both line[0] and line[1] i = cl.find(intersections, int(line[1])) if i > -1: # Check if current street is already in the intersection's list if line[2] not in intersections[i].get_streets: intersections[i].add_street(line[2]) else: # Add new intersection intersections.append( Intersection.Intersection(line[1], line[2])) # Store streets and intersections in the simulation # todo: add check to see if num streets found = self.num_streets sim.set_streets(streets) # todo: add check to see if number of intersections found = self.num_intersections sim.set_intersections(intersections) # Create the cars cars = [] for y in range(sim.get_num_cars): line = f.readline().replace('\n', '').split( ' ' ) # Need to remove new line character to avoid bug when finding unique streets # todo: add security check that line[0] doesn't exceed the number of streets aka line[1:] cars.append(Car.Car(y + 1, line[1:])) # store cars in the simulation's car array sim.set_cars(cars) # Close the file f.close() return sim
def move_traffic(self, street): """ Helper function :param street: :return: """ traffic_areas = street.has_traffic if traffic_areas[0] != -1: if traffic_areas[0] == 0: # Check if the car(s) reached their final destination # todo (clean code): move this block of code into a helper function for car in street.get_traffic_cars(0): if self.cars[cl.find( self.cars, car)].get_destination == street.get_id: self.score_car(car) else: # Add car to queue street.place_car_in_queue(car) # Update the rest of the traffic street.tick_traffic()
def add_delay(self, streets, tick): """ Call this function after calculating delay for the streets first :param tick: Current tick :param streets: list of streets from Simulation for Intersection to query """ new_row = {'tick': tick} # todo: (optimize) find more dynamic way to calculate total_delay total_delay = 0 for i in range(4): new_row['street ' + str(i + 1)] = self.streets[i] current_column = 's' + str(i + 1) + ' delay' new_row[current_column] = streets[cl.find( streets, self.streets[i])].get_current_delay() total_delay += new_row[current_column] # Get total delay new_row['total delay'] = total_delay # Add new row to the dataframe self.intersection_delay_df.append(new_row, ignore_index=True)
def read_submission(self, file): f = open(file, 'r') num_schedules = int(f.readline()) # Read through the file as specified by the first line for x in range(num_schedules): # This line tell us the intersection we're working with intersection = int(f.readline()) # print("Working on intersection " + intersection) # The next line tells us how many lights we're looking at num_lights = int(f.readline()) schedules = [] # need to be able to reference the streets based on the intersection id for y in range(num_lights): # Grab the line line = f.readline().split(' ') # todo: add documentation describing what line parts are what # schedule['street'] = line[0] # todo: add timer variable constraints (1 <= timer <= duration) for i in range(int(line[1])): schedules.append(line[0]) # Give the schedule to the appropriate intersection # todo: add try-except statement in case unable to find intersection for whatever reason self.intersections[cl.find(self.intersections, intersection)].set_schedule( pd.Series(schedules)) # print(intersection) # Finally, cut all unnecessary streets and intersections, where no car will interact with them self.streets, self.intersections = self.cut_streets( self.cars, self.streets, self.intersections)