Example #1
0
    def sort_parse(self, command, reverse=False):
        """
        Parses and validates the sort command
        Input:
            command - the user command
            reverse - the order of the sort
        Return:
            True on valid and False otherwise
        """
        self.set_command(command)

        # simple sort no type use total expense
        pattern_sort = self._regex_search(self._PATTERN_SORT)
        if pattern_sort:
            self._parsed_command = {"type": None, "reverse": reverse}
            return True

        # use an expense type for the sort
        pattern_sort_by_type = self._regex_search(self._PATTERN_SORT_BY_TYPE)
        if pattern_sort_by_type:
            expense_type = pattern_sort_by_type.group(1)
            if not Apartment.is_expense_type(expense_type):
                UI.set_message(UI.get_error_types())
                return False

            self._parsed_command = {"type": expense_type, "reverse": reverse}
            return True

        UI.set_message(UI.get_error_sort())
        return False
Example #2
0
    def filter(self):
        """
        Filter the list of apartments on specific criteria
        """
        self._validate_parsed_command(["greater", "type"])

        # filter by type
        if self._parsed_command["type"]:
            expense_type = self._parsed_command["type"]
            filtered_bloc_dict = {}
            for apartment_id in self._bloc_dict.keys():
                if self._bloc_dict[apartment_id].expenses[expense_type]:
                    filtered_bloc_dict[apartment_id] = self._bloc_dict[apartment_id]

            self._bloc_dict = filtered_bloc_dict

        # filter by total greater than
        if self._parsed_command["greater"]:
            amount_greater = float(self._parsed_command["greater"])
            filtered_bloc_dict = {}
            for apartment_id in self._bloc_dict.keys():
                if self._bloc_dict[apartment_id].get_total_expenses() > amount_greater:
                    filtered_bloc_dict[apartment_id] = self._bloc_dict[apartment_id]

            self._bloc_dict = filtered_bloc_dict

        # print(filtered_bloc_dict)
        if not filtered_bloc_dict:
            UI.set_message("No apartment fits the criteria")
        else:
            UI.set_message("Apartments filtered successfully")
Example #3
0
    def filter_parse(self, command):
        """
        Parses and validates the filter command
        Input:
            command - the user command
        Return:
            True on valid and False otherwise
        """
        self.set_command(command)

        # filter by total amount greater than
        pattern_total_greater = self._regex_search(self._PATTERN_FILTER_GREATER_THAN_TOTAL)
        if pattern_total_greater:
            greater = pattern_total_greater.group(1)
            self._parsed_command = {"greater": greater, "type": None}
            return True

        # filter by only apartments having that type
        pattern_by_type = self._regex_search(self._PATTERN_FILTER_BY_TYPE)
        if pattern_by_type:
            expense_type = pattern_by_type.group(1)
            if not Apartment.is_expense_type(expense_type):
                UI.set_message(UI.get_error_types())
                return False

            self._parsed_command = {"greater": None, "type": expense_type}
            return True

        UI.set_message(UI.get_error_filter())
        return False
Example #4
0
    def list_total_apartment(self):
        """
        Displays the total expenses for an apartment
        """
        self._validate_parsed_command(["id"])

        apartment_id = self._parsed_command["id"]
        UI.set_message("Total expenses = " + str(self._bloc_dict[apartment_id].get_total_expenses()))
Example #5
0
    def _insert_or_replace_apartment_parse(self, command, command_type):
        """
        Protected parse method for insert and replace
        Input:
            command - the user command
            command_type - the command_type, can be insert or replace
        Return:
            True on valid and False otherwise
        Raises:
            Exception on invalid command_type
        """
        self.set_command(command)

        # get the correct pattern
        if command_type is "insert":
            pattern = self._regex_search(self._PATTERN_INSERT)
            if not pattern:
                UI.set_message(UI.get_error("insert <amount>, <expense_type> at <apartment_id>"))
                return False
        elif command_type is "replace":
            pattern = self._regex_search(self._PATTERN_REPLACE)
            if not pattern:
                UI.set_message(UI.get_error("replace <amount>, <expense_type> at <apartment_id>"))
                return False
        else:
            raise Exception("command type is incorrect")

        # get the data
        amount = pattern.group(1)
        expense_type = pattern.group(2)
        apartment_id = pattern.group(3)

        # wrong type
        if not Apartment.is_expense_type(expense_type):
            UI.set_message(UI.get_error_types())
            return False

        if command_type is "insert":
            # apartment does  exist in the list
            if self.is_apartment(apartment_id):
                UI.set_message("Apartment " + apartment_id + " does exist in the list. "
                                                             "Use this command to replace: replace " + amount + ", " +
                               expense_type + " at " + apartment_id)
                return False
        elif command_type is "replace":
            # apartment does not exist in the list
            if not self.is_apartment(apartment_id):
                UI.set_message("Apartment " + apartment_id + " does not exist in the list. "
                                                             "Use this command to add: insert " + amount + ", " +
                               expense_type + " at " + apartment_id)
                return False

        # all good
        self._parsed_command = {"type": expense_type, "amount": amount, "id": apartment_id}
        return True
