def test_illegal_name(self):
     with self.assertRaisesRegexp(ValueError, 'name "A" must contain only'):
         analytics.Visualization('A', 'Foo', 'foo.html')
     with self.assertRaisesRegexp(ValueError, 'name " " must contain only'):
         analytics.Visualization(' ', 'Foo', 'foo.html')
     with self.assertRaisesRegexp(ValueError, 'name "#" must contain only'):
         analytics.Visualization('#', 'Foo', 'foo.html')
Exemple #2
0
def register_on_enable():
    data_sources.Registry.register(ExamsDataSource)
    data_sources.Registry.register(PupilsDataSource)
    data_sources.Registry.register(AnswersDataSource)

    exams = analytics.Visualization('exams', 'Exams',
                                    'fake_visualizations.html',
                                    [ExamsDataSource])
    pupils = analytics.Visualization('pupils', 'Pupils',
                                     'fake_visualizations.html',
                                     [PupilsDataSource])
    scoring = analytics.Visualization(
        'scoring', 'Scoring', 'fake_visualizations.html',
        [ExamsDataSource, PupilsDataSource, AnswersDataSource])

    dashboard.DashboardHandler.add_sub_nav_mapping(
        'analytics',
        'exams',
        'Exams',
        action='analytics_exams',
        contents=analytics.TabRenderer([exams]))
    dashboard.DashboardHandler.add_sub_nav_mapping(
        'analytics',
        'pupils',
        'Pupils',
        action='analytics_pupils',
        contents=analytics.TabRenderer([pupils]))
    dashboard.DashboardHandler.add_sub_nav_mapping(
        'analytics',
        'scoring',
        'Scoring',
        action='analytics_scoring',
        contents=analytics.TabRenderer([scoring]))
Exemple #3
0
def register_analytic():
    data_sources.Registry.register(PeerReviewStatsSource)
    name = 'peer_review'
    title = 'Peer Review'
    peer_review = analytics.Visualization(
        name, title, 'stats.html', data_source_classes=[PeerReviewStatsSource])
    tabs.Registry.register('analytics', name, title, [peer_review])
def register_callbacks():
    # Update enrollments counters when a student enrolls, unenrolls.
    models.StudentLifecycleObserver.EVENT_CALLBACKS[
        models.StudentLifecycleObserver.EVENT_ADD][
            MODULE_NAME] = _count_add
    models.StudentLifecycleObserver.EVENT_CALLBACKS[
        models.StudentLifecycleObserver.EVENT_REENROLL][
            MODULE_NAME] = _count_add
    models.StudentLifecycleObserver.EVENT_CALLBACKS[
        models.StudentLifecycleObserver.EVENT_UNENROLL][
            MODULE_NAME] = _count_drop
    models.StudentLifecycleObserver.EVENT_CALLBACKS[
        models.StudentLifecycleObserver.EVENT_UNENROLL_COMMANDED][
            MODULE_NAME] = _count_drop

    # Set counters for newly-created courses initially to zero (to avoid
    # extraneous enrollments MapReduce runs).
    config.CoursesItemRESTHandler.NEW_COURSE_ADDED_HOOKS[
        MODULE_NAME] = _new_course_counts

    # Delete the corresponding enrollments counters when a course is deleted.
    config.CourseDeleteHandler.COURSE_DELETED_HOOKS[
        MODULE_NAME] = delete_counters

    # Register analytic to show nice zoomable graph of enroll/unenroll rates.
    data_sources.Registry.register(EnrollmentsDataSource)
    visualization = analytics.Visualization(
        'enrollments', 'Enrollments', 'templates/enrollments.html',
        data_source_classes=[EnrollmentsDataSource])
    dashboard.DashboardHandler.add_sub_nav_mapping(
        'analytics', 'enrollments', 'Enrollments',
        action='analytics_enrollments',
        contents=analytics.TabRenderer([visualization]))
Exemple #5
0
def register_module():
    """Registers this module in the registry."""

    data_sources.Registry.register(panalytics.WatchTimeStatsDataSource)

    tab_name = 'watch_time_stats'
    stats = analytics.Visualization(
        tab_name,
        MODULE_NAME,
        'templates/watch_time_stats.html',
        data_source_classes=[panalytics.WatchTimeStatsDataSource])
    tabs.Registry.register('analytics', tab_name, MODULE_NAME, [stats])

    global_routes = []
    watch_time_routes = [('/modules/watch_time/video_watchtime',
                          record_watchtime.RecordWatchTime),
                         ('/modules/nptel/video_watchtime',
                          record_watchtime.RecordWatchTime)]

    global custom_module
    custom_module = custom_modules.Module(
        MODULE_NAME,
        'Provides library to register video watch time related assets/code',
        global_routes, watch_time_routes)
    return custom_module
