From 22dddc2423b0babf2bace6b2bbbfd89ea0030893 Mon Sep 17 00:00:00 2001 From: Timon Bakker Date: Tue, 1 Nov 2022 14:15:25 +0100 Subject: [PATCH] [IMPROVEMENT] Changes highest level reached from highest saved program to highest level quiz score (#3503) **Description** As pointed out by @JimJamShazam our current implementation of "Highest level reached" is a bit outdated and still depends on relic code from when we didn't do any user logging (and didn't have any more stats than "saved programs"). In PR we improve this by iterating the user logs and getting the highest level for which a quiz is finished. Note: We don't look into the actual quiz score, only that it is finished. **Fixes** This PR fixes #3501. **How to test** Make sure you have a class with students in it. Verify that the highest level reached column now depends on the highest level for which a quiz is finished instead of the highest level a program is saved in. --- tests_e2e.py | 2 +- website/for_teachers.py | 25 +++++++++++++++---------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/tests_e2e.py b/tests_e2e.py index b090fdefaaa..e397132a1b9 100644 --- a/tests_e2e.py +++ b/tests_e2e.py @@ -1242,7 +1242,7 @@ def test_see_students_in_class(self): # THEN the class should contain a student with valid fields self.assertEqual(len(Class_data['students']), 1) class_student = Class_data['students'][0] - self.assertEqual(class_student['highest_level'], 0) + self.assertEqual(class_student['highest_level'], "-") self.assertEqual(class_student['programs'], 0) self.assertIsInstance(class_student['last_login'], str) self.assertEqual(class_student['username'], student['username']) diff --git a/website/for_teachers.py b/website/for_teachers.py index b38187d8d1e..47217d4b445 100644 --- a/website/for_teachers.py +++ b/website/for_teachers.py @@ -3,7 +3,8 @@ import hedy import hedyweb from .achievements import Achievements -from website.auth import requires_login, is_teacher, is_admin, current_user, validate_student_signup_data, store_new_student_account +from website.auth import requires_login, is_teacher, is_admin, current_user, validate_student_signup_data, \ + store_new_student_account import utils import uuid from flask import g, request, jsonify, session @@ -13,6 +14,7 @@ from .database import Database from .website_module import WebsiteModule, route + class ForTeachersModule(WebsiteModule): def __init__(self, db: Database, achievements: Achievements): super().__init__('teachers', __name__, url_prefix='/for-teachers') @@ -43,7 +45,6 @@ def for_teachers_page(self, user): teacher_classes=teacher_classes, teacher_adventures=adventures, welcome_teacher=welcome_teacher) - @route('/manual', methods=['GET']) @requires_login def get_teacher_manual(self, user): @@ -63,12 +64,14 @@ def get_class(self, user, class_id): for student_username in Class.get('students', []): student = self.db.user_by_username(student_username) programs = self.db.programs_for_user(student_username) - highest_level = max(program['level'] for program in programs) if len(programs) else 0 + # Fixme: The get_quiz_stats function requires a list of ids -> doesn't work on single string + quiz_scores = self.db.get_quiz_stats([student_username]) + highest_quiz = max([x.get('level') for x in quiz_scores if x.get('finished')]) if quiz_scores else "-" students.append({ 'username': student_username, 'last_login': student['last_login'], 'programs': len(programs), - 'highest_level': highest_level + 'highest_level': highest_quiz }) # Sort the students by their last login @@ -93,10 +96,11 @@ def get_class(self, user, class_id): 'expire_timestamp': utils.localized_date_format(invite['ttl'], short_format=True)}) return render_template('class-overview.html', current_page='my-profile', - page_title=gettext('title_class-overview'), - achievement=achievement, invites=invites, - class_info={'students': students, 'link': os.getenv('BASE_URL') + '/hedy/l/' + Class['link'], - 'teacher': Class['teacher'], 'name': Class['name'], 'id': Class['id']}) + page_title=gettext('title_class-overview'), + achievement=achievement, invites=invites, + class_info={'students': students, + 'link': os.getenv('BASE_URL') + '/hedy/l/' + Class['link'], + 'teacher': Class['teacher'], 'name': Class['name'], 'id': Class['id']}) @route('/customize-class/', methods=['GET']) @requires_login @@ -216,7 +220,7 @@ def create_accounts(self, user, class_id): if not current_class or current_class.get('teacher') != user.get('username'): return utils.error_page(error=403, ui_message=gettext('no_such_class')) - return render_template('create-accounts.html', current_class = current_class) + return render_template('create-accounts.html', current_class=current_class) @route('/create-accounts', methods=['POST']) @requires_login @@ -276,7 +280,8 @@ def view_adventure(self, user, adventure_id): return utils.error_page(error=403, ui_message=gettext('retrieve_adventure_error')) # Add level to the
 tag to let syntax highlighting know which highlighting we need!
-        adventure['content'] = adventure['content'].replace("
", "
")
+        adventure['content'] = adventure['content'].replace("
", "
")
         adventure['content'] = adventure['content'].format(**hedy_content.KEYWORDS.get(g.keyword_lang))
 
         return render_template('view-adventure.html', adventure=adventure,