Example #6
0
    def stat_total_type(self):
        """
        Displays the total for an expense type
        """
        self._validate_parsed_command(["expense_type"])

        sum_type = self._parsed_command["expense_type"]
        total = sum([self._bloc_dict[i].expenses[sum_type] for i in self._bloc_dict])
        # for apartment_id in self._bloc_dict:
        #    total += self._bloc_dict[apartment_id].expenses[sum_type]

        UI.set_message("Total expenses for " + sum_type + " = " + str(total))
Example #7
0
    def stat_max_apartment(self):
        """
        Displays the biggest expense in an apartment
        """
        self._validate_parsed_command(["id"])

        apartment_id = self._parsed_command["id"]
        biggest_types = self._bloc_dict[apartment_id].get_max_expenses_type()

        if biggest_types:
            UI.set_message("Biggest expense is " + biggest_types.__str__() + " = " + str(
                self._bloc_dict[apartment_id].expenses[biggest_types[0]]))
        else:
            UI.set_message("Apartment has all expenses = 0")
Example #8
0
    def list_by_type(self):
        """
        Displays only the apartments having a specific expense type
        """
        self._validate_parsed_command(["expense_type"])

        expense_type = self._parsed_command["expense_type"]
        filtered_bloc_dict = {}
        for apartment_id in self._bloc_dict.keys():
            if self._bloc_dict[apartment_id].expenses[expense_type] != 0:
                filtered_bloc_dict[apartment_id] = self._bloc_dict[apartment_id]

        if filtered_bloc_dict:
            UI.set_message(UI.get_bloc_table(filtered_bloc_dict))
        else:
            UI.set_message("There are no apartments with " + expense_type)
Example #9
0
    def list_greater_than(self):
        """
        Displays only the apartments with an overall expense greater than the given amount
        """
        self._validate_parsed_command(["greater"])

        greater_than = float(self._parsed_command["greater"])
        filtered_bloc_dict = {}
        for apartment_id in self._bloc_dict.keys():
            if self._bloc_dict[apartment_id].get_total_expenses() > greater_than:
                filtered_bloc_dict[apartment_id] = self._bloc_dict[apartment_id]

        # check if empty
        if filtered_bloc_dict:
            UI.set_message(UI.get_bloc_table(filtered_bloc_dict))
        else:
            UI.set_message("There are no apartments with overall expenses greater than " + str(greater_than))
Example #10
0
    def list_greater_than_parse(self, command):
        """
        Parses and validates the 'list greater than' command
        Input:
            command - the user command
        Return:
            True on valid and False otherwise
        """
        # list greater than <amount>
        self.set_command(command)
        pattern_greater = self._regex_search(self._PATTERN_LIST_GREATER)
        if pattern_greater:
            greater = pattern_greater.group(1)

            self._parsed_command = {"greater": greater}
            return True

        UI.set_message(UI.get_error("list greater than <amount>"))
        return False
Example #11
0
    def list_less_than(self):
        """
        Displays only the apartments with an overall expense less than the given amount
        """
        self._validate_parsed_command(["less"])

        less_than = float(self._parsed_command["less"])
        upper_id_limit = self._parsed_command["upper_id_limit"]
        filtered_bloc_dict = {}
        for apartment_id in range(1, int(upper_id_limit) + 1):
            apartment_id = str(apartment_id)
            if self.is_apartment(apartment_id):
                if self._bloc_dict[apartment_id].get_total_expenses() < less_than:
                    filtered_bloc_dict[apartment_id] = self._bloc_dict[apartment_id]

        # check if empty
        if filtered_bloc_dict:
            UI.set_message(UI.get_bloc_table(filtered_bloc_dict))
        else:
            UI.set_message("There are no apartments with overall expenses less than " + str(less_than))
Example #12
0
    def list_less_than_parse(self, command):
        """
        Parses and validates the 'list less than' command
        Input:
            command - the user command
        Return:
            True on valid and False otherwise
        """
        # less than <amount> before <id>
        self.set_command(command)
        pattern_less = self._regex_search(self._PATTERN_LIST_LESS)
        if pattern_less:
            less = pattern_less.group(1)
            upper_id_limit = pattern_less.group(2)

            self._parsed_command = {"less": less, "upper_id_limit": upper_id_limit}
            return True

        UI.set_message(UI.get_error("list less than <amount> before <apartment_id>"))
        return False
