text:
"""Domain objects relating to questions."""

from __future__ import annotations

import collections
import copy
import datetime
import re

from core import feconf
from core import schema_utils
from core import utils
from core.constants import constants
from core.domain import change_domain
from core.domain import customization_args_util
from core.domain import exp_domain
from core.domain import expression_parser
from core.domain import html_cleaner
from core.domain import html_validation_service
from core.domain import interaction_registry
from core.domain import state_domain
from core.platform import models
from extensions import domain

from pylatexenc import latex2text

(question_models,) = models.Registry.import_models([models.NAMES.question])

# Do not modify the values of these constants. This is to preserve backwards
# compatibility with previous change dicts.
QUESTION_PROPERTY_LANGUAGE_CODE = 'language_code'
QUESTION_PROPERTY_QUESTION_STATE_DATA = 'question_state_data'
QUESTION_PROPERTY_LINKED_SKILL_IDS = 'linked_skill_ids'
QUESTION_PROPERTY_INAPPLICABLE_SKILL_MISCONCEPTION_IDS = (
    'inapplicable_skill_misconception_ids')

# This takes additional 'property_name' and 'new_value' parameters and,
# optionally, 'old_value'.
CMD_UPDATE_QUESTION_PROPERTY = 'update_question_property'
CMD_CREATE_NEW_FULLY_SPECIFIED_QUESTION = 'create_new_fully_specified_question'
CMD_MIGRATE_STATE_SCHEMA_TO_LATEST_VERSION = (
    'migrate_state_schema_to_latest_version')

# The following commands are deprecated, as these functionalities will be
# handled by a QuestionSkillLink class in the future.
CMD_ADD_QUESTION_SKILL = 'add_question_skill'
CMD_REMOVE_QUESTION_SKILL = 'remove_question_skill'

CMD_CREATE_NEW = 'create_new'

class QuestionChange(change_domain.BaseChange):
    """Domain object for changes made to question object.

    The allowed commands, together with the attributes:
        - 'create_new'
        - 'update question property' (with property_name, new_value
        and old_value)
        - 'create_new_fully_specified_question' (with question_dict,
        skill_id)
        - 'migrate_state_schema_to_latest_version' (with from_version
        and to_version)
    """

    # The allowed list of question properties which can be used in
    # update_question_property command.
    QUESTION_PROPERTIES = (
        QUESTION_PROPERTY_QUESTION_STATE_DATA,
        QUESTION_PROPERTY_LANGUAGE_CODE,
        QUESTION_PROPERTY_LINKED_SKILL_IDS,
        QUESTION_PROPERTY_INAPPLICABLE_SKILL_MISCONCEPTION_IDS)

    ALLOWED_COMMANDS = [{
        'name': CMD_CREATE_NEW,
        'required_attribute_names': [],
        'optional_attribute_names': [],
        'user_id_attribute_names': []
    }, {
        'name': CMD_UPDATE_QUESTION_PROPERTY,
        'required_attribute_names': ['property_name', 'new_value', 'old_value'],
        'optional_attribute_names': [],
        'user_id_attribute_names': [],
        'allowed_values': {'property_name': QUESTION_PROPERTIES}
    }, {
        'name': CMD_CREATE_NEW_FULLY_SPECIFIED_QUESTION,
        'required_attribute_names': ['question_dict', 'skill_id'],
        'optional_attribute_names': ['topic_name'],
        'user_id_attribute_names': []
    }, {
        'name': CMD_MIGRATE_STATE_SCHEMA_TO_LATEST_VERSION,
        'required_attribute_names': ['from_version', 'to_version'],
        'optional_attribute_names': [],
        'user_id_attribute_names': []
    }]

class QuestionSuggestionChange(change_domain.BaseChange):
    """Domain object for changes made to question suggestion object.

    The allowed commands, together with the attributes:
        - 'create_new_fully_specified_question' (with question_dict,
        skill_id, skill_difficulty)
    """

    ALLOWED_COMMANDS = [
        {
            'name': CMD_CREATE_NEW_FULLY_SPECIFIED_QUESTION,
            'required_attribute_names': [
                'question_dict', 'skill_id', 'skill_difficulty'],
            'optional_attribute_names': [],
            'user_id_attribute_names': []
        }
    ]

