Skip to content

Commit

Permalink
simon feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
az108 committed Dec 2, 2024
1 parent 1a0a907 commit d363283
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
Expand Down Expand Up @@ -626,7 +626,7 @@ public FeedbackAnalysisResponseDTO getFeedbackDetailsOnPage(long exerciseId, Fee
List<FeedbackDetailDTO> processedDetails;
int totalPages = 0;
long levenshteinMaxCount = 0;
if (levenshtein.equals("false")) {
if (!Boolean.parseBoolean(levenshtein)) {
feedbackDetailPage = studentParticipationRepository.findFilteredFeedbackByExerciseId(exerciseId,
StringUtils.isBlank(data.getSearchTerm()) ? "" : data.getSearchTerm().toLowerCase(), data.getFilterTestCases(), includeUnassignedTasks, minOccurrence,
maxOccurrence, filterErrorCategories, pageable);
Expand All @@ -645,7 +645,7 @@ public FeedbackAnalysisResponseDTO getFeedbackDetailsOnPage(long exerciseId, Fee
List<FeedbackDetailDTO> allFeedbackDetails = feedbackDetailPage.getContent();

// Apply Levenshtein-based grouping and aggregation with a similarity threshold of 90%
List<FeedbackDetailDTO> aggregatedFeedbackDetails = aggregateUsingLevenshtein(allFeedbackDetails, 0.9);
List<FeedbackDetailDTO> aggregatedFeedbackDetails = aggregateUsingLevenshtein(allFeedbackDetails, 0.5);

levenshteinMaxCount = aggregatedFeedbackDetails.stream().mapToLong(FeedbackDetailDTO::count).max().orElse(0);
// Apply manual pagination
Expand Down Expand Up @@ -682,43 +682,36 @@ private Comparator<FeedbackDetailDTO> getComparatorForFeedbackDetails(FeedbackPa
}

private List<FeedbackDetailDTO> aggregateUsingLevenshtein(List<FeedbackDetailDTO> feedbackDetails, double similarityThreshold) {
List<FeedbackDetailDTO> aggregatedList = new ArrayList<>();
Set<Integer> processedIndices = new HashSet<>();

for (int i = 0; i < feedbackDetails.size(); i++) {
if (processedIndices.contains(i)) {
continue; // Skip already aggregated feedback
}

FeedbackDetailDTO base = feedbackDetails.get(i);
List<String> aggregatedTexts = new ArrayList<>();
aggregatedTexts.add(base.detailText().getFirst());
long totalCount = base.count();

for (int j = i + 1; j < feedbackDetails.size(); j++) {
if (processedIndices.contains(j)) {
continue;
}

FeedbackDetailDTO compare = feedbackDetails.get(j);
// Group by testCaseName and taskName using nested maps
Map<String, Map<String, List<FeedbackDetailDTO>>> groupedByKeys = feedbackDetails.stream()
.collect(Collectors.groupingBy(FeedbackDetailDTO::testCaseName, Collectors.groupingBy(FeedbackDetailDTO::taskName)));

// Ensure feedbacks have the same testCaseName and taskName
if (base.testCaseName().equals(compare.testCaseName()) && base.taskName().equals(compare.taskName())) {
double similarity = NameSimilarity.levenshteinSimilarity(base.detailText().getFirst(), compare.detailText().getFirst());
List<FeedbackDetailDTO> aggregatedList = new ArrayList<>();

if (similarity > similarityThreshold) {
// Merge the feedbacks
aggregatedTexts.add(compare.detailText().getFirst());
totalCount += compare.count();
processedIndices.add(j);
// Iterate through the grouped data
groupedByKeys.forEach((testCaseName, taskMap) -> {
taskMap.forEach((taskName, feedbackGroup) -> {
List<FeedbackDetailDTO> unprocessed = new ArrayList<>(feedbackGroup);
while (!unprocessed.isEmpty()) {
FeedbackDetailDTO base = unprocessed.removeFirst();
List<String> aggregatedTexts = new ArrayList<>(base.detailText());
long totalCount = base.count();

Iterator<FeedbackDetailDTO> iterator = unprocessed.iterator();
while (iterator.hasNext()) {
FeedbackDetailDTO compare = iterator.next();
double similarity = NameSimilarity.levenshteinSimilarity(base.detailText().get(0), compare.detailText().get(0));
if (similarity > similarityThreshold) {
aggregatedTexts.add(compare.detailText().get(0));
totalCount += compare.count();
iterator.remove(); // Remove processed entry
}
}
}
}

// Add aggregated feedback entry
aggregatedList.add(new FeedbackDetailDTO(totalCount, 0, aggregatedTexts, base.testCaseName(), base.taskName(), base.errorCategory()));
processedIndices.add(i);
}
aggregatedList.add(new FeedbackDetailDTO(totalCount, 0, aggregatedTexts, testCaseName, taskName, base.errorCategory()));
}
});
});

return aggregatedList;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1378,14 +1378,9 @@ SELECT MAX(pr.id)
p.repositoryUri
)
FROM ProgrammingExerciseStudentParticipation p
INNER JOIN p.submissions s ON s.id = (
SELECT MAX(sub.id)
FROM p.submissions sub
WHERE sub.participation.id = p.id
)
INNER JOIN s.results r ON r.id = (
INNER JOIN p.results r ON r.id = (
SELECT MAX(pr.id)
FROM s.results pr
FROM p.results pr
WHERE pr.participation.id = p.id
)
INNER JOIN r.feedbacks f
Expand All @@ -1409,14 +1404,9 @@ Page<FeedbackAffectedStudentDTO> findAffectedStudentsByFeedbackText(@Param("exer
@Query("""
SELECT DISTINCT p.student.login
FROM ProgrammingExerciseStudentParticipation p
INNER JOIN p.submissions s ON s.id = (
SELECT MAX(sub.id)
FROM p.submissions sub
WHERE sub.participation.id = p.id
)
INNER JOIN s.results r ON r.id = (
INNER JOIN p.results r ON r.id = (
SELECT MAX(pr.id)
FROM s.results pr
FROM p.results pr
WHERE pr.participation.id = p.id
)
INNER JOIN r.feedbacks f
Expand Down
4 changes: 2 additions & 2 deletions src/main/webapp/i18n/de/programmingExercise.json
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@
"repository": "Repository",
"totalItems": "Insgesamt {{count}} Element(e)",
"error": "Beim Laden der betroffenen Studierenden ist ein Fehler aufgetreten.",
"levenshteinInfoTitle": "Feedback gruppieren aktiviert",
"levenshteinInfoTitle": "Feedback Gruppierung aktiviert",
"levenshteinInfoDescription": "Die Anzahl der von dem gruppierten Feedback betroffenen Studierenden könnte höher sein, da nur die betroffenen Studierenden für bis zu fünf Feedbackdetails überprüft werden. Mehr Feedbackdetails einzubeziehen ist für die Analyse eines gemeinsamen gruppierten Feedbacks nicht notwendig und könnte zu Leistungseinbußen führen."
},
"feedbackDetailChannel": {
Expand All @@ -407,7 +407,7 @@
"regexValidationErrorName": "Namen können nur Kleinbuchstaben, Zahlen und Striche enthalten. Nur Artemis kann Kanäle erstellen, die mit $ beginnen.",
"requiredValidationErrorDescription": "Die Kanalbeschreibung ist ein Pflichtfeld.",
"maxLengthValidationErrorDescription": "Kanalbeschreibung kann max {{ max }} Zeichen lang sein!",
"levenshteinInfoTitle": "Feedback gruppieren aktiviert",
"levenshteinInfoTitle": "Feedback Gruppierung aktiviert",
"levenshteinInfoDescription": "Die Anzahl der zum Kanal hinzugefügten Studierenden stellt eine Obergrenze dar. Die tatsächliche Anzahl könnte geringer sein, da mehrere Studierende für einen einzelnen Testfall ähnliches Feedback erhalten könnten.",
"confirmationModal": {
"header": "Kanal Erstellen bestätigen",
Expand Down

0 comments on commit d363283

Please sign in to comment.