Ejemplo n.º 1
0
 def handle(self, handler_input):
     print("In PriceIntent – unvalid")
     # request = handler_input.request_envelope.request
     return handler_input.response_builder.speak(
         "Du musst zuerst Gerichte erfragen,\
                 bevor du einen Preis erfahren kannst. ").ask(
             utility.random_phrase(REPROMPTS)).response
Ejemplo n.º 2
0
    def handle(self, handler_input):
        print("In PriceDishIntent – valid & completed")

        # type: (HandlerInput) -> Response
        print("In PriceIntent – valid & completed")

        # get previous response from session attributes
        session_attr = handler_input.attributes_manager.session_attributes

        # define user group names
        user_groups_de = ['Angestellte', 'Andere', 'Schüler', 'Studierende']

        # extract slot values
        # extract slot values
        filled_slots = handler_input.request_envelope.request.intent.slots
        slot_values = utility.get_slot_values(filled_slots)
        print(slot_values)
        current_dish = slot_values['dish']['resolved']
        current_dish_idx = slot_values['dish']['id']
        current_usergroup_id = slot_values['user_group']['id']
        current_user = slot_values['user_group']['resolved']

        # try to get dish by index
        try:
            dish_name = session_attr['all_dishes'][int(
                current_dish_idx)]['name']
            dish_prices = session_attr['all_dishes'][int(
                current_dish_idx)]['prices']
            user_groups = sorted(list(dish_prices.keys()))
            speech = "Das Gericht {} kostet ".format(dish_name)
            # if user asked for a specific user group, only read this price
            if current_usergroup_id:
                price = dish_prices[current_usergroup_id]
                if price != None:
                    speech += utility.build_price_speech(price, current_user)
                else:
                    price = dish_prices['others']
                    speech += utility.build_price_speech(price, current_user)
            # if not: read all prices for each available user group
            else:
                for i in range(len(user_groups)):
                    price = dish_prices[user_groups[i]]
                    if price == None:
                        continue
                    speech += utility.build_price_speech(
                        price, user_groups_de[i])
            speech += '. '

        # dish cannot be found any more: user may have used a higher number
        except Exception as e:
            speech = "Nanu! Das Gericht {} konnte nicht wiedergefunden werden. Bitte versuche es erneut. ".format(
                current_dish)
            print("Intent: {}: message: {}".format(
                handler_input.request_envelope.request.intent.name, str(e)))
            return handler_input.response_builder.speak(speech).ask(
                utility.random_phrase(REPROMPTS)).response

        return handler_input.response_builder.speak(
            speech).set_should_end_session(True).response
Ejemplo n.º 3
0
    def handle(self, handler_input):
        """Der Intent gibt die Adresse einer Mensa zurück. Benötigt wird der Name der Mensa.
        Ist dieser im Katalog, wird die Adresse zurückgegeben.
        Ist dieser nicht vorhanden, wird eine Fehlermeldung zurückgegeben.

        Der Benutzeranfrage und den bereitgestellten Slot Values werden folgende Daten entlockt:
            - Name und ID der Mensa (erforderlich)

        :param handler_input: HandlerInput
        :type handler_input: (HandlerInput) -> Response
        :return: Gibt die vollständige Skill-Antwort zurück
        :rtype: Response
        """
        ### DATA
        api_url_base = "https://openmensa.org/api/v2/canteens"
        all_mensas = utility.http_get_iterate(api_url_base)
        # type: (HandlerInput) -> Response
        print("In AddressIntent")
        filled_slots = handler_input.request_envelope.request.intent.slots
        slot_values = utility.get_slot_values(filled_slots)
        print(slot_values)
        current_mensa_id = slot_values['mensa_name']['id']
        current_mensa_name = slot_values['mensa_name']['resolved']
        try:
            name_address = [(j['name'], j['address']) for j in all_mensas
                            if j['id'] == int(current_mensa_id)]
            speech = "Die Adresse der {} lautet {}".format(
                name_address[0][0], name_address[0][1])
            speech = utility.convert_acronyms(speech)
        except Exception as e:
            speech = "Die Adresse der angefragten Mensa {} konnte leider nicht gefunden werden".format(
                current_mensa_name)
            speech = utility.convert_acronyms(speech) + ". "
            print("Intent: {}: message: {}".format(
                handler_input.request_envelope.request.intent.name, str(e)))
            return handler_input.response_builder.speak(
                speech + utility.random_phrase(REPROMPTS)).ask(
                    utility.random_phrase(REPROMPTS)).response

        return handler_input.response_builder.speak(
            speech).set_should_end_session(True).response