Exemple #6
0
def register_analytic():
  data_sources.Registry.register(NotificationsDataSource)
  name = 'notifications'
  title = 'Notifications'
  visualization = analytics.Visualization(
      name, title, 'stats.html',
      data_source_classes=[NotificationsDataSource])
  tabs.Registry.register('analytics', name, title, [visualization])
def register_analytic():
    data_sources.Registry.register(CertificatesEarnedDataSource)
    name = 'certificates_earned'
    title = 'Certificates Earned'
    certificates_earned = analytics.Visualization(
        name, title, 'certificates_earned.html',
        data_source_classes=[CertificatesEarnedDataSource])
    tabs.Registry.register('analytics', name, title,
                           analytics.TabRenderer([certificates_earned]))
def register_on_enable():
    data_sources.Registry.register(ExamsDataSource)
    data_sources.Registry.register(PupilsDataSource)
    data_sources.Registry.register(AnswersDataSource)

    exams = analytics.Visualization('exams', 'Exams',
                                    'fake_visualizations.html',
                                    [ExamsDataSource])
    pupils = analytics.Visualization('pupils', 'Pupils',
                                     'fake_visualizations.html',
                                     [PupilsDataSource])
    scoring = analytics.Visualization(
        'scoring', 'Scoring', 'fake_visualizations.html',
        [ExamsDataSource, PupilsDataSource, AnswersDataSource])

    tabs.Registry.register('analytics', 'exams', 'Exams', [exams])
    tabs.Registry.register('analytics', 'pupils', 'Pupils', [pupils])
    tabs.Registry.register('analytics', 'scoring', 'Scoring', [scoring])
Exemple #9
0
def register_analytic():
    data_sources.Registry.register(CertificatesEarnedDataSource)
    name = 'certificates_earned'
    title = 'Certificates'
    certificates_earned = analytics.Visualization(
        name, title, 'certificates_earned.html',
        data_source_classes=[CertificatesEarnedDataSource])
    dashboard.DashboardHandler.add_sub_nav_mapping(
        'analytics', name, title, action='analytics_certificates_earned',
        contents=analytics.TabRenderer([certificates_earned]))
    def test_analytics_warns_when_no_gcs_bucket(self):
        name = 'foo'
        analytic = analytics.Visualization(
            name, name, 'models_analytics_section.html', [OneGenSource])

        result = self._generate_analytics_page([analytic])
        self.assertNotIn('enable Google Cloud Storage', result)

        self._mock_identity_module.set_default_gcs_bucket_name(None)
        result = self._generate_analytics_page([analytic])
        self.assertIn('enable Google Cloud Storage', result)
    def test_no_generator_display(self):
        name = 'no_generator'
        analytic = analytics.Visualization(
            name, name, 'models_analytics_section.html', [NoGenSource])
        result = self._generate_analytics_page([analytic])

        # Statistic reports result to page
        self.assertIn('no_generator_no_gen_source: "no_gen_value"', result)
        # Statistic does not have a run/cancel button; it has no generators
        # which depend on jobs.
        self.assertNotIn('gdb-run-analytic-simple', result)
        self.assertNotIn('gdb-cancel-analytic-simple', result)
def register_tabs():
    clusters_visualization = analytics.Visualization(
        'clusters',
        'Cluster Manager',
        'clustering.html',
        data_source_classes=[clustering.ClusterDataSource])
    student_vectors_visualization = analytics.Visualization(
        'student_vectors',
        'Student Vectors',
        'student_vectors.html',
        data_source_classes=[clustering.TentpoleStudentVectorDataSource])
    stats_visualization = analytics.Visualization(
        'clustering_stats',
        'Clustering Statistics',
        'cluster_stats.html',
        data_source_classes=[clustering.ClusterStatisticsDataSource])

    tabs.Registry.register('analytics', 'clustering', 'Clustering', [
        clusters_visualization, student_vectors_visualization,
        stats_visualization
    ])
Exemple #13
0
def register_analytic():
    data_sources.Registry.register(PeerReviewStatsSource)
    name = 'peer_review'
    title = 'Peer review'
    peer_review = analytics.Visualization(
        name, title, 'stats.html', data_source_classes=[PeerReviewStatsSource])
    dashboard.DashboardHandler.add_sub_nav_mapping(
        'analytics',
        name,
        title,
        action='analytics_peer_review',
        contents=analytics.TabRenderer([peer_review]),
        placement=7000)