class Question:
    """Domain object for a question."""

    def __init__(
            self, question_id, question_state_data,
            question_state_data_schema_version, language_code, version,
            linked_skill_ids, inapplicable_skill_misconception_ids,
            created_on=None, last_updated=None):
        """Constructs a Question domain object.

        Args:
            question_id: str. The unique ID of the question.
            question_state_data: State. An object representing the question
                state data.
            question_state_data_schema_version: int. The schema version of the
                question states (equivalent to the states schema version of
                explorations).
            language_code: str. The ISO 639-1 code for the language this
                question is written in.
            version: int. The version of the question.
            linked_skill_ids: list(str). Skill ids linked to the question.
                Note: Do not update this field manually.
            inapplicable_skill_misconception_ids: list(str). Optional
                misconception ids that are marked as not relevant to the
                question.
            created_on: datetime.datetime. Date and time when the question was
                created.
            last_updated: datetime.datetime. Date and time when the
                question was last updated.
        """
        self.id = question_id
        self.question_state_data = question_state_data
        self.language_code = language_code
        self.question_state_data_schema_version = (
            question_state_data_schema_version)
        self.version = version
        self.linked_skill_ids = linked_skill_ids
        self.inapplicable_skill_misconception_ids = (
            inapplicable_skill_misconception_ids)
        self.created_on = created_on
        self.last_updated = last_updated

    def to_dict(self):
        """Returns a dict representing this Question domain object.

        Returns:
            dict. A dict representation of the Question instance.
        """
        return {
            'id': self.id,
            'question_state_data': self.question_state_data.to_dict(),
            'question_state_data_schema_version': (
                self.question_state_data_schema_version),
            'language_code': self.language_code,
            'version': self.version,
            'linked_skill_ids': self.linked_skill_ids,
            'inapplicable_skill_misconception_ids': (
                self.inapplicable_skill_misconception_ids)
        }

    @classmethod
    def create_default_question_state(cls):
        """Return a State domain object with default value for being used as
        question state data.

        Returns:
            State. The corresponding State domain object.
        """
        return state_domain.State.create_default_state(
            None, is_initial_state=True)

    @classmethod
    def _convert_state_v27_dict_to_v28_dict(cls, question_state_dict):
        """Converts from version 27 to 28. Version 28 replaces
        content_ids_to_audio_translations with recorded_voiceovers.

        Args:
            question_state_dict: dict. The dict representation of
                question_state_data.

        Returns:
            dict. The converted question_state_dict.
        """
        question_state_dict['recorded_voiceovers'] = {
            'voiceovers_mapping': (
                question_state_dict.pop('content_ids_to_audio_translations'))
        }
        return question_state_dict

    @classmethod
    def _convert_state_v28_dict_to_v29_dict(cls, question_state_dict):
        """Converts from version 28 to 29. Version 29 adds
        solicit_answer_details boolean variable to the state, which
        allows the creator to ask for answer details from the learner
        about why they landed on a particular answer.

        Args:
            question_state_dict: dict. The dict representation of
                question_state_data.

        Returns:
            dict. The converted question_state_dict.
        """
        question_state_dict['solicit_answer_details'] = False
        return question_state_dict

    @classmethod
    def _convert_state_v29_dict_to_v30_dict(cls, question_state_dict):
        """Converts from version 29 to 30. Version 30 replaces
        tagged_misconception_id with tagged_skill_misconception_id, which
        is default to None.

        Args:
            question_state_dict: dict. A dict where each key-value pair
                represents respectively, a state name and a dict used to
                initialize a State domain object.

        Returns:
            dict. The converted question_state_dict.
        """
        answer_groups = question_state_dict['interaction']['answer_groups']
        for answer_group in answer_groups:
            answer_group['tagged_skill_misconception_id'] = None
            del answer_group['tagged_misconception_id']

        return question_state_dict

    @classmethod
    def _convert_state_v30_dict_to_v31_dict(cls, question_state_dict):
        """Converts from version 30 to 31. Version 31 updates the
        Voiceover model to have an initialized duration_secs attribute of 0.0.

        Args:
            question_state_dict: dict. A dict where each key-value pair
                represents respectively, a state name and a dict used to
                initialize a State domain object.

        Returns:
            dict. The converted question_state_dict.
        """
        # Get the voiceovers_mapping metadata.
        voiceovers_mapping = (
            question_state_dict['recorded_voiceovers']['voiceovers_mapping'])
        language_codes_to_audio_metadata = voiceovers_mapping.values()
        for language_codes in language_codes_to_audio_metadata:
            for audio_metadata in language_codes.values():
                # Initialize duration_secs with 0.0 for every voiceover
                # recording under Content, Feedback, Hints, and Solutions.
                # This is necessary to keep the state functional
                # when migrating to v31.
                audio_metadata['duration_secs'] = 0.0
        return question_state_dict

    @classmethod
    def _convert_state_v31_dict_to_v32_dict(cls, question_state_dict):
        """Converts from version 31 to 32. Version 32 adds a new
        customization arg to SetInput interaction which allows
        creators to add custom text to the "Add" button.

        Args:
            question_state_dict: dict. A dict where each key-value pair
                represents respectively, a state name and a dict used to
                initialize a State domain object.

        Returns:
            dict. The converted question_state_dict.
        """
        if question_state_dict['interaction']['id'] == 'SetInput':
            customization_args = question_state_dict[
                'interaction']['customization_args']
            customization_args.update({
                'buttonText': {
                    'value': 'Add item'
                }
            })

        return question_state_dict

    @classmethod
    def _convert_state_v32_dict_to_v33_dict(cls, question_state_dict):
        """Converts from version 32 to 33. Version 33 adds a new
        customization arg to MultipleChoiceInput Interaction which allows
        answer choices to be shuffled.

        Args:
            question_state_dict: dict. A dict where each key-value pair
                represents respectively, a state name and a dict used to
                initialize a State domain object.

        Returns:
            dict. The converted question_state_dict.
        """
        if question_state_dict['interaction']['id'] == 'MultipleChoiceInput':
            customization_args = question_state_dict[
                'interaction']['customization_args']
            customization_args.update({
                'showChoicesInShuffledOrder': {
                    'value': True
                }
            })

        return question_state_dict

    @classmethod
    def _convert_state_v33_dict_to_v34_dict(cls, question_state_dict):
        """Converts from version 33 to 34. Version 34 adds a new
        attribute for math components. The new attribute has an additional field
        to for storing SVG filenames.

        Args:
            question_state_dict: dict. A dict where each key-value pair
                represents respectively, a state name and a dict used to
                initialize a State domain object.

        Returns:
            dict. The converted question_state_dict.
        """
        question_state_dict = state_domain.State.convert_html_fields_in_state(
            question_state_dict,
            html_validation_service.add_math_content_to_math_rte_components,
            state_uses_old_interaction_cust_args_schema=True,
            state_uses_old_rule_template_schema=True)
        return question_state_dict

    @classmethod
    def _convert_state_v34_dict_to_v35_dict(cls, question_state_dict):
        """Converts from version 34 to 35. Version 35 upgrades all explorations
        that use the MathExpressionInput interaction to use one of
        AlgebraicExpressionInput, NumericExpressionInput, or MathEquationInput
        interactions.

        Args:
            question_state_dict: dict. A dict where each key-value pair
                represents respectively, a state name and a dict used to
                initialize a State domain object.

        Returns:
            dict. The converted question_state_dict.
        """
        is_valid_algebraic_expression = schema_utils.get_validator(
            'is_valid_algebraic_expression')
        is_valid_numeric_expression = schema_utils.get_validator(
            'is_valid_numeric_expression')
        is_valid_math_equation = schema_utils.get_validator(
            'is_valid_math_equation')
        ltt = latex2text.LatexNodes2Text()

        if question_state_dict['interaction']['id'] == 'MathExpressionInput':
            new_answer_groups = []
            types_of_inputs = set()
            for group in question_state_dict['interaction']['answer_groups']:
                new_answer_group = copy.deepcopy(group)
                for rule_spec in new_answer_group['rule_specs']:
                    rule_input = ltt.latex_to_text(rule_spec['inputs']['x'])

                    rule_input = exp_domain.clean_math_expression(
                        rule_input)

                    type_of_input = exp_domain.TYPE_INVALID_EXPRESSION
                    if is_valid_algebraic_expression(rule_input):
                        type_of_input = (
                            exp_domain.TYPE_VALID_ALGEBRAIC_EXPRESSION)
                    elif is_valid_numeric_expression(rule_input):
                        type_of_input = exp_domain.TYPE_VALID_NUMERIC_EXPRESSION
                    elif is_valid_math_equation(rule_input):
                        type_of_input = exp_domain.TYPE_VALID_MATH_EQUATION

                    types_of_inputs.add(type_of_input)

                    if type_of_input != exp_domain.TYPE_INVALID_EXPRESSION:
                        rule_spec['inputs']['x'] = rule_input
                        if type_of_input == exp_domain.TYPE_VALID_MATH_EQUATION:
                            rule_spec['inputs']['y'] = 'both'
                        rule_spec['rule_type'] = 'MatchesExactlyWith'

                new_answer_groups.append(new_answer_group)

            if exp_domain.TYPE_INVALID_EXPRESSION not in types_of_inputs:
                # If at least one rule input is an equation, we remove
                # all other rule inputs that are expressions.
                if exp_domain.TYPE_VALID_MATH_EQUATION in types_of_inputs:
                    new_interaction_id = exp_domain.TYPE_VALID_MATH_EQUATION
                    for group in new_answer_groups:
                        new_rule_specs = []
                        for rule_spec in group['rule_specs']:
                            if is_valid_math_equation(
                                    rule_spec['inputs']['x']):
                                new_rule_specs.append(rule_spec)
                        group['rule_specs'] = new_rule_specs
                # Otherwise, if at least one rule_input is an algebraic
                # expression, we remove all other rule inputs that are
                # numeric expressions.
                elif exp_domain.TYPE_VALID_ALGEBRAIC_EXPRESSION in (
                        types_of_inputs):
                    new_interaction_id = (
                        exp_domain.TYPE_VALID_ALGEBRAIC_EXPRESSION)
                    for group in new_answer_groups:
                        new_rule_specs = []
                        for rule_spec in group['rule_specs']:
                            if is_valid_algebraic_expression(
                                    rule_spec['inputs']['x']):
                                new_rule_specs.append(rule_spec)
                        group['rule_specs'] = new_rule_specs
                else:
                    new_interaction_id = (
                        exp_domain.TYPE_VALID_NUMERIC_EXPRESSION)

                # Removing answer groups that have no rule specs left after
                # the filtration done above.
                new_answer_groups = [
                    answer_group for answer_group in new_answer_groups if (
                        len(answer_group['rule_specs']) != 0)]

                # Removing feedback keys, from voiceovers_mapping and
                # translations_mapping, that correspond to the rules that
                # got deleted.
                old_answer_groups_feedback_keys = [
                    answer_group['outcome'][
                        'feedback']['content_id'] for answer_group in (
                            question_state_dict[
                                'interaction']['answer_groups'])]
                new_answer_groups_feedback_keys = [
                    answer_group['outcome'][
                        'feedback']['content_id'] for answer_group in (
                            new_answer_groups)]
                content_ids_to_delete = set(
                    old_answer_groups_feedback_keys) - set(
                        new_answer_groups_feedback_keys)
                for content_id in content_ids_to_delete:
                    if content_id in question_state_dict['recorded_voiceovers'][
                            'voiceovers_mapping']:
                        del question_state_dict['recorded_voiceovers'][
                            'voiceovers_mapping'][content_id]
                    if content_id in question_state_dict[
                            'written_translations']['translations_mapping']:
                        del question_state_dict['written_translations'][
                            'translations_mapping'][content_id]

                question_state_dict['interaction']['id'] = new_interaction_id
                question_state_dict['interaction']['answer_groups'] = (
                    new_answer_groups)
                if question_state_dict['interaction']['solution']:
                    correct_answer = question_state_dict['interaction'][
                        'solution']['correct_answer']['ascii']
                    correct_answer = exp_domain.clean_math_expression(
                        correct_answer)
                    question_state_dict['interaction'][
                        'solution']['correct_answer'] = correct_answer

        return question_state_dict

    @classmethod
    def _convert_state_v35_dict_to_v36_dict(cls, question_state_dict):
        """Converts from version 35 to 36. Version 35 adds translation support
        for interaction customization arguments. This migration converts
        customization arguments whose schemas have been changed from unicode to
        SubtitledUnicode or html to SubtitledHtml. It also populates missing
        customization argument keys on all interactions, removes extra
        customization arguments, normalizes customization arguments against
        its schema, and changes PencilCodeEditor's customization argument
        name from initial_code to initialCode.

        Args:
            question_state_dict: dict. A dict where each key-value pair
                represents respectively, a state name and a dict used to
                initialize a State domain object.

        Returns:
            dict. The converted question_state_dict.
        """
        max_existing_content_id_index = -1
        translations_mapping = question_state_dict[
            'written_translations']['translations_mapping']
        for content_id in translations_mapping:
            # Find maximum existing content_id index.
            content_id_suffix = content_id.split('_')[-1]

            # Possible values of content_id_suffix are a digit, or from
            # a 'outcome' (from 'default_outcome'). If the content_id_suffix
            # is not a digit, we disregard it here.
            if content_id_suffix.isdigit():
                max_existing_content_id_index = max(
                    max_existing_content_id_index,
                    int(content_id_suffix)
                )

            # Move 'html' field to 'translation' field and set 'data_format'
            # to 'html' for all WrittenTranslations.
            for lang_code in translations_mapping[content_id]:
                translations_mapping[
                    content_id][lang_code]['data_format'] = 'html'
                translations_mapping[
                    content_id][lang_code]['translation'] = (
                        translations_mapping[content_id][lang_code]['html'])
                del translations_mapping[content_id][lang_code]['html']

        interaction_id = question_state_dict['interaction']['id']
        if interaction_id is None:
            question_state_dict['next_content_id_index'] = (
                max_existing_content_id_index + 1)
            return question_state_dict

        class ContentIdCounter:
            """This helper class is used to keep track of
            next_content_id_index and new_content_ids, and provides a
            function to generate new content_ids.
            """

            new_content_ids = []

            def __init__(self, next_content_id_index):
                """Initializes a ContentIdCounter object.

                Args:
                    next_content_id_index: int. The next content id index.
                """
                self.next_content_id_index = next_content_id_index

            def generate_content_id(self, content_id_prefix):
                """Generate a new content_id from the prefix provided and
                the next content id index.

                Args:
                    content_id_prefix: str. The prefix of the content_id.

                Returns:
                    str. The generated content_id.
                """
                content_id = '%s%i' % (
                    content_id_prefix,
                    self.next_content_id_index)
                self.next_content_id_index += 1
                self.new_content_ids.append(content_id)
                return content_id

        content_id_counter = (
            ContentIdCounter(max_existing_content_id_index + 1))

        ca_dict = question_state_dict['interaction']['customization_args']
        if (interaction_id == 'PencilCodeEditor' and
                'initial_code' in ca_dict):
            ca_dict['initialCode'] = ca_dict['initial_code']
            del ca_dict['initial_code']

        # Retrieve a cached version (state schema v35) of
        # interaction_specs.json to ensure that this migration remains
        # stable even when interaction_specs.json is changed.
        ca_specs = [
            domain.CustomizationArgSpec(
                ca_spec_dict['name'],
                ca_spec_dict['description'],
                ca_spec_dict['schema'],
                ca_spec_dict['default_value']
            ) for ca_spec_dict in (
                interaction_registry.Registry
                .get_all_specs_for_state_schema_version(36)[
                    interaction_id]['customization_arg_specs']
            )
        ]

        for ca_spec in ca_specs:
            schema = ca_spec.schema
            ca_name = ca_spec.name
            content_id_prefix = 'ca_%s_' % ca_name

            # We only have to migrate unicode to SubtitledUnicode or
            # list of html to list of SubtitledHtml. No interactions
            # were changed from html to SubtitledHtml.
            is_subtitled_unicode_spec = (
                schema['type'] == schema_utils.SCHEMA_TYPE_CUSTOM and
                schema['obj_type'] ==
                schema_utils.SCHEMA_OBJ_TYPE_SUBTITLED_UNICODE)
            is_subtitled_html_list_spec = (
                schema['type'] == schema_utils.SCHEMA_TYPE_LIST and
                schema['items']['type'] ==
                schema_utils.SCHEMA_TYPE_CUSTOM and
                schema['items']['obj_type'] ==
                schema_utils.SCHEMA_OBJ_TYPE_SUBTITLED_HTML)

            if is_subtitled_unicode_spec:
                # Default is a SubtitledHtml dict or SubtitleUnicode dict.
                new_value = copy.deepcopy(ca_spec.default_value)

                # If available, assign value to html or unicode_str.
                if ca_name in ca_dict:
                    new_value['unicode_str'] = ca_dict[ca_name]['value']

                # Assign content_id.
                new_value['content_id'] = (
                    content_id_counter
                    .generate_content_id(content_id_prefix)
                )

                ca_dict[ca_name] = {'value': new_value}
            elif is_subtitled_html_list_spec:
                new_value = []

                if ca_name in ca_dict:
                    # Assign values to html fields.
                    for html in ca_dict[ca_name]['value']:
                        new_value.append({
                            'html': html, 'content_id': None
                        })
                else:
                    # Default is a list of SubtitledHtml dict.
                    new_value.extend(copy.deepcopy(ca_spec.default_value))

                # Assign content_ids.
                for subtitled_html_dict in new_value:
                    subtitled_html_dict['content_id'] = (
                        content_id_counter
                        .generate_content_id(content_id_prefix)
                    )

                ca_dict[ca_name] = {'value': new_value}
            elif ca_name not in ca_dict:
                ca_dict[ca_name] = {'value': ca_spec.default_value}

        (
            customization_args_util
            .validate_customization_args_and_values(
                'interaction',
                interaction_id,
                ca_dict,
                ca_specs)
        )

        question_state_dict['next_content_id_index'] = (
            content_id_counter.next_content_id_index)
        for new_content_id in content_id_counter.new_content_ids:
            question_state_dict[
                'written_translations'][
                    'translations_mapping'][new_content_id] = {}
            question_state_dict[
                'recorded_voiceovers'][
                    'voiceovers_mapping'][new_content_id] = {}

        return question_state_dict

    @classmethod
    def _convert_state_v36_dict_to_v37_dict(cls, question_state_dict):
        """Converts from version 36 to 37. Version 37 changes all rules with
        type CaseSensitiveEquals to Equals.

        Args:
            question_state_dict: dict. A dict where each key-value pair
                represents respectively, a state name and a dict used to
                initialize a State domain object.

        Returns:
            dict. The converted question_state_dict.
        """
        if question_state_dict['interaction']['id'] != 'TextInput':
            return question_state_dict
        answer_group_dicts = question_state_dict['interaction']['answer_groups']
        for answer_group_dict in answer_group_dicts:
            for rule_spec_dict in answer_group_dict['rule_specs']:
                if rule_spec_dict['rule_type'] == 'CaseSensitiveEquals':
                    rule_spec_dict['rule_type'] = 'Equals'

        return question_state_dict

    @classmethod
    def _convert_state_v37_dict_to_v38_dict(cls, question_state_dict):
        """Converts from version 37 to 38. Version 38 adds a customization arg
        for the Math interactions that allows creators to specify the letters
        that would be displayed to the learner.

        Args:
            question_state_dict: dict. A dict where each key-value pair
                represents respectively, a state name and a dict used to
                initialize a State domain object.

        Returns:
            dict. The converted question_state_dict.
        """
        if question_state_dict['interaction']['id'] in (
                'AlgebraicExpressionInput', 'MathEquationInput'):
            variables = set()
            for group in question_state_dict[
                    'interaction']['answer_groups']:
                for rule_spec in group['rule_specs']:
                    rule_input = rule_spec['inputs']['x']
                    for variable in expression_parser.get_variables(
                            rule_input):
                        # Replacing greek letter names with greek symbols.
                        if len(variable) > 1:
                            variable = (
                                constants.GREEK_LETTER_NAMES_TO_SYMBOLS[
                                    variable])
                        variables.add(variable)

            customization_args = question_state_dict[
                'interaction']['customization_args']
            customization_args.update({
                'customOskLetters': {
                    'value': sorted(variables)
                }
            })

        return question_state_dict

    @classmethod
    def _convert_state_v38_dict_to_v39_dict(cls, question_state_dict):
        """Converts from version 38 to 39. Version 39 adds a new
        customization arg to NumericExpressionInput interaction which allows
        creators to modify the placeholder text.

        Args:
            question_state_dict: dict. A dict where each key-value pair
                represents respectively, a state name and a dict used to
                initialize a State domain object.

        Returns:
            dict. The converted question_state_dict.
        """
        if question_state_dict['interaction']['id'] == 'NumericExpressionInput':
            customization_args = question_state_dict[
                'interaction']['customization_args']
            customization_args.update({
                'placeholder': {
                    'value': {
                        'content_id': 'ca_placeholder_0',
                        'unicode_str': (
                            'Type an expression here, using only numbers.')
                    }
                }
            })
            question_state_dict['written_translations']['translations_mapping'][
                'ca_placeholder_0'] = {}
            question_state_dict['recorded_voiceovers']['voiceovers_mapping'][
                'ca_placeholder_0'] = {}

        return question_state_dict

    @classmethod
    def _convert_state_v39_dict_to_v40_dict(cls, question_state_dict):
        """Converts from version 39 to 40. Version 40 converts TextInput rule
        inputs from NormalizedString to SetOfNormalizedString.

        Args:
            question_state_dict: dict. A dict where each key-value pair
                represents respectively, a state name and a dict used to
                initialize a State domain object.

        Returns:
            dict. The converted question_state_dict.
        """
        if question_state_dict['interaction']['id'] != 'TextInput':
            return question_state_dict

        answer_group_dicts = question_state_dict['interaction']['answer_groups']
        for answer_group_dict in answer_group_dicts:
            rule_type_to_inputs = collections.defaultdict(set)
            for rule_spec_dict in answer_group_dict['rule_specs']:
                rule_type = rule_spec_dict['rule_type']
                rule_inputs = rule_spec_dict['inputs']['x']
                rule_type_to_inputs[rule_type].add(rule_inputs)
            answer_group_dict['rule_specs'] = [{
                'rule_type': rule_type,
                'inputs': {'x': list(rule_type_to_inputs[rule_type])}
            } for rule_type in rule_type_to_inputs]

        return question_state_dict

    @classmethod
    def _convert_state_v40_dict_to_v41_dict(cls, question_state_dict):
        """Converts from version 40 to 41. Version 41 adds
        TranslatableSetOfUnicodeString and TranslatableSetOfNormalizedString
        objects to RuleSpec domain objects to allow for translations.

        Args:
            question_state_dict: dict. A dict where each key-value pair
                represents respectively, a state name and a dict used to
                initialize a State domain object.

        Returns:
            dict. The converted question_state_dict.
        """
        class ContentIdCounter:
            """This helper class is used to keep track of
            next_content_id_index and new_content_ids, and provides a
            function to generate new content_ids.
            """

            def __init__(self, next_content_id_index):
                """Initializes a ContentIdCounter object.

                Args:
                    next_content_id_index: int. The next content id index.
                """
                self.new_content_ids = []
                self.next_content_id_index = next_content_id_index

            def generate_content_id(self, content_id_prefix):
                """Generate a new content_id from the prefix provided and
                the next content id index.

                Args:
                    content_id_prefix: str. The prefix of the content_id.

                Returns:
                    str. The generated content_id.
                """
                content_id = '%s%i' % (
                    content_id_prefix,
                    self.next_content_id_index)
                self.next_content_id_index += 1
                self.new_content_ids.append(content_id)
                return content_id

        # As of Jan 2021, which is when this migration is to be run, only
        # TextInput and SetInput have translatable rule inputs, and every rule
        # for these interactions takes exactly one translatable input named x.
        interaction_id = question_state_dict['interaction']['id']
        if interaction_id not in ['TextInput', 'SetInput']:
            return question_state_dict

        content_id_counter = ContentIdCounter(
            question_state_dict['next_content_id_index'])
        answer_group_dicts = question_state_dict['interaction']['answer_groups']
        for answer_group_dict in answer_group_dicts:
            for rule_spec_dict in answer_group_dict['rule_specs']:
                content_id = content_id_counter.generate_content_id(
                    'rule_input_')
                if interaction_id == 'TextInput':
                    # Convert to TranslatableSetOfNormalizedString.
                    rule_spec_dict['inputs']['x'] = {
                        'contentId': content_id,
                        'normalizedStrSet': rule_spec_dict['inputs']['x']
                    }
                elif interaction_id == 'SetInput':
                    # Convert to TranslatableSetOfUnicodeString.
                    rule_spec_dict['inputs']['x'] = {
                        'contentId': content_id,
                        'unicodeStrSet': rule_spec_dict['inputs']['x']
                    }
        question_state_dict['next_content_id_index'] = (
            content_id_counter.next_content_id_index)
        for new_content_id in content_id_counter.new_content_ids:
            question_state_dict[
                'written_translations'][
                    'translations_mapping'][new_content_id] = {}
            question_state_dict[
                'recorded_voiceovers'][
                    'voiceovers_mapping'][new_content_id] = {}

        return question_state_dict

    @classmethod
    def _convert_state_v41_dict_to_v42_dict(cls, question_state_dict):
        """Converts from version 41 to 42. Version 42 changes rule input types
        for DragAndDropSortInput and ItemSelectionInput interactions to better
        support translations. Specifically, the rule inputs will store content
        ids of the html rather than the raw html. Solution answers for
        DragAndDropSortInput and ItemSelectionInput interactions are also
        updated.

        Args:
            question_state_dict: dict. A dict where each key-value pair
                represents respectively, a state name and a dict used to
                initialize a State domain object.

        Returns:
            dict. The converted question_state_dict.
        """

        def migrate_rule_inputs_and_answers(new_type, value, choices):
            """Migrates SetOfHtmlString to SetOfTranslatableHtmlContentIds,
            ListOfSetsOfHtmlStrings to ListOfSetsOfTranslatableHtmlContentIds,
            and DragAndDropHtmlString to TranslatableHtmlContentId. These
            migrations are necessary to have rules work easily for multiple
            languages; instead of comparing html for equality, we compare
            content_ids for equality.

            Args:
                new_type: str. The type to migrate to.
                value: *. The value to migrate.
                choices: list(dict). The list of subtitled html dicts to extract
                    content ids from.

            Returns:
                *. The migrated rule input.
            """

            def extract_content_id_from_choices(html):
                """Given a html, find its associated content id in choices,
                which is a list of subtitled html dicts.

                Args:
                    html: str. The html to find the content id of.

                Returns:
                    str. The content id of html.
                """
                for subtitled_html_dict in choices:
                    if subtitled_html_dict['html'] == html:
                        return subtitled_html_dict['content_id']
                # If there is no match, we discard the rule input. The frontend
                # will handle invalid content ids similar to how it handled
                # non-matching html.
                return feconf.INVALID_CONTENT_ID

            if new_type == 'TranslatableHtmlContentId':
                return extract_content_id_from_choices(value)
            elif new_type == 'SetOfTranslatableHtmlContentIds':
                return [
                    migrate_rule_inputs_and_answers(
                        'TranslatableHtmlContentId', html, choices
                    ) for html in value
                ]
            elif new_type == 'ListOfSetsOfTranslatableHtmlContentIds':
                return [
                    migrate_rule_inputs_and_answers(
                        'SetOfTranslatableHtmlContentIds', html_set, choices
                    ) for html_set in value
                ]

        interaction_id = question_state_dict['interaction']['id']
        if interaction_id not in [
                'DragAndDropSortInput', 'ItemSelectionInput']:
            return question_state_dict

        solution = question_state_dict['interaction']['solution']
        choices = question_state_dict['interaction']['customization_args'][
            'choices']['value']

        if interaction_id == 'ItemSelectionInput':
            # The solution type will be migrated from SetOfHtmlString to
            # SetOfTranslatableHtmlContentIds.
            if solution is not None:
                solution['correct_answer'] = (
                    migrate_rule_inputs_and_answers(
                        'SetOfTranslatableHtmlContentIds',
                        solution['correct_answer'],
                        choices)
                )
        if interaction_id == 'DragAndDropSortInput':
            # The solution type will be migrated from ListOfSetsOfHtmlString
            # to ListOfSetsOfTranslatableHtmlContentIds.
            if solution is not None:
                solution['correct_answer'] = (
                    migrate_rule_inputs_and_answers(
                        'ListOfSetsOfTranslatableHtmlContentIds',
                        solution['correct_answer'],
                        choices)
                )

        answer_group_dicts = question_state_dict['interaction']['answer_groups']
        for answer_group_dict in answer_group_dicts:
            for rule_spec_dict in answer_group_dict['rule_specs']:
                rule_type = rule_spec_dict['rule_type']
                rule_inputs = rule_spec_dict['inputs']

                if interaction_id == 'ItemSelectionInput':
                    # All rule inputs for ItemSelectionInput will be
                    # migrated from SetOfHtmlString to
                    # SetOfTranslatableHtmlContentIds.
                    rule_inputs['x'] = migrate_rule_inputs_and_answers(
                        'SetOfTranslatableHtmlContentIds',
                        rule_inputs['x'],
                        choices)
                if interaction_id == 'DragAndDropSortInput':
                    rule_types_with_list_of_sets = [
                        'IsEqualToOrdering',
                        'IsEqualToOrderingWithOneItemAtIncorrectPosition'
                    ]
                    if rule_type in rule_types_with_list_of_sets:
                        # For rule type IsEqualToOrdering and
                        # IsEqualToOrderingWithOneItemAtIncorrectPosition,
                        # the x input will be migrated from
                        # ListOfSetsOfHtmlStrings to
                        # ListOfSetsOfTranslatableHtmlContentIds.
                        rule_inputs['x'] = migrate_rule_inputs_and_answers(
                            'ListOfSetsOfTranslatableHtmlContentIds',
                            rule_inputs['x'],
                            choices)
                    elif rule_type == 'HasElementXAtPositionY':
                        # For rule type HasElementXAtPositionY,
                        # the x input will be migrated from
                        # DragAndDropHtmlString to
                        # TranslatableHtmlContentId, and the y input will
                        # remain as DragAndDropPositiveInt.
                        rule_inputs['x'] = migrate_rule_inputs_and_answers(
                            'TranslatableHtmlContentId',
                            rule_inputs['x'],
                            choices)
                    elif rule_type == 'HasElementXBeforeElementY':
                        # For rule type HasElementXBeforeElementY,
                        # the x and y inputs will be migrated from
                        # DragAndDropHtmlString to
                        # TranslatableHtmlContentId.
                        for rule_input_name in ['x', 'y']:
                            rule_inputs[rule_input_name] = (
                                migrate_rule_inputs_and_answers(
                                    'TranslatableHtmlContentId',
                                    rule_inputs[rule_input_name],
                                    choices))

        return question_state_dict

    @classmethod
    def _convert_state_v42_dict_to_v43_dict(cls, question_state_dict):
        """Converts from version 42 to 43. Version 43 adds a new customization
        arg to NumericExpressionInput, AlgebraicExpressionInput, and
        MathEquationInput. The customization arg will allow creators to choose
        whether to render the division sign (÷) instead of a fraction for the
        division operation.

        Args:
            question_state_dict: dict. A dict where each key-value pair
                represents respectively, a state name and a dict used to
                initialize a State domain object.

        Returns:
            dict. The converted question_state_dict.
        """
        if question_state_dict['interaction']['id'] in [
                'NumericExpressionInput', 'AlgebraicExpressionInput',
                'MathEquationInput']:
            customization_args = question_state_dict[
                'interaction']['customization_args']
            customization_args.update({
                'useFractionForDivision': {
                    'value': True
                }
            })

        return question_state_dict

    @classmethod
    def _convert_state_v43_dict_to_v44_dict(cls, question_state_dict):
        """Converts from version 43 to version 44. Version 44 adds
        card_is_checkpoint boolean to the state, which allows creators to
        mark a state as a checkpoint for the learners.

        Args:
            question_state_dict: dict. A dict representation of
                question_state_data.

        Returns:
            dict. The converted question_state_dict.
        """
        question_state_dict['card_is_checkpoint'] = False
        return question_state_dict

    @classmethod
    def _convert_state_v44_dict_to_v45_dict(cls, question_state_dict):
        """Converts from version 44 to 45. Version 45 contains
        linked skil id.

        Args:
            question_state_dict: dict. A dict where each key-value pair
                represents respectively, a state name and a dict used to
                initialize a State domain object.

        Returns:
            dict. The converted states_dict.
        """

        question_state_dict['linked_skill_id'] = None

        return question_state_dict

    @classmethod
    def _convert_state_v45_dict_to_v46_dict(cls, question_state_dict):
        """Converts from version 45 to 46. Version 46 ensures that the written
        translations in a state containing unicode content do not contain HTML
        tags and the data_format is unicode. This does not affect questions, so
        no conversion is required.

        Args:
            question_state_dict: dict. A dict where each key-value pair
                represents respectively, a state name and a dict used to
                initialize a State domain object.

        Returns:
            dict. The converted states_dict.
        """

        return question_state_dict

    @classmethod
    def _convert_state_v46_dict_to_v47_dict(cls, question_state_dict):
        """Converts from version 46 to 47. Version 52 deprecates
        oppia-noninteractive-svgdiagram tag and converts existing occurences of
        it to oppia-noninteractive-image tag.

        Args:
            question_state_dict: dict. A dict where each key-value pair
                represents respectively, a state name and a dict used to
                initialize a State domain object.

        Returns:
            dict. The converted states_dict.
        """

        state_domain.State.convert_html_fields_in_state(
            question_state_dict,
            html_validation_service.convert_svg_diagram_tags_to_image_tags)
        return question_state_dict

    @classmethod
    def _convert_state_v47_dict_to_v48_dict(cls, question_state_dict):
        """Converts draft change list from state version 47 to 48. Version 48
        fixes encoding issues in HTML fields.

        Args:
            question_state_dict: dict. A dict where each key-value pair
                represents respectively, a state name and a dict used to
                initialize a State domain object.

        Returns:
            dict. The converted states_dict.
        """

        state_domain.State.convert_html_fields_in_state(
            question_state_dict,
            html_validation_service.fix_incorrectly_encoded_chars,
            state_schema_version=48)
        return question_state_dict

    @classmethod
    def _convert_state_v48_dict_to_v49_dict(cls, question_state_dict):
        """Converts from version 48 to 49. Version 49 adds
        requireNonnegativeInput customization arg to NumericInput
        interaction which allows creators to set input range greater than
        or equal to zero.

        Args:
            question_state_dict: dict. A dict where each key-value pair
                represents respectively, a state name and a dict used to
                initialize a State domain object.

        Returns:
            dict. The converted question_state_dict.
        """
        if question_state_dict['interaction']['id'] == 'NumericInput':
            customization_args = question_state_dict[
                'interaction']['customization_args']
            customization_args.update({
                'requireNonnegativeInput': {
                    'value': False
                }
            })
        return question_state_dict

    @classmethod
    def update_state_from_model(
            cls, versioned_question_state, current_state_schema_version):
        """Converts the state object contained in the given
        versioned_question_state dict from current_state_schema_version to
        current_state_schema_version + 1.
        Note that the versioned_question_state being passed in is modified
        in-place.

        Args:
            versioned_question_state: dict. A dict with two keys:
                - state_schema_version: int. The state schema version for the
                    question.
                - state: The State domain object representing the question
                    state data.
            current_state_schema_version: int. The current state
                schema version.
        """
        versioned_question_state['state_schema_version'] = (
            current_state_schema_version + 1)

        conversion_fn = getattr(cls, '_convert_state_v%s_dict_to_v%s_dict' % (
            current_state_schema_version, current_state_schema_version + 1))

        versioned_question_state['state'] = conversion_fn(
            versioned_question_state['state'])

    def partial_validate(self):
        """Validates the Question domain object, but doesn't require the
        object to contain an ID and a version. To be used to validate the
        question before it is finalized.
        """

        if not isinstance(self.language_code, str):
            raise utils.ValidationError(
                'Expected language_code to be a string, received %s' %
                self.language_code)

        if not self.linked_skill_ids:
            raise utils.ValidationError(
                'linked_skill_ids is either null or an empty list')

        if not (isinstance(self.linked_skill_ids, list) and (
                all(isinstance(elem, str) for elem in (
                    self.linked_skill_ids)))):
            raise utils.ValidationError(
                'Expected linked_skill_ids to be a list of strings, '
                'received %s' % self.linked_skill_ids)

        if len(set(self.linked_skill_ids)) != len(self.linked_skill_ids):
            raise utils.ValidationError(
                'linked_skill_ids has duplicate skill ids')
        inapplicable_skill_misconception_ids_is_list = isinstance(
            self.inapplicable_skill_misconception_ids, list)
        if not (inapplicable_skill_misconception_ids_is_list and (
                all(isinstance(elem, str) for elem in (
                        self.inapplicable_skill_misconception_ids)))):
            raise utils.ValidationError(
                'Expected inapplicable_skill_misconception_ids to be a list '
                'of strings, received %s'
                % self.inapplicable_skill_misconception_ids)

        if not (all(
                re.match(
                    constants.VALID_SKILL_MISCONCEPTION_ID_REGEX, elem
                ) for elem in self.inapplicable_skill_misconception_ids)):
            raise utils.ValidationError(
                'Expected inapplicable_skill_misconception_ids to be a list '
                'of strings of the format <skill_id>-<misconception_id>, '
                'received %s' % self.inapplicable_skill_misconception_ids)

        if len(set(self.inapplicable_skill_misconception_ids)) != len(
                self.inapplicable_skill_misconception_ids):
            raise utils.ValidationError(
                'inapplicable_skill_misconception_ids has duplicate values')

        if not isinstance(self.question_state_data_schema_version, int):
            raise utils.ValidationError(
                'Expected schema version to be an integer, received %s' %
                self.question_state_data_schema_version)

        if not isinstance(self.question_state_data, state_domain.State):
            raise utils.ValidationError(
                'Expected question state data to be a State object, '
                'received %s' % self.question_state_data)

        if not utils.is_valid_language_code(self.language_code):
            raise utils.ValidationError(
                'Invalid language code: %s' % self.language_code)

        interaction_specs = interaction_registry.Registry.get_all_specs()
        at_least_one_correct_answer = False
        dest_is_specified = False
        interaction = self.question_state_data.interaction
        for answer_group in interaction.answer_groups:
            if answer_group.outcome.labelled_as_correct:
                at_least_one_correct_answer = True
            if answer_group.outcome.dest is not None:
                dest_is_specified = True

        if interaction.default_outcome.labelled_as_correct:
            at_least_one_correct_answer = True

        if interaction.default_outcome.dest is not None:
            dest_is_specified = True

        if not at_least_one_correct_answer:
            raise utils.ValidationError(
                'Expected at least one answer group to have a correct ' +
                'answer.'
            )

        if dest_is_specified:
            raise utils.ValidationError(
                'Expected all answer groups to have destination as None.'
            )

        if not interaction.hints:
            raise utils.ValidationError(
                'Expected the question to have at least one hint')

        if (
                (interaction.solution is None) and
                (interaction_specs[interaction.id]['can_have_solution'])):
            raise utils.ValidationError(
                'Expected the question to have a solution'
            )
        self.question_state_data.validate({}, False)

    def validate(self):
        """Validates the Question domain object before it is saved."""

        if not isinstance(self.id, str):
            raise utils.ValidationError(
                'Expected ID to be a string, received %s' % self.id)

        if not isinstance(self.version, int):
            raise utils.ValidationError(
                'Expected version to be an integer, received %s' %
                self.version)

        self.partial_validate()

    @classmethod
    def from_dict(cls, question_dict):
        """Returns a Question domain object from dict.

        Returns:
            Question. The corresponding Question domain object.
        """
        question = cls(
            question_dict['id'],
            state_domain.State.from_dict(question_dict['question_state_data']),
            question_dict['question_state_data_schema_version'],
            question_dict['language_code'], question_dict['version'],
            question_dict['linked_skill_ids'],
            question_dict['inapplicable_skill_misconception_ids'])

        return question

    @classmethod
    def create_default_question(cls, question_id, skill_ids):
        """Returns a Question domain object with default values.

        Args:
            question_id: str. The unique ID of the question.
            skill_ids: list(str). List of skill IDs attached to this question.

        Returns:
            Question. A Question domain object with default values.
        """
        default_question_state_data = cls.create_default_question_state()

        return cls(
            question_id, default_question_state_data,
            feconf.CURRENT_STATE_SCHEMA_VERSION,
            constants.DEFAULT_LANGUAGE_CODE, 0, skill_ids, [])

    def update_language_code(self, language_code):
        """Updates the language code of the question.

        Args:
            language_code: str. The ISO 639-1 code for the language this
                question is written in.
        """
        self.language_code = language_code

    def update_linked_skill_ids(self, linked_skill_ids):
        """Updates the linked skill ids of the question.

        Args:
            linked_skill_ids: list(str). The skill ids linked to the question.
        """
        self.linked_skill_ids = list(set(linked_skill_ids))

    def update_inapplicable_skill_misconception_ids(
            self, inapplicable_skill_misconception_ids):
        """Updates the optional misconception ids marked as not applicable
        to the question.

        Args:
            inapplicable_skill_misconception_ids: list(str). The optional
                skill misconception ids marked as not applicable to the
                question.
        """
        self.inapplicable_skill_misconception_ids = list(
            set(inapplicable_skill_misconception_ids))

    def update_question_state_data(self, question_state_data):
        """Updates the question data of the question.

        Args:
            question_state_data: State. A State domain object
                representing the question state data.
        """
        self.question_state_data = question_state_data