Ejemplo n.º 4
0
    def handle(self, handler_input):
        """
        Der Intent informiert den Benutzer darüber, dass der Skill die gewünschte Funktionalität nicht besitzt
        und fragt den User, ob er eine andere Suche starten möchte.

        :param handler_input: HandlerInput
        :type handler_input: (HandlerInput) -> Response
        :return: Gibt die vollständige Skill-Antwort zurück
        :rtype: Response
        """
        # type: (HandlerInput) -> Response
        print("In FallbackIntentHandler")
        return handler_input.response_builder.speak(ERROR_PROMPT).ask(
            utility.random_phrase(REPROMPTS)).response
Ejemplo n.º 5
0
    def handle(self, handler_input):
        """Der Intent gibt eine Liste mit Mensen in einer Stadt zurück. Benötigt wird der Name der Stadt.
        Sind Mensen vorhanden, werden diese zurückgegeben; gibt es keine oder ist die Stadt nicht in der
        Datenbank, wird eine Fehldermeldung zurückgegeben.

        Bei jedem Turn werden nur vier Mensen ausgegeben. Will der Nutzer mehr Mensen erfahren, muss er 
        nach \"weiteren Mensen\" fragen.

        Der Benutzeranfrage und den bereitgestellten Slot Values werden folgende Daten entlockt:
            - Stadt (erforderlich)

        :param handler_input: HandlerInput
        :type handler_input: (HandlerInput) -> Response
        :return: Gibt die vollständige Skill-Antwort zurück
        :rtype: Response
        """

        # type: (HandlerInput) -> Response
        print("In ListMensasIntent")
        api_url_base = "https://openmensa.org/api/v2/canteens"
        all_mensas = utility.http_get_iterate(api_url_base)
        # set state for AMAZON.NextIntent
        session_attr = handler_input.attributes_manager.session_attributes
        session_attr['next_intent_state'] = "ListMensas"
        session_attr['last_idx_mensas'] = 0

        filled_slots = handler_input.request_envelope.request.intent.slots
        slot_values = utility.get_slot_values(filled_slots)
        print(slot_values)
        city = slot_values['city']['resolved']
        city_mensas = [d['name'] for d in all_mensas if d['city'].lower() == city]

        # mensas found: build speech with a list of mensas
        if city_mensas:
            if len(city_mensas) == 1:
                speech = "Ich habe eine Mensa in {} gefunden: {}".format(city, city_mensas[0])
            else:
                session_attr['city_mensas'] = city_mensas
                first_mensas, session_attr['last_idx'] = utility.build_mensa_speech(city_mensas, 0)
                speech = "Ich habe {} Mensen in {} gefunden: {}".format(len(city_mensas), city, first_mensas)
                speech = utility.convert_acronyms(speech)
                if session_attr['last_idx_mensas'] < len(city_mensas):
                    session_attr['last_idx_mensas'] += 4
                    question = "Möchtest du mehr Mensen hören? Sag: Weiter!"
                    return handler_input.response_builder.speak(speech+question).ask(question).response

        # no mensas found
        speech = "Leider keine Mensen in {} gefunden. Du kannst eine andere Stadt in Deutschland wählen. ".format(city)
        return handler_input.response_builder.speak(speech+utility.random_phrase(REPROMPTS)).ask(utility.random_phrase(REPROMPTS)).response
