Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* substitution-schedule-parser - Java library for parsing schools' substitution schedules
* Copyright (c) 2016 Johan v. Forstner
*
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package me.vertretungsplan.objects.diff;
import me.vertretungsplan.objects.Substitution;
import me.vertretungsplan.objects.SubstitutionSchedule;
import me.vertretungsplan.objects.SubstitutionScheduleDay;
import org.joda.time.LocalDate;
import java.util.*;
/**
* Represents the difference between two {@link SubstitutionScheduleDay}s.
*/
public class SubstitutionScheduleDayDiff implements Cloneable {
private LocalDate date;
private String dateString;
private Set newSubstitutions;
private Set editedSubstitutions;
private Set removedSubstitutions;
private List newMessages;
private List removedMessages;
public static SubstitutionScheduleDayDiff compare(SubstitutionScheduleDay a,
SubstitutionScheduleDay b) {
if (!a.equalsByDate(b)) {
throw new IllegalArgumentException("Days must have the same date");
}
SubstitutionScheduleDayDiff diff = new SubstitutionScheduleDayDiff();
diff.date = a.getDate();
diff.dateString = a.getDateString();
diff.newMessages = new ArrayList<>();
diff.removedMessages = new ArrayList<>();
diff.newSubstitutions = new HashSet<>();
diff.editedSubstitutions = new HashSet<>();
diff.removedSubstitutions = new HashSet<>();
for (String message : b.getMessages()) {
if (!a.getMessages().contains(message)) {
diff.newMessages.add(message);
}
}
for (String message : a.getMessages()) {
if (!b.getMessages().contains(message)) {
diff.removedMessages.add(message);
}
}
// save all old substitutions that were already handled here to speed up the second run
Set handledOldSubstitutions = new HashSet<>();
// first run: go through all new substitutions and search for matching old substitutions
for (Substitution newSubstitution : b.getSubstitutions()) {
if (a.getSubstitutions().contains(newSubstitution)) {
// this substitution has not changed in any way
handledOldSubstitutions.add(newSubstitution);
continue;
}
Substitution oldSubstitution = findEqualSubtitutionExcludingClasses(newSubstitution, a.getSubstitutions(),
handledOldSubstitutions);
if (oldSubstitution != null) {
// The same substitution was already there, but the set of classes has changed
Set newClasses = new HashSet<>();
for (String currentClass : newSubstitution.getClasses()) {
if (!oldSubstitution.getClasses().contains(currentClass)) {
newClasses.add(currentClass);
}
}
if (!newClasses.isEmpty()) {
diff.newSubstitutions.add(new Substitution(newSubstitution, newClasses));
}
Set removedClasses = new HashSet<>();
for (String currentClass : oldSubstitution.getClasses()) {
if (!newSubstitution.getClasses().contains(currentClass)) {
removedClasses.add(currentClass);
}
}
if (!removedClasses.isEmpty()) {
diff.removedSubstitutions.add(new Substitution(newSubstitution,
removedClasses));
}
handledOldSubstitutions.add(oldSubstitution);
continue;
}
oldSubstitution = findSimilarSubstitution(newSubstitution, a.getSubstitutions(), handledOldSubstitutions);
if (oldSubstitution != null) {
// there is a similar substitution, create a SubstitutionDiff
SubstitutionDiff substitutionDiff = SubstitutionDiff.compare(oldSubstitution, newSubstitution);
// Only use the diff if its complexity is low enough. Otherwise, regard this as a new substitution.
if (substitutionDiff.getComplexity() <= SubstitutionDiff.MAX_COMPLEXITY) {
diff.editedSubstitutions.add(substitutionDiff);
handledOldSubstitutions.add(oldSubstitution);
continue;
}
}
// There seems to be no matching substitution, so this is new
diff.newSubstitutions.add(newSubstitution);
}
// second run: go through all unhandled old substitutions -> they must have been removed
for (Substitution oldSubstitution : a.getSubstitutions()) {
if (!handledOldSubstitutions.contains(oldSubstitution)) {
diff.removedSubstitutions.add(oldSubstitution);
}
}
return diff;
}
private static int calculateSimilarityScore(Substitution a, Substitution b) {
int score = 0;
if (Objects.equals(a.getLesson(), b.getLesson())) score++;
if (Objects.equals(a.getType(), b.getType())) score++;
if (Objects.equals(a.getSubject(), b.getSubject())) score++;
if (Objects.equals(a.getPreviousSubject(), b.getPreviousSubject())) score++;
if (Objects.equals(a.getTeachers(), b.getTeachers())) score++;
if (Objects.equals(a.getPreviousTeachers(), b.getPreviousTeachers())) score++;
if (Objects.equals(a.getRoom(), b.getRoom())) score++;
if (Objects.equals(a.getPreviousRoom(), b.getPreviousRoom())) score++;
if (Objects.equals(a.getDesc(), b.getDesc())) score++;
return score;
}
private static Substitution findSimilarSubstitution(Substitution subst, Set substs,
Set handledSubsts) {
int maxScore = 0;
Substitution maxScoreSubstitution = null;
for (Substitution currentSubst : substs) {
if (currentSubst.getClasses().equals(subst.getClasses())
&& !handledSubsts.contains(currentSubst)) {
int score = calculateSimilarityScore(currentSubst, subst);
if (score > maxScore) {
maxScore = score;
maxScoreSubstitution = currentSubst;
}
}
}
if (maxScore > 0) {
return maxScoreSubstitution;
} else {
return null;
}
}
private static Substitution findEqualSubtitutionExcludingClasses(Substitution subst,
Set substs,
Set handledSubsts) {
for (Substitution currentSubst : substs) {
if (currentSubst.equalsExcludingClasses(subst) && !handledSubsts.contains(currentSubst)) {
return currentSubst;
}
}
return null;
}
public LocalDate getDate() {
return date;
}
public void setDate(LocalDate date) {
this.date = date;
}
public String getDateString() {
return dateString;
}
public void setDateString(String dateString) {
this.dateString = dateString;
}
/**
* @return the set of substitutions that were added to the schedule for this day
*/
public Set getNewSubstitutions() {
return newSubstitutions;
}
public void setNewSubstitutions(Set newSubstitutions) {
this.newSubstitutions = newSubstitutions;
}
/**
* @return the set of substitutions that were edited on the schedule for this day
*/
public Set getEditedSubstitutions() {
return editedSubstitutions;
}
public void setEditedSubstitutions(Set editedSubstitutions) {
this.editedSubstitutions = editedSubstitutions;
}
/**
* @return the set of substitutions that were removed from the schedule for this day
*/
public Set getRemovedSubstitutions() {
return removedSubstitutions;
}
public void setRemovedSubstitutions(Set removedSubstitutions) {
this.removedSubstitutions = removedSubstitutions;
}
/**
* @return the list of messages that were added to the schedule for this day
*/
public List getNewMessages() {
return newMessages;
}
public void setNewMessages(List newMessages) {
this.newMessages = newMessages;
}
/**
* @return the list of messages that were removed from the schedule for this day
*/
public List getRemovedMessages() {
return removedMessages;
}
public void setRemovedMessages(List removedMessages) {
this.removedMessages = removedMessages;
}
public boolean isNotEmpty() {
return !newMessages.isEmpty() || !removedMessages.isEmpty() || !newSubstitutions.isEmpty()
|| !removedSubstitutions.isEmpty() || !editedSubstitutions.isEmpty();
}
public Set getNewSubstitutionsByClassAndExcludedSubject(String theClass, Set excludedSubjects) {
return SubstitutionSchedule.filterBySubject(excludedSubjects, SubstitutionSchedule
.filterByClass(theClass, newSubstitutions));
}
public Set getRemovedSubstitutionsByClassAndExcludedSubject(String theClass,
Set excludedSubjects) {
return SubstitutionSchedule.filterBySubject(excludedSubjects, SubstitutionSchedule
.filterByClass(theClass, removedSubstitutions));
}
public Set getEditedSubstitutionsByClassAndExcludedSubject(String theClass,
Set excludedSubjects) {
return SubstitutionScheduleDiff.filterBySubject(excludedSubjects, SubstitutionScheduleDiff
.filterByClass(theClass, editedSubstitutions));
}
public Set getNewSubstitutionsByTeacherAndExcludedSubject(String teacher,
Set excludedSubjects) {
return SubstitutionSchedule.filterBySubject(excludedSubjects, SubstitutionSchedule
.filterByTeacher(teacher, newSubstitutions));
}
public Set getRemovedSubstitutionsByTeacherAndExcludedSubject(String teacher,
Set excludedSubjects) {
return SubstitutionSchedule.filterBySubject(excludedSubjects, SubstitutionSchedule
.filterByTeacher(teacher, removedSubstitutions));
}
public Set getEditedSubstitutionsByTeacherAndExcludedSubject(String teacher,
Set excludedSubjects) {
return SubstitutionScheduleDiff.filterBySubject(excludedSubjects, SubstitutionScheduleDiff
.filterByTeacher(teacher, editedSubstitutions));
}
public SubstitutionScheduleDayDiff clone() {
try {
return (SubstitutionScheduleDayDiff) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}