class QuestionSummary:
    """Domain object for Question Summary."""

    def __init__(
            self, question_id, question_content, misconception_ids,
            interaction_id, question_model_created_on=None,
            question_model_last_updated=None):
        """Constructs a Question Summary domain object.

        Args:
            question_id: str. The ID of the question.
            question_content: str. The static HTML of the question shown to
                the learner.
            misconception_ids: str. The misconception ids addressed in
                the question. This includes tagged misconceptions ids as well
                as inapplicable misconception ids in the question.
            interaction_id: str. The ID of the interaction.
            question_model_created_on: datetime.datetime. Date and time when
                the question model is created.
            question_model_last_updated: datetime.datetime. Date and time
                when the question model was last updated.
        """
        self.id = question_id
        self.question_content = html_cleaner.clean(question_content)
        self.misconception_ids = misconception_ids
        self.interaction_id = interaction_id
        self.created_on = question_model_created_on
        self.last_updated = question_model_last_updated

    def to_dict(self):
        """Returns a dictionary representation of this domain object.

        Returns:
            dict. A dict representing this QuestionSummary object.
        """
        return {
            'id': self.id,
            'question_content': self.question_content,
            'interaction_id': self.interaction_id,
            'last_updated_msec': utils.get_time_in_millisecs(self.last_updated),
            'created_on_msec': utils.get_time_in_millisecs(self.created_on),
            'misconception_ids': self.misconception_ids
        }

    def validate(self):
        """Validates the Question summary domain object before it is saved.

        Raises:
            ValidationError. One or more attributes of question summary are
                invalid.
        """
        if not isinstance(self.id, str):
            raise utils.ValidationError(
                'Expected id to be a string, received %s' % self.id)

        if not isinstance(self.question_content, str):
            raise utils.ValidationError(
                'Expected question content to be a string, received %s' %
                self.question_content)

        if not isinstance(self.interaction_id, str):
            raise utils.ValidationError(
                'Expected interaction id to be a string, received %s' %
                self.interaction_id)

        if not isinstance(self.created_on, datetime.datetime):
            raise utils.ValidationError(
                'Expected created on to be a datetime, received %s' %
                self.created_on)

        if not isinstance(self.last_updated, datetime.datetime):
            raise utils.ValidationError(
                'Expected last updated to be a datetime, received %s' %
                self.last_updated)

        if not (isinstance(self.misconception_ids, list) and (
                all(isinstance(elem, str) for elem in (
                    self.misconception_ids)))):
            raise utils.ValidationError(
                'Expected misconception ids to be a list of '
                'strings, received %s' % self.misconception_ids)