Example #13
0
    def remove_apartment(self):
        """
            Remove the expenses from an apartment or from a list of apartments.
        """

        if "id" in self._parsed_command:  # remove only from one apartments
            apartment_id = self._parsed_command["id"]
            self._bloc_dict[apartment_id] = Apartment()
            UI.set_message("Removed all expenses from apartment " + apartment_id)

        elif "type" in self._parsed_command:  # remove all types
            expense_type = self._parsed_command["type"]
            for apartment_id in self._bloc_dict.keys():
                self._bloc_dict[apartment_id].expenses[expense_type] = 0

            UI.set_message("Removed " + self._parsed_command["type"] + " from all apartments ")

        elif ("id_min" in self._parsed_command) and ("id_max" in self._parsed_command):  # remove from range
            removed_from = []  # keep track of all removed
            for apartment_id in range(int(self._parsed_command["id_min"]), int(self._parsed_command["id_max"]) + 1):
                apartment_id = str(apartment_id)
                if self.is_apartment(apartment_id):
                    removed_from.append(apartment_id)
                    self._bloc_dict[apartment_id] = Apartment()

            UI.set_message("Removed all expenses from apartments " + removed_from.__str__())
        else:
            raise Exception("Incorrect parsed_command")
Example #14
0
    def sort(self):
        """
        Displays the list of apartments sorted
        """
        self._validate_parsed_command(["type", "reverse"])

        reverse_sort = self._parsed_command["reverse"]
        if reverse_sort is True:
            header_message = " sorted descending"
        else:
            header_message = " sorted ascending"

        # simple sort by total expense
        if self._parsed_command["type"] is None:
            # we create a list of tuples consisting of (id, apartment_obj, total_expense)
            list_of_tuples = [
                (apartment_id, self._bloc_dict[apartment_id], self._bloc_dict[apartment_id].get_total_expenses()) for
                apartment_id in self._bloc_dict]

            # set message
            header_message += " by total expenses"

        else:  # sort by type
            expense_type = self._parsed_command["type"]
            # we create a list of tuples consisting of (id, apartment_obj, expense_type_amount)
            list_of_tuples = [
                (apartment_id, self._bloc_dict[apartment_id], self._bloc_dict[apartment_id].expenses[expense_type]) for
                apartment_id in self._bloc_dict]

            # set message
            header_message += " by expense '" + expense_type + "'"

        # print("raw_list: ", list_of_tuples)
        # use the last key of the tuple for the value
        sorted_list_of_tuples = sorted(list_of_tuples, key=lambda item: item[2], reverse=reverse_sort)
        # print("sorted_list: ", sorted_sort_it)

        UI.set_message(UI.get_bloc_table(sorted_list_of_tuples, header_message))
Example #15
0
    def stat_max_apartment_parse(self, command):
        """
        Parses and validates the 'max id' command
        Input:
            command - the user command
        Return:
            True on valid and False otherwise
        """
        self.set_command(command)

        # max <id>
        pattern_max = self._regex_search(self._PATTERN_STAT_MAX_APARTMENT)
        if pattern_max:
            apartment_id = pattern_max.group(1)
            if not self.is_apartment(apartment_id):
                UI.set_message("Apartment " + apartment_id + " does not exist in the list")
                return False

            self._parsed_command = {"id": apartment_id}
            return True

        UI.set_message(UI.get_error("max <apartment_number>"))
        return False
Example #16
0
    def stat_total_type_parse(self, command):
        """
        Parses and validates the 'sum type' command
        Input:
            command - the user command
        Return:
            True on valid and False otherwise
        """
        self.set_command(command)

        # sum <type>
        pattern_sum = self._regex_search(self._PATTERN_STAT_TOTAL_TYPE)
        if pattern_sum:
            expense_type = pattern_sum.group(1)
            if not Apartment.is_expense_type(expense_type):
                UI.set_message(UI.get_error_types())
                return False

            self._parsed_command = {"expense_type": expense_type}
            return True

        UI.set_message(UI.get_error("sum <type>"))
        return False
Example #17
0
    def list_by_type_parse(self, command):
        """
        Parses and validates the list command
        Input:
            command - the user command
        Return:
            True on valid and False otherwise
        """
        self.set_command(command)

        # list <type>
        pattern_type = self._regex_search(self._PATTERN_LIST_BY_TYPE)
        if pattern_type:
            expense_type = pattern_type.group(1)
            if not Apartment.is_expense_type(expense_type):
                UI.set_message(UI.get_error_types())
                return False

            self._parsed_command = {"expense_type": expense_type}
            return True

        UI.set_message(UI.get_error("list <expense_type>"))
        return False
