Exemplo n.º 1
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)
Exemplo n.º 2
0
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_location_filter_with_large_data() -> None:
    """ Test the functionality of the location 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
    """
    # loading up the large data
    input_dictionary = import_data()
    customers = create_customers(input_dictionary)
    process_event_history(input_dictionary, customers)

    # Populate the list of calls:
    calls = []
    for cust in customers:
        hist = cust.get_history()
        # only look at outgoing calls, we don't want to duplicate calls in test
        calls.extend(hist[0])

    # The different filters we are testing
    filters = [CustomerFilter(), LocationFilter()]

    # 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 = [
        # contents: non-existent id, valid id, valid id
        ["5555", "5524", "9210"],
        # contents: loc of one call, max and min, one cord out, letters, valid loc but no calls
        [
            "-79.54717029563305, 43.58020061333403, -79.54717029563303, 43.58020061333405",  # location of one call
            "-79.697878, 43.576959, -79.196382, 43.799568",  # entire map
            "-80.697877, 43.576960, -79.196383, 43.799567",  # one coordinate in not within range
            "hellolol, erferer, fefergerger, ferereeev",  # isalpaha == true
            "-79.697878, 43.6882635, -79.196382, 43.799568",  # half the map (this one took me hours to count)
            "-79.54717029563305,43.58020061333403,-79.54717029563303,43.58020061333405",  # location of one call but no spaces
            "-79.54717029563305  ,   43.58020061333403   ,    -79.54717029563303,   43.58020061333405",  # ^ spaces
            "-79.196382, 43.799568, -79.697878, 43.576959",  # both cross
            "-79.296382, 43.576959, -79.597878, 43.799568",  # x coords cross
            "-79.697878, 43.576959, -79.196382, 43.499568",  # y coords cross
            "-80.697877, 69.576960, -89.196383, 69.799567",  # all coords not within range
            "hellolol, erferer, fefergergerferereeev",  # alpha + nums
            "#@%#@%#@%,#%@#%@#%,#%#@%#@%#@$%#@%",  # symbols
            "",  # empty
            "SDF(*@$)(*&#!)(*&#HFLKDSJF:LDSJFLKJDSF",  # no commas
            "                              "  # just spaces.......
        ]
    ]

    # These are the expected outputs from the above filter application
    # onto the full list of calls
    expected_return_lengths = [[1000, 45, 33],
                               [
                                   1, 1000, 1000, 1000, 755, 1000, 1, 1000,
                                   1000, 1000, 1000, 1000, 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]
Exemplo n.º 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') == []
Exemplo n.º 5
0
def test_customer_filter(id: int):
    """ Test that CustomerFilter works in the general case - with (more or less)
    valid inputs, aka 4 digit numerical customer IDs. Customer IDs may not
    belong to any customer.
    """
    filt = CustomerFilter()
    results = filt.apply(CUSTOMERS, CALL_LIST, str(id))
    cust = None
    for c in CUSTOMERS:
        if c.get_id() == id:
            cust = c
            break
    if cust is None:
        # if no customer has the ID, the original dataset should be returned
        assert results == CALL_LIST
    else:
        # if a customer has the ID, every call in the results of the filter
        # should involve the customer as either the source or destination
        for c in results:
            assert c.src_number in cust or c.dst_number in cust
Exemplo n.º 6
0
def test_customer_filter() -> None:
    log = create_pure_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 = CustomerFilter()
    invalid_inputs = [
        '', 'dskljgdf', '69.69', 'd1200', 'L200', '-79.6, 43.3, -79.5, 43.4',
        '3690', ' '
    ]
    for input in invalid_inputs:
        filtered = fil.apply(customers, all_calls, input)
        assert filtered == all_calls

    line_of_customer = ['100-2101', '001-2101']
    filtered = fil.apply(customers, all_calls, '2101')
    for call in filtered:
        assert call.src_number in line_of_customer \
               or call.dst_number in line_of_customer
        assert loc[2101] == call.src_loc or loc[2101] == call.dst_loc
Exemplo n.º 7
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"
Exemplo n.º 8
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