use of de.tum.in.www1.artemis.domain.plagiarism.PlagiarismSubmission in project ArTEMiS by ls1intum.
the class ModelingPlagiarismDetectionService method checkPlagiarism.
/**
* Pairwise comparison of text submissions using a TextComparisonStrategy
*
* @param modelingSubmissions List of modeling submissions
* @param minimumSimilarity the minimum similarity so that the result is considered
* @param minimumModelSize the minimum number of model elements to be considered as plagiarism
* @param minimumScore the minimum result score (if available) to be considered as plagiarism
* @param exerciseId the id of the exercise for which the modeling submissions are compared
*
* @return List of submission id pairs and similarity score
*/
public ModelingPlagiarismResult checkPlagiarism(List<ModelingSubmission> modelingSubmissions, double minimumSimilarity, int minimumModelSize, int minimumScore, Long exerciseId) {
String topic = plagiarismWebsocketService.getModelingExercisePlagiarismCheckTopic(exerciseId);
ModelingPlagiarismResult result = new ModelingPlagiarismResult();
Map<UMLDiagram, ModelingSubmission> models = new HashMap<>();
ObjectMapper objectMapper = new ObjectMapper();
AtomicInteger processedSubmissionCount = new AtomicInteger(1);
modelingSubmissions.stream().filter(modelingSubmission -> !modelingSubmission.isEmpty(objectMapper)).filter(modelingSubmission -> minimumScore == 0 || modelingSubmission.getLatestResult() != null && modelingSubmission.getLatestResult().getScore() != null && modelingSubmission.getLatestResult().getScore() >= minimumScore).forEach(modelingSubmission -> {
String progressMessage = "Getting UML diagram for submission: " + processedSubmissionCount + "/" + modelingSubmissions.size();
plagiarismWebsocketService.notifyInstructorAboutPlagiarismState(topic, PlagiarismCheckState.RUNNING, List.of(progressMessage));
try {
log.debug("Build UML diagram from json");
UMLDiagram model = UMLModelParser.buildModelFromJSON(parseString(modelingSubmission.getModel()).getAsJsonObject(), modelingSubmission.getId());
if (model.getAllModelElements().size() >= minimumModelSize) {
models.put(model, modelingSubmission);
}
} catch (IOException e) {
log.error("Parsing the modeling submission " + modelingSubmission.getId() + " did throw an exception:", e);
}
processedSubmissionCount.getAndIncrement();
});
log.info("Found {} modeling submissions with at least {} elements to compare", models.size(), minimumModelSize);
Set<PlagiarismComparison<ModelingSubmissionElement>> comparisons = new HashSet<>();
List<UMLDiagram> nonEmptyDiagrams = new ArrayList<>(models.keySet());
long timeBeforeStartInMillis = System.currentTimeMillis();
// similarity between two different submissions once
for (int i = 0; i < nonEmptyDiagrams.size(); i++) {
String progressMessage = "Comparing submissions: " + (i + 1) + "/" + nonEmptyDiagrams.size();
plagiarismWebsocketService.notifyInstructorAboutPlagiarismState(topic, PlagiarismCheckState.RUNNING, List.of(progressMessage));
for (int j = i + 1; j < nonEmptyDiagrams.size(); j++) {
UMLDiagram model1 = nonEmptyDiagrams.get(i);
UMLDiagram model2 = nonEmptyDiagrams.get(j);
final double similarity = model1.similarity(model2);
log.debug("Compare result {} with {}: {}", i, j, similarity);
if (similarity < minimumSimilarity) {
// ignore comparison results with too small similarity
continue;
}
ModelingSubmission modelingSubmissionA = models.get(model1);
ModelingSubmission modelingSubmissionB = models.get(model2);
log.info("Found similar models {} with {}: {}", i, j, similarity);
PlagiarismSubmission<ModelingSubmissionElement> submissionA = PlagiarismSubmission.fromModelingSubmission(modelingSubmissionA);
submissionA.setSize(model1.getAllModelElements().size());
submissionA.setElements(model1.getAllModelElements().stream().map(ModelingSubmissionElement::fromUMLElement).collect(Collectors.toList()));
PlagiarismSubmission<ModelingSubmissionElement> submissionB = PlagiarismSubmission.fromModelingSubmission(modelingSubmissionB);
submissionB.setSize(model2.getAllModelElements().size());
submissionB.setElements(model2.getAllModelElements().stream().map(ModelingSubmissionElement::fromUMLElement).collect(Collectors.toList()));
PlagiarismComparison<ModelingSubmissionElement> comparison = new PlagiarismComparison<>();
comparison.setPlagiarismResult(result);
comparison.setSimilarity(similarity * 100);
comparison.setSubmissionA(submissionA);
comparison.setSubmissionB(submissionB);
// TODO: Add matches to highlight similar modeling elements
comparison.setMatches(new HashSet<>());
comparisons.add(comparison);
}
}
log.info("Found {} similar modeling submission combinations (>{})", comparisons.size(), minimumSimilarity);
plagiarismWebsocketService.notifyInstructorAboutPlagiarismState(topic, PlagiarismCheckState.COMPLETED, List.of());
long durationInMillis = System.currentTimeMillis() - timeBeforeStartInMillis;
int[] similarityDistribution = calculateSimilarityDistribution(comparisons);
result.setComparisons(comparisons);
result.setDuration(durationInMillis);
result.setSimilarityDistribution(similarityDistribution);
return result;
}
use of de.tum.in.www1.artemis.domain.plagiarism.PlagiarismSubmission in project ArTEMiS by ls1intum.
the class PlagiarismCaseService method createOrAddToPlagiarismCaseForStudent.
/**
* Create or add to a plagiarism case for a student defined via the submission involved in a plagiarism comparison.
* The following logic applies:
* * <ul>
* * <li>Create a new plagiarism case if the student isn't already part of a plagiarism case in the exercise</li>
* * <li>Add the submission of the student to existing plagiarism case otherwise</li>
* * </ul>
*
* @param plagiarismComparison the plagiarism comparison for which to create the plagiarism case
* @param plagiarismSubmission the plagiarism submission of the student for which to create the plagiarism case
*/
public void createOrAddToPlagiarismCaseForStudent(PlagiarismComparison<?> plagiarismComparison, PlagiarismSubmission<?> plagiarismSubmission) {
var plagiarismCase = plagiarismCaseRepository.findByStudentLoginAndExerciseIdWithPlagiarismSubmissions(plagiarismSubmission.getStudentLogin(), plagiarismComparison.getPlagiarismResult().getExercise().getId());
if (plagiarismCase.isPresent()) {
// add submission to existing PlagiarismCase for student
plagiarismSubmission.setPlagiarismCase(plagiarismCase.get());
plagiarismComparisonRepository.save(plagiarismComparison);
} else {
// create new PlagiarismCase for student
var student = userRepository.getUserByLoginElseThrow(plagiarismSubmission.getStudentLogin());
PlagiarismCase newPlagiarismCase = new PlagiarismCase();
newPlagiarismCase.setExercise(plagiarismComparison.getPlagiarismResult().getExercise());
newPlagiarismCase.setStudent(student);
var savedPlagiarismCase = plagiarismCaseRepository.save(newPlagiarismCase);
plagiarismSubmission.setPlagiarismCase(savedPlagiarismCase);
plagiarismComparisonRepository.save(plagiarismComparison);
}
}
use of de.tum.in.www1.artemis.domain.plagiarism.PlagiarismSubmission in project ArTEMiS by ls1intum.
the class ModelingSubmissionIntegrationTest method getModelSubmissionWithResult_involved_allowed.
@Test
@WithMockUser(username = "student1", roles = "USER")
public void getModelSubmissionWithResult_involved_allowed() throws Exception {
ModelingSubmission submission = ModelFactory.generateModelingSubmission(validModel, true);
submission = database.addModelingSubmission(classExercise, submission, "student1");
PlagiarismComparison<ModelingSubmissionElement> plagiarismComparison = new PlagiarismComparison<>();
PlagiarismSubmission<ModelingSubmissionElement> submissionA = new PlagiarismSubmission<>();
submissionA.setStudentLogin("student1");
submissionA.setSubmissionId(submission.getId());
plagiarismComparison.setSubmissionA(submissionA);
PlagiarismCase plagiarismCase = new PlagiarismCase();
plagiarismCase = plagiarismCaseRepository.save(plagiarismCase);
Post post = new Post();
post.setAuthor(userRepo.getUserByLoginElseThrow("instructor1"));
post.setTitle("Title Plagiarism Case Post");
post.setContent("Content Plagiarism Case Post");
post.setVisibleForStudents(true);
post.setPlagiarismCase(plagiarismCase);
postRepository.save(post);
submissionA.setPlagiarismCase(plagiarismCase);
plagiarismComparisonRepository.save(plagiarismComparison);
var submissionResult = request.get("/api/modeling-submissions/" + submission.getId(), HttpStatus.OK, ModelingSubmission.class);
assertThat(submissionResult.getParticipation()).as("Should anonymize participation").isNull();
assertThat(submissionResult.getResults()).as("Should anonymize results").isEmpty();
assertThat(submissionResult.getSubmissionDate()).as("Should anonymize submission date").isNull();
}
use of de.tum.in.www1.artemis.domain.plagiarism.PlagiarismSubmission in project ArTEMiS by ls1intum.
the class SingleUserNotificationFactoryTest method setUp.
/**
* sets up all needed mocks and their wanted behavior once for all test cases.
*/
@BeforeAll
public static void setUp() {
course = new Course();
course.setId(COURSE_ID);
lecture = new Lecture();
lecture.setId(LECTURE_ID);
lecture.setCourse(course);
exercise = new TextExercise();
exercise.setId(EXERCISE_ID);
exercise.setTitle(EXERCISE_TITLE);
exercise.setCourse(course);
exercise.setProblemStatement(PROBLEM_STATEMENT);
post = new Post();
post.setExercise(exercise);
post.setLecture(lecture);
answerPost = new AnswerPost();
answerPost.setPost(post);
cheatingUser = new User();
cheatingUser.setLogin(USER_LOGIN);
plagiarismResult = new TextPlagiarismResult();
plagiarismResult.setExercise(exercise);
plagiarismSubmission = new PlagiarismSubmission();
plagiarismSubmission.setStudentLogin(USER_LOGIN);
plagiarismSubmissionSet = new HashSet<>();
plagiarismSubmissionSet.add(plagiarismSubmission);
plagiarismComparison = new PlagiarismComparison();
plagiarismComparison.setPlagiarismResult(plagiarismResult);
plagiarismComparison.setSubmissionA(plagiarismSubmission);
plagiarismCase = new PlagiarismCase();
plagiarismCase.setExercise(exercise);
plagiarismCase.setStudent(cheatingUser);
plagiarismCase.setPlagiarismSubmissions(plagiarismSubmissionSet);
}
use of de.tum.in.www1.artemis.domain.plagiarism.PlagiarismSubmission in project Artemis by ls1intum.
the class ModelingPlagiarismDetectionService method checkPlagiarism.
/**
* Pairwise comparison of text submissions using a TextComparisonStrategy
*
* @param modelingSubmissions List of modeling submissions
* @param minimumSimilarity the minimum similarity so that the result is considered
* @param minimumModelSize the minimum number of model elements to be considered as plagiarism
* @param minimumScore the minimum result score (if available) to be considered as plagiarism
* @param exerciseId the id of the exercise for which the modeling submissions are compared
*
* @return List of submission id pairs and similarity score
*/
public ModelingPlagiarismResult checkPlagiarism(List<ModelingSubmission> modelingSubmissions, double minimumSimilarity, int minimumModelSize, int minimumScore, Long exerciseId) {
String topic = plagiarismWebsocketService.getModelingExercisePlagiarismCheckTopic(exerciseId);
ModelingPlagiarismResult result = new ModelingPlagiarismResult();
Map<UMLDiagram, ModelingSubmission> models = new HashMap<>();
ObjectMapper objectMapper = new ObjectMapper();
AtomicInteger processedSubmissionCount = new AtomicInteger(1);
modelingSubmissions.stream().filter(modelingSubmission -> !modelingSubmission.isEmpty(objectMapper)).filter(modelingSubmission -> minimumScore == 0 || modelingSubmission.getLatestResult() != null && modelingSubmission.getLatestResult().getScore() != null && modelingSubmission.getLatestResult().getScore() >= minimumScore).forEach(modelingSubmission -> {
String progressMessage = "Getting UML diagram for submission: " + processedSubmissionCount + "/" + modelingSubmissions.size();
plagiarismWebsocketService.notifyInstructorAboutPlagiarismState(topic, PlagiarismCheckState.RUNNING, List.of(progressMessage));
try {
log.debug("Build UML diagram from json");
UMLDiagram model = UMLModelParser.buildModelFromJSON(parseString(modelingSubmission.getModel()).getAsJsonObject(), modelingSubmission.getId());
if (model.getAllModelElements().size() >= minimumModelSize) {
models.put(model, modelingSubmission);
}
} catch (IOException e) {
log.error("Parsing the modeling submission " + modelingSubmission.getId() + " did throw an exception:", e);
}
processedSubmissionCount.getAndIncrement();
});
log.info("Found {} modeling submissions with at least {} elements to compare", models.size(), minimumModelSize);
Set<PlagiarismComparison<ModelingSubmissionElement>> comparisons = new HashSet<>();
List<UMLDiagram> nonEmptyDiagrams = new ArrayList<>(models.keySet());
long timeBeforeStartInMillis = System.currentTimeMillis();
// similarity between two different submissions once
for (int i = 0; i < nonEmptyDiagrams.size(); i++) {
String progressMessage = "Comparing submissions: " + (i + 1) + "/" + nonEmptyDiagrams.size();
plagiarismWebsocketService.notifyInstructorAboutPlagiarismState(topic, PlagiarismCheckState.RUNNING, List.of(progressMessage));
for (int j = i + 1; j < nonEmptyDiagrams.size(); j++) {
UMLDiagram model1 = nonEmptyDiagrams.get(i);
UMLDiagram model2 = nonEmptyDiagrams.get(j);
final double similarity = model1.similarity(model2);
log.debug("Compare result {} with {}: {}", i, j, similarity);
if (similarity < minimumSimilarity) {
// ignore comparison results with too small similarity
continue;
}
ModelingSubmission modelingSubmissionA = models.get(model1);
ModelingSubmission modelingSubmissionB = models.get(model2);
log.info("Found similar models {} with {}: {}", i, j, similarity);
PlagiarismSubmission<ModelingSubmissionElement> submissionA = PlagiarismSubmission.fromModelingSubmission(modelingSubmissionA);
submissionA.setSize(model1.getAllModelElements().size());
submissionA.setElements(model1.getAllModelElements().stream().map(ModelingSubmissionElement::fromUMLElement).collect(Collectors.toList()));
PlagiarismSubmission<ModelingSubmissionElement> submissionB = PlagiarismSubmission.fromModelingSubmission(modelingSubmissionB);
submissionB.setSize(model2.getAllModelElements().size());
submissionB.setElements(model2.getAllModelElements().stream().map(ModelingSubmissionElement::fromUMLElement).collect(Collectors.toList()));
PlagiarismComparison<ModelingSubmissionElement> comparison = new PlagiarismComparison<>();
comparison.setPlagiarismResult(result);
comparison.setSimilarity(similarity * 100);
comparison.setSubmissionA(submissionA);
comparison.setSubmissionB(submissionB);
// TODO: Add matches to highlight similar modeling elements
comparison.setMatches(new HashSet<>());
comparisons.add(comparison);
}
}
log.info("Found {} similar modeling submission combinations (>{})", comparisons.size(), minimumSimilarity);
plagiarismWebsocketService.notifyInstructorAboutPlagiarismState(topic, PlagiarismCheckState.COMPLETED, List.of());
long durationInMillis = System.currentTimeMillis() - timeBeforeStartInMillis;
int[] similarityDistribution = calculateSimilarityDistribution(comparisons);
result.setComparisons(comparisons);
result.setDuration(durationInMillis);
result.setSimilarityDistribution(similarityDistribution);
return result;
}
Aggregations