Ejemplo n.º 6
0
    def handle(self, handler_input):
        """
        Der Intent führt den ListDishesIntent weiter und listet weitere Gerichte auf.
        Die benötigten Daten werden aus den Session-Attributes entnommen.

        Jeder Turn gibt nur vier Gerichte aus. Will der Nutzer mehr Gerichte erfahren, 
        muss er nach \"weiteren Gerichten\" fragen.

        :param handler_input: HandlerInput
        :type handler_input: (HandlerInput) -> Response
        :return: Gibt die vollständige Skill-Antwort zurück
        :rtype: Response
        """

        # type: (HandlerInput) -> Response
        print("In AMAZON.NextIntent")

        # get previous response from session attributes 
        session_attr = handler_input.attributes_manager.session_attributes

        # if dialogue state for NextIntent not set, unvalid intent
        if 'next_intent_state' in session_attr:

            # dialogue state for NextIntent in ListDishes
            if session_attr['next_intent_state'] == 'ListDishes' and 'all_dishes' in session_attr:
                dishes_names = [d['name'] for d in session_attr['all_dishes']]
                chunked_dishes = utility.make_chunking(dishes_names)
                more_dish_speech, session_attr['last_idx'] = utility.build_dish_speech(chunked_dishes, session_attr['last_idx'])
                if session_attr['last_idx'] < len(chunked_dishes):
                    question = 'Möchtest du mehr Gerichte hören oder Details? '
                else:
                    question = 'Möchtest du Details zu einem dieser Gerichte erfahren? \
                                Sag zum Beispiel: Details. oder: Wie viel kostet Gericht Nummer 2 für Studierende. '
                return handler_input.response_builder.speak(more_dish_speech+question).ask(question).response
            # dialogue state for NextIntent in ListMensas
            elif session_attr['next_intent_state'] == 'ListMensas':
                more_mensa_speech, session_attr['last_idx_mensas'] = utility.build_mensa_speech(session_attr['city_mensas'], session_attr['last_idx_mensas'])
                more_mensa_speech = utility.convert_acronyms(more_mensa_speech)
                if session_attr['last_idx_mensas'] < len(session_attr['city_mensas']):
                    question = "Möchtest du mehr Mensen hören? Sage: Weiter! "
                    return handler_input.response_builder.speak(more_mensa_speech+question).ask(question).response
                else:
                    goodbye = "<say-as interpret-as=\"interjection\">zum wohl</say-as>."
                    return handler_input.response_builder.speak(more_mensa_speech+goodbye).set_should_end_session(True).response

            # undefined dialogue state
            print("Undefined Dialogue State {} in NextIntent".format(session_attr['next_intent_state']))
        speech = "Du musst zuerst eine Suche starten, bevor du weitere Gerichte oder Mensen hören kanst. "
        return handler_input.response_builder.speak(speech).ask(utility.random_phrase(REPROMPTS)).response
Ejemplo n.º 7
0
    def handle(self, handler_input):
        print("In DetailsDishIntent – valid & completed")
        session_attr = handler_input.attributes_manager.session_attributes

        # extract slot values
        filled_slots = handler_input.request_envelope.request.intent.slots
        slot_values = utility.get_slot_values(filled_slots)
        # print(filled_slots)
        current_dish = slot_values['dish']['resolved']
        current_dish_idx = slot_values['dish']['id']
        user_groups_de = ['Angestellte', 'Andere', 'Schüler', 'Studierende']
        print(slot_values)
        # try to get dish by index
        try:
            dish_name = session_attr['all_dishes'][int(
                current_dish_idx)]['name']
            dish_prices = session_attr['all_dishes'][int(
                current_dish_idx)]['prices']
            dish_cat = session_attr['all_dishes'][int(
                current_dish_idx)]['category']
            dish_notes = session_attr['all_dishes'][int(
                current_dish_idx)]['notes']
            user_groups = sorted(list(dish_prices.keys()))
            speech = "Du hast das Gericht {} ausgewählt. ".format(dish_name)
            speech += "Es kostet "
            # read all prices for each available user group
            for i in range(len(user_groups)):
                price = dish_prices[user_groups[i]]
                if price == None:
                    continue
                speech += utility.build_price_speech(price, user_groups_de[i])
            speech += '. Es gehört zur Kategorie: {} und enthält '.format(
                dish_cat)
            for i in range(len(dish_notes)):
                if i == len(dish_notes) - 2:
                    speech += dish_notes[i] + ' und '
                else:
                    speech += dish_notes[i] + ', '
            speech += '. '

        # dish cannot be found any more
        except Exception as e:
            speech = "Nanu! Das Gericht {} konnte nicht wiedergefunden werden. Bitte versuche es erneut. ".format(
                current_dish)
            print("Intent: {}: message: {}".format(
                handler_input.request_envelope.request.intent.name, str(e)))
            return handler_input.response_builder.speak(speech).ask(
                utility.random_phrase(REPROMPTS)).response
        return handler_input.response_builder.speak(speech).response
