def test_filters() -> None: """ Test the functionality of the filters. We are only giving you a couple of tests here, you should expand both the dataset and the tests for the different types of applicable filters """ customers = create_customers(test_dict) process_event_history(test_dict, customers) # Populate the list of calls: calls = [] hist = customers[0].get_history() # only consider outgoing calls, we don't want to duplicate calls in the test calls.extend(hist[0]) # The different filters we are testing filters = [DurationFilter(), CustomerFilter(), ResetFilter()] # These are the inputs to each of the above filters in order. # Each list is a test for this input to the filter filter_strings = [["L50", "G10", "L0", "50", "AA", ""], ["5555", "1111", "9999", "aaaaaaaa", ""], ["rrrr", ""]] # These are the expected outputs from the above filter application # onto the full list of calls expected_return_lengths = [[1, 2, 0, 3, 3, 3], [3, 3, 3, 3, 3], [3, 3]] for i in range(len(filters)): for j in range(len(filter_strings[i])): result = filters[i].apply(customers, calls, filter_strings[i][j]) assert len(result) == expected_return_lengths[i][j]
def test_task4() -> None: # Filtering input_dictionary = import_data() customers = create_customers(input_dictionary) process_event_history(input_dictionary, customers) # Populate the list of calls: calls = [] for customer in customers: hist = customer.get_history() calls.extend(hist[0]) # The different filters we are testing # You need write LocationFilter test yourself filters = [ DurationFilter(), CustomerFilter(), ResetFilter() ] # These are the inputs to each of the above filters in order. # Each list is a test for this input to the filter filter_strings = [ ["L50", "G10", "L0", "50", "AA", "", "L100"], ["5555", "1111", "6020", "7930", "3087", "5524", "abc", ""], ["rrrr", ""] ] # These are the expected outputs from the above filter application # onto the full list of calls expected_return_lengths = [ [122, 975, 0, 1000, 1000, 1000, 261], [1000, 1000, 59, 22, 22, 45, 1000, 1000], [1000, 1000] ] for i in range(len(filters)): for j in range(len(filter_strings[i])): result = filters[i].apply(customers, calls, filter_strings[i][j]) assert len(result) == expected_return_lengths[i][j], str(filters[i].__class__.__name__) + ", with keyword " + filter_strings[i][j] + " produce wrong result"
def handle_window_events(self, customers: List[Customer], drawables: List[Call]) \ -> List[Call]: """Handle any user events triggered through the pygame window. The <drawables> are the objects currently displayed, while the <customers> list contains all customers from the input data. Return a new list of Calls, according to user input actions. """ new_drawables = drawables for event in pygame.event.get(): if event.type == pygame.QUIT: self._quit = True elif event.type == pygame.KEYDOWN: f = None num_threads = 1 if event.unicode == "d": f = DurationFilter() elif event.unicode == "l": f = LocationFilter() elif event.unicode == "c": f = CustomerFilter() elif event.unicode == "r": f = ResetFilter() num_threads = 1 if f is not None: def result_wrapper(fun: Callable[ [List[Customer], List[Call], str], List[Call]], customers: List[Customer], data: List[Call], filter_string: str, res: List) -> None: """A final wrapper to return the result of the operation """ res.append(fun(customers, data, filter_string)) def threading_wrapper(customers: List[Customer], data: List[Call], filter_string: str) -> List[Call]: """A wrapper for the application of filters with threading """ chunk_sz_calls = math.ceil( (len(data) + num_threads - 1) / num_threads) print("Num_threads:", num_threads) print("Chunk_calls:", chunk_sz_calls) threads = [] results = [] for i in range(num_threads): res = [] results.append(res) t = threading.Thread( target=result_wrapper, args=(f.apply, customers, data[i * chunk_sz_calls:(i + 1) * chunk_sz_calls], filter_string, res)) t.daemon = True t.start() threads.append(t) # f.apply(customers, data, filter_string) # Wait to finish for t in threads: t.join() # Now reconstruct the data new_data = [] for res in results: new_data.extend(res[0]) return new_data new_drawables = self.entry_window(str(f), customers, drawables, threading_wrapper) # Perform the billing for a selected customer: if event.unicode == "m": try: def get_customer(customers: List[Customer], found_customer: List[Customer], input_string: str) -> None: """ A helper to find the customer specified in the input string appends to the found_customer the matching customer """ try: for c in customers: if c.get_id() == int(input_string): found_customer.append(c) except ValueError: pass customer = [] self.entry_window( "Generate the bill for the customer " "with ID:", customers, customer, get_customer) if len(customer) == 0: raise ValueError # Just want to return the parsed input string def get_input_date(customer: List[Customer], drawables: List[Call], input_string: str) \ -> Optional[List[int]]: """ A helper to get the input date """ try: return [ int(s.strip()) for s in input_string.split(',') ] except ValueError: return None date = self.entry_window( "Bill month and year: " "month, year", customers, drawables, get_input_date) if date is None or date == ([], []): raise ValueError customer[0].print_bill(date[0], date[1]) except ValueError: print("ERROR: bad formatting for input string") except IndexError: print("Customer not found") elif event.type == pygame.MOUSEBUTTONDOWN: if event.button == 1: self._mouse_down = True elif event.button == 4: self._map.zoom(-0.1) elif event.button == 5: self._map.zoom(0.1) elif event.type == pygame.MOUSEBUTTONUP: self._mouse_down = False elif event.type == pygame.MOUSEMOTION: if self._mouse_down: self._map.pan(pygame.mouse.get_rel()) else: pygame.mouse.get_rel() return new_drawables