Example #1
0
 def get_next_slot_text(self, slot_name, slot_required):
     try:
         types_with_options = u.choices_type_list
         slot = self.get_slot(slot_name)
         useful_info = ''
         value_type = slot[u.value_type]
         required_string = fn.get_required_string(slot_required)
         if value_type in types_with_options:
             choice_list = slot[u.choice_list]
             option_string = fn.get_string_from_list(choice_list)
             if value_type in [u.dropdown, u.checkbox]:
                 string = f"Select the {slot_name} in the following list {option_string}. {required_string}"
             elif value_type == u.radio:
                 string = f"Choose your {slot_name} in the following list {option_string}. {required_string}"
             if u.DEBUG:
                 print("choice list")
                 print(choice_list)
         else:
             # we construct some useful info.
             if value_type in [u.number, u.decimal, u.integer]:
                 useful_info = f'\nThe value should be a number between {slot[u.min_value]} and {slot[u.max_value]}.'
             insert_style = styles.get_insert()
             please_style = styles.get_please()
             string = f"{please_style} {insert_style} the {slot_name}. {required_string}"
         string = f'{string}{useful_info}'
         return string
     except:
         print("ERROR: Fail to extract the text for the next slot")
         raise Exception
Example #2
0
    def resume_spelling(self, slot_name):
        try:
            # we update the next fields
            self.set_next_slot(slot_name)

            saved_fields = self.get_saved_spelling_fields()
            saved_values = self.get_saved_spelling_values()
            # we set the saved value as current input value
            index = saved_fields.index(slot_name)
            value = saved_values[index]
            self.set_current_spelling_input_value(value)
            if u.DEBUG:
                print(f'The current value for {slot_name} is {value}')
            # we remove the field from saved state
            saved_fields.remove(slot_name)
            saved_values.remove(value)
            next_style = styles.get_next()
            please_style = styles.get_please()
            string = (
                f'You started filling the field {slot_name} and the current value is {value} '
                + f'\n{please_style} insert the {next_style} character')
            # possible next action is spelling
            self.set_possible_next_action(u.spelling_action)
            # we enable the close prompt
            self.set_close_prompt_enabled()
            return string
        except:
            print('ERROR: Fail to manage the resume of the spelling')
            raise Exception
Example #3
0
def verify_compatibility_integer(value,
                                 min_value=-float('inf'),
                                 max_value=float('inf')):
    try:
        value = value.replace(' ', '')
        int_value = get_integer(value)
        sorry_style = styles.get_sorry()
        insert_style = styles.get_insert()
        please_style = styles.get_please()
        if int_value is None:
            text = f'{sorry_style} the value {value} is not an integer, {please_style} {insert_style} a valid value.'
            return False, text
        number = int(int_value)
        if number < min_value or number > max_value:
            if number < min_value:
                text = f'{sorry_style} the value inserted is less than the minimum value acceptable {min_value}.'
            else:
                text = f'{sorry_style} the value inserted is more than the maximum value acceptable {max_value}.'
            return False, text
        return True, int_value
    except:
        print(
            f'Fail to verify the compatibility of the value {value} for the type integer'
        )
        raise Exception
Example #4
0
def verify_compatibility_number(value,
                                min_value=-float('inf'),
                                max_value=float('inf')):
    try:
        value = value.replace(' ', '')
        int_value = int(get_integer(value))
        interval_text = ''
        if min_value != -float('inf'):
            interval_text = f'The minimum value for this field is {min_value}. '
        if max_value != float('inf'):
            interval_text = f'{interval_text}The maximum value for this field is {max_value}.'
        if int_value is None:
            sorry_style = styles.get_sorry()
            insert_style = styles.get_insert()
            please_style = styles.get_please()
            text = f'{sorry_style} the value {value} is not a number, {please_style} {insert_style} a valid value.'
            return False, text
        if int_value < min_value or int_value > max_value:
            if int_value < min_value:
                text = f'{sorry_style} the value inserted is less than the minimum value acceptable {min_value}.'
            else:
                text = f'{sorry_style} the value inserted is more than the maximum value acceptable {max_value}.'
            return False, text
        return True, value
    except:
        print(
            f'Fail to verify the compatibility of the value {value} for the type number'
        )
        raise Exception
