From f1686043ec502488d322a7602fba07e2c3ce45c9 Mon Sep 17 00:00:00 2001 From: mikaelGusse Date: Wed, 18 Sep 2024 16:36:47 +0300 Subject: [PATCH 1/2] Add filters to Dolos integration in Radar --- data/models.py | 26 ++++++++++++++++ review/templates/review/exercise.html | 43 ++++++++++++++++++++------- review/urls.py | 2 +- review/views.py | 27 ++++++++++------- static/main.css | 19 ++++++++++-- 5 files changed, 94 insertions(+), 23 deletions(-) diff --git a/data/models.py b/data/models.py index 26c2113..260725f 100644 --- a/data/models.py +++ b/data/models.py @@ -232,6 +232,32 @@ def valid_submissions(self): def invalid_submissions(self): return self.submissions.filter(invalid=True) + @property + def best_submissions(self): + students = self.submissions.values_list('student', flat=True).distinct() + + best_submission_ids = [] + + for student in students: + best_submission = self.submissions.filter(student=student).order_by('-grade').first() + if best_submission: + best_submission_ids.append(best_submission.id) + + best_submissions_queryset = self.submissions.filter(id__in=best_submission_ids) + print("Best submissions queryset:", best_submissions_queryset) + return best_submissions_queryset + + @property + def flagged_submissions(self): + submission_ids = (Comparison.objects.filter(submission_a__exercise=self) + .filter(review__gte=5) + .select_related('submission_a') + .values_list('submission_a', flat=True)) + + submissions = Submission.objects.filter(id__in=submission_ids) + return submissions + + @property def valid_matched_submissions(self): return self.valid_submissions.filter(matched=True) diff --git a/review/templates/review/exercise.html b/review/templates/review/exercise.html index 2f1ec6f..d204eaa 100644 --- a/review/templates/review/exercise.html +++ b/review/templates/review/exercise.html @@ -8,14 +8,25 @@

-
- - View in Dolos - - -
-
-
Preparing files...
+ +
+
+

View in Dolos

+

Include only...

+
+ +
+
@@ -23,6 +34,11 @@

Dolos is a modern similarity detection tool for source code. Opening this exercise in Dolos will redirect you to an Aalto hosted version of Dolos. This feature is still in its early stages, so some issues might occur.

+
+
+
Preparing files...
+
+

Similarity distribution of matches

@@ -49,10 +65,17 @@

Comparison pairs with highest similarity

