def test_duration_filter(s: str, t: int): """ Test that DurationFilter works in the general case - with valid inputs, aka either 'L' or 'G' followed by the limit time (in seconds). """ filt = DurationFilter() results = filt.apply(CUSTOMERS, CALL_LIST, s + str(t)) for call in results: if s == 'L': assert call.duration < t else: assert call.duration > t
def test_absolute_garbage(s: str) -> None: """ Test that none of the filters raise errors when absolute garbage input strings are passed in. """ print(s) cf = CustomerFilter() df = DurationFilter() lf = LocationFilter() # test that nothing crashes cf.apply(CUSTOMERS, CALL_LIST, s) df.apply(CUSTOMERS, CALL_LIST, s) lf.apply(CUSTOMERS, CALL_LIST, s)
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_combined_filters() -> None: log = create_task4_log() customers = create_customers(log) process_event_history(log, customers) all_calls = [] for c in customers: hist = c.get_history() all_calls.extend(hist[0]) fil = LocationFilter() filtered = fil.apply(customers, all_calls, f'{x2}, {y3}, {x2}, {y3}') fil = DurationFilter() filtered = fil.apply(customers, filtered, f'G{69 * 60 - 1}') filtered = fil.apply(customers, filtered, f'L{69 * 60 + 1}') assert len(filtered) == 3 count = 0 for call in filtered: assert call.src_number == '001-3111' if call.time.month == 1: count += 1 assert count == 2 fil = CustomerFilter() filtered = fil.apply(customers, all_calls, "1020") fil = DurationFilter() filtered = fil.apply(customers, filtered, f'G{10 * 60 - 1}') filtered = fil.apply(customers, filtered, f'L{130 * 60 + 1}') for call in filtered: assert 10 * 60 - 1 < call.duration < 130 * 60 + 1 print( f'src: {call.src_number}, dst: {call.dst_number}, dur: {call.duration}' ) assert len(filtered) == 23 + 11 + 6 fil = LocationFilter() filtered = fil.apply(customers, all_calls, f'{x3}, {y2}, {x3}, {y2}') #2101 fil = CustomerFilter() filtered = fil.apply(customers, filtered, "1002") assert len(filtered) == 3 * 2 * 3 for call in filtered: assert call.src_number[4:] == '1002' or call.src_number[4:] == '2101' assert fil.apply(customers, filtered, "3111") == [] fil = DurationFilter() assert fil.apply(customers, filtered, 'L60') == []
def test_duration_filter() -> None: log = create_task4_log() customers = create_customers(log) process_event_history(log, customers) all_calls = [] for c in customers: hist = c.get_history() all_calls.extend(hist[0]) fil = DurationFilter() invalid_inputs = ['', 'LG40', 'l50', 'g65', '50', 'sdklfjeind', ' '] for input in invalid_inputs: filtered = fil.apply(customers, all_calls, input) assert filtered == all_calls filtered = fil.apply(customers, all_calls, 'L60') for call in filtered: assert call.duration < 60 filtered = fil.apply(customers, filtered, 'G60') assert filtered == [] filtered = fil.apply(customers, all_calls, 'G5400') for call in filtered: assert call.duration > 5400
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