Search in sources :

Example 1 with Substitution

use of me.vertretungsplan.objects.Substitution in project substitution-schedule-parser by vertretungsplanme.

the class IndiwareParser method parseIndiwareDay.

SubstitutionScheduleDay parseIndiwareDay(Element doc, boolean html) throws IOException, JSONException {
    SubstitutionScheduleDay day = new SubstitutionScheduleDay();
    DataSource ds;
    if (html) {
        ds = new HTMLDataSource(doc);
    } else {
        ds = new XMLDataSource(doc);
    }
    Matcher matcher = datePattern.matcher(ds.titel().text());
    if (!matcher.find())
        throw new IOException("malformed date: " + ds.titel().text());
    String date = matcher.group();
    day.setDate(DateTimeFormat.forPattern("EEEE, dd. MMMM yyyy").withLocale(Locale.GERMAN).parseLocalDate(date));
    matcher = lastChangePattern.matcher(ds.datum().text());
    if (!matcher.find())
        throw new IOException("malformed date: " + ds.datum().text());
    String lastChange = matcher.group();
    day.setLastChange(DateTimeFormat.forPattern("dd.MM.yyyy, HH:mm").withLocale(Locale.GERMAN).parseLocalDateTime(lastChange));
    if (ds.kopfinfos().size() > 0) {
        for (Element kopfinfo : ds.kopfinfos()) {
            String title = html ? kopfinfo.select("th").text() : kopfinfoTitle(kopfinfo.tagName()) + ":";
            StringBuilder message = new StringBuilder();
            if (title != null && !title.isEmpty()) {
                message.append("<b>").append(title).append("</b>").append(" ");
            }
            message.append(html ? kopfinfo.select("td").text() : kopfinfo.text());
            day.addMessage(message.toString());
        }
    }
    if (ds.fuss() != null) {
        StringBuilder message = new StringBuilder();
        boolean first = true;
        for (Element fusszeile : ds.fusszeilen()) {
            if (first) {
                first = false;
            } else {
                message.append("<br>\n");
            }
            message.append(fusszeile.text());
        }
        day.addMessage(message.toString());
    }
    if (ds.aufsichten() != null) {
        StringBuilder message = new StringBuilder();
        message.append("<b>").append("GeƤnderte Aufsichten:").append("</b>");
        for (Element aufsicht : ds.aufsichtzeilen()) {
            message.append("<br>\n");
            message.append(aufsicht.text());
        }
        day.addMessage(message.toString());
    }
    List<String> columnTypes = null;
    if (html) {
        columnTypes = new ArrayList<>();
        for (Element th : ((HTMLDataSource) ds).headers()) {
            Set<String> classNames = th.classNames();
            for (String className : classNames) {
                if (className.contains("thplan") || className.contains("thlplan")) {
                    columnTypes.add(className.replace("thplan", "").replace("thlplan", "").replace("_scheuler", // sic! -> http://www.hildebrand-gymnasium.de/index.php/klasse-5.html
                    ""));
                    break;
                }
            }
        }
    }
    for (Element aktion : ds.aktionen()) {
        Substitution substitution = new Substitution();
        String course = null;
        int i = 0;
        for (Element info : aktion.children()) {
            String value = info.text().replace("\u00a0", "");
            if (value.equals("---")) {
                i++;
                continue;
            }
            final String columnType = html ? columnTypes.get(i) : info.tagName();
            switch(columnType) {
                case "klasse":
                    ClassAndCourse cac = new ClassAndCourse(value, data);
                    course = cac.course;
                    substitution.setClasses(cac.classes);
                    break;
                case "stunde":
                    substitution.setLesson(value);
                    break;
                case "fach":
                    String subject = subjectAndCourse(course, value);
                    if (columnTypes != null && columnTypes.contains("vfach")) {
                        substitution.setPreviousSubject(subject);
                    } else {
                        substitution.setSubject(subject);
                    }
                    break;
                case "vfach":
                    substitution.setSubject(subjectAndCourse(course, value));
                case "lehrer":
                    Matcher bracesMatcher = bracesPattern.matcher(value);
                    if (bracesMatcher.matches()) {
                        value = bracesMatcher.group(1);
                        substitution.setPreviousTeachers(new HashSet<>(Arrays.asList(value.split(", "))));
                    } else {
                        substitution.setTeachers(new HashSet<>(Arrays.asList(value.split(", "))));
                    }
                    break;
                case "raum":
                    if (columnTypes != null && columnTypes.contains("vraum")) {
                        substitution.setPreviousRoom(value);
                    } else {
                        substitution.setRoom(value);
                    }
                    break;
                case "vraum":
                    substitution.setRoom(value);
                case "info":
                    handleDescription(substitution, value);
                    break;
            }
            i++;
        }
        if (substitution.getType() == null)
            substitution.setType("Vertretung");
        substitution.setColor(colorProvider.getColor(substitution.getType()));
        if (course != null && substitution.getSubject() == null) {
            substitution.setSubject(course);
        }
        day.addSubstitution(substitution);
    }
    return day;
}
Also used : Matcher(java.util.regex.Matcher) Element(org.jsoup.nodes.Element) IOException(java.io.IOException) Substitution(me.vertretungsplan.objects.Substitution) SubstitutionScheduleDay(me.vertretungsplan.objects.SubstitutionScheduleDay)

