Make API responses structure flat (#149)

This commit is contained in:
Mikołaj Pich 2018-07-27 13:28:32 +02:00 committed by Rafał Borcz
parent ef5d3aead9
commit d7eac45e96
34 changed files with 1088 additions and 14 deletions

View File

@ -9,15 +9,16 @@ const val API_DATE_PATTERN = "yyyy-MM-dd"
const val TICKS_AT_EPOCH = 621355968000000000L
const val TICKS_PER_MILLISECOND = 10000
fun getFormattedDate(date: String): String {
fun getFormattedDate(date: String?): String {
return getFormattedDate(date, API_DATE_PATTERN)
}
fun getFormattedDate(date: String, format: String): String {
fun getFormattedDate(date: String?, format: String): String {
return getFormattedDate(date, LOG_DATE_PATTERN, format)
}
fun getFormattedDate(date: String, fromFormat: String, toFormat: String): String {
fun getFormattedDate(date: String?, fromFormat: String, toFormat: String): String {
if (date.isNullOrEmpty()) return ""
val sdf = SimpleDateFormat(fromFormat, Locale.ROOT)
val d = sdf.parse(date)
sdf.applyPattern(toFormat)

View File

@ -6,12 +6,20 @@ import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.List;
import io.github.wulkanowy.api.attendance.Attendance;
import io.github.wulkanowy.api.attendance.AttendanceLesson;
import io.github.wulkanowy.api.attendance.AttendanceStatistics;
import io.github.wulkanowy.api.attendance.AttendanceTable;
import io.github.wulkanowy.api.exams.ExamEntry;
import io.github.wulkanowy.api.exams.Exams;
import io.github.wulkanowy.api.exams.ExamsWeek;
import io.github.wulkanowy.api.generic.School;
import io.github.wulkanowy.api.grades.GradeKt;
import io.github.wulkanowy.api.grades.Grades;
import io.github.wulkanowy.api.grades.GradesList;
import io.github.wulkanowy.api.grades.GradesSummary;
import io.github.wulkanowy.api.grades.SubjectsList;
import io.github.wulkanowy.api.grades.Summary;
import io.github.wulkanowy.api.messages.Messages;
import io.github.wulkanowy.api.mobile.RegisterDevice;
import io.github.wulkanowy.api.mobile.RegisteredDevices;
@ -20,6 +28,8 @@ import io.github.wulkanowy.api.notes.NotesList;
import io.github.wulkanowy.api.school.SchoolInfo;
import io.github.wulkanowy.api.school.TeachersInfo;
import io.github.wulkanowy.api.timetable.Timetable;
import io.github.wulkanowy.api.timetable.TimetableKt;
import io.github.wulkanowy.api.timetable.TimetableLesson;
import io.github.wulkanowy.api.user.BasicInformation;
import io.github.wulkanowy.api.user.FamilyInformation;
@ -71,6 +81,11 @@ public class Vulcan {
return this.snp;
}
public List<AttendanceLesson> getAttendance(String dateStart) throws VulcanException, IOException {
return new Attendance(getStudentAndParent()).getAttendance(dateStart);
}
@Deprecated
public AttendanceTable getAttendanceTable() throws IOException, VulcanException {
return new AttendanceTable(getStudentAndParent());
}
@ -79,14 +94,29 @@ public class Vulcan {
return new AttendanceStatistics(getStudentAndParent());
}
public List<ExamEntry> getExams(String dateStart) throws VulcanException, IOException {
return new Exams(getStudentAndParent()).getExams(dateStart);
}
@Deprecated
public ExamsWeek getExamsList() throws IOException, VulcanException {
return new ExamsWeek(getStudentAndParent());
}
public List<GradeKt> getGrades(String semester) throws VulcanException, IOException {
return new Grades(getStudentAndParent()).getGrades(semester);
}
@Deprecated
public GradesList getGradesList() throws IOException, VulcanException {
return new GradesList(getStudentAndParent());
}
public List<Summary> getGradesSummary(String semester) throws VulcanException, IOException {
return new GradesSummary(getStudentAndParent()).getSummary(semester);
}
@Deprecated
public SubjectsList getSubjectsList() throws IOException, VulcanException {
return new SubjectsList(getStudentAndParent());
}
@ -107,6 +137,11 @@ public class Vulcan {
return new TeachersInfo(getStudentAndParent());
}
public List<TimetableLesson> getTimetable(String dateStart) throws VulcanException, IOException {
return new TimetableKt(getStudentAndParent()).getTimetable(dateStart);
}
@Deprecated
public Timetable getTimetable() throws IOException, VulcanException {
return new Timetable(getStudentAndParent());
}

View File

@ -0,0 +1,69 @@
package io.github.wulkanowy.api.attendance
import io.github.wulkanowy.api.SnP
import io.github.wulkanowy.api.getDateAsTick
import io.github.wulkanowy.api.getFormattedDate
import org.jsoup.nodes.Element
import org.jsoup.select.Elements
class Attendance(private val snp: SnP) {
fun getAttendance() = getAttendance("")
fun getAttendance(start: String): List<AttendanceLesson> {
val table = snp.getSnPPageDocument("Frekwencja.mvc?data=" + getDateAsTick(start))
.selectFirst(".mainContainer .presentData")
val days = getDays(table.select("thead th"))
return table.select("tbody tr").map {
val hours = it.select("td")
hours.drop(1).mapIndexed { i, item ->
getLesson(item, days[i], hours[0].text().toInt())
}
}.flatten().sortedBy {
it.date
}.filter {
it.subject.isNotBlank()
}
}
private fun getDays(el: Elements): List<String> {
return el.drop(1).map {
getFormattedDate(it.html().split("<br>")[1])
}
}
private fun getLesson(cell: Element, date: String, number: Int): AttendanceLesson {
val lesson = AttendanceLesson(number = number, date = date, subject = cell.select("span").text())
if (Types.CLASS_NOT_EXIST == cell.attr("class")) {
lesson.notExist = true
return lesson
}
when (cell.select("div").attr("class")) {
Types.CLASS_PRESENCE -> lesson.presence = true
Types.CLASS_ABSENCE_UNEXCUSED -> lesson.absenceUnexcused = true
Types.CLASS_ABSENCE_EXCUSED -> lesson.absenceExcused = true
Types.CLASS_ABSENCE_FOR_SCHOOL_REASONS -> lesson.absenceForSchoolReasons = true
Types.CLASS_UNEXCUSED_LATENESS -> lesson.unexcusedLateness = true
Types.CLASS_EXCUSED_LATENESS -> lesson.excusedLateness = true
Types.CLASS_EXEMPTION -> lesson.exemption = true
}
return lesson
}
private object Types {
const val CLASS_NOT_EXIST = "x-sp-nieobecny-w-oddziale"
const val CLASS_PRESENCE = "x-obecnosc"
const val CLASS_ABSENCE_UNEXCUSED = "x-nieobecnosc-nieuspr"
const val CLASS_ABSENCE_EXCUSED = "x-nieobecnosc-uspr"
const val CLASS_ABSENCE_FOR_SCHOOL_REASONS = "x-nieobecnosc-przycz-szkol"
const val CLASS_UNEXCUSED_LATENESS = "x-sp-nieusprawiedliwione"
const val CLASS_EXCUSED_LATENESS = "x-sp-spr"
const val CLASS_EXEMPTION = "x-sp-zwolnienie"
}
}

View File

@ -0,0 +1,26 @@
package io.github.wulkanowy.api.attendance
data class AttendanceLesson(
val number: Int,
val date: String,
val subject: String,
var notExist: Boolean = false,
var presence: Boolean = false,
var absenceUnexcused: Boolean = false,
var absenceExcused: Boolean = false,
var unexcusedLateness: Boolean = false,
var absenceForSchoolReasons: Boolean = false,
var excusedLateness: Boolean = false,
var exemption: Boolean = false
)

View File

@ -16,6 +16,7 @@ import io.github.wulkanowy.api.generic.Week;
import static io.github.wulkanowy.api.DateTimeUtilsKt.getDateAsTick;
import static io.github.wulkanowy.api.DateTimeUtilsKt.getFormattedDate;
@Deprecated
public class AttendanceTable {
private final static String ATTENDANCE_PAGE_URL = "Frekwencja.mvc?data=";

View File

@ -1,5 +1,6 @@
package io.github.wulkanowy.api.attendance;
@Deprecated
class LessonTypes {
static final String CLASS_NOT_EXIST = "x-sp-nieobecny-w-oddziale";

View File

@ -1,5 +1,6 @@
package io.github.wulkanowy.api.exams;
@Deprecated
public class Exam {
private String subjectAndGroup = "";

View File

@ -5,6 +5,7 @@ import java.util.List;
import io.github.wulkanowy.api.generic.Day;
@Deprecated
public class ExamDay extends Day {
private List<Exam> examList = new ArrayList<>();

View File

@ -0,0 +1,20 @@
package io.github.wulkanowy.api.exams
data class ExamEntry(
val date: String,
val entryDate: String,
val subject: String,
val group: String,
val type: String,
val description: String,
val teacher: String,
val teacherSymbol: String
)

View File

@ -0,0 +1,40 @@
package io.github.wulkanowy.api.exams
import io.github.wulkanowy.api.SnP
import io.github.wulkanowy.api.getDateAsTick
import io.github.wulkanowy.api.getFormattedDate
import org.jsoup.nodes.Element
class Exams(private val snp: SnP) {
fun getExams() = getExams("")
fun getExams(start: String): List<ExamEntry> {
return snp.getSnPPageDocument("Sprawdziany.mvc/Terminarz?rodzajWidoku=2&data=" + getDateAsTick(start))
.select(".mainContainer > div:not(.navigation)").map {
val date = getFormattedDate(it.selectFirst("h2")?.text()?.split(", ")?.last()?.trim())
it.select("article").map { getExam(it, date) }
}.flatten()
}
private fun getExam(e: Element, date: String): ExamEntry {
val subjectAndGroup = snp.getRowDataChildValue(e, 1)
val groupAndClass = subjectAndGroup.split(" ").last()
val group = if (groupAndClass.contains("|")) groupAndClass.split("|").last() else ""
val teacherAndDate = snp.getRowDataChildValue(e, 4).split(", ")
val teacherSymbol = teacherAndDate.first().split(" ").last().removeSurrounding("[", "]")
val teacher = teacherAndDate.first().replace(" [$teacherSymbol]", "")
return ExamEntry(
date = date,
entryDate = getFormattedDate(teacherAndDate.last()),
subject = subjectAndGroup.replace(groupAndClass, "").trim(),
group = group,
type = snp.getRowDataChildValue(e, 2),
description = snp.getRowDataChildValue(e, 3),
teacher = teacher,
teacherSymbol = teacherSymbol
)
}
}

View File

@ -16,6 +16,7 @@ import io.github.wulkanowy.api.generic.Week;
import static io.github.wulkanowy.api.DateTimeUtilsKt.getDateAsTick;
import static io.github.wulkanowy.api.DateTimeUtilsKt.getFormattedDate;
@Deprecated
public class ExamsWeek {
private static final String EXAMS_PAGE_URL = "Sprawdziany.mvc/Terminarz?rodzajWidoku=2&data=";

View File

@ -3,6 +3,7 @@ package io.github.wulkanowy.api.generic;
import java.util.ArrayList;
import java.util.List;
@Deprecated
public class Day {
private List<Lesson> lessons = new ArrayList<>();

View File

@ -1,5 +1,6 @@
package io.github.wulkanowy.api.generic;
@Deprecated
public class Lesson {
private int number = 0;

View File

@ -3,6 +3,7 @@ package io.github.wulkanowy.api.generic;
import java.util.ArrayList;
import java.util.List;
@Deprecated
public class Week<T> {
private List<T> days = new ArrayList<>();

View File

@ -1,5 +1,6 @@
package io.github.wulkanowy.api.grades;
@Deprecated
public class Grade {
protected String value = "";

View File

@ -0,0 +1,20 @@
package io.github.wulkanowy.api.grades
data class GradeKt(
val subject: String,
val value: String,
val color: String,
val symbol: String,
val description: String,
val weight: String,
val date: String,
val teacher: String
)

View File

@ -0,0 +1,45 @@
package io.github.wulkanowy.api.grades
import io.github.wulkanowy.api.SnP
import io.github.wulkanowy.api.getFormattedDate
import org.jsoup.nodes.Element
import java.util.regex.Pattern
class Grades(private val snp: SnP) {
private val colorPattern by lazy { Pattern.compile("#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})") }
fun getGrades() = getGrades("")
fun getGrades(semester: String): List<GradeKt> {
return snp.getSnPPageDocument("Oceny/Wszystkie?details=2&okres=$semester")
.select(".ocenySzczegoly-table > tbody > tr").map { getGrade(it) }.filter {
it.value != "Brak ocen"
}
}
private fun getGrade(e: Element): GradeKt {
val tds = e.select("td")
val symbol = tds[2].text().split(", ").first()
return GradeKt(
subject = tds[0].text(),
value = tds[1].text(),
color = getColor(tds[1].select(".ocenaCzastkowa").attr("style")),
symbol = symbol,
description = tds[2].text().replaceFirst(symbol, "").replaceFirst(", ", ""),
weight = tds[3].text(),
date = getFormattedDate(tds[4].text()),
teacher = tds[5].text()
)
}
private fun getColor(styleAttr: String): String {
val matcher = colorPattern.matcher(styleAttr)
while (matcher.find()) {
return matcher.group(1)
}
return ""
}
}

View File

@ -15,6 +15,7 @@ import io.github.wulkanowy.api.VulcanException;
import static io.github.wulkanowy.api.DateTimeUtilsKt.getFormattedDate;
@Deprecated
public class GradesList {
private static final String GRADES_PAGE_URL = "Oceny/Wszystkie?details=2&okres=";

View File

@ -0,0 +1,22 @@
package io.github.wulkanowy.api.grades
import io.github.wulkanowy.api.SnP
class GradesSummary(private val snp: SnP) {
fun getSummary() = getSummary("")
fun getSummary(semester: String): List<Summary> {
val subjects = snp.getSnPPageDocument("Oceny/Wszystkie?details=2&okres=$semester")
.select(".ocenyZwykle-table > tbody > tr")
return subjects.map {
val tds = it.select("td")
Summary(
name = tds[0].text(),
predicted = tds[tds.size - 2].text(),
final = tds[tds.size - 1].text()
)
}
}
}

View File

@ -1,5 +1,6 @@
package io.github.wulkanowy.api.grades;
@Deprecated
public class Subject {
private String name;

View File

@ -11,6 +11,7 @@ import java.util.List;
import io.github.wulkanowy.api.SnP;
import io.github.wulkanowy.api.VulcanException;
@Deprecated
public class SubjectsList {
private static final String SUBJECTS_PAGE_URL = "Oceny/Wszystkie?details=1&okres=";

View File

@ -0,0 +1,10 @@
package io.github.wulkanowy.api.grades
data class Summary(
val name: String,
val predicted: String,
val final: String
)

View File

@ -1,5 +1,6 @@
package io.github.wulkanowy.api.timetable;
@Deprecated
class LessonTypes {
static final String CLASS_PLANNING = "x-treelabel-ppl";

View File

@ -18,6 +18,7 @@ import io.github.wulkanowy.api.generic.Week;
import static io.github.wulkanowy.api.DateTimeUtilsKt.getDateAsTick;
import static io.github.wulkanowy.api.DateTimeUtilsKt.getFormattedDate;
@Deprecated
public class Timetable {
private static final String TIMETABLE_PAGE_URL = "Lekcja.mvc/PlanZajec?data=";

View File

@ -2,6 +2,7 @@ package io.github.wulkanowy.api.timetable;
import io.github.wulkanowy.api.generic.Day;
@Deprecated
public class TimetableDay extends Day {
private boolean isFreeDay = false;

View File

@ -0,0 +1,201 @@
package io.github.wulkanowy.api.timetable
import io.github.wulkanowy.api.SnP
import io.github.wulkanowy.api.getDateAsTick
import io.github.wulkanowy.api.getFormattedDate
import org.apache.commons.lang3.StringUtils
import org.jsoup.nodes.Element
import org.jsoup.select.Elements
class TimetableKt(private val snp: SnP) {
fun getTimetable() = getTimetable("")
fun getTimetable(start: String): List<TimetableLesson> {
val table = snp.getSnPPageDocument("Lekcja.mvc/PlanZajec?data=" + getDateAsTick(start))
.select(".mainContainer .presentData").first()
val days = getDays(table.select("thead th"))
return table.select("tbody tr").map {
val hours = it.select("td")
hours.drop(2).mapIndexed { i, item ->
getLesson(item, days[i], hours[1].text().split(" "), hours[0].text().toInt())
}
}.flatten().sortedBy {
it.date
}.filter {
it.subject.isNotBlank()
}
}
private fun getDays(el: Elements): List<Pair<String, String>> {
return el.drop(2).map {
val info = it.html().split("<br>")
Pair(getFormattedDate(info[1].trim()), info.getOrElse(2) { "" }.trim())
}
}
private fun getLesson(cell: Element, day: Pair<String, String>, hours: List<String>, number: Int): TimetableLesson {
val lesson = TimetableLesson(
number = number,
date = day.first,
freeDayName = day.second,
startTime = hours[0],
endTime = hours[1]
)
addLessonDetails(lesson, cell.select("div"))
return lesson
}
private fun addLessonDetails(lesson: TimetableLesson, e: Elements) {
moveWarningToLessonNode(e)
when (e.size) {
1 -> addLessonInfoFromElement(lesson, e.first())
2 -> {
val span = e.last().selectFirst("span")
when {
null == span -> addLessonInfoFromElement(lesson, e.first())
span.hasClass(Types.CLASS_MOVED_OR_CANCELED) -> {
lesson.newMovedInOrChanged = true
lesson.description = "poprzednio: " + getLessonAndGroupInfoFromSpan(span)[0]
addLessonInfoFromElement(lesson, e.first())
}
else -> addLessonInfoFromElement(lesson, e.last())
}
}
3 -> addLessonInfoFromElement(lesson, e[1])
else -> lesson.empty = true
}
}
private fun moveWarningToLessonNode(e: Elements) {
val warn = e.select(".uwaga-panel")
if (!warn.isEmpty()) {
e.select("span").last()
.addClass("x-treelabel-rlz")
.text(warn.text())
e.removeAt(1)
}
}
private fun addLessonInfoFromElement(lesson: TimetableLesson, e: Element) {
val spans = e.select("span")
if (spans.isEmpty()) {
return
}
addTypeInfo(lesson, spans)
addNormalLessonInfo(lesson, spans)
addChangesInfo(lesson, spans)
addGroupLessonInfo(lesson, spans)
}
private fun addTypeInfo(lesson: TimetableLesson, spans: Elements) {
if (spans.first().hasClass(Types.CLASS_PLANNING)) {
lesson.planning = true
}
if (spans.first().hasClass(Types.CLASS_MOVED_OR_CANCELED)) {
lesson.movedOrCanceled = true
}
if (spans.first().hasClass(Types.CLASS_NEW_MOVED_IN_OR_CHANGED)) {
lesson.newMovedInOrChanged = true
}
if (spans.last().hasClass(Types.CLASS_REALIZED) || "" == spans.first().attr("class")) {
lesson.realized = true
}
}
private fun addNormalLessonInfo(lesson: TimetableLesson, spans: Elements) {
if (3 == spans.size) {
lesson.subject = spans[0].text()
lesson.teacher = spans[1].text()
lesson.room = spans[2].text()
}
}
private fun addChangesInfo(lesson: TimetableLesson, spans: Elements) {
if (!spans.last().hasClass(Types.CLASS_REALIZED)) {
return
}
when {
7 == spans.size -> {
lesson.subject = spans[3].text()
lesson.teacher = spans[4].text()
lesson.room = spans[5].text()
lesson.movedOrCanceled = false
lesson.newMovedInOrChanged = true
lesson.description = (StringUtils.defaultString(StringUtils.substringBetween(
spans.last().text(), "(", ")"), spans.last().text())
+ " (poprzednio: " + spans[0].text() + ")")
}
9 == spans.size -> {
val subjectAndGroupInfo = getLessonAndGroupInfoFromSpan(spans[4])
lesson.subject = subjectAndGroupInfo[0]
lesson.groupName = subjectAndGroupInfo[1]
lesson.teacher = spans[6].text()
lesson.room = spans[7].text()
lesson.movedOrCanceled = false
lesson.newMovedInOrChanged = true
lesson.divisionIntoGroups = true
lesson.description = (StringUtils.defaultString(StringUtils.substringBetween(
spans.last().text(), "(", ")"), spans.last().text())
+ " (poprzednio: " + getLessonAndGroupInfoFromSpan(spans[0])[0] + ")")
}
4 <= spans.size -> {
lesson.subject = spans[0].text()
lesson.teacher = spans[1].text()
lesson.room = spans[2].text()
lesson.description = StringUtils.defaultString(StringUtils.substringBetween(
spans.last().text(), "(", ")"), spans.last().text())
}
}
}
private fun addGroupLessonInfo(lesson: TimetableLesson, spans: Elements) {
if (4 == spans.size && !spans.last().hasClass(Types.CLASS_REALIZED)) {
lesson.room = spans.last().text()
}
if (4 == spans.size && !spans.last().hasClass(Types.CLASS_REALIZED) || 5 == spans.size) {
val subjectAndGroupInfo = getLessonAndGroupInfoFromSpan(spans[0])
lesson.subject = subjectAndGroupInfo[0]
lesson.groupName = subjectAndGroupInfo[1]
lesson.teacher = spans[2].text()
lesson.divisionIntoGroups = true
}
if (5 == spans.size) {
lesson.room = spans[3].text()
}
}
private fun getLessonAndGroupInfoFromSpan(span: Element): Array<String> {
if (!span.text().contains("[")) {
return arrayOf(span.text(), "")
}
val subjectNameArray = span.text().split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
val groupName = subjectNameArray[subjectNameArray.size - 1]
return arrayOf(span.text().replace(" $groupName", ""), StringUtils.defaultString(StringUtils.substringBetween(
groupName, "[", "]"), groupName))
}
private object Types {
const val CLASS_PLANNING = "x-treelabel-ppl"
const val CLASS_REALIZED = "x-treelabel-rlz"
const val CLASS_MOVED_OR_CANCELED = "x-treelabel-inv"
const val CLASS_NEW_MOVED_IN_OR_CHANGED = "x-treelabel-zas"
}
}

View File

@ -0,0 +1,36 @@
package io.github.wulkanowy.api.timetable
data class TimetableLesson(
val number: Int,
val date: String,
val freeDayName: String,
val startTime: String,
val endTime: String,
var subject: String = "",
var teacher: String = "",
var room: String = "",
var description: String = "",
var groupName: String = "",
var empty: Boolean = false,
var divisionIntoGroups: Boolean = false,
var planning: Boolean = false,
var realized: Boolean = false,
var movedOrCanceled: Boolean = false,
var newMovedInOrChanged: Boolean = false
)

View File

@ -0,0 +1,90 @@
package io.github.wulkanowy.api.attendance
import io.github.wulkanowy.api.StudentAndParentTestCase
import org.junit.Assert.*
import org.junit.Test
class AttendanceTest : StudentAndParentTestCase() {
private val full by lazy { Attendance(getSnp("Frekwencja-full.html")) }
private val excellent by lazy { Attendance(getSnp("Frekwencja-excellent.html")) }
@Test fun getAttendanceFull() {
assertTrue(full.getAttendance().isNotEmpty())
assertEquals(38, full.getAttendance().size)
}
@Test fun getAttendanceExcellent() {
assertTrue(excellent.getAttendance().isNotEmpty())
assertEquals(22, excellent.getAttendance().size)
}
@Test fun getLessonSubject() {
assertEquals("Uroczyste rozpoczęcie roku szkolnego 2015/2016", excellent.getAttendance()[0].subject)
assertEquals("Geografia", excellent.getAttendance()[11].subject)
assertEquals("Naprawa komputera", full.getAttendance()[14].subject)
assertEquals("Religia", full.getAttendance()[23].subject)
assertEquals("Metodologia programowania", full.getAttendance()[34].subject)
}
@Test fun getLessonIsPresence() {
assertTrue(excellent.getAttendance()[0].presence)
assertTrue(excellent.getAttendance()[15].presence)
assertTrue(full.getAttendance()[0].presence)
assertTrue(full.getAttendance()[21].presence)
assertFalse(full.getAttendance()[36].presence)
assertFalse(full.getAttendance()[37].presence)
}
@Test fun getLessonIsAbsenceUnexcused() {
assertFalse(excellent.getAttendance()[0].absenceUnexcused)
assertTrue(full.getAttendance()[14].absenceUnexcused)
assertFalse(full.getAttendance()[24].absenceUnexcused)
assertFalse(full.getAttendance()[37].absenceUnexcused)
}
@Test fun getLessonIsAbsenceExcused() {
assertFalse(excellent.getAttendance()[0].absenceExcused)
assertFalse(full.getAttendance()[5].absenceExcused)
assertFalse(full.getAttendance()[10].absenceExcused)
assertTrue(full.getAttendance()[36].absenceExcused)
}
@Test fun getLessonIsAbsenceForSchoolReasons() {
assertFalse(excellent.getAttendance()[6].absenceForSchoolReasons)
assertTrue(full.getAttendance()[19].absenceForSchoolReasons)
assertFalse(full.getAttendance()[0].absenceForSchoolReasons)
assertFalse(full.getAttendance()[37].absenceForSchoolReasons)
}
@Test fun getLessonIsUnexcusedLateness() {
assertFalse(excellent.getAttendance()[7].unexcusedLateness)
assertTrue(full.getAttendance()[12].unexcusedLateness)
assertFalse(full.getAttendance()[13].unexcusedLateness)
assertFalse(full.getAttendance()[36].unexcusedLateness)
}
@Test fun getLessonIsExcusedLateness() {
assertFalse(excellent.getAttendance()[8].excusedLateness)
assertTrue(full.getAttendance()[13].excusedLateness)
assertFalse(full.getAttendance()[14].excusedLateness)
assertFalse(full.getAttendance()[35].excusedLateness)
}
@Test fun getLessonIsExemption() {
assertFalse(excellent.getAttendance()[9].exemption)
assertFalse(full.getAttendance()[0].exemption)
assertFalse(full.getAttendance()[15].exemption)
assertTrue(full.getAttendance()[37].exemption)
}
}

View File

@ -0,0 +1,70 @@
package io.github.wulkanowy.api.exams
import io.github.wulkanowy.api.StudentAndParentTestCase
import org.junit.Assert.assertEquals
import org.junit.Test
class ExamsTest : StudentAndParentTestCase() {
private val onePerDay by lazy { Exams(getSnp("Sprawdziany-one-per-day.html")) }
private val empty by lazy { Exams(getSnp("Sprawdziany-empty.html")) }
@Test fun getExamsSizeTest() {
assertEquals(6, onePerDay.getExams().size)
assertEquals(0, empty.getExams().size)
}
@Test fun getExamsDateTest() {
assertEquals("2017-10-23", onePerDay.getExams()[0].date)
assertEquals("2017-10-24", onePerDay.getExams()[1].date)
assertEquals("2017-10-25", onePerDay.getExams()[2].date)
assertEquals("2017-10-25", onePerDay.getExams()[3].date)
assertEquals("2017-10-26", onePerDay.getExams()[4].date)
assertEquals("2017-10-27", onePerDay.getExams()[5].date)
}
@Test fun getExamSubjectTest() {
assertEquals("Sieci komputerowe", onePerDay.getExams()[0].subject)
assertEquals("Język angielski", onePerDay.getExams()[1].subject)
assertEquals("Język polski", onePerDay.getExams()[4].subject)
assertEquals("Metodologia programowania", onePerDay.getExams()[5].subject)
}
@Test fun getExamGroupTest() {
assertEquals("zaw2", onePerDay.getExams()[0].group)
assertEquals("J1", onePerDay.getExams()[1].group)
assertEquals("", onePerDay.getExams()[4].group)
}
@Test fun getExamTypeTest() {
assertEquals("Sprawdzian", onePerDay.getExams()[0].type)
assertEquals("Sprawdzian", onePerDay.getExams()[1].type)
assertEquals("Sprawdzian", onePerDay.getExams()[2].type)
assertEquals("Kartkówka", onePerDay.getExams()[3].type)
}
@Test fun getExamDescriptionTest() {
assertEquals("Łącza danych", onePerDay.getExams()[0].description)
assertEquals("Czasy teraźniejsze", onePerDay.getExams()[1].description)
assertEquals("", onePerDay.getExams()[5].description)
}
@Test fun getExamTeacherTest() {
assertEquals("Adam Wiśniewski", onePerDay.getExams()[0].teacher)
assertEquals("Natalia Nowak", onePerDay.getExams()[1].teacher)
assertEquals("Małgorzata Nowacka", onePerDay.getExams()[5].teacher)
}
@Test fun getExamTeacherSymbolTest() {
assertEquals("AW", onePerDay.getExams()[0].teacherSymbol)
assertEquals("NN", onePerDay.getExams()[1].teacherSymbol)
assertEquals("MN", onePerDay.getExams()[5].teacherSymbol)
}
@Test fun getExamEntryDateTest() {
assertEquals("2017-10-16", onePerDay.getExams()[0].entryDate)
assertEquals("2017-10-17", onePerDay.getExams()[1].entryDate)
assertEquals("2017-10-16", onePerDay.getExams()[5].entryDate)
}
}

View File

@ -28,7 +28,7 @@ public class ExamsWeekTest extends StudentAndParentTestCase {
@Test
public void getDaysListTest() throws Exception {
Assert.assertEquals(3, onePerDay.getCurrent().getDays().size());
Assert.assertEquals(5, onePerDay.getCurrent().getDays().size());
Assert.assertEquals(7, onePerDay.getWeek("", false).getDays().size());
Assert.assertEquals(0, empty.getCurrent().getDays().size());
}
@ -38,7 +38,7 @@ public class ExamsWeekTest extends StudentAndParentTestCase {
List<ExamDay> notEmpty = onePerDay.getCurrent().getDays();
Assert.assertEquals(1, notEmpty.get(0).getExamList().size());
Assert.assertEquals(1, notEmpty.get(1).getExamList().size());
Assert.assertEquals(1, notEmpty.get(2).getExamList().size());
Assert.assertEquals(1, notEmpty.get(4).getExamList().size());
List<ExamDay> emptyToo = onePerDay.getWeek("", false).getDays();
Assert.assertEquals(1, emptyToo.get(0).getExamList().size());
@ -52,7 +52,7 @@ public class ExamsWeekTest extends StudentAndParentTestCase {
Assert.assertEquals("2017-10-23", dayList.get(0).getDate());
Assert.assertEquals("2017-10-24", dayList.get(1).getDate());
Assert.assertEquals("2017-10-27", dayList.get(2).getDate());
Assert.assertEquals("2017-10-27", dayList.get(4).getDate());
}
@Test
@ -61,7 +61,7 @@ public class ExamsWeekTest extends StudentAndParentTestCase {
Assert.assertEquals("Poniedziałek", dayList.get(0).getDayName());
Assert.assertEquals("Wtorek", dayList.get(1).getDayName());
Assert.assertEquals("Piątek", dayList.get(2).getDayName());
Assert.assertEquals("Piątek", dayList.get(4).getDayName());
}
@Test
@ -70,7 +70,7 @@ public class ExamsWeekTest extends StudentAndParentTestCase {
Assert.assertEquals("Sieci komputerowe 3Ti|zaw2", dayList.get(0).getExamList().get(0).getSubjectAndGroup());
Assert.assertEquals("Język angielski 3Ti|J1", dayList.get(1).getExamList().get(0).getSubjectAndGroup());
Assert.assertEquals("Metodologia programowania 3Ti|zaw2", dayList.get(2).getExamList().get(0).getSubjectAndGroup());
Assert.assertEquals("Metodologia programowania 3Ti|zaw2", dayList.get(4).getExamList().get(0).getSubjectAndGroup());
}
@Test
@ -79,7 +79,7 @@ public class ExamsWeekTest extends StudentAndParentTestCase {
Assert.assertEquals("Sprawdzian", dayList.get(0).getExamList().get(0).getType());
Assert.assertEquals("Sprawdzian", dayList.get(1).getExamList().get(0).getType());
Assert.assertEquals("Sprawdzian", dayList.get(2).getExamList().get(0).getType());
Assert.assertEquals("Sprawdzian", dayList.get(4).getExamList().get(0).getType());
}
@Test
@ -88,7 +88,7 @@ public class ExamsWeekTest extends StudentAndParentTestCase {
Assert.assertEquals("Łącza danych", dayList.get(0).getExamList().get(0).getDescription());
Assert.assertEquals("Czasy teraźniejsze", dayList.get(1).getExamList().get(0).getDescription());
Assert.assertEquals("", dayList.get(2).getExamList().get(0).getDescription());
Assert.assertEquals("", dayList.get(4).getExamList().get(0).getDescription());
}
@Test
@ -97,7 +97,7 @@ public class ExamsWeekTest extends StudentAndParentTestCase {
Assert.assertEquals("Adam Wiśniewski [AW]", dayList.get(0).getExamList().get(0).getTeacher());
Assert.assertEquals("Natalia Nowak [NN]", dayList.get(1).getExamList().get(0).getTeacher());
Assert.assertEquals("Małgorzata Nowacka [MN]", dayList.get(2).getExamList().get(0).getTeacher());
Assert.assertEquals("Małgorzata Nowacka [MN]", dayList.get(4).getExamList().get(0).getTeacher());
}
@Test
@ -106,6 +106,6 @@ public class ExamsWeekTest extends StudentAndParentTestCase {
Assert.assertEquals("2017-10-16", dayList.get(0).getExamList().get(0).getEntryDate());
Assert.assertEquals("2017-10-17", dayList.get(1).getExamList().get(0).getEntryDate());
Assert.assertEquals("2017-10-16", dayList.get(2).getExamList().get(0).getEntryDate());
Assert.assertEquals("2017-10-16", dayList.get(4).getExamList().get(0).getEntryDate());
}
}

View File

@ -0,0 +1,59 @@
package io.github.wulkanowy.api.grades
import io.github.wulkanowy.api.StudentAndParentTestCase
import org.junit.Assert.assertEquals
import org.junit.Test
class GradesSummaryTest : StudentAndParentTestCase() {
private val std by lazy { GradesSummary(getSnp("OcenyWszystkie-subjects.html")) }
private val average by lazy { GradesSummary(getSnp("OcenyWszystkie-subjects-average.html")) }
@Test fun getSummaryTest() {
assertEquals(5, std.getSummary().size)
assertEquals(5, average.getSummary().size)
}
@Test fun getNameTest() {
assertEquals("Zachowanie", std.getSummary()[0].name)
assertEquals("Praktyka zawodowa", std.getSummary()[1].name)
assertEquals("Metodologia programowania", std.getSummary()[2].name)
assertEquals("Podstawy przedsiębiorczości", std.getSummary()[3].name)
assertEquals("Wychowanie do życia w rodzinie", std.getSummary()[4].name)
assertEquals("Zachowanie", average.getSummary()[0].name)
assertEquals("Język polski", average.getSummary()[1].name)
assertEquals("Wychowanie fizyczne", average.getSummary()[2].name)
assertEquals("Język angielski", average.getSummary()[3].name)
assertEquals("Wiedza o społeczeństwie", average.getSummary()[4].name)
}
@Test fun getPredictedRatingTest() {
assertEquals("bardzo dobre", std.getSummary()[0].predicted)
assertEquals("-", std.getSummary()[1].predicted)
assertEquals("bardzo dobry", std.getSummary()[2].predicted)
assertEquals("3/4", std.getSummary()[3].predicted)
assertEquals("-", std.getSummary()[4].predicted)
assertEquals("bardzo dobre", average.getSummary()[0].predicted)
assertEquals("-", average.getSummary()[1].predicted)
assertEquals("bardzo dobry", average.getSummary()[2].predicted)
assertEquals("4/5", average.getSummary()[3].predicted)
assertEquals("-", average.getSummary()[4].predicted)
}
@Test fun getFinalRatingTest() {
assertEquals("bardzo dobre", std.getSummary()[0].final)
assertEquals("celujący", std.getSummary()[1].final)
assertEquals("celujący", std.getSummary()[2].final)
assertEquals("dostateczny", std.getSummary()[3].final)
assertEquals("-", std.getSummary()[4].final)
assertEquals("bardzo dobre", average.getSummary()[0].final)
assertEquals("dobry", average.getSummary()[1].final)
assertEquals("celujący", average.getSummary()[2].final)
assertEquals("bardzo dobry", average.getSummary()[3].final)
assertEquals("-", average.getSummary()[4].final)
}
}

View File

@ -0,0 +1,74 @@
package io.github.wulkanowy.api.grades
import io.github.wulkanowy.api.StudentAndParentTestCase
import org.junit.Assert
import org.junit.Test
import org.junit.Assert.*
class GradesTest : StudentAndParentTestCase() {
private val filled by lazy { Grades(getSnp("OcenyWszystkie-filled.html")) }
@Test fun getAllTest() {
Assert.assertEquals(7, filled.getGrades().size) // 2 items are skipped
}
@Test fun getSubjectTest() {
assertEquals("Zajęcia z wychowawcą", filled.getGrades()[0].subject)
assertEquals("Język angielski", filled.getGrades()[3].subject)
assertEquals("Wychowanie fizyczne", filled.getGrades()[4].subject)
assertEquals("Język polski", filled.getGrades()[5].subject)
}
@Test fun getValueTest() {
assertEquals("5", filled.getGrades()[0].value)
assertEquals("5", filled.getGrades()[3].value)
assertEquals("1", filled.getGrades()[4].value)
assertEquals("1", filled.getGrades()[5].value)
}
@Test fun getColorTest() {
assertEquals("000000", filled.getGrades()[0].color)
assertEquals("1289F7", filled.getGrades()[3].color)
assertEquals("6ECD07", filled.getGrades()[4].color)
assertEquals("6ECD07", filled.getGrades()[5].color)
}
@Test fun getSymbolTest() {
assertEquals("A1", filled.getGrades()[0].symbol)
assertEquals("BW3", filled.getGrades()[3].symbol)
assertEquals("STR", filled.getGrades()[4].symbol)
assertEquals("K", filled.getGrades()[5].symbol)
assertEquals("+Odp", filled.getGrades()[6].symbol)
}
@Test fun getDescriptionTest() {
assertEquals("Dzień Kobiet w naszej klasie", filled.getGrades()[0].description)
assertEquals("Writing", filled.getGrades()[3].description)
assertEquals("", filled.getGrades()[4].description)
assertEquals("Kordian", filled.getGrades()[5].description)
assertEquals("Kordian", filled.getGrades()[6].description)
}
@Test fun getWeightTest() {
assertEquals("1,00", filled.getGrades()[0].weight)
assertEquals("3,00", filled.getGrades()[3].weight)
assertEquals("8,00", filled.getGrades()[4].weight)
assertEquals("5,00", filled.getGrades()[5].weight)
}
@Test fun getDateTest() {
assertEquals("2017-03-21", filled.getGrades()[0].date)
assertEquals("2017-06-02", filled.getGrades()[3].date)
assertEquals("2017-04-02", filled.getGrades()[4].date)
assertEquals("2017-02-06", filled.getGrades()[5].date)
}
@Test fun getTeacherTest() {
assertEquals("Patryk Maciejewski", filled.getGrades()[0].teacher)
assertEquals("Oliwia Woźniak", filled.getGrades()[3].teacher)
assertEquals("Klaudia Dziedzic", filled.getGrades()[4].teacher)
assertEquals("Amelia Stępień", filled.getGrades()[5].teacher)
}
}

View File

@ -0,0 +1,183 @@
package io.github.wulkanowy.api.timetable
import io.github.wulkanowy.api.StudentAndParentTestCase
import org.junit.Assert.*
import org.junit.Test
class TimetableKtTest : StudentAndParentTestCase() {
private val std by lazy { TimetableKt(getSnp("PlanLekcji-std.html")) }
private val full by lazy { TimetableKt(getSnp("PlanLekcji-full.html")) }
private val holidays by lazy { TimetableKt(getSnp("PlanLekcji-holidays.html")) }
@Test fun getTimetableTest() {
assertEquals(32, std.getTimetable().size)
assertEquals(43, full.getTimetable().size)
assertEquals(0, holidays.getTimetable().size)
}
@Test fun getStartDayDateTest() {
assertEquals("2017-06-19", std.getTimetable()[0].date)
assertEquals("2017-06-20", std.getTimetable()[8].date)
assertEquals("2017-06-21", std.getTimetable()[16].date)
assertEquals("2017-06-19", full.getTimetable()[0].date)
assertEquals("2017-06-20", full.getTimetable()[10].date)
assertEquals("2017-06-22", full.getTimetable()[30].date)
}
@Test fun getDayIsFreeTest() {
assertFalse(std.getTimetable().first().freeDayName.isNotEmpty())
assertFalse(full.getTimetable().last().freeDayName.isNotEmpty())
}
@Test fun getDayFreeDayName() {
assertNotEquals("Wakacje", std.getTimetable()[0].freeDayName)
assertNotEquals("Ferie letnie", full.getTimetable()[15].freeDayName)
}
@Test fun getLessonNumberTest() {
assertEquals(2, std.getTimetable()[1].number)
assertEquals(5, std.getTimetable()[10].number)
assertEquals(0, full.getTimetable()[0].number)
assertEquals(9, full.getTimetable()[19].number)
}
@Test fun getLessonSubjectTest() {
assertEquals("Historia", std.getTimetable()[1].subject)
assertEquals("Zajęcia techniczne", std.getTimetable()[17].subject)
assertEquals("Wychowanie fizyczne", std.getTimetable()[7].subject)
assertEquals("Fizyka", full.getTimetable()[0].subject)
assertEquals("Język angielski", full.getTimetable()[1].subject)
assertEquals("Wychowanie fizyczne", full.getTimetable()[9].subject)
assertEquals("Metodologia programowania", full.getTimetable()[10].subject)
assertEquals("Wychowanie do życia w rodzinie", full.getTimetable()[20].subject)
assertEquals("Wychowanie fizyczne", full.getTimetable()[30].subject)
assertEquals("Uroczyste zakończenie roku szkolnego", full.getTimetable()[37].subject)
assertEquals("Język niemiecki", full.getTimetable()[39].subject)
}
@Test fun getLessonTeacherTest() {
assertEquals("Bogatka Katarzyna", std.getTimetable()[1].teacher)
assertEquals("Chlebowski Stanisław", std.getTimetable()[17].teacher)
assertEquals("Kobczyk Iwona", full.getTimetable()[1].teacher)
assertEquals("Bączek Grzegorz", full.getTimetable()[7].teacher)
assertEquals("Nowak Jadwiga", full.getTimetable()[20].teacher)
assertEquals("Nowicka Irena", full.getTimetable()[30].teacher)
assertEquals("Baran Małgorzata", full.getTimetable()[37].teacher)
assertEquals("", full.getTimetable()[38].teacher)
}
@Test fun getLessonRoomTest() {
assertEquals("", std.getTimetable()[15].room)
assertEquals("19", full.getTimetable()[0].room)
assertEquals("33", full.getTimetable()[7].room)
assertEquals("32", full.getTimetable()[10].room)
assertEquals("32", full.getTimetable()[18].room)
assertEquals("32", full.getTimetable()[28].room)
assertEquals("G4", full.getTimetable()[30].room)
assertEquals("37", full.getTimetable()[37].room)
}
@Test fun getLessonDescriptionTest() {
assertEquals("", std.getTimetable()[15].description)
assertEquals("okienko dla uczniów", full.getTimetable()[7].description)
assertEquals("przeniesiona z lekcji 7, 01.12.2017", full.getTimetable()[11].description)
assertEquals("przeniesiona z lekcji 7, 20.06.2017", full.getTimetable()[12].description)
assertEquals("przeniesiona z lekcji 4, 20.06.2017", full.getTimetable()[13].description)
assertEquals("zastępstwo (poprzednio: Religia)", full.getTimetable()[20].description)
assertEquals("egzamin", full.getTimetable()[29].description)
assertEquals("zastępstwo (poprzednio: Wychowanie fizyczne)", full.getTimetable()[30].description)
assertEquals("", full.getTimetable()[37].description)
assertEquals("", full.getTimetable()[38].description)
assertEquals("poprzednio: Wychowanie fizyczne", full.getTimetable()[39].description)
assertEquals("bez nawiasów (poprzednio: Religia)", full.getTimetable()[40].description)
assertEquals("opis w uwadze bez klasy w spanie", full.getTimetable()[41].description)
assertEquals("poprzednio: Zajęcia z wychowawcą", full.getTimetable()[42].description)
}
@Test fun getLessonGroupNameTest() {
assertEquals("CH", std.getTimetable()[2].groupName)
assertEquals("JNPW", std.getTimetable()[26].groupName)
assertEquals("", full.getTimetable()[7].groupName)
assertEquals("zaw2", full.getTimetable()[10].groupName)
assertEquals("wf2", full.getTimetable()[13].groupName)
assertEquals("zaw1", full.getTimetable()[30].groupName)
}
@Test fun getLessonStartTimeTest() {
assertEquals("08:00", std.getTimetable()[0].startTime)
assertEquals("13:20", std.getTimetable()[12].startTime)
assertEquals("07:10", full.getTimetable()[0].startTime)
assertEquals("12:20", full.getTimetable()[26].startTime)
}
@Test fun getLessonEndTimeTest() {
assertEquals("08:45", std.getTimetable()[0].endTime)
assertEquals("14:05", std.getTimetable()[12].endTime)
assertEquals("07:55", full.getTimetable()[10].endTime)
assertEquals("13:55", full.getTimetable()[36].endTime)
}
@Test fun getLessonIsEmptyTest() {
assertFalse(std.getTimetable()[9].empty)
assertFalse(full.getTimetable()[7].empty)
assertFalse(full.getTimetable()[10].empty)
assertFalse(full.getTimetable()[12].empty)
}
@Test fun getLessonIsDivisionIntoGroupsTest() {
assertTrue(std.getTimetable()[2].divisionIntoGroups)
assertTrue(std.getTimetable()[26].divisionIntoGroups)
assertFalse(full.getTimetable()[7].divisionIntoGroups)
assertTrue(full.getTimetable()[13].divisionIntoGroups)
assertTrue(full.getTimetable()[30].divisionIntoGroups)
}
@Test fun getLessonIsPlanningTest() {
assertFalse(std.getTimetable()[30].planning)
assertFalse(full.getTimetable()[1].planning)
assertTrue(full.getTimetable()[13].planning)
assertTrue(full.getTimetable()[37].planning)
}
@Test fun getLessonIsRealizedTest() {
assertTrue(std.getTimetable()[15].realized)
assertTrue(full.getTimetable()[1].realized)
assertTrue(full.getTimetable()[13].realized)
assertFalse(full.getTimetable()[37].realized)
}
@Test fun getLessonIsMovedOrCanceledTest() {
assertFalse(std.getTimetable()[15].movedOrCanceled)
assertTrue(full.getTimetable()[7].movedOrCanceled)
assertFalse(full.getTimetable()[13].movedOrCanceled)
assertFalse(full.getTimetable()[37].movedOrCanceled)
}
@Test fun getLessonIsNewMovedInOrChangedTest() {
assertFalse(std.getTimetable()[15].newMovedInOrChanged)
assertFalse(full.getTimetable()[1].newMovedInOrChanged)
assertTrue(full.getTimetable()[12].newMovedInOrChanged)
assertTrue(full.getTimetable()[13].newMovedInOrChanged)
assertTrue(full.getTimetable()[30].newMovedInOrChanged)
assertFalse(full.getTimetable()[38].newMovedInOrChanged)
assertTrue(full.getTimetable()[39].newMovedInOrChanged)
}
}

View File

@ -50,8 +50,66 @@
</div>
</article>
</div>
<div></div>
<div></div>
<div>
<h2>środa, 25.10.2017</h2>
<article>
<div class="daneWiersz">
<div class="tytul">Przedmiot i grupa:</div>
<div class="wartosc">Język angielski 3Ti|J2</div>
</div>
<div class="daneWiersz">
<div class="tytul">Rodzaj sprawdzianu:</div>
<div class="wartosc">Sprawdzian</div>
</div>
<div class="daneWiersz">
<div class="tytul">Opis:</div>
<div class="wartosc">słownictwo (zdrowie)</div>
</div>
<div class="daneWiersz">
<div class="tytul">Nauczyciel i data wpisu:</div>
<div class="wartosc">Natalia Nowak [NN], 17.10.2017</div>
</div>
</article>
<article>
<div class="daneWiersz">
<div class="tytul">Przedmiot i grupa:</div>
<div class="wartosc">Metodologia programowania 3Ti|zaw1</div>
</div>
<div class="daneWiersz">
<div class="tytul">Rodzaj sprawdzianu:</div>
<div class="wartosc">Kartkówka</div>
</div>
<div class="daneWiersz">
<div class="tytul">Opis:</div>
<div class="wartosc">programowanie obiektowe</div>
</div>
<div class="daneWiersz">
<div class="tytul">Nauczyciel i data wpisu:</div>
<div class="wartosc">Małgorzata Nowacka [MN], 16.10.2017</div>
</div>
</article>
</div>
<div>
<h2>czwartek, 26.10.2017</h2>
<article>
<div class="daneWiersz">
<div class="tytul">Przedmiot i grupa:</div>
<div class="wartosc">Język polski 3Ti</div>
</div>
<div class="daneWiersz">
<div class="tytul">Rodzaj sprawdzianu:</div>
<div class="wartosc">Sprawdzian</div>
</div>
<div class="daneWiersz">
<div class="tytul">Opis:</div>
<div class="wartosc">Dwudziestolecie</div>
</div>
<div class="daneWiersz">
<div class="tytul">Nauczyciel i data wpisu:</div>
<div class="wartosc">Czerwieńska Agata [CA], 16.10.2017</div>
</div>
</article>
</div>
<div>
<h2>piątek, 27.10.2017</h2>
<article>