<commit_before>"""
Interaction Model

This module basically maps out the response tree for the skill.
"""
from datetime import timedelta, datetime, date
from operator import attrgetter
from typing import Union
from textwrap import dedent
import logging
from . import wods
from . import speechlet
from . import env

LOG = logging.getLogger(__name__)
LOG.setLevel(logging.DEBUG)


def _get_speech_date(d: Union[date, datetime]) -> str:
    return '{} {}, {}'.format(d.strftime('%A %B'), d.day, d.year)


def _confirm_choice(should_confirm: bool, relative_qualifier: str, query: str) -> str:
    if should_confirm:
        if relative_qualifier:
            return '<p>OK, {}\'s {}</p>'.format(relative_qualifier, query)
        return '<p>OK, {}.</p>'.format(query)
    return ''


def _wod_ssml(wod: wods.WOD) -> str:
    if wod:
        if wod.publish_datetime > env.now():
            return '<p>The wod for {} has not been posted yet.</p>'.format(_get_speech_date(wod.date))
        return wod.full_ssml()
    return '<p>There is no workout.</p>'


def _wod_card(wod: wods.WOD, relative_qualifier: str, query_type: str) -> speechlet.SimpleCard:
    card_content = wod.pprint()
    card_title = '{} for {}'.format(query_type, relative_qualifier) if relative_qualifier else query_type
    if wod.image:
        return speechlet.StandardCard(title=card_title, content=card_content, large_image_url=wod.image)
    return speechlet.SimpleCard(title=card_title, content=card_content)


def goodbye(intent: dict, attributes: dict) -> speechlet.SpeechletResponse:
    return end_session()


def end_session() -> speechlet.SpeechletResponse:
    return speechlet.SpeechletResponse(
        speechlet.PlainText('Goodbye.'),
        should_end=True
    )


def query_intent(intent: dict, attributes: dict) -> speechlet.SpeechletResponse:
    """
    Responds to most queries of the skill.
    :param intent:
    :param attributes:
    :return:
    """
    try:
        relative_qualifier = intent['slots']['RelativeQualifier']['value']
    except KeyError:
        relative_qualifier = None
    try:
        query_type = intent['slots']['Query']['value']
    except KeyError:
        query_type = None

    wod = wods.get_wod(env.localdate())
    ssml = speechlet.SSML(
        '<speak>' +
        _confirm_choice(attributes.get('confirm_choice', False), relative_qualifier, query_type) +
        _wod_ssml(wod)
    )
    card = _wod_card(wod, relative_qualifier, query_type)
    return speechlet.SpeechletResponse(
        ssml,
        card=card,
        should_end=True
    )


def help_intent(intent: dict, attributes: dict) -> speechlet.SpeechletResponse:
    """
    This is triggered when the user asks for "help".

    :param intent:
    :param attributes:
    :return:<commit_msg>Add support to interaction model for asking for just conditioning or strength<commit_after>"""
Interaction Model