Example 2 with Substitution

use of me.vertretungsplan.objects.Substitution in project substitution-schedule-parser by vertretungsplanme.

the class LegionBoardParser method parseLegionBoard.

void parseLegionBoard(SubstitutionSchedule substitutionSchedule, JSONArray changes, JSONArray courses, JSONArray teachers) throws IOException, JSONException {
    if (changes == null) {
        return;
    }
    // Link course IDs to their names
    HashMap<String, String> coursesHashMap = null;
    if (courses != null) {
        coursesHashMap = new HashMap<>();
        for (int i = 0; i < courses.length(); i++) {
            JSONObject course = courses.getJSONObject(i);
            coursesHashMap.put(course.getString("id"), course.getString("name"));
        }
    }
    // Link teacher IDs to their names
    HashMap<String, String> teachersHashMap = null;
    if (teachers != null) {
        teachersHashMap = new HashMap<>();
        for (int i = 0; i < teachers.length(); i++) {
            JSONObject teacher = teachers.getJSONObject(i);
            teachersHashMap.put(teacher.getString("id"), teacher.getString("name"));
        }
    }
    // Add changes to SubstitutionSchedule
    LocalDate currentDate = LocalDate.now();
    SubstitutionScheduleDay substitutionScheduleDay = new SubstitutionScheduleDay();
    substitutionScheduleDay.setDate(currentDate);
    for (int i = 0; i < changes.length(); i++) {
        final JSONObject change = changes.getJSONObject(i);
        final Substitution substitution = getSubstitution(change, coursesHashMap, teachersHashMap);
        final LocalDate startingDate = new LocalDate(change.getString("startingDate"));
        final LocalDate endingDate = new LocalDate(change.getString("endingDate"));
        // Handle multi-day changes
        if (!startingDate.isEqual(endingDate)) {
            if (!substitutionScheduleDay.getSubstitutions().isEmpty()) {
                substitutionSchedule.addDay(substitutionScheduleDay);
            }
            for (int k = 0; k < 8; k++) {
                final LocalDate date = LocalDate.now().plusDays(k);
                if ((date.isAfter(startingDate) || date.isEqual(startingDate)) && (date.isBefore(endingDate) || date.isEqual(endingDate))) {
                    substitutionScheduleDay = new SubstitutionScheduleDay();
                    substitutionScheduleDay.setDate(date);
                    substitutionScheduleDay.addSubstitution(substitution);
                    substitutionSchedule.addDay(substitutionScheduleDay);
                    currentDate = date;
                }
            }
            continue;
        }
        // If starting date of change does not equal date of SubstitutionScheduleDay
        if (!startingDate.isEqual(currentDate)) {
            if (!substitutionScheduleDay.getSubstitutions().isEmpty()) {
                substitutionSchedule.addDay(substitutionScheduleDay);
            }
            substitutionScheduleDay = new SubstitutionScheduleDay();
            substitutionScheduleDay.setDate(startingDate);
            currentDate = startingDate;
        }
        substitutionScheduleDay.addSubstitution(substitution);
    }
    substitutionSchedule.addDay(substitutionScheduleDay);
}
Also used : JSONObject(org.json.JSONObject) Substitution(me.vertretungsplan.objects.Substitution) SubstitutionScheduleDay(me.vertretungsplan.objects.SubstitutionScheduleDay) LocalDate(org.joda.time.LocalDate)

Example 3 with Substitution

use of me.vertretungsplan.objects.Substitution in project substitution-schedule-parser by vertretungsplanme.

the class LegionBoardParser method getSubstitution.

