use of de.tum.in.www1.artemis.domain.modeling.ModelingSubmission in project ArTEMiS by ls1intum.
the class ModelingPlagiarismDetectionService method checkPlagiarism.
/**
* Convenience method to extract all latest submissions from a ModelingExercise and compute pair-wise distances.
*
* @param exerciseWithParticipationsSubmissionsResults Text Exercise with fetched participations and 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
* @return List of submission id pairs and similarity score
*/
public ModelingPlagiarismResult checkPlagiarism(ModelingExercise exerciseWithParticipationsSubmissionsResults, double minimumSimilarity, int minimumModelSize, int minimumScore) {
final List<ModelingSubmission> modelingSubmissions = modelingSubmissionsForComparison(exerciseWithParticipationsSubmissionsResults);
log.info("Found {} modeling submissions in exercise {}", modelingSubmissions.size(), exerciseWithParticipationsSubmissionsResults.getId());
Long exerciseId = exerciseWithParticipationsSubmissionsResults.getId();
ModelingPlagiarismResult result = checkPlagiarism(modelingSubmissions, minimumSimilarity, minimumModelSize, minimumScore, exerciseId);
result.setExercise(exerciseWithParticipationsSubmissionsResults);
return result;
}
use of de.tum.in.www1.artemis.domain.modeling.ModelingSubmission 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.modeling.ModelingSubmission in project ArTEMiS by ls1intum.
the class ExamIntegrationTest method testStartExercisesWithModelingExercise.
@Test
@WithMockUser(username = "instructor1", roles = "INSTRUCTOR")
public void testStartExercisesWithModelingExercise() throws Exception {
// TODO IMPORTANT test more complex exam configurations (mixed exercise type, more variants and more registered students)
// registering users
var student1 = database.getUserByLogin("student1");
var student2 = database.getUserByLogin("student2");
var registeredUsers = Set.of(student1, student2);
exam2.setRegisteredUsers(registeredUsers);
// setting dates
exam2.setStartDate(now().plusHours(2));
exam2.setEndDate(now().plusHours(3));
exam2.setVisibleDate(now().plusHours(1));
// creating exercise
ModelingExercise modelingExercise = ModelFactory.generateModelingExerciseForExam(DiagramType.ClassDiagram, exam2.getExerciseGroups().get(0));
exam2.getExerciseGroups().get(0).addExercise(modelingExercise);
exerciseGroupRepository.save(exam2.getExerciseGroups().get(0));
modelingExercise = exerciseRepo.save(modelingExercise);
List<StudentExam> createdStudentExams = new ArrayList<>();
// creating student exams
for (User user : registeredUsers) {
StudentExam studentExam = new StudentExam();
studentExam.addExercise(modelingExercise);
studentExam.setUser(user);
exam2.addStudentExam(studentExam);
createdStudentExams.add(studentExamRepository.save(studentExam));
}
exam2 = examRepository.save(exam2);
// invoke start exercises
Integer noGeneratedParticipations = request.postWithResponseBody("/api/courses/" + course1.getId() + "/exams/" + exam2.getId() + "/student-exams/start-exercises", Optional.empty(), Integer.class, HttpStatus.OK);
assertThat(noGeneratedParticipations).isEqualTo(exam2.getStudentExams().size());
List<Participation> studentParticipations = participationTestRepository.findAllWithSubmissions();
for (Participation participation : studentParticipations) {
assertThat(participation.getExercise()).isEqualTo(modelingExercise);
assertThat(participation.getExercise().getCourseViaExerciseGroupOrCourseMember()).isNotNull();
assertThat(participation.getExercise().getExerciseGroup()).isEqualTo(exam2.getExerciseGroups().get(0));
assertThat(participation.getSubmissions()).hasSize(1);
var textSubmission = (ModelingSubmission) participation.getSubmissions().iterator().next();
assertThat(textSubmission.getModel()).isNull();
assertThat(textSubmission.getExplanationText()).isNull();
}
// Cleanup of Bidirectional Relationships
for (StudentExam studentExam : createdStudentExams) {
exam2.removeStudentExam(studentExam);
}
examRepository.save(exam2);
}
use of de.tum.in.www1.artemis.domain.modeling.ModelingSubmission in project ArTEMiS by ls1intum.
the class ExampleSubmissionIntegrationTest method importExampleSubmissionWithModelingSubmission_exerciseIdNotMatched.
@Test
@WithMockUser(username = "instructor1", roles = "INSTRUCTOR")
public void importExampleSubmissionWithModelingSubmission_exerciseIdNotMatched() throws Exception {
Submission submission = ModelFactory.generateModelingSubmission(validModel, true);
submission = database.addModelingSubmission(modelingExercise, (ModelingSubmission) submission, "student1");
Exercise modelingExerciseToBeConflicted = new ModelingExercise();
modelingExerciseToBeConflicted.setCourse(course);
Exercise exercise = exerciseRepository.save(modelingExerciseToBeConflicted);
importExampleSubmission(exercise.getId(), submission.getId(), HttpStatus.BAD_REQUEST);
}
use of de.tum.in.www1.artemis.domain.modeling.ModelingSubmission in project ArTEMiS by ls1intum.
the class AssessmentKnowledgeIntegrationTest method testSetModelAssessmentKnowledgeToModelElements.
/**
* Tests that a ModelAssessmentKnowledge is correctly set to model elements
* based on the ModelAssessmentKnowledge of the respective exercise
*
* @throws Exception might be thrown from Network Call to Artemis API
*/
@Test
@WithMockUser(username = "instructor1", roles = "INSTRUCTOR")
public void testSetModelAssessmentKnowledgeToModelElements() throws Exception {
ModelingSubmission submission1 = ModelFactory.generateModelingSubmission(FileUtils.loadFileFromResources("test-data/model-submission/model.54727.json"), true);
submission1.setId(1L);
ModelingSubmission submission2 = ModelFactory.generateModelingSubmission(FileUtils.loadFileFromResources("test-data/model-submission/model.54727.cpy.json"), true);
submission2.setId(2L);
ModelingSubmission submission3 = ModelFactory.generateModelingSubmission(FileUtils.loadFileFromResources("test-data/model-submission/model.54727.cpy.json"), true);
submission3.setId(3L);
ModelingSubmission submission4 = ModelFactory.generateModelingSubmission(FileUtils.loadFileFromResources("test-data/model-submission/model.54727.cpy.json"), true);
submission4.setId(4L);
Course course = database.addEmptyCourse();
ModelingExercise exercise1 = modelingExerciseUtilService.createModelingExercise(course.getId());
ModelingExercise exercise2 = modelingExerciseUtilService.createModelingExercise(course.getId());
modelAssessmentKnowledgeService = new ModelAssessmentKnowledgeService(modelAssessmentKnowledgeRepository, modelingExerciseRepository);
exercise1.setKnowledge(modelAssessmentKnowledgeService.createNewKnowledge());
exercise2.setKnowledge(modelAssessmentKnowledgeService.createNewKnowledge());
ModelClusterFactory modelClusterFactory = new ModelClusterFactory();
List<ModelCluster> modelClusters1 = modelClusterFactory.buildClusters(List.of(submission1, submission2), exercise1);
List<ModelCluster> modelClusters2 = modelClusterFactory.buildClusters(List.of(submission3, submission4), exercise2);
ModelCluster modelCluster = modelClusters1.get(0);
for (ModelElement element : modelCluster.getModelElements()) {
assertThat(element.getKnowledge().getId()).isEqualTo(exercise1.getKnowledge().getId());
}
modelCluster = modelClusters2.get(0);
for (ModelElement element : modelCluster.getModelElements()) {
assertThat(element.getKnowledge().getId()).isEqualTo(exercise2.getKnowledge().getId());
}
assertThat(exercise1.getKnowledge().getId()).isNotEqualTo(exercise2.getKnowledge().getId());
}
Aggregations