def register_analytic():
    """This isn't exactly an analytic, but we register that way to be included
    with the other analytics sub-tabs on the Dashboard."""
    name = 'sample_data'
    title = 'Generate Sample Data'
    sample_data = analytics.Visualization(
        name, title,
        os.path.join('modules', 'gen_sample_data', 'templates',
                     'sample_data.html'))
    dashboard.DashboardHandler.add_sub_nav_mapping(
        'analytics',
        name,
        title,
        action='analytics_sample_data',
        contents=analytics.TabRenderer([sample_data]))
Exemple #15
0
def register_analytic():
    data_sources.Registry.register(NotificationsDataSource)
    name = 'notifications'
    title = 'Notifications'
    visualization = analytics.Visualization(
        name,
        title,
        'stats.html',
        data_source_classes=[NotificationsDataSource])
    dashboard.DashboardHandler.add_sub_nav_mapping(
        'analytics',
        name,
        title,
        action='analytics_notifications',
        contents=analytics.TabRenderer([visualization]))
    def test_generator_run_cancel_state_display(self):
        name = 'foo'
        analytic = analytics.Visualization(name, name,
                                           'models_analytics_section.html',
                                           [OneGenSource])

        result = self._generate_analytics_page([analytic])
        self.assertIn('Statistics for gen one have not been', result)
        self.assertIn('Update Statistic', result)
        self.assertIn('action=run_visualizations', result)

        self._run_generators_for_visualizations(self._mock_app_context,
                                                [analytic])
        result = self._generate_analytics_page([analytic])
        self.assertIn('Job for gen one statistics started at', result)
        self.assertIn('Cancel Statistic Calculation', result)
        self.assertIn('action=cancel_visualizations', result)

        self._cancel_generators_for_visualizations(self._mock_app_context,
                                                   [analytic])
        result = self._generate_analytics_page([analytic])
        self.assertIn('There was an error updating gen one statistics', result)
        self.assertIn('<pre>Canceled</pre>', result)
        self.assertIn('Update Statistic', result)
        self.assertIn('action=run_visualizations', result)

        self._run_generators_for_visualizations(self._mock_app_context,
                                                [analytic])
        result = self._generate_analytics_page([analytic])
        self.assertIn('Job for gen one statistics started at', result)
        self.assertIn('Cancel Statistic Calculation', result)
        self.assertIn('action=cancel_visualizations', result)

        GenOne(self._mock_app_context).load().complete('run_state_display')
        result = self._generate_analytics_page([analytic])
        self.assertIn('Statistics for gen one were last updated at', result)
        self.assertIn('in about 0 sec', result)
        self.assertIn('Update Statistic', result)
        self.assertIn('action=run_visualizations', result)
        self.assertIn('foo_one_gen_source_gen_one: "run_state_display"',
                      result)
Exemple #17
0
def register_tabs():
    multiple_choice_question = analytics.Visualization(
        'multiple_choice_question',
        'Multiple Choice Question',
        'multiple_choice_question.html',
        data_source_classes=[synchronous_providers.QuestionStatsSource])
    student_progress = analytics.Visualization(
        'student_progress',
        'Student Progress',
        'student_progress.html',
        data_source_classes=[synchronous_providers.StudentProgressStatsSource])
    enrollment_assessment = analytics.Visualization(
        'enrollment_assessment',
        'Enrollment/Assessment',
        'enrollment_assessment.html',
        data_source_classes=[
            synchronous_providers.StudentEnrollmentAndScoresSource
        ])
    assessment_difficulty = analytics.Visualization(
        'assessment_difficulty',
        'Assessment Difficulty',
        'assessment_difficulty.html',
        data_source_classes=[rest_providers.StudentAssessmentScoresDataSource])
    labels_on_students = analytics.Visualization(
        'labels_on_students',
        'Labels on Students',
        'labels_on_students.html',
        data_source_classes=[rest_providers.LabelsOnStudentsDataSource])
    question_answers = analytics.Visualization(
        'question_answers',
        'Question Answers',
        'question_answers.html',
        data_source_classes=[
            student_answers.QuestionAnswersDataSource,
            student_answers.CourseQuestionsDataSource,
            student_answers.CourseUnitsDataSource
        ])
    gradebook = analytics.Visualization(
        'gradebook',
        'Gradebook',
        'gradebook.html',
        data_source_classes=[
            student_answers.RawAnswersDataSource,
            student_answers.OrderedQuestionsDataSource
        ])
    clusters_visualization = analytics.Visualization(
        'clusters',
        'Cluster Manager',
        'clustering.html',
        data_source_classes=[clustering.ClusterDataSource])
    student_vectors_visualization = analytics.Visualization(
        'student_vectors',
        'Student Vectors',
        'student_vectors.html',
        data_source_classes=[clustering.TentpoleStudentVectorDataSource])
    stats_visualization = analytics.Visualization(
        'clustering_stats',
        'Clustering Statistics',
        'cluster_stats.html',
        data_source_classes=[clustering.ClusterStatisticsDataSource])

    dashboard.DashboardHandler.add_sub_nav_mapping(
        ANALYTICS,
        'students',
        'Students',
        action='analytics_students',
        contents=analytics.TabRenderer(
            [labels_on_students, student_progress, enrollment_assessment]),
        placement=1000)
    dashboard.DashboardHandler.add_sub_nav_mapping(
        ANALYTICS,
        'questions',
        'Questions',
        action='analytics_questions',
        contents=analytics.TabRenderer(
            [multiple_choice_question, question_answers]),
        placement=2000)
    dashboard.DashboardHandler.add_sub_nav_mapping(
        ANALYTICS,
        'assessments',
        'Assessments',
        action='analytics_assessments',
        contents=analytics.TabRenderer([assessment_difficulty]),
        placement=3000)
    dashboard.DashboardHandler.add_sub_nav_mapping(
        ANALYTICS,
        'gradebook',
        'Gradebook',
        action='analytics_gradebook',
        contents=analytics.TabRenderer([gradebook]),
        placement=5000)
    dashboard.DashboardHandler.add_sub_nav_mapping(
        ANALYTICS,
        'clustering',
        'Clustering',
        action='analytics_clustering',
        contents=analytics.TabRenderer([
            clusters_visualization, student_vectors_visualization,
            stats_visualization
        ]),
        placement=8000)