private Substitution getSubstitution(JSONObject change, HashMap<String, String> coursesHashMap, HashMap<String, String> teachersHashMap) throws IOException, JSONException {
    final Substitution substitution = new Substitution();
    // Set class
    final String classId = change.getString("course");
    if (!classId.equals("0")) {
        if (coursesHashMap == null) {
            throw new IOException("Change references a course but courses are empty.");
        }
        final String singleClass = coursesHashMap.get(classId);
        final HashSet<String> classes = new HashSet<>();
        classes.add(singleClass);
        substitution.setClasses(classes);
    }
    // Set type
    String type = "Unknown";
    switch(change.getString("type")) {
        case "0":
            type = "Entfall";
            break;
        case "1":
            type = "Vertretung";
            break;
        case "2":
            type = "Information";
            break;
    }
    substitution.setType(type);
    // Set color
    substitution.setColor(colorProvider.getColor(type));
    // Set covering teacher
    final String coveringTeacherId = change.getString("coveringTeacher");
    if (!coveringTeacherId.equals("0")) {
        if (teachersHashMap == null) {
            throw new IOException("Change references a covering teacher but teachers are empty.");
        }
        if (!teachersHashMap.get(coveringTeacherId).equals("-")) {
            substitution.setTeacher(teachersHashMap.get(coveringTeacherId));
        }
    }
    // Set teacher
    final String teacherId = change.getString("teacher");
    if (!teacherId.equals("0")) {
        if (teachersHashMap == null) {
            throw new IOException("Change references a teacher but teachers are empty.");
        }
        if (!teachersHashMap.get(teacherId).equals("-")) {
            if (type.equals("Vertretung") || substitution.getTeacher() != null) {
                substitution.setPreviousTeacher(teachersHashMap.get(teacherId));
            } else {
                substitution.setTeacher(teachersHashMap.get(teacherId));
            }
        }
    }
    // Set description
    substitution.setDesc(change.getString("text"));
    // Set lesson
    final String startingHour = change.getString("startingHour").replaceFirst("^0+(?!$)", "");
    final String endingHour = change.getString("endingHour").replaceFirst("^0+(?!$)", "");
    if (!startingHour.equals("") || !endingHour.equals("")) {
        String lesson = "";
        if (!startingHour.equals("") && endingHour.equals("")) {
            lesson = "Ab " + startingHour;
        }
        if (startingHour.equals("") && !endingHour.equals("")) {
            lesson = "Bis " + endingHour;
        }
        if (!startingHour.equals("") && !endingHour.equals("")) {
            if (startingHour.equals(endingHour)) {
                lesson = startingHour;
            } else {
                lesson = startingHour + " - " + endingHour;
            }
        }
        substitution.setLesson(lesson);
    }
    return substitution;
}
Also used : Substitution(me.vertretungsplan.objects.Substitution) IOException(java.io.IOException)

Example 4 with Substitution

use of me.vertretungsplan.objects.Substitution in project substitution-schedule-parser by vertretungsplanme.

the class ESchoolParser method parseTable.

private void parseTable(Element table, SubstitutionScheduleDay day) {
    for (Element th : table.select("th[colspan=10]")) {
        String lesson;
        Pattern pattern = Pattern.compile("(\\d+)\\. Stunde");
        Matcher matcher = pattern.matcher(th.text());
        if (matcher.find()) {
            lesson = matcher.group(1);
        } else {
            lesson = th.text();
        }
        // skip over table headers
        Element row = th.parent().nextElementSibling().nextElementSibling();
        while (row != null && row.select("th").size() == 0) {
            Substitution subst = new Substitution();
            subst.setLesson(lesson);
            Elements columns = row.select("td");
            String[] classes = columns.get(0).text().split(", |\\+");
            subst.setClasses(new HashSet<>(Arrays.asList(classes)));
            subst.setPreviousTeacher(getPreviousValue(columns.get(1)));
            subst.setTeacher(getNewValue(columns.get(1)));
            subst.setPreviousSubject(getPreviousValue(columns.get(2)));
            subst.setSubject(getNewValue(columns.get(2)));
            subst.setPreviousRoom(getPreviousValue(columns.get(3)));
            subst.setRoom(getNewValue(columns.get(3)));
            if (columns.get(4).text().isEmpty()) {
                subst.setType("Vertretung");
                subst.setColor(colorProvider.getColor("Vertretung"));
            } else {
                String desc = columns.get(4).text();
                subst.setDesc(desc);
                String recognizedType = recognizeType(desc);
                if (recognizedType == null)
                    recognizedType = "Vertretung";
                subst.setType(recognizedType);
                subst.setColor(colorProvider.getColor(recognizedType));
            }
            day.addSubstitution(subst);
            row = row.nextElementSibling();
        }
    }
}
Also used : Pattern(java.util.regex.Pattern) Substitution(me.vertretungsplan.objects.Substitution) Matcher(java.util.regex.Matcher) Element(org.jsoup.nodes.Element) Elements(org.jsoup.select.Elements)

Example 5 with Substitution

use of me.vertretungsplan.objects.Substitution in project substitution-schedule-parser by vertretungsplanme.

the class SubstitutionScheduleDayDiff method compare.

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<Substitution> 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<String> 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<String> 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;
}
Also used : Substitution(me.vertretungsplan.objects.Substitution)

Aggregations

Substitution (me.vertretungsplan.objects.Substitution)35 Test (org.junit.Test)15 SubstitutionScheduleDay (me.vertretungsplan.objects.SubstitutionScheduleDay)14 Element (org.jsoup.nodes.Element)11 LocalDate (org.joda.time.LocalDate)9 SubstitutionSchedule (me.vertretungsplan.objects.SubstitutionSchedule)8 LocalDateTime (org.joda.time.LocalDateTime)7 Elements (org.jsoup.select.Elements)5 IOException (java.io.IOException)4 ArrayList (java.util.ArrayList)4 Document (org.jsoup.nodes.Document)4 Matcher (java.util.regex.Matcher)3 Pattern (java.util.regex.Pattern)2 JSONArray (org.json.JSONArray)2 JSONObject (org.json.JSONObject)2 HashSet (java.util.HashSet)1 SubstitutionDiff (me.vertretungsplan.objects.diff.SubstitutionDiff)1 NotNull (org.jetbrains.annotations.NotNull)1