Repository: oppia/oppia

Issue:
Fixes/Additions related to the new math interactions
The following things are to be done re the new math interactions:

 - [ ] Add a warning for keyboard users if they enter a variable that is not present in the custom variables list. The warning should say "You have entered an invalid character: {invalid character}. Please use only the characters {valid character list} in your answer." 
 - [ ] Fix a nit mentioned [here](https://github.com/oppia/oppia/pull/10136#discussion_r467618143) re audit job output.
 - [ ] Remove the MathExpressionValidationOneOff job. ([link](https://github.com/oppia/oppia/blob/6f99ce42489ff0d0cca419e750c4f0e3759b4bd3/core/domain/exp_jobs_one_off.py#L164))
 - [ ] The editor is not fully visible on smaller mobile screens:
![toobig](https://user-images.githubusercontent.com/35144226/89742236-b9d68180-dab5-11ea-8a14-403c4c613c2f.png)


Fixes/Additions related to the new math interactions
The following things are to be done re the new math interactions:

 - [ ] Add a warning for keyboard users if they enter a variable that is not present in the custom variables list. The warning should say "You have entered an invalid character: {invalid character}. Please use only the characters {valid character list} in your answer." 
 - [ ] Fix a nit mentioned [here](https://github.com/oppia/oppia/pull/10136#discussion_r467618143) re audit job output.
 - [ ] Remove the MathExpressionValidationOneOff job. ([link](https://github.com/oppia/oppia/blob/6f99ce42489ff0d0cca419e750c4f0e3759b4bd3/core/domain/exp_jobs_one_off.py#L164))
 - [ ] The editor is not fully visible on smaller mobile screens:
![toobig](https://user-images.githubusercontent.com/35144226/89742236-b9d68180-dab5-11ea-8a14-403c4c613c2f.png)




Discussion:

Resolving patch:
diff --git a/core/domain/exp_jobs_one_off.py b/core/domain/exp_jobs_one_off.py
--- a/core/domain/exp_jobs_one_off.py
+++ b/core/domain/exp_jobs_one_off.py
@@ -38,35 +38,6 @@
     models.NAMES.exploration])
 
 
-class MathExpressionValidationOneOffJob(jobs.BaseMapReduceOneOffJobManager):
-    """Job that produces a list of explorations that use the MathExpressionInput
-    along with the validity and type (expression/equation) of the inputs present
-    in the exploration.
-
-    This validation is done by the validator functions present in schema_utils.
-    """
-
-    @classmethod
-    def entity_classes_to_map_over(cls):
-        return [exp_models.ExplorationModel]
-
-    @staticmethod
-    def map(item):
-        if not item.deleted:
-            try:
-                exp_fetchers.get_exploration_from_model(item)
-            except Exception:
-                yield (
-                    exp_domain.TYPE_INVALID_EXPRESSION,
-                    'The exploration with ID: %s had some issues during '
-                    'migration. This is most likely due to the exploration '
-                    'having invalid solution(s).' % item.id)
-
-    @staticmethod
-    def reduce(key, values):
-        yield (key, values)
-
-
 class ExplorationFirstPublishedOneOffJob(jobs.BaseMapReduceOneOffJobManager):
     """One-off job that finds first published time in milliseconds for all
     explorations.
@@ -171,7 +142,7 @@ def map(item):
                 break
 
             if states_schema_version == current_state_schema_version:
-                yield ('SUCCESS', None)
+                yield ('SUCCESS', 1)
 
     @staticmethod
     def reduce(key, values):
diff --git a/core/jobs_registry.py b/core/jobs_registry.py
--- a/core/jobs_registry.py
+++ b/core/jobs_registry.py
@@ -61,7 +61,6 @@
     exp_jobs_one_off.ExplorationMigrationJobManager,
     exp_jobs_one_off.ExplorationValidityJobManager,
     exp_jobs_one_off.HintsAuditOneOffJob,
-    exp_jobs_one_off.MathExpressionValidationOneOffJob,
     exp_jobs_one_off.RTECustomizationArgsValidationOneOffJob,
     exp_jobs_one_off.ViewableExplorationsAuditJob,
     feedback_jobs_one_off.FeedbackThreadCacheOneOffJob,


Test patch:
diff --git a/core/domain/exp_jobs_one_off_test.py b/core/domain/exp_jobs_one_off_test.py
--- a/core/domain/exp_jobs_one_off_test.py
+++ b/core/domain/exp_jobs_one_off_test.py
@@ -90,175 +90,6 @@ def run_job_for_deleted_exp(
         self.assertEqual(job_class.get_output(job_id), [])
 
 
-class MathExpressionValidationOneOffJobTests(test_utils.GenericTestBase):
-
-    ALBERT_EMAIL = 'albert@example.com'
-    ALBERT_NAME = 'albert'
-
-    VALID_EXP_ID = 'exp_id0'
-    NEW_EXP_ID = 'exp_id1'
-    EXP_TITLE = 'title'
-
-    def setUp(self):
-        super(MathExpressionValidationOneOffJobTests, self).setUp()
-
-        # Setup user who will own the test explorations.
-        self.signup(self.ALBERT_EMAIL, self.ALBERT_NAME)
-        self.albert_id = self.get_user_id_from_email(self.ALBERT_EMAIL)
-        self.process_and_flush_pending_tasks()
-
-    def test_exp_state_pairs_are_produced_only_for_desired_interactions(self):
-        """Checks output is produced only for desired interactions."""
-
-        answer_groups_1 = [{
-            'outcome': {
-                'dest': 'Introduction',
-                'feedback': {
-                    'content_id': 'feedback_1',
-                    'html': '<p>Feedback</p>'
-                },
-                'labelled_as_correct': True,
-                'param_changes': [],
-                'refresher_exploration_id': None,
-                'missing_prerequisite_skill_id': None
-            },
-            'rule_input_translations': {},
-            'rule_types_to_inputs': {
-                'IsMathematicallyEquivalentTo': [{
-                    'x': 'x+y'
-                }, {
-                    'x': 'x=y'
-                }]
-            },
-            'training_data': [],
-            'tagged_skill_misconception_id': None
-        }]
-
-        states_dict = state_domain.State.from_dict({
-            'content': {
-                'content_id': 'content_1',
-                'html': 'Question 1'
-            },
-            'recorded_voiceovers': {
-                'voiceovers_mapping': {
-                    'content_1': {},
-                    'feedback_1': {},
-                    'feedback_2': {},
-                    'hint_1': {},
-                    'content_2': {}
-                }
-            },
-            'written_translations': {
-                'translations_mapping': {
-                    'content_1': {},
-                    'feedback_1': {},
-                    'feedback_2': {},
-                    'hint_1': {},
-                    'content_2': {}
-                }
-            },
-            'interaction': {
-                'answer_groups': answer_groups_1,
-                'confirmed_unclassified_answers': [],
-                'customization_args': {},
-                'default_outcome': {
-                    'dest': 'Introduction',
-                    'feedback': {
-                        'content_id': 'feedback_2',
-                        'html': 'Correct Answer'
-                    },
-                    'param_changes': [],
-                    'refresher_exploration_id': None,
-                    'labelled_as_correct': True,
-                    'missing_prerequisite_skill_id': None
-                },
-                'hints': [{
-                    'hint_content': {
-                        'content_id': 'hint_1',
-                        'html': 'Hint 1'
-                    }
-                }],
-                'solution': {
-                    'correct_answer': {
-                        'ascii': 'x+y',
-                        'latex': 'x+y'
-                    },
-                    'answer_is_exclusive': False,
-                    'explanation': {
-                        'html': 'Solution explanation',
-                        'content_id': 'content_2'
-                    }
-                },
-                'id': 'MathExpressionInput'
-            },
-            'next_content_id_index': 3,
-            'param_changes': [],
-            'solicit_answer_details': False,
-            'classifier_model_id': None
-        }).to_dict()
-
-        self.save_new_exp_with_custom_states_schema_version(
-            self.VALID_EXP_ID, 'user_id', states_dict, 34)
-
-        job_id = (
-            exp_jobs_one_off.MathExpressionValidationOneOffJob.create_new())
-        exp_jobs_one_off.MathExpressionValidationOneOffJob.enqueue(job_id)
-        self.process_and_flush_pending_tasks()
-
-        actual_output = (
-            exp_jobs_one_off.MathExpressionValidationOneOffJob.get_output(
-                job_id))
-        expected_output = [
-            u'[u\'Invalid\', [u\'The exploration with ID: exp_id0 had some '
-            u'issues during migration. This is most likely due to the '
-            u'exploration having invalid solution(s).\']]']
-
-        self.assertEqual(actual_output, expected_output)
-
-    def test_no_action_is_performed_for_deleted_exploration(self):
-        """Test that no action is performed on deleted explorations."""
-
-        exploration = exp_domain.Exploration.create_default_exploration(
-            self.VALID_EXP_ID, title='title', category='category')
-
-        exploration.add_states(['State1'])
-
-        state1 = exploration.states['State1']
-
-        state1.update_interaction_id('MathExpressionInput')
-
-        answer_group_list = [{
-            'rule_input_translations': {},
-            'rule_types_to_inputs': {
-                'IsMathematicallyEquivalentTo': [{
-                    'x': u'[\'y=mx+c\']'
-                }]
-            },
-            'outcome': {
-                'dest': 'Introduction',
-                'feedback': {
-                    'content_id': 'feedback',
-                    'html': '<p>Outcome for state1</p>'
-                },
-                'param_changes': [],
-                'labelled_as_correct': False,
-                'refresher_exploration_id': None,
-                'missing_prerequisite_skill_id': None
-            },
-            'training_data': [],
-            'tagged_skill_misconception_id': None
-        }]
-
-        state1.update_interaction_answer_groups(answer_group_list)
-
-        exp_services.save_new_exploration(self.albert_id, exploration)
-
-        exp_services.delete_exploration(self.albert_id, self.VALID_EXP_ID)
-
-        run_job_for_deleted_exp(
-            self, exp_jobs_one_off.MathExpressionValidationOneOffJob)
-
-
 class OneOffExplorationFirstPublishedJobTests(test_utils.GenericTestBase):
 
     EXP_ID = 'exp_id'