class QuestionSkillLink:
    """Domain object for Question Skill Link.

    Attributes:
        question_id: str. The ID of the question.
        skill_id: str. The ID of the skill to which the
            question is linked.
        skill_description: str. The description of the corresponding skill.
        skill_difficulty: float. The difficulty between [0, 1] of the skill.
    """

    def __init__(
            self, question_id, skill_id, skill_description, skill_difficulty):
        """Constructs a Question Skill Link domain object.

        Args:
            question_id: str. The ID of the question.
            skill_id: str. The ID of the skill to which the question is linked.
            skill_description: str. The description of the corresponding skill.
            skill_difficulty: float. The difficulty between [0, 1] of the skill.
        """
        self.question_id = question_id
        self.skill_id = skill_id
        self.skill_description = skill_description
        self.skill_difficulty = skill_difficulty

    def to_dict(self):
        """Returns a dictionary representation of this domain object.

        Returns:
            dict. A dict representing this QuestionSkillLink object.
        """
        return {
            'question_id': self.question_id,
            'skill_id': self.skill_id,
            'skill_description': self.skill_description,
            'skill_difficulty': self.skill_difficulty,
        }

class MergedQuestionSkillLink:
    """Domain object for the Merged Question Skill Link object, returned to the
    editors.

    Attributes:
        question_id: str. The ID of the question.
        skill_ids: list(str). The skill IDs of the linked skills.
        skill_descriptions: list(str). The descriptions of the skills to which
            the question is linked.
        skill_difficulties: list(float). The difficulties between [0, 1] of the
            skills.
    """

    def __init__(
            self, question_id, skill_ids, skill_descriptions,
            skill_difficulties):
        """Constructs a Merged Question Skill Link domain object.

        Args:
            question_id: str. The ID of the question.
            skill_ids: list(str). The skill IDs of the linked skills.
            skill_descriptions: list(str). The descriptions of the skills to
                which the question is linked.
            skill_difficulties: list(float). The difficulties between [0, 1] of
                the skills.
        """
        self.question_id = question_id
        self.skill_ids = skill_ids
        self.skill_descriptions = skill_descriptions
        self.skill_difficulties = skill_difficulties

    def to_dict(self):
        """Returns a dictionary representation of this domain object.

        Returns:
            dict. A dict representing this MergedQuestionSkillLink object.
        """
        return {
            'question_id': self.question_id,
            'skill_ids': self.skill_ids,
            'skill_descriptions': self.skill_descriptions,
            'skill_difficulties': self.skill_difficulties,
        }