Ejemplo n.º 8
0
    def handle(self, handler_input):
        """
        Der Intent unterstützt den Nutzer bei der Bedienung des Skills. 
        Er informiert den Nutzer über den Umfang des Skills und gibt Beispielanfragen zurück.
        
        :param handler_input: HandlerInput
        :type handler_input: (HandlerInput) -> Response
        :return: Gibt die vollständige Skill-Antwort zurück
        :rtype: Response
        """

        # type: (HandlerInput) -> Response
        print("In HelpIntentHandler")
        speech = "Mensaauskunft kann dir dabei helfen, passende Gerichte in deiner Mensa zu finden! \
                Du kannst nach dem Tagesplan, nach Mensen in deiner Nähe, Adressen und nach einem Gericht mit Zutaten deiner Wahl suchen. \
                Sag zum Beispiel: {}.".format(
            utility.random_phrase(HELP_SAMPLES))
        return handler_input.response_builder.speak(speech).ask(
            'Was möchtest du tun? ').response
Ejemplo n.º 9
0
 def handle(self, handler_input):
     # type: (HandlerInput) -> Response
     print("In YesIntentHandler")
     return handler_input.response_builder.speak(
         "Los geht's! Was möchtest du wissen? ").ask(
             utility.random_phrase(REPROMPTS)).response
Ejemplo n.º 10
0
    def handle(self, handler_input):
        """
        Der Intent listet alle verfügbaren Gerichte auf, die nach verschiedenen Mustern gesucht werden:

            1. Zunächst wird eine Mensa und ein Datum festgelegt. Die Slots werden elizitiert, 
            wenn die Nutzeranfrage diese noch nicht enthält.
            2. Die Suchanfrage kann spezifiziert werden, indem der User zusätzlich bis zu zwei Zutaten mit angeben kann,
            die entweder im Gericht enthalten sind oder nicht im Gericht enthalten sein sollen.

        Der Benutzeranfrage und den bereitgestellten Slot Values werden folgende Daten entlockt:
            - Tag bzw. Datum der Suchanfrage (erforderlich)
            - Mensaname (erforderlich)
            - (nicht) erwünschte Zutaten (optional)

        Anschließend wird eine Suchanfrage mithilfe der Mensa-ID und dem Datum gestartet und 
        die Daten von der OpenMensa API erfragt. 
        Diese werden ebenfalls in den Session-Attributes gespeichert.

        Gibt es zusätzlich Zutaten in der Nutzeranfrage, werden die API-Daten gefiltert.

        Zuletzt werden die Ergebnisse in einen String überführt, für den Chunking benutzt wird,
        um die Antwort von Alexa kurz zu halten (siehe lambda_utility.py).

        Außerdem werden bei jedem Turn nur vier Gerichte ausgegeben. Will der Nutzer mehr Gerichte erfahren, 
        muss er nach \"weiteren Gerichten\" fragen.

        :param handler_input: HandlerInput
        :type handler_input: (HandlerInput) -> Response
        :return: Gibt die vollständige Skill-Antwort zurück
        :rtype: Response
        """
        # type: (HandlerInput) -> Response
        print("In ListDishesIntent")
        # extract slot values
        filled_slots = handler_input.request_envelope.request.intent.slots
        slot_values = utility.get_slot_values(filled_slots)

        # extract (un)desired ingredients
        ingredients = {}
        ingredients['first'] = slot_values['first_ingredient']['resolved']
        ingredients['first_prep'] = slot_values['first_prep']['resolved']
        ingredients['second'] = slot_values['second_ingredient']['resolved']
        ingredients['second_prep'] = slot_values['second_prep']['resolved']    

        # assigning session attributes to the mensa_name slot values
        session_attr = handler_input.attributes_manager.session_attributes
        session_attr['current_date'] = slot_values['date']['resolved']
        session_attr['mensa_name'] = slot_values['mensa_name']['resolved']
        session_attr['mensa_id'] = slot_values['mensa_name']['id']
        print(slot_values)

        # Easteregg :P
        if str(ingredients['first']).lower() == 'schlangen' or str(ingredients['second']).lower() == 'schlangen':
            speech = "<say-as interpret-as=\"interjection\">ähm </say-as> <break time=\"0.25s\"/> Herr Schlangen ist nicht zum Verzehr geeignet! "
            return handler_input.response_builder.speak(speech).set_should_end_session(True).response

        # set state for AMAZON.NextIntent
        session_attr['next_intent_state'] = "ListDishes"

        # Mensa does not exist => return error prompt
        if session_attr['mensa_id'] is None:
            speech = "Sorry, Essenspläne für {} habe ich leider nicht im Angebot. ".format(session_attr['mensa_name'])
            return handler_input.response_builder.speak(speech+utility.random_phrase(REPROMPTS)).ask(utility.random_phrase(REPROMPTS)).response
        # create API link
        try:
            mensa_url = utility.create_mensa_url(mensa_id=session_attr['mensa_id'], date=session_attr['current_date'])
            # request mensa plan from API
            api_response = utility.http_get(mensa_url)
        # No dishes found for requested date or API is down 
        except Exception as e:
            speech = "Sorry, für den ausgewählten Tag {} gibt es leider keinen Essensplan für {}. \
                    Bitte überprüfe, ob die Mensa an diesem Tag geöffnet ist. ".format(session_attr['current_date'], session_attr['mensa_name'])
            print("Intent: {}: message: {}".format('ListDishesIntent', str(e)))
            return handler_input.response_builder.speak(speech+utility.random_phrase(REPROMPTS)).ask(utility.random_phrase(REPROMPTS)).response

        # try to find matching dishes
        session_attr['all_dishes'] = utility.find_matching_dishes(api_response, ingredients)
        # build speech for dish list
        dishes_names = [d['name'] for d in session_attr['all_dishes']]
        chunked_dishes = utility.make_chunking(dishes_names)
        dish_speech, session_attr['last_idx'] = utility.build_dish_speech(chunked_dishes, 0)
        updated_values = [Entity(id=i, name=EntityValueAndSynonyms(value=d, synonyms=d.split()
                                                            )
                        )
                for i, d in enumerate(chunked_dishes)
                ]
        print(updated_values)
        replace_entity_directive = DynamicEntitiesDirective(update_behavior=UpdateBehavior.REPLACE,
                                                            types=[EntityListItem(name="Dish", values=updated_values)])
        
        ingredients_pre, ingredients_post = utility.build_preposition_speech(ingredients)

        # dishes found: build speech with a list of dishes
        if dish_speech:
            if session_attr['last_idx'] < len(session_attr['all_dishes']):
                question = 'Möchtest du mehr Gerichte hören oder Details? '
            else: 
                question = 'Möchtest du Details zu einem dieser Gerichte erfahren? \
                            Sag zum Beispiel: Details. oder: Wie viel kostet Gericht Nummer 2 für Studierende. '

            speech = 'Es gibt {} {} Gerichte {} zur Auswahl: {}. {}'.format(len(session_attr['all_dishes']),
                                                                            ingredients_pre,
                                                                            ingredients_post,
                                                                            dish_speech,
                                                                            question)

        # no dishes found, e.g. there is no dish containing the requested ingredients
        else:
            # back up question in case it there is no dish_speech
            question = utility.random_phrase(REPROMPTS)
            if ingredients_post or ingredients_pre:
                speech = 'Leider gibt es keine passenden {} Gerichte {}. '.format(ingredients_pre,
                                                                                ingredients_post)
            else:
                speech = 'Es gibt leider keine passenden Gerichte zu deiner Anfrage. '
            speech += question
        print('Session attributes: ',session_attr)
        return handler_input.response_builder.speak(speech).ask(question).add_directive(replace_entity_directive).response