document.addEventListener('DOMContentLoaded', function() { const dolosButton = document.querySelector('.dolos-button'); const viewInDolosButton = dolosButton.querySelector('a'); - const dolosProgressParent = dolosButton.querySelector('.dolos-progress-parent'); + const dolosProgressParent = document.querySelector('.dolos-progress-parent'); viewInDolosButton.addEventListener('click', function() { - dolosProgressParent.style.display = 'block'; + dolosProgressParent.style.display = 'block'; + + let bestSubmissions = document.getElementById('best_submissions').selected.toString(); + let flagged = document.getElementById('flagged').selected.toString(); + + console.log(bestSubmissions, flagged); + const url = `${bestSubmissions}/${flagged}/gen_dolos`; + document.getElementById('dolos-gen-button').href = url; }); // Hide dolos-progress-parent initially diff --git a/review/urls.py b/review/urls.py index 5b9fda5..8390936 100644 --- a/review/urls.py +++ b/review/urls.py @@ -100,7 +100,7 @@ name='comparison', ), re_path( - r'^(?P\w+)/(?P\w+)/gen_dolos$', + r'^(?P\w+)/(?P\w+)/(?P\w+)/(?P\w+)/gen_dolos$', generate_dolos_view, name='dolos', ), diff --git a/review/views.py b/review/views.py index 19b8841..18785b9 100644 --- a/review/views.py +++ b/review/views.py @@ -478,15 +478,15 @@ def download_file(output_dir, submission, local_course): p_config = provider_config(local_course.provider) get_submission_text = configured_function(p_config, "get_submission_text") - with open(os.path.join(output_dir, filename + "|" + str(submission.id)), 'w') as f: + with open(os.path.join(output_dir, filename + "|" + str(str(submission.student.name))), 'w') as f: submission_text = get_submission_text(submission, p_config) print("Writing something with length: ", len(submission_text)) f.write(submission_text) -def download_files(output_dir, local_exercise, local_course): +def download_files(output_dir, local_exercise, local_course, submissions): with concurrent.futures.ThreadPoolExecutor() as executor: futures = [executor.submit(download_file, output_dir, sub, local_course) for - sub in local_exercise.valid_submissions | local_exercise.invalid_submissions] + sub in submissions] concurrent.futures.wait(futures) def zip_files(directory, output_dir): @@ -505,9 +505,7 @@ def zip_files(directory, output_dir): zip_handle.write(file_path, arcname=filename) -def write_metadata_for_dolos(exercise_directory, local_exercise) -> None: - submissions = local_exercise.valid_submissions | local_exercise.invalid_submissions - +def write_metadata_for_dolos(exercise_directory, local_exercise, submissions) -> None: # Write metadata to CSV file with open(exercise_directory + '/info.csv', 'w', newline='') as csvfile: writer = csv.writer(csvfile) @@ -515,7 +513,7 @@ def write_metadata_for_dolos(exercise_directory, local_exercise) -> None: writer.writerow(['filename', 'label', 'created_at']) for submission in submissions: - filename = "student" + submission.student.key + "|" + str(submission.id) + filename = "student" + submission.student.key + "|" + str(submission.student.name) created_at = submission.provider_submission_time if isinstance(created_at, datetime.datetime): @@ -536,7 +534,9 @@ def go_to_dolos_view(request, course_key=None, exercise_key=None) -> HttpRespons @access_resource -def generate_dolos_view(request, course_key=None, exercise_key=None, course=None, exercise=None, ) -> HttpResponse: +def generate_dolos_view( + request, course_key=None, exercise_key=None, course=None, exercise=None, best_submissions=False, flagged=False + ) -> HttpResponse: """ Create a Dolos report of this exercise and redirect to the report visualization """ @@ -549,8 +549,15 @@ def generate_dolos_view(request, course_key=None, exercise_key=None, course=None if not os.path.exists(new_submissions_dir): os.mkdir(new_submissions_dir) - download_files(new_submissions_dir, exercise, course) - write_metadata_for_dolos(new_submissions_dir, exercise) + submissions = (exercise.valid_submissions | exercise.invalid_submissions) + if best_submissions == 'true': + submissions = exercise.best_submissions + elif flagged == 'true': + submissions = exercise.flagged_submissions + print("Submissions", submissions) + + download_files(new_submissions_dir, exercise, course, submissions.distinct()) + write_metadata_for_dolos(new_submissions_dir, exercise, submissions.distinct()) zip_files(new_submissions_dir, temp_submissions_dir) timestamp = time.time() diff --git a/static/main.css b/static/main.css index 972832b..899d5bf 100644 --- a/static/main.css +++ b/static/main.css @@ -126,8 +126,24 @@ pre.sample-highlight { display:inline-block; } animation: bounce 1s ease-in-out infinite; } -.dolos-button { +.dolos-div{ display: flex; + align-items: center; +} + +.dolos-filter-container{ + font-size: 14px; + line-height: 1.5; + color: #333; + overflow-wrap: break-word; + max-width: 500px; + padding: 10px; + border: 1px solid #e0e0e0; + background-color: #f4f4f4; +} + +.dolos-button { + margin-top: 10px; } .dolos-progress-parent { @@ -138,7 +154,6 @@ pre.sample-highlight { display:inline-block; } font-size: 14px; line-height: 1.5; color: #333; - margin-bottom: 20px; overflow-wrap: break-word; max-width: 500px; padding: 10px; From 5da6ca4a9858d428fbb5db94c6f1a6b6e95fc386 Mon Sep 17 00:00:00 2001 From: mikaelGusse Date: Wed, 25 Sep 2024 14:19:14 +0300 Subject: [PATCH 2/2] Improve filters of Dolos+Radar --- data/models.py | 10 ++++++++-- review/views.py | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/data/models.py b/data/models.py index 260725f..2c74d40 100644 --- a/data/models.py +++ b/data/models.py @@ -249,11 +249,17 @@ def best_submissions(self): @property def flagged_submissions(self): - submission_ids = (Comparison.objects.filter(submission_a__exercise=self) + submission_ids_a = (Comparison.objects.filter(submission_a__exercise=self) .filter(review__gte=5) - .select_related('submission_a') + .select_related('submission_a', 'submission_b') .values_list('submission_a', flat=True)) + submission_ids_b = (Comparison.objects.filter(submission_b__exercise=self) + .filter(review__gte=5) + .select_related('submission_b') + .values_list('submission_b', flat=True)) + submission_ids = list(set(submission_ids_a) | set(submission_ids_b)) + print(submission_ids) submissions = Submission.objects.filter(id__in=submission_ids) return submissions diff --git a/review/views.py b/review/views.py index 18785b9..b280d62 100644 --- a/review/views.py +++ b/review/views.py @@ -478,7 +478,7 @@ def download_file(output_dir, submission, local_course): p_config = provider_config(local_course.provider) get_submission_text = configured_function(p_config, "get_submission_text") - with open(os.path.join(output_dir, filename + "|" + str(str(submission.student.name))), 'w') as f: + with open(os.path.join(output_dir, filename + "|" + str( "Points: " + str(submission.grade))), 'w') as f: submission_text = get_submission_text(submission, p_config) print("Writing something with length: ", len(submission_text)) f.write(submission_text) @@ -513,7 +513,7 @@ def write_metadata_for_dolos(exercise_directory, local_exercise, submissions) -> writer.writerow(['filename', 'label', 'created_at']) for submission in submissions: - filename = "student" + submission.student.key + "|" + str(submission.student.name) + filename = "student" + submission.student.key + "|" + "Points: " + str(submission.grade) created_at = submission.provider_submission_time if isinstance(created_at, datetime.datetime):