Example #5
0
def verify_compatibility_tel(value):
    try:
        text = value
        # we should not have the space in the final value
        if ' ' in value:
            text = text.replace(' ', '')
        if '-' in value:
            text = text.replace('-', '')
        plus_sign = "+"
        num_occur = value.count(plus_sign)
        if num_occur == 1:
            if value[0] != plus_sign:
                text = f'The character < {plus_sign} > could only be at the beginning of the number'
                return False, text
        elif num_occur > 1:
            text = f'A telephone number should not contain the character < {plus_sign} > several times'
            return False, text
        # we remove the eventual plus sign at the beginning
        number = value.replace(plus_sign, '')
        # we verify if the remaining string only contains digits from 0 to 9
        number = fn.convert_to_int(number)
        if number is None or len(value) < u.min_length_phone_number:
            sorry_style = styles.get_sorry()
            insert_style = styles.get_insert()
            please_style = styles.get_please()
            text = f'{sorry_style} the value {value} is not valid, {please_style} {insert_style} a valid phone number'
            return False, text
        return True, text
    except:
        print(
            f'Fail to verify the compatibility of {value} for the type phone number'
        )
        raise Exception
def next_char_string():
    try:
        # we add styles to the output
        next_style = styles.get_next()
        please_style = styles.get_please()
        insert_style = styles.get_insert()
        end_style = styles.get_end()
        # we set the message to be returned to the user
        string = (f'{please_style} {insert_style} the {next_style} character, remember that you can use the expression SPACE for the blank' +
                  f' and the expression TERMINATE to {end_style} the spelling')
        return string
    except:
        print('Fail to get the string for asking the next character')
        raise Exception
Example #7
0
 def manage_next_step(self):
     try:
         slot_name, next_slot_required = self.get_next_slot()
         if slot_name is not None:
             if u.DEBUG:
                 print("The next slot is: " + slot_name)
                 # to observe the modification that happened
                 print(self.get_slots_value())
             string = "{}".format(
                 self.get_next_slot_text(slot_name, next_slot_required))
             if slot_name in self.get_spelling_fields() and u.USE_SPELLING:
                 # we add the field to the spelling list
                 self.add_spelling_name(slot_name)
                 # we verify if the field has been previously saved
                 saved_fields = self.get_saved_spelling_fields()
                 if u.DEBUG:
                     print(f'The saved fields are {saved_fields}')
                 if slot_name in saved_fields:
                     # we set the saved value and we get the next step string
                     return self.resume_spelling(slot_name)
                 else:
                     please_style = styles.get_please()
                     string = (
                         f'{string}\nSince it is a field requiring the spelling, we are going to take'
                         +
                         f' its value one character at a time.\n{please_style} insert the first character:'
                     )
                     # possible next action is spelling
                     self.set_possible_next_action(u.spelling_action)
                     return string
             else:
                 # possible next action is fillGenericCamp
                 self.set_possible_next_action(u.fill_field_action)
                 return string
         else:
             # the submit button here is one shot so we enable the alarm
             self.set_submit_alarm_enabled()
             string = self.submit_string()
             self.set_possible_next_action(u.submit_action)
             return string
     except:
         print("ERROR: Fail to get the string for the next field")
         raise Exception