Ejemplo n.º 11
0
    def handle(self, handler_input):
        """Der Intent gibt den Preis für ein bestimmtes Gericht zurück. 
        Der Benutzer muss dabei die Nummer des Gerichts angeben und kann optional eine Zielgruppe
        (Studierende, Angestellte, Andere) definieren.

        Der Benutzeranfrage und den bereitgestellten Slot Values werden folgende Daten entlockt:
            - Nummer des Gerichts (erforderlich)
            - Zielgruppe (optional)

        Über die Session-Attributes müssen folgende Daten abgerufen werden:
            - Daten zu den gespeicherten Gerichten:
                - 'name'
                - 'prices'

        :param handler_input: HandlerInput
        :type handler_input: (HandlerInput) -> Response
        :return: Gibt die vollständige Skill-Antwort zurück
        :rtype: Response
        """
        # type: (HandlerInput) -> Response
        print("In PriceIntent – valid & completed")

        # get previous response from session attributes
        session_attr = handler_input.attributes_manager.session_attributes

        # define user group names
        user_groups_de = ['Angestellte', 'Andere', 'Schüler', 'Studierende']

        filled_slots = handler_input.request_envelope.request.intent.slots
        slot_values = utility.get_slot_values(filled_slots)
        print(slot_values)
        current_number = slot_values['number']['resolved']
        current_usergroup_id = slot_values['user_group']['id']
        current_user = slot_values['user_group']['resolved']

        # try to get dish by index
        try:
            dish_name = session_attr['all_dishes'][int(current_number)]['name']
            dish_prices = session_attr['all_dishes'][int(
                current_number)]['prices']
            user_groups = sorted(list(dish_prices.keys()))
            speech = "Das Gericht {} kostet ".format(dish_name)
            # if user asked for a specific user group, only read this price
            if current_usergroup_id:
                price = dish_prices[current_usergroup_id]
                if price != None:
                    speech += utility.build_price_speech(price, current_user)
                else:
                    price = dish_prices['others']
                    speech += utility.build_price_speech(price, current_user)
            # if not: read all prices for each available user group
            else:
                for i in range(len(user_groups)):
                    price = dish_prices[user_groups[i]]
                    if price == None:
                        continue
                    speech += utility.build_price_speech(
                        price, user_groups_de[i])
            speech += '. '
        # dish cannot be found any more
        except Exception as e:
            speech = "Nanu! Das Gericht {} konnte nicht wiedergefunden werden. Bitte versuche es erneut. ".format(
                dish_name)
            print("Intent: {}: message: {}".format(
                handler_input.request_envelope.request.intent.name, str(e)))
            return handler_input.response_builder.speak(speech).ask(
                utility.random_phrase(REPROMPTS)).response
        return handler_input.response_builder.speak(speech).response