This module basically maps out the response tree for the skill.
"""
from datetime import timedelta, datetime, date
from operator import attrgetter
from typing import Union
from textwrap import dedent
from enum import Enum
import logging
from . import wods
from . import speechlet
from . import env

LOG = logging.getLogger(__name__)
LOG.setLevel(logging.DEBUG)


class QueryType(Enum):
    WORKOUT = 1
    STRENGTH = 2
    CONDITIONING = 3

    @property
    def pname(self):
        return self.name[0] + self.name[1:].lower()


def _get_speech_date(d: Union[date, datetime]) -> str:
    return '{} {}, {}'.format(d.strftime('%A %B'), d.day, d.year)


def _confirm_choice(should_confirm: bool, relative_qualifier: str, query: QueryType) -> str:
    if should_confirm:
        if relative_qualifier:
            return '<p>OK, {}\'s {}</p>'.format(relative_qualifier, query.name.lower())
        return '<p>OK, {}.</p>'.format(query.name.lower())
    return ''


def _wod_ssml(wod: wods.WOD, query_type: QueryType) -> str:
    if query_type == QueryType.CONDITIONING:
        return wod.conditioning_ssml()
    elif query_type == QueryType.STRENGTH:
        return wod.strength_ssml()
    return wod.full_ssml()


def _wod_card(wod: wods.WOD, query_type: QueryType) -> speechlet.SimpleCard:
    card_title = '{} for {}'.format(query_type.pname, _get_speech_date(wod.date))
    if query_type == QueryType.STRENGTH:
        card_content = wod.strength_pprint()
    elif query_type == QueryType.CONDITIONING:
        card_content = wod.conditioning_pprint()
    else:
        card_content = wod.pprint()
    if wod.image and query_type == QueryType.WORKOUT: # full workout w/ announcement, show pic
        return speechlet.StandardCard(title=card_title, content=card_content, large_image_url=wod.image)
    return speechlet.SimpleCard(title=card_title, content=card_content)


def goodbye(intent: dict, attributes: dict) -> speechlet.SpeechletResponse:
    return end_session()


def end_session() -> speechlet.SpeechletResponse:
    return speechlet.SpeechletResponse(
        speechlet.PlainText('Goodbye.'),
        should_end=True
    )


def query_intent(intent: dict, attributes: dict) -> speechlet.SpeechletResponse:
    """
    Responds to most queries of the skill.
    :param intent:
    :param attributes:
    :return:
    """
    try:
        relative_qualifier = intent['slots']['RelativeQualifier']['value']
    except KeyError:
        try:
            relative_qualifier = attributes['RelativeQualifier']
        except KeyError:
            relative_qualifier = None
    try:
        query_type = intent['slots']['Query']['value']
    except KeyError:
        try:
            query_type = attributes['Query']
        except KeyError:
            query_type = None
    target_date = env.localdate()
    if query_type:
        if 'strength' in query_type.lower():
            qt = QueryType.STRENGTH
        elif 'condition' in query_type.lower():
            qt = QueryType.CONDITIONING
        else:
            qt = QueryType.WORKOUT
        ssml_txt = '<speak>' + _confirm_choice(attributes.get('confirm_choice', False), relative_qualifier, qt)
        wod = wods.get_wod(target_date)
        if wod:
            if wod.publish_datetime < env.now():
                ssml_txt += _wod_ssml(wod, qt)
                card = _wod_card(wod, qt)
            else:
                ssml_txt += '<p>The wod for {} has not been posted yet.</p>'.format(_get_speech_date(wod.date))
                card = speechlet.SimpleCard(
                    title='{} for {}'.format(qt.pname, _get_speech_date(wod.date)),
                    content='Not posted yet.'
                )
        else:
            ssml_txt += '<p>No workout was found for {}</p>'.format(_get_speech_date(target_date))
            card = speechlet.SimpleCard(
                title='{} for {}'.format(qt.pname, _get_speech_date(target_date)),
                content='Not found.'
            )
        return speechlet.SpeechletResponse(
            speechlet.SSML(ssml_txt + '</speak>'),
            card=card,
            should_end=True
        )
    else:
        ssml_txt = 'You can say workout, strength, or conditioning. Which do you want?'
        if relative_qualifier:
            ssml_txt = 'I\'m not sure what you want for {}. '.format(relative_qualifier) + ssml_txt
        return speechlet.SpeechletResponse(
            speechlet.SSML(ssml_txt),
            should_end=False,
            attributes={
                'RelativeQualifier': relative_qualifier
            }
        )


def help_intent(intent: dict, attributes: dict) -> speechlet.SpeechletResponse:
    """
    This is triggered when the user asks for "help".

    :param intent:
    :param attributes:
    :return:
{'fraction_non_alphanumeric': 0.11315583398590447, 'fraction_numerical': 0.0006525711302531976, 'mean_word_length': 2.8918232605383443, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4489897', 'n_tokens_mistral': 2406, 'n_tokens_neox': 2334, 'n_words': 567}