Exemple #18
0
def register_module():
    """Registers this module in the registry."""
    data_sources.Registry.register(panalytics.ProgrammingStatsDataSource)

    tab_name = 'programming_assignment_stats'
    stats = analytics.Visualization(
        tab_name,
        base.ProgAssignment.NAME,
        'templates/prog_assignment_stats.html',
        data_source_classes=[panalytics.ProgrammingStatsDataSource])
    tabs.Registry.register('analytics', tab_name, base.ProgAssignment.NAME,
                           [stats])

    settings.ProgrammingAssignmentSettings.register()

    tabs.Registry.register(scoring_base.ScoringBase.DASHBOARD_NAV,
                           base.ProgAssignment.DASHBOARD_REEVALUATION_TAB,
                           'Programming Assignments',
                           pdashboard.ProgAssignmentDashboardHandler)

    tabs.Registry.register(base.ProgAssignment.DASHBOARD_NAV,
                           base.ProgAssignment.DASHBOARD_TEST_RUN_TAB,
                           'Test Run Details',
                           pdashboard.ProgAssignmentTestRunHandler)

    tabs.Registry.register(base.ProgAssignment.DASHBOARD_NAV,
                           base.ProgAssignment.DASHBOARD_DOWNLOAD_TAB,
                           'Download',
                           pdashboard.ProgAssignmentDownloadDashboardHandler)

    dashboard.DashboardHandler.add_custom_get_action(
        base.ProgAssignment.DASHBOARD_NAV, None)

    dashboard.DashboardHandler.add_custom_post_action(
        base.ProgAssignment.REEVAL_ACTION,
        pdashboard.ProgAssignmentDashboardHandler.confirm_reevaluation_page)
    dashboard.DashboardHandler.add_custom_post_action(
        base.ProgAssignment.REEVAL_CONFIRMED_ACTION,
        pdashboard.ProgAssignmentDashboardHandler.reevalaute_assignment)

    dashboard.DashboardHandler.add_custom_post_action(
        base.ProgAssignment.DOWNLOAD_ACTION,
        pdashboard.ProgAssignmentDownloadDashboardHandler.download_assignment)

    dashboard.DashboardHandler.add_custom_get_action(
        base.ProgAssignment.TEST_RUN_ACTION,
        pdashboard.ProgAssignmentTestRunHandler.get_show_results)

    dashboard.DashboardHandler.add_nav_mapping(
        base.ProgAssignment.DASHBOARD_NAV, base.ProgAssignment.NAME)

    associated_js_files_handlers = [
        ('/static/edit_area/(.*)',
         sites.make_zip_handler(
             os.path.join(appengine_config.BUNDLE_ROOT, 'lib/edit-area.zip'))),
        ('/static/prettify/(.*)',
         sites.make_zip_handler(
             os.path.join(appengine_config.BUNDLE_ROOT,
                          'lib/google-code-prettify.zip'))),
        ('/cron/compute_programming_test_case_stats',
         panalytics.ComputeProgrammingStatsHandler),
        ('/cron/reevaluate_programming_submissions',
         reevaluator.ReevaulateSubmissionHandler),
        ('/modules/programming_assignments/assets/.*', tags.ResourcesHandler)
    ]

    prog_assignment_handlers = [(base.ProgAssignment.UNIT_URL,
                                 assignment.ProgAssignmentHandler),
                                (question.ProgAssignmentRESTHandler.URI,
                                 question.ProgAssignmentRESTHandler)]

    global custom_module  # pylint: disable=global-statement
    custom_module = custom_modules.Module(
        base.ProgAssignment.NAME,
        'A set pages to manage programming assignments.',
        associated_js_files_handlers, prog_assignment_handlers)

    global custom_unit  # pylint: disable=global-statement
    custom_unit = custom_units.CustomUnit(
        base.ProgAssignment.UNIT_TYPE_ID,
        base.ProgAssignment.NAME,
        question.ProgAssignmentRESTHandler,
        base.ProgAssignment.get_public_url,
        create_helper=question.create_assignment,
        cleanup_helper=base.ProgAssignment.delete_content,
        import_helper=question.import_assignment,
        is_graded=True)
    return custom_module
 def test_illegal_generator(self):
     with self.assertRaisesRegexp(
             ValueError,
             'All data source classes used in visualizations must be'):
         analytics.Visualization('foo', 'foo', 'foo', [MockHandler])
    def test_multiple_visualizationsmultiple_generators_multiple_sources(self):
        visualizations = []
        visualizations.append(
            analytics.Visualization('trivial', 'Trivial Statistics',
                                    'models_analytics_section.html',
                                    [NoGenSource]))
        visualizations.append(
            analytics.Visualization('simple', 'Simple Statistics',
                                    'models_analytics_section.html',
                                    [OneGenSource]))
        visualizations.append(
            analytics.Visualization(
                'complex', 'Complex Statistics',
                'models_analytics_section.html',
                [NoGenSource, OneGenSource, TwoGenSource, ThreeGenSource]))

        self._run_generators_for_visualizations(self._mock_app_context,
                                                visualizations)
        # Verify that not-all generators are running, but that 'complex'
        # is still not reporting data, as the generator it's relying on
        # (GenThree) is still running.
        GenOne(self._mock_app_context).load().complete('gen_one_data')
        GenTwo(self._mock_app_context).load().complete('gen_two_data')
        result = self._generate_analytics_page(visualizations)
        self.assertIn('simple_one_gen_source_gen_one: "gen_one_data"', result)
        self.assertIn('Statistics for gen one were last updated', result)
        self.assertIn('Statistics for gen two were last updated', result)
        self.assertIn('Job for gen three statistics started at', result)
        self.assertNotIn('complex_three_gen_source', result)

        # Finish last generator; should now have all data from all sources.
        GenThree(self._mock_app_context).load().complete('gen_three_data')
        result = self._generate_analytics_page(visualizations)
        self.assertIn('trivial_no_gen_source: "no_gen_value"', result)
        self.assertIn('simple_one_gen_source_gen_one: "gen_one_data"', result)
        self.assertIn('complex_no_gen_source: "no_gen_value"', result)
        self.assertIn('complex_one_gen_source_gen_one: "gen_one_data"', result)
        self.assertIn('complex_two_gen_source_gen_one: "gen_one_data"', result)
        self.assertIn('complex_two_gen_source_gen_two: "gen_two_data"', result)
        self.assertIn('complex_three_gen_source_gen_one: "gen_one_data"',
                      result)
        self.assertIn('complex_three_gen_source_gen_two: "gen_two_data"',
                      result)
        self.assertIn('complex_three_gen_source_gen_three: "gen_three_data"',
                      result)

        # Verify that we _don't_ have data for sections that didn't specify
        # that source.
        self.assertIn('trivial_one_gen_source_gen_one: ""', result)
        self.assertIn('simple_no_gen_source: ""', result)

        # We should have all headers
        self.assertIn('<h3>Trivial Statistics</h3>', result)
        self.assertIn('<h3>Simple Statistics</h3>', result)
        self.assertIn('<h3>Complex Statistics</h3>', result)

        # And submission forms for analytics w/ generators
        self.assertNotIn(
            '<input type="hidden" name="visualization" value="trivial"',
            result)
        self.assertIn(
            '<input type="hidden" name="visualization" value="simple"', result)
        self.assertIn(
            '<input type="hidden" name="visualization" value="complex"',
            result)