Ejemplo n.º 12
0
    def handle(self, handler_input):
        """Der Intent listet die Details zu einem bestimmten Gericht auf.

        (Alle verfügbaren Informationen der OpenMensa API.)

        Dazu gehören:
            - Der vollständige Titel des Gerichts
            - Die Preise für Studierende, Angestellte und Andere
            - Die Kategorie des Gerichts
            - Die zusätzlichen Notes
        Der Benutzeranfrage und den bereitgestellten Slot Values werden folgende Daten entnommen:
            - Gerichtnummer

        Über die Session-Attributes müssen folgende Daten abgerufen werden:
            - Daten zu den gespeicherten Gerichten:
                - 'name'
                - 'price'
                - 'category'
                - 'notes'

        :param handler_input: HandlerInput
        :type handler_input: (HandlerInput) -> Response
        :return: Gibt die vollständige Skill-Antwort zurück
        :rtype: Response
        """
        # type:
        print("In DetailsIntent – valid & completed")
        # extract slot values
        filled_slots = handler_input.request_envelope.request.intent.slots
        # get previous response from session attributes
        session_attr = handler_input.attributes_manager.session_attributes
        user_groups_de = ['Angestellte', 'Andere', 'Schüler', 'Studierende']

        # extract slot values
        filled_slots = handler_input.request_envelope.request.intent.slots
        slot_values = utility.get_slot_values(filled_slots)
        print(slot_values)
        print(session_attr)
        current_number = slot_values['number']['resolved']

        # try to get dish by index
        try:
            dish_name = session_attr['all_dishes'][int(current_number) -
                                                   1]['name']
            dish_prices = session_attr['all_dishes'][int(current_number) -
                                                     1]['prices']
            dish_cat = session_attr['all_dishes'][int(current_number) -
                                                  1]['category']
            dish_notes = session_attr['all_dishes'][int(current_number) -
                                                    1]['notes']
            user_groups = sorted(list(dish_prices.keys()))
            speech = "Du hast das Gericht {} ausgewählt. ".format(dish_name)
            speech += "Es kostet "
            # read all prices for each available user group
            for i in range(len(user_groups)):
                price = dish_prices[user_groups[i]]
                if price == None:
                    continue
                speech += utility.build_price_speech(price, user_groups_de[i])
            speech += '. Es gehört zur Kategorie: {} und enthält '.format(
                dish_cat)
            for i in range(len(dish_notes)):
                if i == len(dish_notes) - 2:
                    speech += dish_notes[i] + ' und '
                else:
                    speech += dish_notes[i] + ', '
            speech += '. '

        # dish cannot be found any more: user may have used a higher number
        except Exception as e:
            speech = "Nanu! Das Gericht Nummer {} konnte nicht wiedergefunden werden. Bitte versuche es erneut. ".format(
                current_number)
            print("Intent: {}: message: {}".format(
                handler_input.request_envelope.request.intent.name, str(e)))
            return handler_input.response_builder.speak(speech).ask(
                utility.random_phrase(REPROMPTS)).response
        return handler_input.response_builder.speak(
            speech).set_should_end_session(True).response