Example #8
0
def verify_compatibility_decimal(value,
                                 precision=2,
                                 min_value=-float('inf'),
                                 max_value=float('inf')):
    try:
        value = value.replace(' ', '')
        dec_value = get_decimal(value)
        sorry_style = styles.get_sorry()
        insert_style = styles.get_insert()
        please_style = styles.get_please()
        if dec_value is None:
            text = f'{sorry_style} the value {value} is not a decimal, {please_style} {insert_style} a valid value.'
            return False, text
        # float takes the 'dot' as separator, so we should transform it before getting the float
        number = float(dec_value.replace(',', '.'))
        if number < min_value or number > max_value:
            if number < min_value:
                text = f'{sorry_style} the value inserted is less than the minimum value acceptable {min_value}.'
            else:
                text = f'{sorry_style} the value inserted is more than the maximum value acceptable {max_value}.'
            return False, text
        if ',' not in dec_value:
            return True, dec_value
        # the value has a decimal part
        if precision == float('inf'):
            return True, dec_value
        dec_part = dec_value[dec_value.index(',') + 1:]
        if len(dec_part) <= 2:
            # the precision is respected
            return True, dec_value
        # the precision is more accurate then what required, we decide to troncate, no rounding
        dec_value = dec_value[:dec_value.index(',') + precision + 1]
        return True, dec_value
    except:
        print(
            f'Fail to verify the compatibility of the value {value} for the type decimal with precision {precision}'
        )
        raise Exception
 def verifyPresenceOfField(self):
     try:
         entities = self.state.get_latest_message()["entities"]
         count = len(entities)
         if count == 0:
             # in principle should never occur given the training
             please_style = styles.get_please()
             text = f"{please_style} indicate which field you are interested to,"
             _, required = self.state.get_next_slot()
             if not required:
                 text = f'{text} otherwise, you can {u.fun_submit}, {u.fun_verify_presence_field} or {u.fun_skip}'
             else:
                 text = f'{text} otherwise, you can {u.fun_verify_value} or {u.fun_form_description}'
             self.state.set_warning_message(text)
             raise Exception
         slot_name_list = fn.extract_fields_names_and_values(
             entities, only_names=True)
         # we first verify if each slot_name corresponds to a field in the dorm
         correct, string = self.state.all_fields_present(slot_name_list)
         if not correct:
             return string
         good_style = styles.get_good()
         string = f"{good_style}, "
         for name in slot_name_list:
             text = fn.verify_presence(name,
                                       self.state.form_slots(),
                                       only_text=True)
             string = f'{string}, {text}'
         next_step_string = self.state.manage_next_step()
         string = f'{string}\n{next_step_string}'
         return string
     except:
         if not self.state.get_warning_present():
             print(
                 "A problem occured while a registration form bot tries to verify the presence of a label"
             )
         raise Exception