text:
module EV3r
   class RunMotor < Motor

      def reset
         position 0
      end

      def start(speed=450)
         pulses_per_second speed
         run 1
      end

      def stop
         run 0
      end

   def initialize(port)
      super port

      run_mode :forever
      stop_mode :brake
      regulation_mode :on
      ramp_up 300
      ramp_down 300
   end

end
end

redpajama_set_name: RedPajamaGithub


text:
package uk.ac.ebi.spot.goci.service;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.InvalidOperationException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.io.IOException;

/**
 * Created by emma on 13/04/2016.
 *
 * @author emma
 *         <p>
 *         Create sheet from file, this is then used to read through each row
 */
@Lazy
@Service
public class SheetCreationService {

    public XSSFSheet createSheet(String fileName) throws InvalidFormatException, IOException,
                                                         InvalidOperationException {
        // Open file
        OPCPackage pkg = OPCPackage.open(fileName);
        XSSFWorkbook current = new XSSFWorkbook(pkg);
        pkg.close();
        return current.getSheetAt(0);
    }
}


text:
title: "Speech"
tags: ena5.2 etusivu
---

Puheen ohjeet ja aihevaihtoehdot löytyvät nyt portfolio-ohjeiden alta, kun kelaat alaspäin. Lue ohjeet tarkasti ja käy lukemassa annetut linkit ennen kirjoittamista.


