Exemple #1
0
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
Exemple #2
0
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]
Exemple #4
0
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') == []
Exemple #5
0
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
Exemple #6
0
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"
Exemple #7
0
    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