Example #10
0
 def set_choices_checkbox(self, slot_name, choice_values):
     try:
         slot = self.get_slot(slot_name)
         choice_name = slot[u.value_name].lower()
         choices_lower = []
         for choice_value in choice_values:
             choices_lower.append(choice_value.lower())
         elems = self.form_element.find_elements_by_name(choice_name)
         value_present = False
         for elem in elems:
             value = elem.get_attribute("value")
             if value in choices_lower:
                 if not elem.is_selected():
                     elem.click()
                     value_present = True
             else:
                 if elem.is_selected():
                     elem.click()
                     value_present = True
         if not value_present:
             choices_string = fn.get_string_from_list(choice_values)
             sorry_style = styles.get_sorry()
             please_style = styles.get_please()
             text = (
                 f"{sorry_style} none of the choices {choices_string} you proposed is valid for the field {slot_name}"
                 +
                 f"{please_style} choose them in the following list: {choice_list}"
             )
             self.set_warning_message(text)
             raise Exception
     except:
         if not self.get_warning_present():
             choices_list = fn.get_string_from_list(choice_values)
             print(
                 f"ERROR: A problem occured while trying to set the choices {choices_list} in the checkbox with name {choice_name}"
             )
         raise Exception
    def fillSpellingField(self):
        try:
            if len(self.state.get_spelling_list()) == 0:
                # misinterpretation
                text = 'I did not get you well, could you precise your action please?'
                _, required = self.state.get_next_slot()
                if not required:
                    text = f'{text} otherwise, you can {u.fun_skip}, {u.fun_reset} or {u.fun_submit}'
                else:
                    text = f'{text} otherwise, you can {u.fun_remaining_fields} or {u.fun_modify_field}'
                self.state.set_warning_message(text)
                raise Exception
            # we have to verify if we just finished the spelling of a field
            if self.state.get_after_spelling():
                # after spelling is desabled since we are going to insert the vale for a field
                self.state.set_after_spelling(False)
                slot_name = self.state.get_next_slot(only_name=True)
                slot_value = self.state.get_current_spelling_input_value()
                # we go to the filling procedure. The spelling list can be modified in this phase
                string = self.state.filling_procedure(slot_name, slot_value)
                if 'inserted!' in string.lower() and 'not' in string.lower():
                    self.state.reset_current_spelling_input_value()
                    return string
                # verify if all the fields in spelling list have been completed
                if len(self.state.get_spelling_list()) - 1 == 0:
                    self.state.reset_spelling_list()
                else:
                    # there are still fields to spell
                    self.state.update_spelling_list(slot_name)
                    next_field = self.state.get_spelling_list()[0]
                    please_style = styles.get_please()
                    string = (
                        f"Web Form updated. Now you are going to spell the value for the field {next_field}.\n"
                        + f"{please_style} insert the first character")
                # after the spelling we insert the value for the given field and we reset the string
                self.state.reset_current_spelling_input_value()
                return string
            """we are not after spelling so the fillGenericField directly called this function(at the
            previous step it was triggered by the spelling function) or it is triggered by
            the mofifySpellingField function"""

            # we look if one of the fields in spelling fields has been saved to resume it. In case of many fields saved we take the first
            slot_name_list = self.state.get_spelling_list()
            saved_fields = self.state.get_saved_spelling_fields()
            if len(saved_fields) > 0:
                # there is at least one saved field
                for field in slot_name_list:
                    if field in saved_fields:
                        string = self.state.resume_spelling(field)
                        return string
            # we set the first spelling field of the list as the next field
            slot_name = slot_name_list[0]
            self.state.set_next_slot(slot_name)
            # we add styles to the output
            please_style = styles.get_please()
            end_style = styles.get_end()
            fields_string = fn.get_string_from_list(slot_name_list)
            if len(slot_name_list) == 1:
                intro = f"You will have to spell the value of the field {slot_name_list[0]}."
            else:
                intro = (
                    f"You will have to spell the values of the following fields {fields_string}.\n"
                    + f"We start by the field {slot_name_list[0]}.")
            # we set the message to be returned to the user
            string = (
                f'{intro}\n{please_style} insert the first character, you will be able to use SPACE for spacing'
                + f'and TERMINATE to {end_style} the spelling')
            self.state.set_possible_next_action(u.spelling_action)
            return string
        except:
            if not self.state.get_warning_present():
                print(
                    "A problem occured while a registration form bot tries to fill a spelling camp"
                )
            raise Exception
 def fillGenericField(self):
     try:
         entities = self.state.get_latest_message()["entities"]
         intent = self.state.get_latest_message()["intent"]["name"]
         count = len(entities)
         if count == 0:
             # the user wants to modify a field but did not specify which field
             modify_style = styles.get_modify()
             insert_style = styles.get_insert()
             string = (
                 f"Which field exactly do you want to {modify_style}, and which value"
                 + f" do you want to {insert_style} for that field?")
             self.state.set_possible_next_action(u.fill_field_action)
             return string
         slot_name_list, slot_value_list = fn.extract_fields_names_and_values(
             entities)
         # we first verify if each slot_name corresponds to a field in the dorm
         correct, string = self.state.all_fields_present(slot_name_list)
         if not correct:
             return string
         """we extract now the spelling field and we insert them in the spelling list
         after that we fill the generic fields before passing the floor to 
         fillSpellingField to complete the fields in spelling list."""
         slot_name_list, slot_value_list = self.state.set_spelling_list(
             slot_name_list, slot_value_list)
         # the spelling list have been set and we can continue
         if len(slot_value_list) + len(slot_name_list) == 0:
             string = self.fillSpellingField()
             return string
         if len(slot_value_list) + len(slot_name_list) >= 1:
             # there is at least one generic info
             # the use of possible_next_action here is to mitigate training error. with a perfect training they are not necessary
             if len(slot_value_list) == 1 and len(slot_name_list) == 0 and (
                     self.state.get_possible_next_action()
                     == u.fill_field_action
                     or intent == u.fill_field_action):
                 # we are inserting a value for the current field
                 slot_name = self.state.get_next_slot(
                     only_name=True
                 )  # return also if the next slot is required or not
                 # We make verify if the current field is spelling
                 spelling_fields = self.state.get_spelling_fields()
                 if slot_name in spelling_fields:
                     string = self.fillSpellingField()
                     return string
                 slot_value = slot_value_list[0]
                 # the slot value can change, being put in the right format
                 # we go to the filling procedure insuring that the field is not spelling
                 string = self.state.filling_procedure(
                     slot_name, slot_value)
             elif self.state.get_possible_next_action(
             ) != u.fill_field_action and intent != u.fill_field_action:
                 # probably bad destination due to misinterpretation
                 sorry_style = styles.get_sorry()
                 please_style = styles.get_please()
                 text = f'{sorry_style} i do not understand your request, could you reformulate {please_style}?'
                 _, required = self.state.get_next_slot()
                 if not required:
                     text = f'{text} otherwise, you can {u.fun_skip} or {u.fun_submit}'
                 else:
                     text = f'{text} otherwise, you can {u.fun_explain_field} or {u.fun_complete_field}'
                 self.state.set_warning_message(text)
                 raise Exception
             else:
                 # we have a list of fields with their values
                 string = self.state.fill_generic_slots(
                     slot_name_list=slot_name_list,
                     slot_value_list=slot_value_list)
         next_field_before = self.state.get_next_slot(only_name=True)
         # we verify if the spelling_list is empty or not
         if len(self.state.get_spelling_list()) != 0:
             string_spelling = self.fillSpellingField()
             next_field_after = self.state.get_next_slot(only_name=True)
             if next_field_before == next_field_after:
                 # the spelling did not modified the Web page, we return the string from the non spelling fields
                 return string
             # the spelling mofified the Web Form, so we use its string
             return string_spelling
         return string
     except:
         if not self.state.get_warning_present():
             print(
                 "A problem occured while a registration form bot tries to fill a camp"
             )
         raise Exception