Example #18
0
    def list_total_apartment_parse(self, command):
        """
        Parses and validates the 'list total' command
        Input:
            command - the user command
        Return:
            True on valid and False otherwise
        """
        self.set_command(command)

        # sold|total <apartment_number>
        pattern_total = self._regex_search(self._PATTERN_LIST_TOTAL_APARTMENT)
        if pattern_total:
            apartment_id = pattern_total.group(1)
            if not self.is_apartment(apartment_id):
                UI.set_message("Apartment " + apartment_id + " does not exist in the list")
                return False

            self._parsed_command = {"id": apartment_id}
            return True

        UI.set_message(UI.get_error("list total <apartment_id>"))
        return False
Example #19
0
    def remove_apartment_parse(self, command):
        """
        Parses and validates the remove command
        Input:
            command - the user command
        Return:
            True on valid and False otherwise
        """
        self.set_command(command)
        # first case by apartment id
        pattern_remove_by_id = self._regex_search(self._PATTERN_REMOVE_BY_ID)
        if pattern_remove_by_id:
            apartment_id = pattern_remove_by_id.group(1)
            if not self.is_apartment(apartment_id):
                UI.set_message(
                    "Apartment " + apartment_id + " does not exist in this list so all the expenses are by default 0")
                return False

            self._parsed_command = {"id": apartment_id}
            return True

        # second case remove from interval
        pattern_remove_by_interval = self._regex_search(self._PATTERN_REMOVE_BY_INTERVAL)
        if pattern_remove_by_interval:
            id_min = pattern_remove_by_interval.group(1)
            id_max = pattern_remove_by_interval.group(2)

            self._parsed_command = {"id_min": id_min, "id_max": id_max}
            return True

        # third case by type
        pattern_remove_by_type = self._regex_search(self._PATTERN_REMOVE_BY_TYPE)
        if pattern_remove_by_type:
            expense_type = pattern_remove_by_type.group(1)
            if not Apartment.is_expense_type(expense_type):
                UI.set_message(UI.get_error_types())
                return False

            self._parsed_command = {"type": expense_type}
            return True

        UI.set_message(UI.get_error("remove <apartment_id> \n\tremove from 5 to 10 \n\tremove type"))
        return False
Example #20
0
    def run(self):
        """
        Main loop of the application
        """
        print(UI.get_help_menu())

        while True:
            # get the command from the user
            command = UI.get_command()

            # find out the command type and handle each command correctly
            if "help" in command:
                UI.set_message(UI.get_help_menu())

            elif ("quit" in command) or ("exit" in command):
                self.exit()

            elif "insert" in command:
                if self.bloc.insert_apartment_parse(command):
                    self._undo_start("insert")
                    self.bloc.insert_apartment()

            elif "replace" in command:
                if self.bloc.replace_apartment_parse(command):
                    self._undo_start("replace")
                    self.bloc.insert_apartment()

            elif "remove" in command:
                if self.bloc.remove_apartment_parse(command):
                    self._undo_start("remove")
                    self.bloc.remove_apartment()

            elif "list" in command:
                if "list" == command:
                    self.bloc.list_all()
                elif "greater" in command:
                    if self.bloc.list_greater_than_parse(command):
                        self.bloc.list_greater_than()

                elif "less" in command:
                    if self.bloc.list_less_than_parse(command):
                        self.bloc.list_less_than()

                elif ("sold" in command) or ("total" in command):
                    if self.bloc.list_total_apartment_parse(command):
                        self.bloc.list_total_apartment()

                else:  # check list by type
                    if self.bloc.list_by_type_parse(command):
                        self.bloc.list_by_type()

            elif "sum" in command:
                if self.bloc.stat_total_type_parse(command):
                    self.bloc.stat_total_type()

            elif "max" in command:
                if self.bloc.stat_max_apartment_parse(command):
                    self.bloc.stat_max_apartment()

            elif "filter" in command:
                if self.bloc.filter_parse(command):
                    self._undo_start("filter")
                    self.bloc.filter()

            elif "sort" in command:
                if "asc" in command:
                    if self.bloc.sort_parse(command, reverse=False):
                        self.bloc.sort()

                elif "desc" in command:
                    if self.bloc.sort_parse(command, reverse=True):
                        self.bloc.sort()

                else:
                    UI.set_message(UI.get_error_sort())

            elif "undo" in command:
                if self._undo_last_operation:
                    UI.set_message("Undo operation '" + self._undo_last_operation + "' finished")
                    self._undo_end()
                else:
                    UI.set_message("Nothing to undo")

            elif "save" == command:
                self.save()
                UI.set_message("Current bloc state saved to file.")

            else:
                UI.set_message("Command unknown. type help for a list of commands")

            # print all messages
            print(UI.get_message())
Example #21
0
 def list_all(self):
     """
     Displays all the apartments in the bloc
     """
     UI.set_message(UI.get_bloc_table(self._bloc_dict))