From b4b931fffa509192b7b5b6c65fa0374c4db16b3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kruli=C5=A1?= Date: Fri, 26 Jan 2024 14:40:28 +0100 Subject: [PATCH] Improving notification and filtering of solutions suspected from plagiarism. --- recodex-web.spec | 4 ++-- src/locales/cs.json | 4 +++- src/locales/en.json | 6 ++++-- .../AssignmentSolutions/AssignmentSolutions.js | 15 +++++++++++---- .../GroupUserSolutions/GroupUserSolutions.js | 15 +++++++++++---- 5 files changed, 31 insertions(+), 13 deletions(-) diff --git a/recodex-web.spec b/recodex-web.spec index 0d0b84950..7a2231bb8 100644 --- a/recodex-web.spec +++ b/recodex-web.spec @@ -1,8 +1,8 @@ %define name recodex-web %define short_name web-app %define version 2.10.0 -%define unmangled_version 71640583ebf97d6c8f73a78a97f272d2aaa24a6a -%define release 1 +%define unmangled_version 137ce75c61aec51b5c721de71173ae6f67266283 +%define release 2 Summary: ReCodEx web-app component Name: %{name} diff --git a/src/locales/cs.json b/src/locales/cs.json index f71ca09a2..f6d0c54be 100644 --- a/src/locales/cs.json +++ b/src/locales/cs.json @@ -157,13 +157,15 @@ "app.assignmentSolutions.assignmentSolutions": "Řešení zadané úlohy", "app.assignmentSolutions.noSolutions": "Momentálně zde nejsou žádná odevzdaná řešení.", "app.assignmentSolutions.pendingReviews": "V tuto chvíli {count, plural, one {je otevřena} =2 {jsou otevřeny} =3 {jsou otevřeny} =4 {jsou otevřeny} other {je otevřeno}} {count} {count, plural, one {revize} =2 {revize} =3 {revize} =4 {revize} other {revizí}} ze všech řešení vybrané úlohy. Nezapomeňte, že autoři úloh vidí vaše komentáře zdrojových kódů až poté, co jsou příslušné revize uzavřeny.", - "app.assignmentSolutions.plagiarismsDetected": "V seznamu {count, plural, one {je zobrazeno} =2 {jsou zobrazena} =3 {jsou zobrazena} =4 {jsou zobrazena} other {je zobrazeno}} {count} řešení, {count, plural, one {ke kterému} other {ke kterým}} byla nelezena podobná řešení. V takových případech se může jednat o plagiáty.", + "app.assignmentSolutions.plagiarismsDetected.assignments": "V seznamu {count, plural, one {je zobrazeno} =2 {jsou zobrazena} =3 {jsou zobrazena} =4 {jsou zobrazena} other {je zobrazeno}} {count} řešení ({assignments, plural, =2 {ze} =3 {ze} =4 {ze} other {z}} {assignments} {assignments, plural, one {úlohy} other {úloh}}), {count, plural, one {ke kterému} other {ke kterým}} byla nalezena podobná řešení. V takových případech se může jednat o plagiáty.", + "app.assignmentSolutions.plagiarismsDetected.authors": "V seznamu {count, plural, one {je zobrazeno} =2 {jsou zobrazena} =3 {jsou zobrazena} =4 {jsou zobrazena} other {je zobrazeno}} {count} řešení (od {authors} {authors, plural, one {autora} other {různých autorů}}), {count, plural, one {ke kterému} other {ke kterým}} byla nalezena podobná řešení. V takových případech se může jednat o plagiáty.", "app.assignmentSolutions.title": "Všechna řešení zadané úlohy", "app.assignmentSolutions.viewModes.accepted": "Pouze akceptovaná řešení", "app.assignmentSolutions.viewModes.best": "Pouze nejlepší řešení", "app.assignmentSolutions.viewModes.default": "Všechna řešení (výchozí)", "app.assignmentSolutions.viewModes.grouped": "Seskupit dle uživatelů", "app.assignmentSolutions.viewModes.last": "Pouze poslední řešení", + "app.assignmentSolutions.viewModes.plagiarism": "Řešení podezřelá z plagiátorství", "app.assignmentSolutions.viewModes.reviewed": "Pouze revidovaná řešení", "app.assignmentSolutions.viewModesTitle": "Vyberte způsob zobrazení řešení", "app.assignments.deadline": "Termín odevzdání", diff --git a/src/locales/en.json b/src/locales/en.json index a48ae748b..579715f6e 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -157,13 +157,15 @@ "app.assignmentSolutions.assignmentSolutions": "Assignment Solutions", "app.assignmentSolutions.noSolutions": "There are currently no submitted solutions.", "app.assignmentSolutions.pendingReviews": "There {count, plural, one {is} other {are}} {count} pending {count, plural, one {review} other {reviews}} among the solutions of the selected assignment. Remember that the review comments are visible to the author after a review is closed.", - "app.assignmentSolutions.plagiarismsDetected": "There {count, plural, one {is} other {are}} {count} {count, plural, one {solution} other {solutions}} with detected similarities. Such solutions may be plagiarisms.", + "app.assignmentSolutions.plagiarismsDetected.assignments": "There {count, plural, one {is} other {are}} {count} {count, plural, one {solution} other {solutions}} (of {assignments} {assignments, plural, one {assignment} other {assignments}}) with detected similarities. Such solutions may be plagiarisms.", + "app.assignmentSolutions.plagiarismsDetected.authors": "There {count, plural, one {is} other {are}} {count} {count, plural, one {solution} other {solutions}} (from {authors} {authors, plural, one {author} other {unique authors}}) with detected similarities. Such solutions may be plagiarisms.", "app.assignmentSolutions.title": "All Submissions of The Assignment", "app.assignmentSolutions.viewModes.accepted": "Accepted solutions only", "app.assignmentSolutions.viewModes.best": "Best solutions only", "app.assignmentSolutions.viewModes.default": "All solutions (default)", "app.assignmentSolutions.viewModes.grouped": "Grouped by users", "app.assignmentSolutions.viewModes.last": "Latest solutions only", + "app.assignmentSolutions.viewModes.plagiarism": "Only plagiarism suspects", "app.assignmentSolutions.viewModes.reviewed": "Reviewed solutions only", "app.assignmentSolutions.viewModesTitle": "Select solutions view filter", "app.assignments.deadline": "Deadline", @@ -2067,4 +2069,4 @@ "recodex-judge-shuffle-all": "Unordered-tokens-and-rows judge", "recodex-judge-shuffle-newline": "Unordered-tokens judge (ignoring ends of lines)", "recodex-judge-shuffle-rows": "Unordered-rows judge" -} +} \ No newline at end of file diff --git a/src/pages/AssignmentSolutions/AssignmentSolutions.js b/src/pages/AssignmentSolutions/AssignmentSolutions.js index 11632d208..aa149c6e6 100644 --- a/src/pages/AssignmentSolutions/AssignmentSolutions.js +++ b/src/pages/AssignmentSolutions/AssignmentSolutions.js @@ -67,7 +67,7 @@ import { isReady, getJsData, getId } from '../../redux/helpers/resourceManager'; import { storageGetItem, storageSetItem } from '../../helpers/localStorage'; import withLinks from '../../helpers/withLinks'; -import { safeGet, identity, arrayToObject, toPlainAscii, hasPermissions } from '../../helpers/common'; +import { safeGet, identity, arrayToObject, toPlainAscii, hasPermissions, unique } from '../../helpers/common'; // View mode keys, labels, and filtering functions const VIEW_MODE_DEFAULT = 'default'; @@ -76,6 +76,7 @@ const VIEW_MODE_BEST = 'best'; const VIEW_MODE_LAST = 'last'; const VIEW_MODE_ACCEPTED = 'accepted'; const VIEW_MODE_REVIEWD = 'reviewed'; +const VIEW_MODE_PLAGIARISM = 'plagiarism'; const viewModes = { [VIEW_MODE_DEFAULT]: ( @@ -96,6 +97,9 @@ const viewModes = { [VIEW_MODE_REVIEWD]: ( ), + [VIEW_MODE_PLAGIARISM]: ( + + ), }; const _getLastAttemptIndices = defaultMemoize(solutions => { @@ -114,6 +118,7 @@ const viewModeFilters = { solution && solution.attemptIndex === _getLastAttemptIndices(solutions)[solution.authorId], [VIEW_MODE_ACCEPTED]: solution => solution && solution.accepted, [VIEW_MODE_REVIEWD]: solution => solution && solution.review, + [VIEW_MODE_PLAGIARISM]: solution => solution && solution.plagiarism, }; const prepareTableColumnDescriptors = defaultMemoize((loggedUserId, assignmentId, groupId, viewMode, locale, links) => { @@ -323,6 +328,8 @@ const getPlagiarisms = defaultMemoize(assignmentSolutions => .filter(solution => solution && solution.plagiarism) ); +const getPlagiarismUniqueAuthors = defaultMemoize(plagiarisms => unique(plagiarisms.map(({ authorId }) => authorId))); + const localStorageStateKey = 'AssignmentSolutions.state'; class AssignmentSolutions extends Component { @@ -438,9 +445,9 @@ class AssignmentSolutions extends Component { {plagiarisms && plagiarisms.length > 0 && ( }> )} diff --git a/src/pages/GroupUserSolutions/GroupUserSolutions.js b/src/pages/GroupUserSolutions/GroupUserSolutions.js index 61bd7be83..658e75086 100644 --- a/src/pages/GroupUserSolutions/GroupUserSolutions.js +++ b/src/pages/GroupUserSolutions/GroupUserSolutions.js @@ -59,7 +59,7 @@ import { compareAssignmentsReverted } from '../../components/helpers/assignments import { storageGetItem, storageSetItem } from '../../helpers/localStorage'; import { getLocalizedName } from '../../helpers/localizedData'; import withLinks from '../../helpers/withLinks'; -import { safeGet, identity, hasPermissions, hasOneOfPermissions } from '../../helpers/common'; +import { safeGet, identity, hasPermissions, hasOneOfPermissions, unique } from '../../helpers/common'; /** * Sorts all assignments and create a numerical index, so the solutions can be sorted faster @@ -292,6 +292,10 @@ const getPlagiarisms = defaultMemoize((assignments, getAssignmentSolutions) => : [] ); +const getPlagiarismUniqueAssignments = defaultMemoize(plagiarisms => + unique(plagiarisms.map(({ assignmentId }) => assignmentId)) +); + const localStorageStateKey = 'GroupUserSolutions.state'; class GroupUserSolutions extends Component { @@ -403,9 +407,12 @@ class GroupUserSolutions extends Component { {plagiarisms && plagiarisms.length > 0 && ( }> )}