text:
// Code generated by informer-gen. DO NOT EDIT.

package flowcontrol

import (
	v1alpha1 "k8s.io/client-go/informers/flowcontrol/v1alpha1"
	v1beta1 "k8s.io/client-go/informers/flowcontrol/v1beta1"
	v1beta2 "k8s.io/client-go/informers/flowcontrol/v1beta2"
	v1beta3 "k8s.io/client-go/informers/flowcontrol/v1beta3"
	internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
)

// Interface provides access to each of this group's versions.
type Interface interface {
	// V1alpha1 provides access to shared informers for resources in V1alpha1.
	V1alpha1() v1alpha1.Interface
	// V1beta1 provides access to shared informers for resources in V1beta1.
	V1beta1() v1beta1.Interface
	// V1beta2 provides access to shared informers for resources in V1beta2.
	V1beta2() v1beta2.Interface
	// V1beta3 provides access to shared informers for resources in V1beta3.
	V1beta3() v1beta3.Interface
}

type group struct {
	factory          internalinterfaces.SharedInformerFactory
	namespace        string
	tweakListOptions internalinterfaces.TweakListOptionsFunc
}

// New returns a new Interface.
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
	return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}

// V1alpha1 returns a new v1alpha1.Interface.
func (g *group) V1alpha1() v1alpha1.Interface {
	return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions)
}

// V1beta1 returns a new v1beta1.Interface.
func (g *group) V1beta1() v1beta1.Interface {
	return v1beta1.New(g.factory, g.namespace, g.tweakListOptions)
}

// V1beta2 returns a new v1beta2.Interface.
func (g *group) V1beta2() v1beta2.Interface {
	return v1beta2.New(g.factory, g.namespace, g.tweakListOptions)
}

// V1beta3 returns a new v1beta3.Interface.
func (g *group) V1beta3() v1beta3.Interface {
	return v1beta3.New(g.factory, g.namespace, g.tweakListOptions)
}


text:
package com.smartdevicelink.test.rpc.requests;

import com.smartdevicelink.marshal.JsonRPCMarshaller;
import com.smartdevicelink.protocol.enums.FunctionID;
import com.smartdevicelink.proxy.RPCMessage;
import com.smartdevicelink.proxy.rpc.CancelInteraction;
import com.smartdevicelink.test.BaseRpcTests;
import com.smartdevicelink.test.JsonUtils;
import com.smartdevicelink.test.TestValues;
import com.smartdevicelink.test.json.rpc.JsonFileReader;

import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Test;

import java.util.Hashtable;

import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertNotNull;
import static junit.framework.TestCase.assertNull;
import static junit.framework.TestCase.fail;

/**
 * This is a unit test class for the SmartDeviceLink library project class :
 * {@link com.smartdevicelink.proxy.rpc.CancelInteraction}
 */
public class CancelInteractionTests extends BaseRpcTests {

    @Override
    protected RPCMessage createMessage() {
        CancelInteraction msg = new CancelInteraction();
        msg.setInteractionFunctionID(TestValues.GENERAL_INTEGER);
        msg.setCancelID(TestValues.GENERAL_INTEGER);
        return msg;
    }

    @Override
    protected String getMessageType() {
        return RPCMessage.KEY_REQUEST;
    }

    @Override
    protected String getCommandType() {
        return FunctionID.CANCEL_INTERACTION.toString();
    }

    @Override
    protected JSONObject getExpectedParameters(int sdlVersion) {
        JSONObject result = new JSONObject();

        try {
            result.put(CancelInteraction.KEY_FUNCTION_ID, TestValues.GENERAL_INTEGER);
            result.put(CancelInteraction.KEY_CANCEL_ID, TestValues.GENERAL_INTEGER);
        } catch (JSONException e) {
            fail(TestValues.JSON_FAIL);
        }

        return result;
    }

    /**
     * Tests the expected values of the RPC message.
     */
    @Test
    public void testRpcValues() {
        // Test Values
        Integer testFunctionID = ((CancelInteraction) msg).getInteractionFunctionID();
        Integer testCancelID = ((CancelInteraction) msg).getCancelID();

        // Valid Tests
        assertEquals(TestValues.MATCH, TestValues.GENERAL_INTEGER, testFunctionID);
        assertEquals(TestValues.MATCH, TestValues.GENERAL_INTEGER, testCancelID);

        // Invalid/Null Tests
        CancelInteraction msg = new CancelInteraction();
        assertNotNull(TestValues.NOT_NULL, msg);
        testNullBase(msg);

        assertNull(TestValues.NULL, msg.getInteractionFunctionID());
        assertNull(TestValues.NULL, msg.getCancelID());
    }

    /**
     * Tests a valid JSON construction of this RPC message.
     */
    @Test
    public void testJsonConstructor() {
        JSONObject commandJson = JsonFileReader.readId(getInstrumentation().getTargetContext(), getCommandType(), getMessageType());
        assertNotNull(TestValues.NOT_NULL, commandJson);

        try {
            Hashtable<String, Object> hash = JsonRPCMarshaller.deserializeJSONObject(commandJson);
            CancelInteraction cmd = new CancelInteraction(hash);
            JSONObject body = JsonUtils.readJsonObjectFromJsonObject(commandJson, getMessageType());
            assertNotNull(TestValues.NOT_NULL, body);

            // Test everything in the json body.
            assertEquals(TestValues.MATCH, JsonUtils.readStringFromJsonObject(body, RPCMessage.KEY_FUNCTION_NAME), cmd.getFunctionName());
            assertEquals(TestValues.MATCH, JsonUtils.readIntegerFromJsonObject(body, RPCMessage.KEY_CORRELATION_ID), cmd.getCorrelationID());
            JSONObject parameters = JsonUtils.readJsonObjectFromJsonObject(body, RPCMessage.KEY_PARAMETERS);

            assertEquals(TestValues.MATCH, JsonUtils.readIntegerFromJsonObject(parameters, CancelInteraction.KEY_FUNCTION_ID), cmd.getInteractionFunctionID());
            assertEquals(TestValues.MATCH, JsonUtils.readIntegerFromJsonObject(parameters, CancelInteraction.KEY_CANCEL_ID), cmd.getCancelID());
        } catch (JSONException e) {
            fail(TestValues.JSON_FAIL);
        }
    }
}