Example #13
0
 def fill_input(self, slot_name, slot_value):
     # returns the slot value eventually modified to be in the right format, and a string to
     # eventuelly mention some incopatibilities
     try:
         string = ""
         # substitute the underscores with spaces to outpu the right message
         input_type_list = u.input_type_list
         slot = self.get_slot(slot_name)
         value_type = slot[u.value_type]
         value_name = slot[u.value_name]
         # the slot_value is not None
         if u.DEBUG:
             print(f"value_name: {value_name}, value_type: {value_type}")
         compatible, text = fn.is_compatible(slot_value, slot)
         if not compatible:
             next_step_string = self.manage_next_step()
             string = f'{text}\n{next_step_string}'
             return None, string
         # the value and the type are compatible so it is pssible that the value has been converted
         # to an appropriate form contained in text
         slot_value = text
         if value_type in input_type_list:
             elem = self.form_element.find_element_by_name(value_name)
             elem.clear()
             if slot_value is None:
                 return "", string
             elem.send_keys(slot_value)
             return slot_value, string
         # the value_type is in u.choices_list
         # the value is put in lowercase to coincide with the choice
         slot_value = slot_value.lower()
         if u.DEBUG:
             print(f"choice: {slot_value}")
         # we verify that slot_value is in the list of choices
         choice_list = slot[u.choice_list]
         length = len(choice_list)
         for index in range(length):
             choice_list[index] = choice_list[index].lower()
         if slot_value not in choice_list:
             sorry_style = styles.get_sorry()
             please_style = styles.get_please()
             string = (
                 f"{sorry_style} the choice {slot_value} is not valid for the field {slot_name}"
                 +
                 f"{please_style} choose one in the following list: {choice_list}"
             )
             self.set_possible_next_action(u.fill_field_action)
             return None, string
         # we are sure that the choice of the user is in the list of choices
         if value_type == u.dropdown:
             self.set_choice_dropdown(slot_name=slot_name,
                                      choice_value=slot_value)
         elif value_type == u.checkbox:
             self.set_choice_checkbox(slot_name=slot_name,
                                      choice_value=slot_value)
         elif value_type == u.radio:
             self.set_choice_radio(slot_name=slot_name,
                                   choice_value=slot_value)
         return slot_value, string
     except:
         next_step_string = self.manage_next_step()
         string = f'The value {slot_value} is not valid for the field {slot_name}.\n{next_step_string}'
         return None, string