text:
[![Crates.io](https://img.shields.io/crates/d/bio.svg?style=flat-square)](https://crates.io/crates/bio)
[![Crates.io](https://img.shields.io/crates/v/bio.svg?style=flat-square)](https://crates.io/crates/bio)
[![Crates.io](https://img.shields.io/crates/l/bio.svg?style=flat-square)](https://crates.io/crates/bio)
[![Travis](https://img.shields.io/travis/rust-bio/rust-bio/master.svg?style=flat-square)](https://travis-ci.org/rust-bio/rust-bio)
[![Coveralls](https://img.shields.io/coveralls/rust-bio/rust-bio.svg?style=flat-square)](https://coveralls.io/github/rust-bio/rust-bio)

# Rust-Bio, a bioinformatics library for Rust.

This library provides implementations of many algorithms and data structures
that are useful for bioinformatics.
All provided implementations are rigorously tested via continuous
integration.

**Please see the [homepage](https://rust-bio.github.io) for examples and documentation.**

Currently, rust-bio provides

* most major pattern matching algorithms,
* a convenient alphabet implementation,
* pairwise alignment,
* suffix arrays,
* BWT and FM-Index,
* FMD-Index for finding supermaximal exact matches,
* a q-gram index,
* an orf research algorithm,
* a rank/select data structure,
* [serde](https://github.com/serde-rs/serde) support for all data structures when built with `nightly` feature,
* FASTQ and FASTA and BED readers and writers,
* helper functions for combinatorics and dealing with log probabilities.

For reading and writing BAM and BCF files, have a look at https://github.com/christopher-schroeder/rust-htslib.

## Author

[Johannes Köster](https://github.com/johanneskoester)

## Contributors

* [Christopher Schröder](https://github.com/christopher-schroeder)
* [Peer Aramillo Irizar](https://github.com/parir)
* [Fedor Gusev](https://github.com/gusevfe)
* [Vadim Nazarov](https://github.com/vadimnazarov)
* [Brad Chapman](https://github.com/chapmanb)
* [Florian Gilcher](https://github.com/skade)
* [Erik Clarke](https://github.com/eclarke)
* [Rizky Luthfianto](https://github.com/rilut)
* [Adam Perry](https://github.com/dikaiosune)
* [Taylor Cramer](https://github.com/cramertj)
* [Andre Bogus](https://github.com/llogiq)
* [Martin Larralde](https://github.com/althonos)
* Philipp Angerer
* [Pierre Marijon](https://github.com/natir)
* [Franklin Delehelle](https://github.com/delehef)
* [Marcin Fatyga](https://github.com/rednum)
* [Patrick Marks](https://github.com/pmarks)

The next name in this list could be you! If you are interested in joining the effort to build a general purpose Rust bioinformatics library, just introduce yourself [here](https://github.com/rust-bio/rust-bio/issues/3), or issue a pull request with your first contribution.

## License

Licensed under the MIT license http://opensource.org/licenses/MIT. This project may not be copied, modified, or distributed except according to those terms.


text:
<?php

namespace phpstream\util;

use BadMethodCallException;
use Exception;
use InvalidArgumentException;
use phpstream\functions\UnaryFunction;
use phpstream\operators\MapOperator;

/**
 * A container object which may or may not contain a non-null value.
 *
 * If a value is present, isEmpty() will return `FALSE` and get() will return the value.
 */
abstract class Optional {

	/**
	 * Construct a new Optional instance
	 */
	protected function __construct() {}

	/**
	 * Returns an empty Optional instance.
	 *
	 * @return Optional An empty Optional instance.
	 */
	public static function absent(): Optional {
		return _optional\Absent::instance();
	}

	/**
	 * Returns an Optional instance containing the given non-null reference.
	 *
	 * @param mixed $reference Non-null reference to store.
	 *
	 * @return Optional An Optional instance containing the given reference.
	 *
	 * @throws InvalidArgumentException if given reference is null.
	 */
	public static function of(mixed $reference): Optional {
		if ($reference instanceof Optional)
			return $reference;

		return new _optional\Present(static::checkNotNull($reference));
	}

	/**
	 * Returns an empty Optional instance if given reference is null, an Optional instance containing
	 * the given reference otherwise.
	 *
	 * @param mixed $reference Reference to store.
	 *
	 * @return Optional An empty Optional instance or an Optional instance containing the given reference.
	 */
	public static function ofNullable(mixed $reference): Optional {
		if ($reference instanceof Optional)
			return $reference;

		return $reference === null ? static::absent() : new _optional\Present($reference);
	}

	/**
	 * Returns the Optional instance emptiness.
	 *
	 * @return boolean `TRUE` if the current Optional instance is empty, `FALSE` otherwise.
	 */
	public abstract function isEmpty(): bool;

	/**
	 * Returns the Optional instance completeness.
	 *
	 * @return boolean `TRUE` if the current Optional instance is not empty (contains any value), `FALSE` otherwise.
	 */
	public function isNotEmpty(): bool {
		return !$this->isEmpty();
	}

	/**
	 * Returns the contained reference for a non empty Optional instance, an Exception otherwise.
	 *
	 * @return mixed The contained reference for a non empty Optional instance.
	 *
	 * @throws BadMethodCallException If the current Optional instance is empty.
	 */
	public abstract function get(): mixed;

	/**
	 * Applying mapper on contained reference and return a new Optional element.
	 *
	 * @param callable|UnaryFunction|MapOperator|string $mapper Mapping function. If function is a string, use object property or method as mapper.
	 *
	 * @return Optional Optional instance containing mapped value or Absent.
	 */
	public abstract function map(callable|UnaryFunction|MapOperator|string $mapper): Optional;

	/**
	 * Returns the contained reference for a non empty Optional instance, the not-null default value otherwise.
	 *
	 * @param mixed $defaultValue The default value.
	 *
	 * @return mixed The contained reference for a non empty Optional instance or the default value.
	 *
	 * @throws InvalidArgumentException if default value is null.
	 */
	public abstract function orElse(mixed $defaultValue): mixed;

	/**
	 * Returns the contained reference for a non empty Optional instance, throw given exception otherwise.
	 *
	 * @param Exception $ex The exception to throw if empty
	 *
	 * @return mixed The contained reference for a non empty Optional instance or the default value.
	 *
	 * @throws Exception if default value is null.
	 */
	public abstract function orElseThrow(Exception $ex): mixed;

	/**
	 * Returns the contained reference for a non empty Optional instance, null otherwise.
	 *
	 * @return mixed The contained reference for a non empty Optional instance or `null`.
	 */
	public abstract function orNull(): mixed;

	/**
	 * Checks if current instance and given Optional instance contains same object.
	 *
	 * @param mixed $object Other object
	 *
	 * @return boolean `TRUE` if current instance and given Optional instance contains same object, `FALSE` otherwise.
	 *
	 * @ignore
	 */
	public abstract function equals(mixed $object): bool;

	/**
	 * Make sure the passed reference is not null.
	 *
	 * @param mixed $reference Reference to test.
	 * @param string|null $message Error message if reference is null
	 *
	 * @return mixed
	 *
	 * @throws InvalidArgumentException If reference is null.
	 */
	protected static function checkNotNull(mixed $reference, ?string $message = null): mixed {
		if ($message === null) {
			$message = "Disallowed null in reference found.";
		}

		if ($reference === null) {
			throw new InvalidArgumentException($message);
		}
		return $reference;
	}
}


text:
// Type definitions for Segment's analytics.js for Node.js
// Project: https://segment.com/docs/libraries/node/
// Definitions by: Andrew Fong <https://github.com/fongandrew>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped

export = AnalyticsNode.Analytics;

declare namespace AnalyticsNode {

  interface Integrations {
    [index: string]: boolean;
  }

  export class Analytics {
    constructor(writeKey: string, opts?: {
      flushAt?: number,
      flushAfter?: number
    });

    /* The identify method lets you tie a user to their actions and record
       traits about them. */
    identify(message: {
      userId: string | number;
      traits?: Object;
      timestamp?: Date;
      context?: Object;
      integrations?: Integrations;
    }): Analytics;

    /* The track method lets you record the actions your users perform. */
    track(message: {
      userId: string | number;
      event: string;
      properties?: Object;
      timestamp?: Date;
      context?: Object;
      integrations?: Integrations;
    }): Analytics;

    /* The page method lets you record page views on your website, along with
       optional extra information about the page being viewed. */
    page(message: {
      userId: string | number;
      category?: string;
      name?: string;
      properties?: Object;
      timestamp?: Date;
      context?: Object;
      integrations?: Integrations;
    }): Analytics;

    /* alias is how you associate one identity with another. */
    alias(message: {
      previousId: string | number;
      userId: string | number;
      integrations?: Integrations;
    }): Analytics;

    /* Group calls can be used to associate individual users with shared
       accounts or companies. */
    group(message: {
      userId: string | number;
      groupId: string | number;
      traits?: Object;
      context?: Object;
      timestamp?: Date;
      anonymous_id?: string | number;
      integrations?: Integrations;
    }): Analytics;

    /* Flush batched calls to make sure nothing is left in the queue */
    flush(fn?: (err: Error, batch: {
      batch: Array<{
        type: string;
      }>;
      messageId: string;
      sentAt: Date;
      timestamp: Date;
    }) => void): Analytics;
  }
}


text:
//Cleversafe open-source code header - Version 1.1 - December 1, 2006
//
//Cleversafe Dispersed Storage(TM) is software for secure, private and
//reliable storage of the world's data using information dispersal.
//
//Copyright (C) 2005-2007 Cleversafe, Inc.
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either version 2
//of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
//USA.
//
//Contact Information:
// Cleversafe, 10 W. 35th Street, 16th Floor #84,
// Chicago IL 60616
// email: licensing@cleversafe.org
//
//END-OF-HEADER
//-----------------------
//@author: John Quigley <jquigley@cleversafe.com>
//@date: January 1, 2008
//---------------------

package org.jscsi.scsi.tasks;

/**
 * Valid task attributes as defined in SAM-3 section 8.6.1.
 */
public enum TaskAttribute
{
   /**
    * If only SIMPLE QUEUE TAG messages are used, the target may execute the
    * commands in any order that is deemed desirable within the constraints of
    * the queue management algorithm specified in the control mode page (see
    * [SAM2, 8.3.3.1]).
    */
   SIMPLE,
   /**
    * If ORDERED QUEUE TAG messages are used, the target shall execute the
    * commands in the order received with respect to other commands received
    * with ORDERED QUEUE TAG messages. All commands received with a SIMPLE
    * QUEUE TAG message prior to a command received with an ORDERED QUEUE TAG
    * message, regardless of initiator, shall be executed before that command
    * with the ORDERED QUEUE TAG message. All commands received with a SIMPLE
    * QUEUE TAG message after a command received with an ORDERED QUEUE TAG
    * message, regardless of initiator, shall be executed after that command
    * with the ORDERED QUEUE TAG message.
    */
   ORDERED,
   /**
    * A command received with a HEAD OF QUEUE TAG message is placed first in
    * the queue, to be executed next. A command received with a HEAD OF QUEUE
    * TAG message shall be executed prior to any queued I/O process.
    * Consecutive commands received with HEAD OF QUEUE TAG messages are
    * executed in a last-in-first-out order.
    */
   HEAD_OF_QUEUE,
   /**
    * If accepted, a task having the ACA attribute shall be entered into the task set in the
    * enabled task state. There shall be no more than one ACA task per task set.
    */
   ACA;

}


text:
#ifndef PARTICLEAFFECTOR_H
#define PARTICLEAFFECTOR_H

#include <glm/glm.hpp>

#include <Engine/Behaviour/IBehaviour.hpp>
#include <Engine/Attribute/Transform.hpp>
#include <Engine/Attribute/ShaderProgram.hpp>

namespace Behaviour
{
	class ParticleAffector : public Engine::Behaviour::IBehaviour
	{
	public:
		/**
		 * Constructor.
		 *
		 * @param window Shared pointer to the window.
		 * @param resourceManager Shared pointer to the resource manager.
		 * @param sceneEventDispatcher Shared pointer to the scene's event
		 * dispatcher.
		 * @param gameObjectEventDispatcher Shared pointer to the game
		 * object's event dispatcher.
		 * @param gameObject Weak pointer to the Game Object that the
		 * behaviour is attached to.
		 * @param transformAttribute Shared pointer to the game object's
		 * transform attribute.
		 * @param shaderProgramAttribute Shared pointer to the game object's
		 * shader program attribute.
		 * @param timeToLive Time for the game object to live (in seconds).
		 * @param velocity The game object's velocity.
		 * @param startScale The initial scale for the game object.
		 * @param endScale The final scale for the game object.
		 */
		ParticleAffector(std::shared_ptr<Engine::Window> window,
			std::shared_ptr<Engine::ResourceManager> resourceManager,
			std::shared_ptr<Engine::EventDispatcher> sceneEventDispatcher,
			std::shared_ptr<Engine::EventDispatcher> gameObjectEventDispatcher,
			std::weak_ptr<Engine::GameObject> gameObject,
			std::shared_ptr<Engine::Attribute::Transform> transformAttribute,
			std::shared_ptr<Engine::Attribute::ShaderProgram> shaderProgramAttribute,
			double timeToLive,
			const glm::vec3& velocity,
			float startScale,
			float endScale);

		/**
		 * Destructor.
		 */
		~ParticleAffector();

		/**
		 * Transforms the game object.
		 */
		virtual void Update(double deltaTime);

	private:
		/**
		 * Returns the interpolated value from the starting value to the ending
		 * value by the current time and given total duration using exponential
		 * easing out.
		 *
		 * @param currentTime The current time.
		 * @param startValue The starting value.
		 * @param endValue The ending value.
		 * @param duration The total duration.
		 * @return Interpolated value using exponential easing out.
		 */
		static float EaseOutExponential(double currentTime, float startValue, float endValue, double duration);

	private:
		/**
		 * Shared pointer to the game object's transform attribute.
		 */
		std::shared_ptr<Engine::Attribute::Transform> m_transformAttribute;

		/**
		 * Shared pointer to the game object's shader program attribute.
		 */
		std::shared_ptr<Engine::Attribute::ShaderProgram> m_shaderProgramAttribute;

		/**
		 * The amount of time that the game object should live for (in seconds).
		 */
		double m_timeToLive;

		/**
		 * The game object's velocity.
		 */
		glm::vec3 m_velocity;

		/**
		 * The inital scale for the game object.
		 */
		float m_startScale;

		/**
		 * The final scale for the game object.
		 */
		float m_endScale;

		/**
		 * The amount of elapsed time (in seconds).
		 */
		double m_elapsedTime;
	};
}

#endif


text: Cheers Exercise NSS


text:
package javasmmr.zoowsome.models.animals;

/**
 *
 * @author Marius Bologa
 *
 */
public class Tuatara extends Reptile {
	/**
	 *
	 */
	private int legs = 4;
	/**
	 *
	 */
	private String nameT = " Triasic";

	/**
	 *
	 * @param maintenanceCost
	 *            How many hours per week each animal require.
	 *
	 * @param dangerPerc
	 *            How dangerous an animal is.
	 *
	 */
	public Tuatara(final double maintenanceCost, final double dangerPerc) {
		super(maintenanceCost, dangerPerc);

		setLaysEggs(true);
		setName(nameT);
		setNrOfLegs(legs);
	}

	/**
	 *
	 * @param name
	 *            The name of the tuatara.
	 * @param maintenanceCost
	 *            How many hours per week each animal require.
	 *
	 * @param dangerPerc
	 *            How dangerous an animal is.
	 */
	public Tuatara(final String name, final double maintenanceCost, final double dangerPerc) {
		super(maintenanceCost, dangerPerc);
		setLaysEggs(true);
		setName(name);
		setNrOfLegs(legs);
	}

}


text:
from simwrapper import Sim
from simserver import SimMgr

print "Testing sim mgr"
# Test Creation
mgr = SimMgr()

s1uuid = mgr.create()
assert len(mgr.list()) == 1

mgr.delete(s1uuid)
assert len(mgr.list()) == 0

print "Testing sim init"
# Test Sims themselves.
s = Sim()
s.init()
print "Testing sim getstate"
# tests that getting state at various times
# works as expected
r100 = s.getStateAt(100)
assert s.t == 100

r200 = s.getStateAt(200)
assert s.t == 200
assert r100 != r200

r100_2 = s.getStateAt(100)
assert s.t == 200
assert r100 == r100_2

print "Testing performaction"
# This blocks
s.performAction("eat", [50], 350, async=False)
assert s.t == 350

# This doesn't block
s.performAction("eat", [50], 500)
assert s.t == 350
s.waitTillIdle()
assert s.t == 500

"""
These tests are highly nondeterministic, they work when laptop is in power saving mode and cpu is slow.

"""
# Events happen in a priority Q fashion,
#   so that we don't have to wait for Future events to finish
#   before accessing already computed data.
#   Also this makes it harder to accidentally go back in time.
s.performAction("eat", [50], 10750)
# 1st eat starts executing since Q was empty prior to this.
s.performAction("eat", [50], 20900)
# 2nd eat gets queued up.
s.getStateAt(10700)
# 3. getState gets added to Q, and the above call blocks until it completes
assert s.t == 10750
# 1st eat has occured 1st, then getStateAt, then 2nd eat.
s.waitTillIdle()
assert s.t == 20900


text:
'use strict';

var Vec2 = acmejs.Vec2;
var random = acmejs.random;
var Color = acmejs.Color;
var Context = acmejs.Context;
var Entity = acmejs.Entity;
var Component = acmejs.Component;
var Registry = acmejs.Registry;
var Particle = acmejs.Particle;

Context.init(document.getElementById('game-1'));

var Renderer = acmejs.Renderer;
Context.renderer = new Renderer(Context.element.getElementsByClassName('game-canvas')[0], Vec2(480, 320));
Context.renderer.color = Color.black;
Context.createComponent('spriteCanvasRenderer');

/**
 * WhiteScene
 * @extends Component
 */
function WhiteScene() {
	Component.call(this);
	this.started = 0;
	this.velocity = 0;
	this.position = 0;
	this.grow = true;
}

var force = Vec2();

WhiteScene.prototype = {
	create: function() {
		this.velocity = 25;
		this.position = 10;
		this.grow = true;
		var gui = Context.components.sceneController.gui.addFolder('whiteScene');
		gui.add(this, 'velocity', 0, 100);
		gui.add(this, 'position', 0, 100);
		gui.add(this, 'grow');
		this.gui = gui;
	},

	dealloc: function() {
		Context.sceneController.gui.remove(this.gui);
		this.gui = null;
	},

	update: function(dt) {
		var input = Context.components.input;
		// console.log(input.touchState);
		if (input.touchState == 'began') {
			var emitter = this.entity.createChild('particleEmitter', {
				transform: {
					position: input.position
				},
				particleEmitter: {
					prefab: 'spark'
				}
			});
		}
		// if (input.touchState || input.keys.space) {
		// 	var factor = (this.grow) ? ((this.started += dt) + 1) : 1;
		// 	var i = 100 * dt * factor | 0;
		// 	var speed = 10;
		// 	while (i--) {
		// 		var spark = Prefab.create(this.entity, 'spark');
		// 		Vec2.variantCirc(Vec2.zero, speed * factor * this.velocity, impulse);
		// 		spark.components.body.applyForce(impulse);
		// 		Vec2.variantCirc(input.position, this.position,
		// 			spark.components.transform.position);
		// 		spark.components.particle.radius = random(2, 15);
		// 	}
		// } else if (this.started) {
		// 	this.started = 0;
		// }
	}
};

Component.create(WhiteScene, 'whiteScene');

Entity.createPrefab('spark', {
	transform: null,
	body: {
		mass: 0.1,
		fast: true,
		maxVelocity: 200,
		maxForce: 0
	},
	particle: {
		lifetime: 4,
		lifetimeVariance: 2,
		fade: null,
		shrink: null
	},
	spriteTween: {
		asset: Particle.generateSpriteSheet({
			color: Color(164, 164, 164),
			shape: 'rect'
		})
	},
	jitter: null
});

function ParticleEmitter() {
	Component.call(this);
	this.amount = 0;
	this.lifetime = 0.0;
	this.prefab = '';
	this.positionVariance = 0.0;
	this.force = 0.0;
	this.forceVariance = 0.0;
	this.radius = 0.0;
	this.radiusVariance = 0.0;
	this.age = 0.0;
}

ParticleEmitter.prototype = {
	attributes: {
		amount: 100,
		lifetime: 2,
		prefab: 'particle',
		positionVariance: 10,
		force: 10,
		forceVariance: 5,
		radius: 8,
		radiusVariance: 5
	},

	create: function() {
		this.age = 0.0;
	},

	update: function(dt) {
		this.age += dt;
		// if (this.age > dt) {
		if (this.age > this.lifetime) {
			if (this.entity.firstChild == null) {
				this.entity.destroy();
			}
			return;
		}
		// var l = dt * this.amount | 0;
		var l = 1;
		for (var i = 0; i < l; i++) {
			var particle = this.entity.createChild(this.prefab);
			Vec2.variantCirc(Vec2.zero, this.force, force);
			particle.components.body.applyForce(force);
			Vec2.variantCirc(Vec2.zero, this.positionVariance,
				particle.components.transform.position);
			particle.components.particle.radius = this.radius +
				random(-this.radiusVariance, this.radiusVariance);
		}
	}
};

Component.create(ParticleEmitter, 'particleEmitter');

Entity.createPrefab('particleEmitter', {
	transform: null,
	particleEmitter: null
});

/**
 * FireScene
 */
function FireScene() {
	Component.call(this);
}

FireScene.prototype = {
	create: function() {
		this.velocity = 25;
		var gui = Context.components.sceneController.gui.addFolder('fireScene');
		gui.add(this, 'velocity', 0, 100);
		this.gui = gui;
	},

	dealloc: function() {
		Context.sceneController.gui.remove(this.gui);
		this.gui = null;
	}
};

Component.create(FireScene, 'fireScene');

/**
 * SceneController
 */
function SceneController() {
	Component.call(this);
}

SceneController.prototype = {
	create: function() {
		this.sceneId = 'white';
		this.running = true;

		var controller = this;

		var gui = new dat.GUI();
		gui.add(this, 'sceneId', ['white', 'fire', 'explosion']).onFinishChange(function() {
			controller.changeScene();
		});
		gui.add(this, 'running').onFinishChange(function(running) {
			if (running) {
				Context.start();
			} else {
				Context.pause();
			}
		});
		gui.close();
		this.gui = gui;

		this.changeScene();
	},

	changeScene: function() {
		var component = this.sceneId + 'Scene';
		var attributes = {};
		attributes[component] = null;

		var entity = Entity.create(this.root, attributes);
		Context.play(entity);
	}
};

Component.create(SceneController, 'sceneController');

// Attaching the controller starts the first scene
Context.createComponent('sceneController');


text:
musikata.path
=================

Mini-App to Display a Course Path