From 872564016824e86d889616c0976f37732490c77e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Fri, 29 Jun 2018 11:27:18 +0200 Subject: [PATCH 01/11] User short grade names in grades summary (#141) --- .../ui/main/grades/GradesHeader.java | 4 ++-- .../ui/main/grades/GradesSummarySubItem.java | 5 +++-- .../io/github/wulkanowy/utils/GradeUtils.java | 21 ++++++++++++++++++- .../wulkanowy/utils/GradeUtilsTest.java | 7 +++++++ 4 files changed, 32 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradesHeader.java b/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradesHeader.java index c39fcc4d..03f8564a 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradesHeader.java +++ b/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradesHeader.java @@ -113,9 +113,9 @@ public class GradesHeader averageText.setText(getGradesAverageString()); predictedText.setText(resources.getString(R.string.info_grades_predicted_rating, - item.getPredictedRating())); + GradeUtils.getShortGradeValue(item.getPredictedRating()))); finalText.setText(resources.getString(R.string.info_grades_final_rating, - item.getFinalRating())); + GradeUtils.getShortGradeValue(item.getFinalRating()))); resetViews(); toggleSubjectText(); diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradesSummarySubItem.java b/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradesSummarySubItem.java index 8ca9e484..58f418aa 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradesSummarySubItem.java +++ b/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradesSummarySubItem.java @@ -16,6 +16,7 @@ import eu.davidea.flexibleadapter.items.IFlexible; import eu.davidea.viewholders.FlexibleViewHolder; import io.github.wulkanowy.R; import io.github.wulkanowy.data.db.dao.entities.Subject; +import io.github.wulkanowy.utils.GradeUtils; public class GradesSummarySubItem extends AbstractSectionableItem { @@ -76,8 +77,8 @@ public class GradesSummarySubItem } void onBind(Subject item) { - predictedGrade.setText(item.getPredictedRating()); - finalGrade.setText(item.getFinalRating()); + predictedGrade.setText(GradeUtils.getShortGradeValue(item.getPredictedRating())); + finalGrade.setText(GradeUtils.getShortGradeValue(item.getFinalRating())); } } } diff --git a/app/src/main/java/io/github/wulkanowy/utils/GradeUtils.java b/app/src/main/java/io/github/wulkanowy/utils/GradeUtils.java index 29111457..d274da97 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/GradeUtils.java +++ b/app/src/main/java/io/github/wulkanowy/utils/GradeUtils.java @@ -101,7 +101,7 @@ public final class GradeUtils { return counter / denominator; } - private static float getGradeValue(String grade) { + public static float getGradeValue(String grade) { if (validGradePattern.matcher(grade).matches()) { return getWeightedGradeValue(grade); } @@ -128,6 +128,25 @@ public final class GradeUtils { } } + public static String getShortGradeValue(String grade) { + switch (grade) { + case "celujący": + return "6"; + case "bardzo dobry": + return "5"; + case "dobry": + return "4"; + case "dostateczny": + return "3"; + case "dopuszczający": + return "2"; + case "niedostateczny": + return "1"; + default: + return grade; + } + } + private static float getWeightedGradeValue(String value) { if (validGradePattern.matcher(value).matches()) { if (value.matches("[-][0-6]") || value.matches("[0-6][-]")) { diff --git a/app/src/test/java/io/github/wulkanowy/utils/GradeUtilsTest.java b/app/src/test/java/io/github/wulkanowy/utils/GradeUtilsTest.java index 1a5f9e4a..4bf6de51 100644 --- a/app/src/test/java/io/github/wulkanowy/utils/GradeUtilsTest.java +++ b/app/src/test/java/io/github/wulkanowy/utils/GradeUtilsTest.java @@ -75,4 +75,11 @@ public class GradeUtilsTest { assertEquals(R.color.default_grade, GradeUtils.getValueColor("7")); assertEquals(R.color.default_grade, GradeUtils.getValueColor("")); } + + @Test + public void getShortGradeValueTest() { + assertEquals("6", GradeUtils.getShortGradeValue("celujący")); + assertEquals("1", GradeUtils.getShortGradeValue("niedostateczny")); + assertEquals("wzorowe", GradeUtils.getShortGradeValue("wzorowe")); + } } From 5a4b8b22f317b56c8fde0fc2701029a7b9470376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Sat, 14 Jul 2018 14:06:57 +0200 Subject: [PATCH 02/11] Stop synchronization on holidays (#142) --- .circleci/config.yml | 16 +- README.md | 2 +- api/build.gradle | 26 ---- .../android-sonarqube.gradle | 0 app/build.gradle | 16 +- app/jacoco.gradle | 56 +++++++ .../wulkanowy/services/jobs/SyncJob.java | 8 + .../wulkanowy/ui/main/MainPresenter.java | 5 +- .../main/attendance/AttendancePresenter.java | 8 +- .../ui/main/exams/ExamsPresenter.java | 8 +- .../ui/main/settings/SettingsFragment.java | 10 +- .../ui/main/timetable/TimetablePresenter.java | 8 +- .../timetable/tab/TimetableTabPresenter.java | 8 +- .../ui/widgets/TimetableWidgetFactory.java | 8 +- .../ui/widgets/TimetableWidgetProvider.java | 5 +- .../io/github/wulkanowy/utils/TimeUtils.java | 81 ---------- .../io/github/wulkanowy/utils/TimeUtils.kt | 97 ++++++++++++ app/src/main/res/values-pl/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + .../github/wulkanowy/utils/TimeUtilsTest.java | 48 ------ .../github/wulkanowy/utils/TimeUtilsTest.kt | 140 ++++++++++++++++++ build.gradle | 31 +++- jacoco.gradle | 40 ----- 23 files changed, 381 insertions(+), 242 deletions(-) rename android-sonarqube.gradle => app/android-sonarqube.gradle (100%) create mode 100644 app/jacoco.gradle delete mode 100644 app/src/main/java/io/github/wulkanowy/utils/TimeUtils.java create mode 100644 app/src/main/java/io/github/wulkanowy/utils/TimeUtils.kt delete mode 100644 app/src/test/java/io/github/wulkanowy/utils/TimeUtilsTest.java create mode 100644 app/src/test/java/io/github/wulkanowy/utils/TimeUtilsTest.kt delete mode 100644 jacoco.gradle diff --git a/.circleci/config.yml b/.circleci/config.yml index fe74ebe6..b017fe23 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -87,11 +87,8 @@ jobs: name: Upload unit code coverage to codecov command: bash <(curl -s https://codecov.io/bash) -F app - store_artifacts: - path: ./app/build/reports/tests/ - destination: tests_reports/ - - store_artifacts: - path: ./app/build/reports/jacoco/jacocoTestDebugUnitTestReport/ - destination: coverage_reports/ + path: ./app/build/reports/ + destination: reports/ - store_test_results: path: ./app/build/test-results - persist_to_workspace: @@ -112,11 +109,8 @@ jobs: name: Upload code coverage to codecov command: bash <(curl -s https://codecov.io/bash) -F api - store_artifacts: - path: ./api/build/reports/tests/ - destination: tests_reports/ - - store_artifacts: - path: ./api/build/reports/jacoco/test/ - destination: coverage_reports/ + path: ./api/build/reports/ + destination: reports/ - store_test_results: path: ./api/build/test-results - persist_to_workspace: @@ -130,7 +124,7 @@ jobs: - *attach_workspace - run: name: Setup emulator - command: sdkmanager "system-images;android-19;google_apis;armeabi-v7a" && echo "no" | avdmanager create avd -n test -k "system-images;android-19;google_apis;armeabi-v7a" + command: sdkmanager "system-images;android-16;default;armeabi-v7a" && echo "no" | avdmanager create avd -n test -k "system-images;android-16;default;armeabi-v7a" - run: name: Launch emulator command: export LD_LIBRARY_PATH=${ANDROID_HOME}/emulator/lib64:${ANDROID_HOME}/emulator/lib64/qt/lib && emulator64-arm -avd test -noaudio -no-boot-anim -no-window -accel on diff --git a/README.md b/README.md index 6ccaa20a..ee11a9c6 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,6 @@ [Pobierz wersję beta](https://play.google.com/store/apps/details?id=io.github.wulkanowy&utm_source=vcs) -[Pobierz wersję rozwojową](https://bitrise-redirector.herokuapp.com/v0.1/apps/daeff1893f3c8128/builds/master/artifacts/app-debug-bitrise-signed.apk) +[Pobierz wersję DEV](https://bitrise-redirector.herokuapp.com/v0.1/apps/daeff1893f3c8128/builds/master/artifacts/0) Androidowy klient dziennika VULCAN UONET+. diff --git a/api/build.gradle b/api/build.gradle index 1f7cf197..5e5eeee3 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -119,29 +119,3 @@ artifacts { archives sourcesJar archives javadocJar } - -buildscript { - ext.kotlin_version = '1.2.41' - repositories { - mavenCentral() - } - dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } -} - -repositories { - mavenCentral() -} - -compileKotlin { - kotlinOptions { - jvmTarget = "1.8" - } -} - -compileTestKotlin { - kotlinOptions { - jvmTarget = "1.8" - } -} diff --git a/android-sonarqube.gradle b/app/android-sonarqube.gradle similarity index 100% rename from android-sonarqube.gradle rename to app/android-sonarqube.gradle diff --git a/app/build.gradle b/app/build.gradle index dc655e90..e8a9ab48 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,11 +17,13 @@ repositories { maven { url 'https://maven.fabric.io/public' } } -apply plugin: 'com.android.application' apply plugin: 'org.greenrobot.greendao' +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-kapt' // sync warning probably caused by bug https://issuetracker.google.com/issues/74537216 apply plugin: 'io.fabric' -apply from: '../jacoco.gradle' -apply from: '../android-sonarqube.gradle' +apply from: 'jacoco.gradle' +apply from: 'android-sonarqube.gradle' apply plugin: 'com.google.gms.oss.licenses.plugin' apply plugin: 'com.github.triplet.play' @@ -128,12 +130,12 @@ dependencies { transitive = true } - annotationProcessor "com.google.dagger:dagger-android-processor:$dagger2" - annotationProcessor "com.google.dagger:dagger-compiler:$dagger2" - annotationProcessor "com.jakewharton:butterknife-compiler:$butterknife" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" + kapt "com.google.dagger:dagger-compiler:$dagger2" + kapt "com.google.dagger:dagger-android-processor:$dagger2" + kapt "com.jakewharton:butterknife-compiler:$butterknife" debugImplementation "com.amitshekhar.android:debug-db:$debugDb" - debugImplementation "net.zetetic:android-database-sqlcipher:$sqlcipher" testImplementation "junit:junit:$junit" testImplementation "org.mockito:mockito-core:$mockito" diff --git a/app/jacoco.gradle b/app/jacoco.gradle new file mode 100644 index 00000000..f59b3857 --- /dev/null +++ b/app/jacoco.gradle @@ -0,0 +1,56 @@ +apply plugin: "jacoco" + +jacoco { + toolVersion "0.8.1" + reportsDir = file("$buildDir/reports") +} + +tasks.withType(Test) { + jacoco.includeNoLocationClasses = true +} + +// run ./gradlew clean createDebugCoverageReport jacocoTestReport +task jacocoTestReport(type: JacocoReport) { + + group = "Reporting" + description = "Generate Jacoco coverage reports" + + reports { + xml.enabled = true + html.enabled = true + } + + def excludes = [ + "**/R.class", + "**/R\$*.class", + "**/*\$ViewInjector*.*", + "**/BuildConfig.*", + "**/Manifest*.*", + "**/*Test*.*", + "android/**/*.*", + "**/*Fragment.*", + "**/*Activity.*" + ] + + // generated classes + classDirectories = fileTree( + // Java generated classes on Android project (debug build) + dir: "$buildDir/intermediates/classes/debug", + excludes: excludes + ) + fileTree( + // Kotlin generated classes on Android project (debug build) + dir: "$buildDir/tmp/kotlin-classes/debug", + excludes: excludes + ) + + // sources + sourceDirectories = files([ + android.sourceSets.main.java.srcDirs, + "src/main/kotlin" + ]) + + executionData = fileTree( + dir: project.projectDir, + includes: ["**/*.exec" , "**/*.ec"] + ) +} diff --git a/app/src/main/java/io/github/wulkanowy/services/jobs/SyncJob.java b/app/src/main/java/io/github/wulkanowy/services/jobs/SyncJob.java index d0fc73d6..9854666e 100644 --- a/app/src/main/java/io/github/wulkanowy/services/jobs/SyncJob.java +++ b/app/src/main/java/io/github/wulkanowy/services/jobs/SyncJob.java @@ -30,6 +30,8 @@ import io.github.wulkanowy.ui.main.MainActivity; import io.github.wulkanowy.utils.FabricUtils; import timber.log.Timber; +import static io.github.wulkanowy.utils.TimeUtilsKt.isHolidays; + public class SyncJob extends SimpleJobService { public static final String JOB_TAG = "SyncJob"; @@ -66,6 +68,12 @@ public class SyncJob extends SimpleJobService { @Override public int onRunJob(JobParameters job) { + if (isHolidays()) { + stop(getApplicationContext()); + + return JobService.RESULT_FAIL_NORETRY; + } + try { repository.getSyncRepo().initLastUser(); repository.getSyncRepo().syncAll(); diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/MainPresenter.java b/app/src/main/java/io/github/wulkanowy/ui/main/MainPresenter.java index c6741c3e..2ca9eefa 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/main/MainPresenter.java +++ b/app/src/main/java/io/github/wulkanowy/ui/main/MainPresenter.java @@ -1,6 +1,5 @@ package io.github.wulkanowy.ui.main; - import android.support.annotation.NonNull; import javax.inject.Inject; @@ -8,6 +7,8 @@ import javax.inject.Inject; import io.github.wulkanowy.data.RepositoryContract; import io.github.wulkanowy.ui.base.BasePresenter; +import static io.github.wulkanowy.utils.TimeUtilsKt.isHolidays; + public class MainPresenter extends BasePresenter implements MainContract.Presenter { @@ -35,7 +36,7 @@ public class MainPresenter extends BasePresenter getView().initiationBottomNav(tabPosition); getView().initiationViewPager(tabPosition); - if (getRepository().getSharedRepo().isServicesEnable()) { + if (getRepository().getSharedRepo().isServicesEnable() && !isHolidays()) { getView().startSyncService(getRepository().getSharedRepo().getServicesInterval(), getRepository().getSharedRepo().isMobileDisable()); } diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendancePresenter.java b/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendancePresenter.java index 9cfb1384..73a2837c 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendancePresenter.java +++ b/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendancePresenter.java @@ -10,10 +10,12 @@ import javax.inject.Inject; import io.github.wulkanowy.data.RepositoryContract; import io.github.wulkanowy.ui.base.BasePresenter; import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener; -import io.github.wulkanowy.utils.TimeUtils; import io.github.wulkanowy.utils.async.AbstractTask; import io.github.wulkanowy.utils.async.AsyncListeners; +import static io.github.wulkanowy.utils.TimeUtilsKt.getFirstDayOfCurrentWeek; +import static io.github.wulkanowy.utils.TimeUtilsKt.getMondaysFromCurrentSchoolYear; + public class AttendancePresenter extends BasePresenter implements AttendanceContract.Presenter, AsyncListeners.OnFirstLoadingListener { @@ -42,11 +44,11 @@ public class AttendancePresenter extends BasePresenter } if (dates.isEmpty()) { - dates = TimeUtils.getMondaysFromCurrentSchoolYear(); + dates = getMondaysFromCurrentSchoolYear(); } if (positionToScroll == 0) { - positionToScroll = dates.indexOf(TimeUtils.getDateOfCurrentMonday(true)); + positionToScroll = dates.indexOf(getFirstDayOfCurrentWeek()); } if (!isFirstSight) { diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsPresenter.java b/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsPresenter.java index a5bd1055..20c0fe2e 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsPresenter.java +++ b/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsPresenter.java @@ -10,10 +10,12 @@ import javax.inject.Inject; import io.github.wulkanowy.data.RepositoryContract; import io.github.wulkanowy.ui.base.BasePresenter; import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener; -import io.github.wulkanowy.utils.TimeUtils; import io.github.wulkanowy.utils.async.AbstractTask; import io.github.wulkanowy.utils.async.AsyncListeners; +import static io.github.wulkanowy.utils.TimeUtilsKt.getFirstDayOfCurrentWeek; +import static io.github.wulkanowy.utils.TimeUtilsKt.getMondaysFromCurrentSchoolYear; + public class ExamsPresenter extends BasePresenter implements ExamsContract.Presenter, AsyncListeners.OnFirstLoadingListener { @@ -42,11 +44,11 @@ public class ExamsPresenter extends BasePresenter } if (dates.isEmpty()) { - dates = TimeUtils.getMondaysFromCurrentSchoolYear(); + dates = getMondaysFromCurrentSchoolYear(); } if (positionToScroll == 0) { - positionToScroll = dates.indexOf(TimeUtils.getDateOfCurrentMonday(true)); + positionToScroll = dates.indexOf(getFirstDayOfCurrentWeek()); } if (!isFirstSight) { diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/settings/SettingsFragment.java b/app/src/main/java/io/github/wulkanowy/ui/main/settings/SettingsFragment.java index 8bd93024..0f2009be 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/main/settings/SettingsFragment.java +++ b/app/src/main/java/io/github/wulkanowy/ui/main/settings/SettingsFragment.java @@ -18,6 +18,8 @@ import io.github.wulkanowy.services.jobs.SyncJob; import io.github.wulkanowy.ui.main.MainActivity; import io.github.wulkanowy.utils.AppConstant; +import static io.github.wulkanowy.utils.TimeUtilsKt.isHolidays; + public class SettingsFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener { @@ -86,7 +88,13 @@ public class SettingsFragment extends PreferenceFragmentCompat findPreference(SHARED_KEY_ABOUT_VERSION).setOnPreferenceClickListener(onProgrammerListener); findPreference(SHARED_KEY_ABOUT_REPO).setIntent(new Intent(Intent.ACTION_VIEW, Uri.parse(AppConstant.REPO_URL))); findPreference(SHARED_KEY_ABOUT_LICENSES).setIntent(new Intent(getActivity(), OssLicensesMenuActivity.class) - .putExtra("title", getString(R.string.pref_about_osl))); + .putExtra("title", R.string.pref_about_osl)); + + if (isHolidays()) { + Preference services = findPreference(SHARED_KEY_SERVICES_ENABLE); + services.setSummary(R.string.pref_services_suspended_on_holidays); + services.setEnabled(false); + } } @Override diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetablePresenter.java b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetablePresenter.java index 8c9bfaba..1e9cf0b8 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetablePresenter.java +++ b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetablePresenter.java @@ -10,10 +10,12 @@ import javax.inject.Inject; import io.github.wulkanowy.data.RepositoryContract; import io.github.wulkanowy.ui.base.BasePresenter; import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener; -import io.github.wulkanowy.utils.TimeUtils; import io.github.wulkanowy.utils.async.AbstractTask; import io.github.wulkanowy.utils.async.AsyncListeners; +import static io.github.wulkanowy.utils.TimeUtilsKt.getFirstDayOfCurrentWeek; +import static io.github.wulkanowy.utils.TimeUtilsKt.getMondaysFromCurrentSchoolYear; + public class TimetablePresenter extends BasePresenter implements TimetableContract.Presenter, AsyncListeners.OnFirstLoadingListener { @@ -42,11 +44,11 @@ public class TimetablePresenter extends BasePresenter } if (dates.isEmpty()) { - dates = TimeUtils.getMondaysFromCurrentSchoolYear(); + dates = getMondaysFromCurrentSchoolYear(); } if (positionToScroll == 0) { - positionToScroll = dates.indexOf(TimeUtils.getDateOfCurrentMonday(true)); + positionToScroll = dates.indexOf(getFirstDayOfCurrentWeek()); } if (!isFirstSight) { diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/timetable/tab/TimetableTabPresenter.java b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/tab/TimetableTabPresenter.java index 42f2424d..f30dd804 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/main/timetable/tab/TimetableTabPresenter.java +++ b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/tab/TimetableTabPresenter.java @@ -16,10 +16,12 @@ import io.github.wulkanowy.data.db.dao.entities.Week; import io.github.wulkanowy.ui.base.BasePresenter; import io.github.wulkanowy.utils.AppConstant; import io.github.wulkanowy.utils.FabricUtils; -import io.github.wulkanowy.utils.TimeUtils; import io.github.wulkanowy.utils.async.AbstractTask; import io.github.wulkanowy.utils.async.AsyncListeners; +import static io.github.wulkanowy.utils.TimeUtilsKt.getParsedDate; +import static io.github.wulkanowy.utils.TimeUtilsKt.isDateInWeek; + public class TimetableTabPresenter extends BasePresenter implements TimetableTabContract.Presenter, AsyncListeners.OnRefreshListener, AsyncListeners.OnFirstLoadingListener { @@ -162,9 +164,9 @@ public class TimetableTabPresenter extends BasePresenter getMondaysFromCurrentSchoolYear() { - LocalDate startDate = LocalDate.of(getCurrentSchoolYear(), 9, 1); - LocalDate endDate = LocalDate.of(getCurrentSchoolYear() + 1, 8, 31); - - List dateList = new ArrayList<>(); - - LocalDate thisMonday = startDate.with(DayOfWeek.MONDAY); - - if (startDate.isAfter(thisMonday)) { - startDate = thisMonday.plusWeeks(1); - } else { - startDate = thisMonday; - } - - while (startDate.isBefore(endDate)) { - dateList.add(startDate.format(formatter)); - startDate = startDate.plusWeeks(1); - } - return dateList; - } - - public static int getCurrentSchoolYear() { - LocalDate localDate = LocalDate.now(); - return localDate.getMonthValue() <= 8 ? localDate.getYear() - 1 : localDate.getYear(); - } - - public static String getDateOfCurrentMonday(boolean normalize) { - LocalDate currentDate = LocalDate.now(); - - if (currentDate.getDayOfWeek() == DayOfWeek.SATURDAY && normalize) { - currentDate = currentDate.plusDays(2); - } else if (currentDate.getDayOfWeek() == DayOfWeek.SUNDAY && normalize) { - currentDate = currentDate.plusDays(1); - } else { - currentDate = currentDate.with(DayOfWeek.MONDAY); - } - return currentDate.format(formatter); - } - - public static int getTodayOrNextDayValue(boolean nextDay) { - DayOfWeek day = LocalDate.now().getDayOfWeek(); - if (nextDay) { - if (day == DayOfWeek.SUNDAY) { - return 0; - } - return day.getValue(); - } - return day.getValue() - 1; - } - - public static String getTodayOrNextDay(boolean nextDay) { - LocalDate current = LocalDate.now(); - return nextDay ? current.plusDays(1).format(formatter) : current.format(formatter); - } - - public static boolean isDateInWeek(LocalDate firstWeekDay, LocalDate date) { - return date.isAfter(firstWeekDay.minusDays(1)) && date.isBefore(firstWeekDay.plusDays(5)); - - } -} diff --git a/app/src/main/java/io/github/wulkanowy/utils/TimeUtils.kt b/app/src/main/java/io/github/wulkanowy/utils/TimeUtils.kt new file mode 100644 index 00000000..c61c7e0d --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/utils/TimeUtils.kt @@ -0,0 +1,97 @@ +package io.github.wulkanowy.utils + +import org.threeten.bp.DayOfWeek.* +import org.threeten.bp.LocalDate +import org.threeten.bp.Year +import org.threeten.bp.format.DateTimeFormatter +import org.threeten.bp.temporal.TemporalAdjusters +import java.util.* + +private val formatter = DateTimeFormatter.ofPattern(AppConstant.DATE_PATTERN) + +fun getParsedDate(dateString: String, dateFormat: String): LocalDate { + return LocalDate.parse(dateString, DateTimeFormatter.ofPattern(dateFormat)) +} + +fun getMondaysFromCurrentSchoolYear() = getMondaysFromCurrentSchoolYear(LocalDate.now()) + +fun getMondaysFromCurrentSchoolYear(date: LocalDate): List { + val startDate = getFirstSchoolDay(getSchoolYearForDate(date)) + ?.with(TemporalAdjusters.previousOrSame(MONDAY)) + val endDate = getFirstSchoolDay(getSchoolYearForDate(date) + 1) + ?.with(TemporalAdjusters.previousOrSame(MONDAY)) + + val dateList = ArrayList() + var monday = startDate as LocalDate + while (monday.isBefore(endDate)) { + dateList.add(monday.format(formatter)) + monday = monday.plusWeeks(1) + } + + return dateList +} + +fun getSchoolYearForDate(date: LocalDate): Int { + return if (date.monthValue <= 8) date.year - 1 else date.year +} + +fun getFirstDayOfCurrentWeek(): String = getFirstDayOfCurrentWeek(LocalDate.now()) + +fun getFirstDayOfCurrentWeek(date: LocalDate): String { + return when (date.dayOfWeek) { + SATURDAY -> date.plusDays(2) + SUNDAY -> date.plusDays(1) + else -> date.with(MONDAY) + }.format(formatter) +} + +fun getTodayOrNextDayOrder(next: Boolean): Int = getTodayOrNextDayOrder(next, LocalDate.now()) + +fun getTodayOrNextDayOrder(next: Boolean, date: LocalDate): Int { + val day = date.dayOfWeek + return if (next) { + if (day == SUNDAY) { + 0 + } else day.value + } else day.value - 1 +} + +fun getTodayOrNextDay(next: Boolean): String? = getTodayOrNextDay(next, LocalDate.now()) + +fun getTodayOrNextDay(next: Boolean, date: LocalDate): String? { + return (if (next) { + date.plusDays(1) + } else date).format(formatter) +} + +fun isDateInWeek(firstWeekDay: LocalDate, date: LocalDate): Boolean { + return date.isAfter(firstWeekDay.minusDays(1)) && date.isBefore(firstWeekDay.plusDays(5)) +} + +/** + * [Dz.U. 2016 poz. 1335](http://prawo.sejm.gov.pl/isap.nsf/DocDetails.xsp?id=WDU20160001335) + */ +fun isHolidays(): Boolean = isHolidays(LocalDate.now(), Year.now().value) + +fun isHolidays(day: LocalDate, year: Int): Boolean { + return day.isAfter(getLastSchoolDay(year)) && day.isBefore(getFirstSchoolDay(year)) +} + +fun getFirstSchoolDay(year: Int): LocalDate? { + val firstSeptember = LocalDate.of(year, 9, 1) + + return when (firstSeptember.dayOfWeek) { + FRIDAY, + SATURDAY, + SUNDAY -> firstSeptember.with(TemporalAdjusters.firstInMonth(MONDAY)) + else -> { + firstSeptember + } + } +} + +fun getLastSchoolDay(year: Int): LocalDate? { + return LocalDate + .of(year, 6, 20) + .with(TemporalAdjusters.next(FRIDAY)) +} diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 1af99630..d6f4cc7d 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -136,6 +136,7 @@ Usługi Włącz odświeżanie danych w tle + Zawieszone na wakacjach Interwał między odświeżaniem danych Synchronizacja tylko przez WiFi diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 21e63f5f..32c1efa8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -132,6 +132,7 @@ Services Enable background data refreshing + Suspended on holidays Interval between data refreshing Synchronization via WiFi only diff --git a/app/src/test/java/io/github/wulkanowy/utils/TimeUtilsTest.java b/app/src/test/java/io/github/wulkanowy/utils/TimeUtilsTest.java deleted file mode 100644 index e216392e..00000000 --- a/app/src/test/java/io/github/wulkanowy/utils/TimeUtilsTest.java +++ /dev/null @@ -1,48 +0,0 @@ -package io.github.wulkanowy.utils; - -import org.junit.Assert; -import org.junit.Test; -import org.threeten.bp.LocalDate; - -public class TimeUtilsTest { - - @Test - public void getParsedDateTest() { - Assert.assertEquals(LocalDate.of(1970, 1, 1), - TimeUtils.getParsedDate("1970-01-01", "yyyy-MM-dd")); - } - - @Test - public void isDateInWeekInsideTest() { - Assert.assertTrue(TimeUtils.isDateInWeek( - LocalDate.of(2018, 5, 28), - LocalDate.of(2018, 5, 31) - )); - } - - @Test - public void isDateInWeekExtremesTest() { - Assert.assertTrue(TimeUtils.isDateInWeek( - LocalDate.of(2018, 5, 28), - LocalDate.of(2018, 5, 28) - )); - - Assert.assertTrue(TimeUtils.isDateInWeek( - LocalDate.of(2018, 5, 28), - LocalDate.of(2018, 6, 1) - )); - } - - @Test - public void isDateInWeekOutOfTest() { - Assert.assertFalse(TimeUtils.isDateInWeek( - LocalDate.of(2018, 5, 28), - LocalDate.of(2018, 6, 2) - )); - - Assert.assertFalse(TimeUtils.isDateInWeek( - LocalDate.of(2018, 5, 28), - LocalDate.of(2018, 5, 27) - )); - } -} diff --git a/app/src/test/java/io/github/wulkanowy/utils/TimeUtilsTest.kt b/app/src/test/java/io/github/wulkanowy/utils/TimeUtilsTest.kt new file mode 100644 index 00000000..2edffbb0 --- /dev/null +++ b/app/src/test/java/io/github/wulkanowy/utils/TimeUtilsTest.kt @@ -0,0 +1,140 @@ +package io.github.wulkanowy.utils + +import org.junit.Test +import org.threeten.bp.LocalDate + +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue + +class TimeUtilsTest { + + @Test fun getParsedDateTest() { + assertEquals(LocalDate.of(1970, 1, 1), + getParsedDate("1970-01-01", "yyyy-MM-dd")) + } + + @Test fun getMondaysFromCurrentSchoolYearTest() { + val y201718 = getMondaysFromCurrentSchoolYear(LocalDate.of(2018, 1, 1)) + assertEquals("2017-09-04", y201718.first()) + assertEquals("2018-08-27", y201718.last()) + + val y202122 = getMondaysFromCurrentSchoolYear(LocalDate.of(2022, 1, 1)) + assertEquals("2021-08-30", y202122.first()) + assertEquals("2022-08-22", y202122.last()) + + val y202223 = getMondaysFromCurrentSchoolYear(LocalDate.of(2023, 1, 1)) + assertEquals("2022-08-29", y202223.first()) + assertEquals("2023-08-28", y202223.last()) + } + + @Test fun getCurrentSchoolYearTest() { + assertEquals(2017, getSchoolYearForDate(LocalDate.of(2018, 8, 31))) + assertEquals(2018, getSchoolYearForDate(LocalDate.of(2018, 9, 1))) + } + + @Test fun getFirstWeekDayTest() { + assertEquals("2018-06-18", getFirstDayOfCurrentWeek(LocalDate.of(2018, 6, 21))) + assertEquals("2018-06-18", getFirstDayOfCurrentWeek(LocalDate.of(2018, 6, 22))) + assertEquals("2018-06-25", getFirstDayOfCurrentWeek(LocalDate.of(2018, 6, 23))) + assertEquals("2018-06-25", getFirstDayOfCurrentWeek(LocalDate.of(2018, 6, 24))) + assertEquals("2018-06-25", getFirstDayOfCurrentWeek(LocalDate.of(2018, 6, 25))) + assertEquals("2018-06-25", getFirstDayOfCurrentWeek(LocalDate.of(2018, 6, 26))) + } + + @Test fun getTodayOrNextDayOrderTest() { + assertEquals(0, getTodayOrNextDayOrder(true, LocalDate.of(2018, 6, 24))) // sunday + assertEquals(6, getTodayOrNextDayOrder(false, LocalDate.of(2018, 6, 24))) + assertEquals(1, getTodayOrNextDayOrder(true, LocalDate.of(2018, 6, 25))) + assertEquals(0, getTodayOrNextDayOrder(false, LocalDate.of(2018, 6, 25))) + } + + @Test fun getTodayOrNextDayTest() { + assertEquals("2018-06-26", getTodayOrNextDay(false, LocalDate.of(2018, 6, 26))) + assertEquals("2018-06-27", getTodayOrNextDay(true, LocalDate.of(2018, 6, 26))) + } + + @Test fun isDateInWeekInsideTest() { + assertTrue(isDateInWeek( + LocalDate.of(2018, 5, 28), + LocalDate.of(2018, 5, 31) + )) + } + + @Test fun isDateInWeekExtremesTest() { + assertTrue(isDateInWeek( + LocalDate.of(2018, 5, 28), + LocalDate.of(2018, 5, 28) + )) + + assertTrue(isDateInWeek( + LocalDate.of(2018, 5, 28), + LocalDate.of(2018, 6, 1) + )) + } + + @Test fun isDateInWeekOutOfTest() { + assertFalse(isDateInWeek( + LocalDate.of(2018, 5, 28), + LocalDate.of(2018, 6, 2) + )) + + assertFalse(isDateInWeek( + LocalDate.of(2018, 5, 28), + LocalDate.of(2018, 5, 27) + )) + } + + @Test fun isHolidaysInSchoolEndTest() { + assertFalse(isHolidays(LocalDate.of(2017, 6, 23), 2017)) + assertFalse(isHolidays(LocalDate.of(2018, 6, 22), 2018)) + assertFalse(isHolidays(LocalDate.of(2019, 6, 21), 2019)) + assertFalse(isHolidays(LocalDate.of(2020, 6, 26), 2020)) + assertFalse(isHolidays(LocalDate.of(2021, 6, 25), 2021)) + assertFalse(isHolidays(LocalDate.of(2022, 6, 24), 2022)) + assertFalse(isHolidays(LocalDate.of(2023, 6, 23), 2023)) + assertFalse(isHolidays(LocalDate.of(2024, 6, 21), 2024)) + assertFalse(isHolidays(LocalDate.of(2025, 6, 27), 2025)) + } + + @Test fun isHolidaysInHolidaysStartTest() { + assertTrue(isHolidays(LocalDate.of(2017, 6, 24), 2017)) + assertTrue(isHolidays(LocalDate.of(2018, 6, 23), 2018)) + assertTrue(isHolidays(LocalDate.of(2019, 6, 22), 2019)) + assertTrue(isHolidays(LocalDate.of(2020, 6, 27), 2020)) + assertTrue(isHolidays(LocalDate.of(2021, 6, 26), 2021)) + assertTrue(isHolidays(LocalDate.of(2022, 6, 25), 2022)) + assertTrue(isHolidays(LocalDate.of(2023, 6, 24), 2023)) + assertTrue(isHolidays(LocalDate.of(2024, 6, 22), 2024)) + assertTrue(isHolidays(LocalDate.of(2025, 6, 28), 2025)) + } + + @Test fun isHolidaysInHolidaysEndTest() { + assertTrue(isHolidays(LocalDate.of(2017, 9, 1), 2017)) // friday + assertTrue(isHolidays(LocalDate.of(2017, 9, 2), 2017)) // saturday + assertTrue(isHolidays(LocalDate.of(2017, 9, 3), 2017)) // sunday + assertTrue(isHolidays(LocalDate.of(2018, 9, 1), 2018)) // saturday + assertTrue(isHolidays(LocalDate.of(2018, 9, 2), 2018)) // sunday + assertTrue(isHolidays(LocalDate.of(2019, 9, 1), 2019)) // sunday + assertTrue(isHolidays(LocalDate.of(2020, 8, 31), 2020)) // monday + assertTrue(isHolidays(LocalDate.of(2021, 8, 31), 2021)) // tuesday + assertTrue(isHolidays(LocalDate.of(2022, 8, 31), 2022)) // wednesday + assertTrue(isHolidays(LocalDate.of(2023, 9, 1), 2023)) // friday + assertTrue(isHolidays(LocalDate.of(2023, 9, 2), 2023)) // saturday + assertTrue(isHolidays(LocalDate.of(2023, 9, 3), 2023)) // sunday + assertTrue(isHolidays(LocalDate.of(2024, 9, 1), 2024)) // sunday + assertTrue(isHolidays(LocalDate.of(2025, 8, 31), 2025)) // sunday + } + + @Test fun isHolidaysInSchoolStartTest() { + assertFalse(isHolidays(LocalDate.of(2017, 9, 4), 2017)) // monday + assertFalse(isHolidays(LocalDate.of(2018, 9, 3), 2018)) // monday + assertFalse(isHolidays(LocalDate.of(2019, 9, 2), 2019)) // monday + assertFalse(isHolidays(LocalDate.of(2020, 9, 1), 2020)) // tuesday + assertFalse(isHolidays(LocalDate.of(2021, 9, 1), 2021)) // wednesday + assertFalse(isHolidays(LocalDate.of(2022, 9, 1), 2022)) // thursday + assertFalse(isHolidays(LocalDate.of(2023, 9, 4), 2023)) // monday + assertFalse(isHolidays(LocalDate.of(2024, 9, 2), 2024)) // monday + assertFalse(isHolidays(LocalDate.of(2025, 9, 1), 2025)) // monday + } +} diff --git a/build.gradle b/build.gradle index 760fb09f..2815bd0f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,5 @@ buildscript { + ext.kotlin_version = '1.2.51' repositories { mavenCentral() google() @@ -8,18 +9,21 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.1.3' classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.6.2" - classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.0' + classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4' classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } plugins { // gradle dependencyUpdates -Drevision=release - id "com.github.ben-manes.versions" version "0.17.0" + id "com.github.ben-manes.versions" version "0.20.0" } project.ext.preDexLibs = !project.hasProperty("disablePreDex") subprojects { + apply plugin: 'build-dashboard' // build/reports/buildDashboard/index.html + project.plugins.whenPluginAdded { plugin -> if ("com.android.build.gradle.AppPlugin" == plugin.class.name) { project.android.dexOptions.preDexLibraries = rootProject.ext.preDexLibs @@ -52,17 +56,16 @@ ext { slf4jApi = "1.7.25" slf4jTimber = "1.0.1" - timber = "4.7.0" + timber = "4.7.1" - debugDb = "1.0.3" - sqlcipher = "3.5.9" + debugDb = "1.0.4" junit = "4.12" - mockito = "2.18.3" + mockito = "2.19.0" testRunner = "1.0.2" fabricGradle = "1.25.4" - crashlyticsSdk = "2.9.3" + crashlyticsSdk = "2.9.4" crashlyticsAnswers = "1.4.2" playPublisher = "1.2.2" @@ -73,10 +76,22 @@ allprojects { mavenCentral() google() jcenter() - maven { url "https://jitpack.io" } } } task clean(type: Delete) { delete rootProject.buildDir } + +dependencyUpdates.resolutionStrategy { + componentSelection { rules -> + rules.all { ComponentSelection selection -> + boolean rejected = ['alpha', 'beta', 'rc', 'cr', 'm'].any { qualifier -> + selection.candidate.version ==~ /(?i).*[.-]${qualifier}[.\d-]*/ + } + if (rejected) { + selection.reject('Release candidate') + } + } + } +} diff --git a/jacoco.gradle b/jacoco.gradle deleted file mode 100644 index 84a0ce97..00000000 --- a/jacoco.gradle +++ /dev/null @@ -1,40 +0,0 @@ -apply plugin: "jacoco" - -jacoco { - toolVersion "0.8.1" -} - -tasks.withType(Test) { - jacoco.includeNoLocationClasses = true -} - -// run ./gradlew clean createDebugCoverageReport jacocoTestReport -task jacocoTestReport(type: JacocoReport) { - - group = "Reporting" - description = "Generate Jacoco coverage reports" - - reports { - xml.enabled = true - html.enabled = true - } - - def fileFilter = ["**/R.class", - "**/R\$*.class", - "**/BuildConfig.*", - "**/Manifest*.*", - "android/**/*.*", - "**/Lambda.class", - "**/*Lambda.class", - "**/*Lambda*.class", - "**/*Lambda*.*", - "**/*Builder.*" - ] - - def debugTree = fileTree(dir: "${buildDir}/intermediates/classes/debug", excludes: fileFilter) - def mainSrc = "${project.projectDir}/src/main/java" - - sourceDirectories = files([mainSrc]) - classDirectories = files([debugTree]) - executionData = fileTree(dir: project.projectDir, includes: ["**/*.exec" , "**/*.ec"]) -} From 378aba971692d334aa671933fb8bde500acddd57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Sat, 14 Jul 2018 16:52:09 +0200 Subject: [PATCH 03/11] Add support for multiple SnP sites (#140) --- .../java/io/github/wulkanowy/api/Client.java | 40 +++- .../java/io/github/wulkanowy/api/SnP.java | 2 - .../wulkanowy/api/StudentAndParent.java | 56 +----- .../java/io/github/wulkanowy/api/Vulcan.java | 12 +- .../io/github/wulkanowy/api/generic/School.kt | 7 + .../io/github/wulkanowy/api/login/Login.java | 15 +- .../github/wulkanowy/api/login/StartPage.kt | 45 +++++ .../io/github/wulkanowy/api/ClientTest.java | 37 ++-- .../wulkanowy/api/StudentAndParentTest.java | 67 +------ .../github/wulkanowy/api/login/LoginTest.java | 16 +- .../wulkanowy/api/login/StartPageTest.kt | 68 +++++++ .../io/github/wulkanowy/api/Start-multi.html | 27 +++ .../api/{Start.html => Start-std.html} | 2 +- .../api/login/Logowanie-success.html | 13 ++ app/build.gradle | 2 +- .../data/db/dao/entities/SchoolTest.java | 22 +++ .../wulkanowy/data/db/dao/DbContract.java | 2 + .../wulkanowy/data/db/dao/DbHelper.java | 2 + .../wulkanowy/data/db/dao/DbRepository.java | 11 +- .../data/db/dao/entities/School.java | 179 ++++++++++++++++++ .../data/db/dao/entities/Student.java | 18 +- .../data/db/dao/entities/Symbol.java | 46 ++--- .../data/db/dao/migrations/Migration27.java | 2 +- .../data/db/dao/migrations/Migration29.kt | 60 ++++++ .../wulkanowy/data/sync/AccountSync.java | 78 +++++--- .../wulkanowy/utils/DataObjectConverter.java | 20 +- 26 files changed, 630 insertions(+), 219 deletions(-) create mode 100644 api/src/main/java/io/github/wulkanowy/api/generic/School.kt create mode 100644 api/src/main/java/io/github/wulkanowy/api/login/StartPage.kt create mode 100644 api/src/test/java/io/github/wulkanowy/api/login/StartPageTest.kt create mode 100644 api/src/test/resources/io/github/wulkanowy/api/Start-multi.html rename api/src/test/resources/io/github/wulkanowy/api/{Start.html => Start-std.html} (85%) create mode 100644 app/src/androidTest/java/io/github/wulkanowy/data/db/dao/entities/SchoolTest.java create mode 100644 app/src/main/java/io/github/wulkanowy/data/db/dao/entities/School.java create mode 100644 app/src/main/java/io/github/wulkanowy/data/db/dao/migrations/Migration29.kt diff --git a/api/src/main/java/io/github/wulkanowy/api/Client.java b/api/src/main/java/io/github/wulkanowy/api/Client.java index 8bbae7ca..c6360d04 100644 --- a/api/src/main/java/io/github/wulkanowy/api/Client.java +++ b/api/src/main/java/io/github/wulkanowy/api/Client.java @@ -8,9 +8,11 @@ import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.Date; +import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; +import io.github.wulkanowy.api.generic.School; import io.github.wulkanowy.api.login.Login; public class Client { @@ -25,16 +27,21 @@ public class Client { private String symbol; + private String schoolId; + + private List schools; + private Date lastSuccessRequest; private Cookies cookies = new Cookies(); private static final Logger logger = LoggerFactory.getLogger(Client.class); - Client(String email, String password, String symbol) { + Client(String email, String password, String symbol, String schoolId) { this.email = email; this.password = password; this.symbol = symbol; + this.schoolId = schoolId; setFullEndpointInfo(email); } @@ -62,14 +69,18 @@ public class Client { return; } + logger.info("Not logged. Login..."); + clearCookies(); - this.symbol = new Login(this).login(email, password, symbol); + new Login(this).login(email, password, symbol); + lastSuccessRequest = new Date(); + logger.info("Login successful on {} at {}", getHost(), new Date()); } private boolean isLoggedIn() { - logger.debug("Last success request: {}", lastSuccessRequest); - logger.debug("Cookies: {}", getCookies().size()); + logger.trace("Last success request: {}", lastSuccessRequest); + logger.trace("Cookies: {}", getCookies().size()); return getCookies().size() > 0 && lastSuccessRequest != null && 5 > TimeUnit.MILLISECONDS.toMinutes(new Date().getTime() - lastSuccessRequest.getTime()); @@ -92,15 +103,30 @@ public class Client { cookies = new Cookies(); } - String getHost() { + public String getHost() { return host; } + public void setSchools(List schools) { + this.schools = schools; + this.schoolId = schools.get(0).getId(); + } + + public List getSchools() throws IOException, VulcanException { + login(); + return schools; + } + + public String getSchoolId() throws IOException, VulcanException { + return schoolId != null ? schoolId : getSchools().get(0).getId(); + } + String getFilledUrl(String url) { return url .replace("{schema}", protocol) - .replace("{host}", host.replace(":", "%253A")) - .replace("{symbol}", symbol); + .replace("{host}", host) + .replace("{symbol}", symbol) + .replace("{ID}", schoolId != null ? schoolId : ""); } public Document getPageByUrl(String url) throws IOException, VulcanException { diff --git a/api/src/main/java/io/github/wulkanowy/api/SnP.java b/api/src/main/java/io/github/wulkanowy/api/SnP.java index 6747faf0..84ec1aed 100644 --- a/api/src/main/java/io/github/wulkanowy/api/SnP.java +++ b/api/src/main/java/io/github/wulkanowy/api/SnP.java @@ -13,8 +13,6 @@ import io.github.wulkanowy.api.generic.Student; public interface SnP { - String getSchoolID(); - void setDiaryID(String id); String getStudentID(); diff --git a/api/src/main/java/io/github/wulkanowy/api/StudentAndParent.java b/api/src/main/java/io/github/wulkanowy/api/StudentAndParent.java index 03a7b0e5..ba527f6a 100644 --- a/api/src/main/java/io/github/wulkanowy/api/StudentAndParent.java +++ b/api/src/main/java/io/github/wulkanowy/api/StudentAndParent.java @@ -20,32 +20,27 @@ import io.github.wulkanowy.api.generic.Student; public class StudentAndParent implements SnP { - private static final String START_PAGE_URL = "{schema}://uonetplus.{host}/{symbol}/Start.mvc/Index"; - private static final String BASE_URL = "{schema}://uonetplus-opiekun.{host}/{symbol}/{ID}/"; private static final String GRADES_PAGE_URL = "Oceny/Wszystkie"; private Client client; - private String schoolID; - private String studentID; private String diaryID; private static final Logger logger = LoggerFactory.getLogger(StudentAndParent.class); - StudentAndParent(Client client, String schoolID, String studentID, String diaryID) { + StudentAndParent(Client client, String studentID, String diaryID) { this.client = client; - this.schoolID = schoolID; this.studentID = studentID; this.diaryID = diaryID; } public StudentAndParent setUp() throws IOException, VulcanException { if (null == getStudentID() || "".equals(getStudentID())) { - Document doc = client.getPageByUrl(getSnpHomePageUrl()); + Document doc = client.getPageByUrl(BASE_URL); if (doc.select("#idSection").isEmpty()) { logger.error("Expected SnP page, got page with title: {} {}", doc.title(), doc.selectFirst("body")); @@ -62,51 +57,10 @@ public class StudentAndParent implements SnP { return this; } - public String getSchoolID() { - return schoolID; - } - public String getStudentID() { return studentID; } - private String getBaseUrl() { - return BASE_URL.replace("{ID}", getSchoolID()); - } - - String getSnpHomePageUrl() throws IOException, VulcanException { - if (null != getSchoolID()) { - return getBaseUrl(); - } - - // get url to uonetplus-opiekun.fakelog.cf - Document startPage = client.getPageByUrl(START_PAGE_URL); - Elements studentTileLink = startPage.select(".panel.linkownia.pracownik.klient > a"); - - logger.debug("studentTileLink: {}", studentTileLink.size()); - - if (studentTileLink.isEmpty()) { - throw new VulcanException("Na pewno używasz konta z dostępem do Witryny ucznia i rodzica?"); - } - - String snpPageUrl = studentTileLink.last().attr("href"); - - this.schoolID = getExtractedIdFromUrl(snpPageUrl); - - return snpPageUrl; - } - - String getExtractedIdFromUrl(String snpPageUrl) throws VulcanException { - String[] path = snpPageUrl.split(client.getHost())[1].split("/"); - - if (5 != path.length) { - logger.error("Expected snp url, got {}", snpPageUrl); - throw new VulcanException("Na pewno używasz konta z dostępem do Witryny ucznia i rodzica?"); - } - - return path[2]; - } - public String getRowDataChildValue(Element e, int index) { return e.select(".daneWiersz .wartosc").get(index - 1).text(); } @@ -120,7 +74,7 @@ public class StudentAndParent implements SnP { cookies.put("idBiezacyDziennik", diaryID); cookies.put("idBiezacyUczen", studentID); - Document doc = client.getPageByUrl(getBaseUrl() + url, true, cookies); + Document doc = client.getPageByUrl(BASE_URL + url, true, cookies); if (!doc.title().startsWith("Witryna ucznia i rodzica")) { logger.error("Expected SnP page, got page with title: {} {}", doc.title(), doc.selectFirst("body")); @@ -135,7 +89,7 @@ public class StudentAndParent implements SnP { } public List getDiaries() throws IOException, VulcanException { - return getDiaries(client.getPageByUrl(getBaseUrl())); + return getDiaries(client.getPageByUrl(BASE_URL)); } private List getDiaries(Document doc) throws IOException, VulcanException { @@ -143,7 +97,7 @@ public class StudentAndParent implements SnP { } public List getStudents() throws IOException, VulcanException { - return getStudents(client.getPageByUrl(getBaseUrl())); + return getStudents(client.getPageByUrl(BASE_URL)); } private List getStudents(Document doc) throws IOException, VulcanException { diff --git a/api/src/main/java/io/github/wulkanowy/api/Vulcan.java b/api/src/main/java/io/github/wulkanowy/api/Vulcan.java index 2b4d1205..bf482969 100644 --- a/api/src/main/java/io/github/wulkanowy/api/Vulcan.java +++ b/api/src/main/java/io/github/wulkanowy/api/Vulcan.java @@ -4,10 +4,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; +import java.util.List; import io.github.wulkanowy.api.attendance.AttendanceStatistics; import io.github.wulkanowy.api.attendance.AttendanceTable; import io.github.wulkanowy.api.exams.ExamsWeek; +import io.github.wulkanowy.api.generic.School; import io.github.wulkanowy.api.grades.GradesList; import io.github.wulkanowy.api.grades.SubjectsList; import io.github.wulkanowy.api.messages.Messages; @@ -27,8 +29,6 @@ public class Vulcan { private Client client; - private String schoolId; - private String studentId; private String diaryId; @@ -36,11 +36,10 @@ public class Vulcan { private static final Logger logger = LoggerFactory.getLogger(Vulcan.class); public void setCredentials(String email, String password, String symbol, String schoolId, String studentId, String diaryId) { - this.schoolId = schoolId; this.studentId = studentId; this.diaryId = diaryId; - client = new Client(email, password, symbol); + client = new Client(email, password, symbol, schoolId); logger.debug("Client created with symbol " + symbol); } @@ -55,7 +54,10 @@ public class Vulcan { public String getSymbol() throws NotLoggedInErrorException { return getClient().getSymbol(); + } + public List getSchools() throws VulcanException, IOException { + return getClient().getSchools(); } public SnP getStudentAndParent() throws VulcanException, IOException { @@ -63,7 +65,7 @@ public class Vulcan { return this.snp; } - this.snp = new StudentAndParent(getClient(), schoolId, studentId, diaryId) + this.snp = new StudentAndParent(getClient(), studentId, diaryId) .setUp(); return this.snp; diff --git a/api/src/main/java/io/github/wulkanowy/api/generic/School.kt b/api/src/main/java/io/github/wulkanowy/api/generic/School.kt new file mode 100644 index 00000000..c14fc5d2 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/generic/School.kt @@ -0,0 +1,7 @@ +package io.github.wulkanowy.api.generic + +data class School( + val name: String, + val id: String, + val current: Boolean +) diff --git a/api/src/main/java/io/github/wulkanowy/api/login/Login.java b/api/src/main/java/io/github/wulkanowy/api/login/Login.java index f6d4cd11..443a9387 100644 --- a/api/src/main/java/io/github/wulkanowy/api/login/Login.java +++ b/api/src/main/java/io/github/wulkanowy/api/login/Login.java @@ -16,8 +16,9 @@ import io.github.wulkanowy.api.VulcanException; public class Login { - static final String LOGIN_PAGE_URL = "{schema}://cufs.{host}/{symbol}/Account/LogOn" + - "?ReturnUrl=%2F{symbol}%2FFS%2FLS%3Fwa%3Dwsignin1.0%26wtrealm%3D" + + protected static final String LOGIN_PAGE_URL = "{schema}://cufs.{host}/{symbol}/Account/LogOn"; + + private static final String LOGIN_PAGE_URL_QUERY = "?ReturnUrl=%2F{symbol}%2FFS%2FLS%3Fwa%3Dwsignin1.0%26wtrealm%3D" + "{schema}%253a%252f%252fuonetplus.{host}%252f{symbol}%252fLoginEndpoint.aspx%26wctx%3D" + "{schema}%253a%252f%252fuonetplus.{host}%252f{symbol}%252fLoginEndpoint.aspx"; @@ -29,7 +30,7 @@ public class Login { this.client = client; } - public String login(String email, String password, String symbol) throws VulcanException, IOException { + public void login(String email, String password, String symbol) throws VulcanException, IOException { Document certDoc = sendCredentials(email, password); if ("Błąd".equals(certDoc.title())) { @@ -37,7 +38,7 @@ public class Login { throw new NotLoggedInErrorException(certDoc.body().text()); } - return sendCertificate(certDoc, symbol); + sendCertificate(certDoc, symbol); } Document sendCredentials(String email, String password) throws IOException, VulcanException { @@ -46,7 +47,7 @@ public class Login { {"Password", password} }; - Document nextDoc = sendCredentialsData(credentials, LOGIN_PAGE_URL); + Document nextDoc = sendCredentialsData(credentials, LOGIN_PAGE_URL + LOGIN_PAGE_URL_QUERY.replace(":", "%253A")); Element errorMessage = nextDoc.selectFirst(".ErrorMessage, #ErrorTextLabel"); if (null != errorMessage) { @@ -86,7 +87,7 @@ public class Login { }; } - String sendCertificate(Document doc, String defaultSymbol) throws IOException, VulcanException { + void sendCertificate(Document doc, String defaultSymbol) throws IOException, VulcanException { client.setSymbol(findSymbol(defaultSymbol, doc.select("input[name=wresult]").val())); Document targetDoc = sendCertData(doc); @@ -106,7 +107,7 @@ public class Login { throw new LoginErrorException("Expected page title `UONET+`, got " + title); } - return client.getSymbol(); + client.setSchools(new StartPage(client).getSchools(targetDoc)); } private Document sendCertData(Document doc) throws IOException, VulcanException { diff --git a/api/src/main/java/io/github/wulkanowy/api/login/StartPage.kt b/api/src/main/java/io/github/wulkanowy/api/login/StartPage.kt new file mode 100644 index 00000000..6f6b1490 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/login/StartPage.kt @@ -0,0 +1,45 @@ +package io.github.wulkanowy.api.login + +import io.github.wulkanowy.api.Client +import io.github.wulkanowy.api.VulcanException +import io.github.wulkanowy.api.generic.School +import org.jsoup.nodes.Document +import org.slf4j.LoggerFactory + +class StartPage(val client: Client) { + + private val logger = LoggerFactory.getLogger(StartPage::class.java) + + fun getSchools(startPage: Document): MutableList { + val schoolList = mutableListOf() + + val snpLinks = startPage.select(".panel.linkownia.pracownik.klient a") + + logger.debug("SnP links: {}", snpLinks.size) + + if (snpLinks.isEmpty()) { + throw VulcanException("Na pewno używasz konta z dostępem do Witryny ucznia i rodzica?") + } + + snpLinks.map { + schoolList.add(School( + it.text(), + getExtractedIdFromUrl(it.attr("href")), + it == snpLinks.first() + )) + } + + return schoolList + } + + internal fun getExtractedIdFromUrl(snpPageUrl: String): String { + val path = snpPageUrl.split(client.host).getOrNull(1)?.split("/") + + if (6 != path?.size) { + logger.error("Expected snp url, got {}", snpPageUrl) + throw VulcanException("Na pewno używasz konta z dostępem do Witryny ucznia i rodzica?") + } + + return path[2] + } +} diff --git a/api/src/test/java/io/github/wulkanowy/api/ClientTest.java b/api/src/test/java/io/github/wulkanowy/api/ClientTest.java index 50724875..298affac 100644 --- a/api/src/test/java/io/github/wulkanowy/api/ClientTest.java +++ b/api/src/test/java/io/github/wulkanowy/api/ClientTest.java @@ -12,16 +12,24 @@ public class ClientTest { } @Test - public void setFullEndpointInfoTest() throws Exception { - Client client = new Client("http://fakelog.net\\\\admin", "pass", "Default"); + public void setFullEndpointInfoTest() { + Client client = new Client("http://fakelog.cf\\\\admin", "pass", "Default", "123"); - Assert.assertEquals("fakelog.net", client.getHost()); + Assert.assertEquals("fakelog.cf", client.getHost()); Assert.assertEquals("Default", client.getSymbol()); } + @Test + public void setFullEndpointInfoWithSymbolTest() { + Client client = new Client("http://fakelog.cf/notdefault\\\\admin", "pass", "Default", "123"); + + Assert.assertEquals("fakelog.cf", client.getHost()); + Assert.assertEquals("notdefault", client.getSymbol()); // + } + @Test public void checkForNoErrorsTest() throws Exception { - Client client = new Client("", "", ""); + Client client = new Client("", "", "", "123"); Document doc = Jsoup.parse(getFixtureAsString("login/Logowanie-success.html")); @@ -30,7 +38,7 @@ public class ClientTest { @Test(expected = VulcanOfflineException.class) public void checkForErrorsOffline() throws Exception { - Client client = new Client("", "", ""); + Client client = new Client("", "", "", "123"); Document doc = Jsoup.parse(getFixtureAsString("login/PrzerwaTechniczna.html")); @@ -39,7 +47,7 @@ public class ClientTest { @Test(expected = NotLoggedInErrorException.class) public void checkForErrors() throws Exception { - Client client = new Client("", "", ""); + Client client = new Client("", "", "", "123"); Document doc = Jsoup.parse(getFixtureAsString("login/Logowanie-notLoggedIn.html")); @@ -48,16 +56,23 @@ public class ClientTest { @Test public void getFilledUrlTest() throws Exception { - Client client = new Client("http://fakelog.cf\\\\admin", "", "symbol123"); + Client client = new Client("http://fakelog.cf\\\\admin", "", "symbol123", "321"); - Assert.assertEquals("http://uonetplus.fakelog.cf/symbol123/LoginEndpoint.aspx", - client.getFilledUrl("{schema}://uonetplus.{host}/{symbol}/LoginEndpoint.aspx")); + Assert.assertEquals("http://uonetplus-opiekun.fakelog.cf/symbol123/321/Oceny/Wszystkie", + client.getFilledUrl("{schema}://uonetplus-opiekun.{host}/{symbol}/{ID}/Oceny/Wszystkie")); } @Test - public void getSymbolTest() throws Exception { - Client client = new Client("", "", "symbol4321"); + public void getSymbolTest() { + Client client = new Client("", "", "symbol4321", "123"); Assert.assertEquals("symbol4321", client.getSymbol()); } + + @Test + public void getSchoolIdTest() throws Exception { + Client client = new Client("", "", "1", "123456"); + + Assert.assertEquals("123456", client.getSchoolId()); + } } diff --git a/api/src/test/java/io/github/wulkanowy/api/StudentAndParentTest.java b/api/src/test/java/io/github/wulkanowy/api/StudentAndParentTest.java index ba0c8f7f..4c6443b1 100644 --- a/api/src/test/java/io/github/wulkanowy/api/StudentAndParentTest.java +++ b/api/src/test/java/io/github/wulkanowy/api/StudentAndParentTest.java @@ -32,68 +32,13 @@ public class StudentAndParentTest { @Test public void snpTest() { - StudentAndParent snp = new StudentAndParent(client, "id123", null, null); - Assert.assertEquals("id123", snp.getSchoolID()); - } - - @Test - public void getSnpPageUrlWithIdTest() throws Exception { - Assert.assertEquals("{schema}://uonetplus-opiekun.{host}/{symbol}/123456/", - (new StudentAndParent(client, "123456", null, null)).getSnpHomePageUrl()); - } - - @Test - public void getSnpPageUrlWithoutIdTest() throws Exception { - String input = FixtureHelper.getAsString(getClass().getResourceAsStream("Start.html")); - Document startPageDocument = Jsoup.parse(input); - - Mockito.when(client.getHost()).thenReturn("vulcan.net.pl"); - Mockito.when(client.getPageByUrl(Mockito.anyString())).thenReturn(startPageDocument); - StudentAndParent snp = new StudentAndParent(client, null, null, null); - - Assert.assertEquals("https://uonetplus-opiekun.vulcan.net.pl/symbol/534213/Start/Index/", - snp.getSnpHomePageUrl()); - } - - @Test(expected = VulcanException.class) - public void getSnpPageUrlWithWrongPage() throws Exception { - Document wrongPageDocument = Jsoup.parse( - FixtureHelper.getAsString(getClass().getResourceAsStream("OcenyWszystkie-semester.html")) - ); - - Mockito.when(client.getPageByUrl(Mockito.anyString())).thenReturn(wrongPageDocument); - StudentAndParent snp = new StudentAndParent(client, null, null, null); - - snp.getSnpHomePageUrl(); - } - - @Test - public void getExtractedIDStandardTest() throws Exception { - Mockito.when(client.getHost()).thenReturn("vulcan.net.pl"); - StudentAndParent snp = new StudentAndParent(client, "symbol", null, null); - Assert.assertEquals("123456", snp.getExtractedIdFromUrl("https://uonetplus-opiekun" - + ".vulcan.net.pl/powiat/123456/Start/Index/")); - } - - @Test - public void getExtractedIDDemoTest() throws Exception { - Mockito.when(client.getHost()).thenReturn("vulcan.net.pl"); - StudentAndParent snp = new StudentAndParent(client, "symbol", null, null); - Assert.assertEquals("demo12345", - snp.getExtractedIdFromUrl("https://uonetplus-opiekun.vulcan.net.pl/demoupowiat/demo12345/Start/Index/")); - } - - @Test(expected = VulcanException.class) - public void getExtractedIDNotLoggedTest() throws Exception { - Mockito.when(client.getHost()).thenReturn("vulcan.net.pl"); - StudentAndParent snp = new StudentAndParent(client, "symbol", null, null); - Assert.assertEquals("123", - snp.getExtractedIdFromUrl("https://uonetplus.vulcan.net.pl/powiat/")); + StudentAndParent snp = new StudentAndParent(client, "1234", null); + Assert.assertEquals("1234", snp.getStudentID()); } @Test public void getSemestersTest() throws Exception { - SnP snp = new StudentAndParent(client, "123456", null, null); + SnP snp = new StudentAndParent(client, null, null); List semesters = snp.getSemesters(); Assert.assertEquals(2, semesters.size()); @@ -113,7 +58,7 @@ public class StudentAndParentTest { semesters.add(new Semester().setName("1500100900").setId("1").setCurrent(false)); semesters.add(new Semester().setName("1500100901").setId("2").setCurrent(true)); - SnP snp = new StudentAndParent(client, "", null, null); + SnP snp = new StudentAndParent(client, null, null); Semester semester = snp.getCurrent(semesters); Assert.assertTrue(semester.isCurrent()); @@ -123,7 +68,7 @@ public class StudentAndParentTest { @Test public void getCurrentSemesterFromEmptyTest() { - SnP snp = new StudentAndParent(client, "", null, null); + SnP snp = new StudentAndParent(client, null, null); List semesters = new ArrayList<>(); Assert.assertNull(snp.getCurrent(semesters)); @@ -136,7 +81,7 @@ public class StudentAndParentTest { client = Mockito.mock(Client.class); Mockito.when(client.getPageByUrl(Mockito.anyString())).thenReturn(snpHome); - SnP snp = new StudentAndParent(client, "", null, null); + SnP snp = new StudentAndParent(client, null, null); snp.setUp(); diff --git a/api/src/test/java/io/github/wulkanowy/api/login/LoginTest.java b/api/src/test/java/io/github/wulkanowy/api/login/LoginTest.java index 4a4f8915..86a3ef40 100644 --- a/api/src/test/java/io/github/wulkanowy/api/login/LoginTest.java +++ b/api/src/test/java/io/github/wulkanowy/api/login/LoginTest.java @@ -38,9 +38,11 @@ public class LoginTest { .thenReturn(getFixtureAsDocument("Logowanie-certyfikat.html")); Mockito.doCallRealMethod().when(client).setSymbol(Mockito.anyString()); Mockito.when(client.getSymbol()).thenCallRealMethod(); + Mockito.when(client.getHost()).thenReturn("fakelog.cf"); Login login = new Login(client); + login.login("a@a", "pswd", "d123"); - Assert.assertEquals("d123", login.login("a@a", "pswd", "d123")); + Assert.assertEquals("d123", client.getSymbol()); } @Test(expected = BadCredentialsException.class) @@ -74,10 +76,12 @@ public class LoginTest { Client client = getClient("Logowanie-success.html"); Mockito.doCallRealMethod().when(client).setSymbol(Mockito.anyString()); Mockito.when(client.getSymbol()).thenCallRealMethod(); + Mockito.when(client.getHost()).thenReturn("fakelog.cf"); Login login = new Login(client); - Assert.assertEquals("wulkanowyschool321", login.sendCertificate( - getFixtureAsDocument("Logowanie-certyfikat.html"), "wulkanowyschool321")); + login.sendCertificate(getFixtureAsDocument("Logowanie-certyfikat.html"), "wulkanowyschool321"); + + Assert.assertEquals("wulkanowyschool321", client.getSymbol()); } @Test @@ -85,10 +89,12 @@ public class LoginTest { Client client = getClient("Logowanie-success.html"); Mockito.doCallRealMethod().when(client).setSymbol(Mockito.anyString()); Mockito.when(client.getSymbol()).thenCallRealMethod(); + Mockito.when(client.getHost()).thenReturn("fakelog.cf"); Login login = new Login(client); - Assert.assertEquals("demo12345", - login.sendCertificate(getFixtureAsDocument("Logowanie-certyfikat.html"), "Default")); + login.sendCertificate(getFixtureAsDocument("Logowanie-certyfikat.html"), "Default"); + + Assert.assertEquals("demo12345", client.getSymbol()); } @Test(expected = AccountPermissionException.class) diff --git a/api/src/test/java/io/github/wulkanowy/api/login/StartPageTest.kt b/api/src/test/java/io/github/wulkanowy/api/login/StartPageTest.kt new file mode 100644 index 00000000..271b3bb0 --- /dev/null +++ b/api/src/test/java/io/github/wulkanowy/api/login/StartPageTest.kt @@ -0,0 +1,68 @@ +package io.github.wulkanowy.api.login + +import io.github.wulkanowy.api.Client +import io.github.wulkanowy.api.FixtureHelper +import io.github.wulkanowy.api.VulcanException +import org.jsoup.Jsoup +import org.jsoup.nodes.Document +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test +import org.mockito.Mockito +import org.mockito.Mockito.mock + +class StartPageTest { + + private val client: Client = mock(Client::class.java) + + @Before fun setUp() { + Mockito.`when`(client.host).thenReturn("fakelog.cf") + } + + private fun getDoc(name: String): Document = Jsoup.parse(FixtureHelper.getAsString(javaClass.getResourceAsStream(name))) + + @Test fun getSchoolTest() { + assertEquals("534213", StartPage(client).getSchools(getDoc("../Start-std.html"))[0].id) + } + + @Test fun getMultiSchoolTest() { + val schools = StartPage(client).getSchools(getDoc("../Start-multi.html")) + + assertEquals("123456", schools[0].id) + assertEquals("123457", schools[1].id) + } + + @Test fun getSchoolNameTest() { + assertEquals("Uczeń", StartPage(client).getSchools(getDoc("../Start-std.html"))[0].name) + } + + @Test fun getMultiSchoolNameTest() { + val schools = StartPage(client).getSchools(getDoc("../Start-multi.html")) + + assertEquals("GIMBB", schools[0].name) + assertEquals("SPBB", schools[1].name) + } + + @Test(expected = VulcanException::class) + fun getSnpPageUrlWithWrongPage() { + StartPage(client).getSchools(getDoc("../OcenyWszystkie-semester.html")) + } + + @Test + fun getExtractedIDStandardTest() { + assertEquals("123456", StartPage(client) + .getExtractedIdFromUrl("https://uonetplus-opiekun.fakelog.cf/powiat/123456/Start/Index/")) + } + + @Test + fun getExtractedIDDemoTest() { + assertEquals("demo12345", StartPage(client) + .getExtractedIdFromUrl("https://uonetplus-opiekun.fakelog.cf/demoupowiat/demo12345/Start/Index/")) + } + + @Test(expected = VulcanException::class) + fun getExtractedIDNotLoggedTest() { + assertEquals("123", StartPage(client) + .getExtractedIdFromUrl("https://uonetplus.NOTfakelog.cf/powiat/")) + } +} diff --git a/api/src/test/resources/io/github/wulkanowy/api/Start-multi.html b/api/src/test/resources/io/github/wulkanowy/api/Start-multi.html new file mode 100644 index 00000000..98d385ee --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/Start-multi.html @@ -0,0 +1,27 @@ + + + + + Uonet+ + + +
+
+
+ +
+
+
+ + diff --git a/api/src/test/resources/io/github/wulkanowy/api/Start.html b/api/src/test/resources/io/github/wulkanowy/api/Start-std.html similarity index 85% rename from api/src/test/resources/io/github/wulkanowy/api/Start.html rename to api/src/test/resources/io/github/wulkanowy/api/Start-std.html index 40e69161..574bd9b9 100644 --- a/api/src/test/resources/io/github/wulkanowy/api/Start.html +++ b/api/src/test/resources/io/github/wulkanowy/api/Start-std.html @@ -9,7 +9,7 @@
diff --git a/app/build.gradle b/app/build.gradle index e8a9ab48..df08a23e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -93,7 +93,7 @@ play { } greendao { - schemaVersion 28 + schemaVersion 29 generateTests = true } diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/db/dao/entities/SchoolTest.java b/app/src/androidTest/java/io/github/wulkanowy/data/db/dao/entities/SchoolTest.java new file mode 100644 index 00000000..13f63e0d --- /dev/null +++ b/app/src/androidTest/java/io/github/wulkanowy/data/db/dao/entities/SchoolTest.java @@ -0,0 +1,22 @@ +package io.github.wulkanowy.data.db.dao.entities; + +import org.greenrobot.greendao.test.AbstractDaoTestLongPk; + +import io.github.wulkanowy.data.db.dao.entities.School; +import io.github.wulkanowy.data.db.dao.entities.SchoolDao; + +public class SchoolTest extends AbstractDaoTestLongPk { + + public SchoolTest() { + super(SchoolDao.class); + } + + @Override + protected School createEntity(Long key) { + School entity = new School(); + entity.setId(key); + entity.setCurrent(false); + return entity; + } + +} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/DbContract.java b/app/src/main/java/io/github/wulkanowy/data/db/dao/DbContract.java index f32884f5..22eaa944 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/DbContract.java +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/DbContract.java @@ -17,6 +17,8 @@ public interface DbContract { List getNewGrades(int semesterName); + long getCurrentSchoolId(); + long getCurrentStudentId(); long getCurrentSymbolId(); diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/DbHelper.java b/app/src/main/java/io/github/wulkanowy/data/db/dao/DbHelper.java index 904fa343..33b19311 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/DbHelper.java +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/DbHelper.java @@ -21,6 +21,7 @@ import io.github.wulkanowy.data.db.dao.migrations.Migration23; import io.github.wulkanowy.data.db.dao.migrations.Migration26; import io.github.wulkanowy.data.db.dao.migrations.Migration27; import io.github.wulkanowy.data.db.dao.migrations.Migration28; +import io.github.wulkanowy.data.db.dao.migrations.Migration29; import io.github.wulkanowy.data.db.shared.SharedPrefContract; import timber.log.Timber; @@ -79,6 +80,7 @@ public class DbHelper extends DaoMaster.OpenHelper { migrations.add(new Migration26()); migrations.add(new Migration27()); migrations.add(new Migration28()); + migrations.add(new Migration29()); // Sorting just to be safe, in case other people add migrations in the wrong order. Comparator migrationComparator = new Comparator() { diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/DbRepository.java b/app/src/main/java/io/github/wulkanowy/data/db/dao/DbRepository.java index 2c92c55d..d869bfe9 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/DbRepository.java +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/DbRepository.java @@ -11,6 +11,7 @@ import io.github.wulkanowy.data.db.dao.entities.DaoSession; import io.github.wulkanowy.data.db.dao.entities.DiaryDao; import io.github.wulkanowy.data.db.dao.entities.Grade; import io.github.wulkanowy.data.db.dao.entities.GradeDao; +import io.github.wulkanowy.data.db.dao.entities.SchoolDao; import io.github.wulkanowy.data.db.dao.entities.Semester; import io.github.wulkanowy.data.db.dao.entities.SemesterDao; import io.github.wulkanowy.data.db.dao.entities.StudentDao; @@ -72,10 +73,18 @@ public class DbRepository implements DbContract { return getCurrentSymbol().getId(); } + @Override + public long getCurrentSchoolId() { + return daoSession.getSchoolDao().queryBuilder().where( + SchoolDao.Properties.SymbolId.eq(getCurrentSymbolId()), + SchoolDao.Properties.Current.eq(true) + ).unique().getId(); + } + @Override public long getCurrentStudentId() { return daoSession.getStudentDao().queryBuilder().where( - StudentDao.Properties.SymbolId.eq(getCurrentSymbolId()), + StudentDao.Properties.SchoolId.eq(getCurrentSchoolId()), StudentDao.Properties.Current.eq(true) ).unique().getId(); } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/School.java b/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/School.java new file mode 100644 index 00000000..59860e9e --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/School.java @@ -0,0 +1,179 @@ +package io.github.wulkanowy.data.db.dao.entities; + +import org.greenrobot.greendao.DaoException; +import org.greenrobot.greendao.annotation.Entity; +import org.greenrobot.greendao.annotation.Generated; +import org.greenrobot.greendao.annotation.Id; +import org.greenrobot.greendao.annotation.Property; +import org.greenrobot.greendao.annotation.ToMany; + +import java.util.List; + +@Entity( + nameInDb = "Schools", + active = true +) +public class School { + + @Id(autoincrement = true) + private Long id; + + @Property(nameInDb = "symbol_id") + private Long symbolId; + + @Property(nameInDb = "current") + private boolean current; + + @Property(nameInDb = "real_id") + private String realId; + + @Property(nameInDb = "name") + private String name; + + @ToMany(referencedJoinProperty = "schoolId") + private List studentList; + + /** + * Used to resolve relations + */ + @Generated(hash = 2040040024) + private transient DaoSession daoSession; + + /** + * Used for active entity operations. + */ + @Generated(hash = 1796006707) + private transient SchoolDao myDao; + + @Generated(hash = 975562398) + public School(Long id, Long symbolId, boolean current, String realId, + String name) { + this.id = id; + this.symbolId = symbolId; + this.current = current; + this.realId = realId; + this.name = name; + } + + @Generated(hash = 1579966795) + public School() { + } + + public Long getId() { + return this.id; + } + + public School setId(Long id) { + this.id = id; + return this; + } + + public Long getSymbolId() { + return this.symbolId; + } + + public School setSymbolId(Long symbolId) { + this.symbolId = symbolId; + return this; + } + + public boolean getCurrent() { + return this.current; + } + + public School setCurrent(boolean current) { + this.current = current; + return this; + } + + public String getRealId() { + return this.realId; + } + + public School setRealId(String realId) { + this.realId = realId; + return this; + } + + public String getName() { + return this.name; + } + + public School setName(String name) { + this.name = name; + return this; + } + + /** + * To-many relationship, resolved on first access (and after reset). + * Changes to to-many relations are not persisted, make changes to the target entity. + */ + @Generated(hash = 180118651) + public List getStudentList() { + if (studentList == null) { + final DaoSession daoSession = this.daoSession; + if (daoSession == null) { + throw new DaoException("Entity is detached from DAO context"); + } + StudentDao targetDao = daoSession.getStudentDao(); + List studentListNew = targetDao._querySchool_StudentList(id); + synchronized (this) { + if (studentList == null) { + studentList = studentListNew; + } + } + } + return studentList; + } + + /** + * Resets a to-many relationship, making the next get call to query for a fresh result. + */ + @Generated(hash = 1628625923) + public synchronized void resetStudentList() { + studentList = null; + } + + /** + * Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}. + * Entity must attached to an entity context. + */ + @Generated(hash = 128553479) + public void delete() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.delete(this); + } + + /** + * Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}. + * Entity must attached to an entity context. + */ + @Generated(hash = 1942392019) + public void refresh() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.refresh(this); + } + + /** + * Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}. + * Entity must attached to an entity context. + */ + @Generated(hash = 713229351) + public void update() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.update(this); + } + + /** called by internal mechanisms, do not call yourself. */ + @Generated(hash = 234091322) + public void __setDaoSession(DaoSession daoSession) { + this.daoSession = daoSession; + myDao = daoSession != null ? daoSession.getSchoolDao() : null; + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Student.java b/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Student.java index f8ae0e31..1d545473 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Student.java +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Student.java @@ -18,8 +18,8 @@ public class Student { @Id(autoincrement = true) private Long id; - @Property(nameInDb = "symbol_id") - private Long symbolId; + @Property(nameInDb = "school_id") + private Long schoolId; @Property(nameInDb = "current") private boolean current; @@ -45,10 +45,10 @@ public class Student { @Generated(hash = 1943931642) private transient StudentDao myDao; - @Generated(hash = 1334215952) - public Student(Long id, Long symbolId, boolean current, String realId, String name) { + @Generated(hash = 470181623) + public Student(Long id, Long schoolId, boolean current, String realId, String name) { this.id = id; - this.symbolId = symbolId; + this.schoolId = schoolId; this.current = current; this.realId = realId; this.name = name; @@ -66,12 +66,12 @@ public class Student { this.id = id; } - public Long getSymbolId() { - return this.symbolId; + public Long getSchoolId() { + return this.schoolId; } - public Student setSymbolId(Long symbolId) { - this.symbolId = symbolId; + public Student setSchoolId(Long schoolId) { + this.schoolId = schoolId; return this; } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Symbol.java b/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Symbol.java index 2b5984b5..7cc46111 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Symbol.java +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Symbol.java @@ -24,9 +24,6 @@ public class Symbol { @Property(nameInDb = "host") private String host; - @Property(nameInDb = "school_id") - private String schoolId; - @Property(nameInDb = "symbol") private String symbol; @@ -34,7 +31,7 @@ public class Symbol { private String type; @ToMany(referencedJoinProperty = "symbolId") - private List studentList; + private List schoolList; /** * Used to resolve relations @@ -48,13 +45,11 @@ public class Symbol { @Generated(hash = 684907977) private transient SymbolDao myDao; - @Generated(hash = 242774339) - public Symbol(Long id, Long userId, String host, String schoolId, String symbol, - String type) { + @Generated(hash = 1034469460) + public Symbol(Long id, Long userId, String host, String symbol, String type) { this.id = id; this.userId = userId; this.host = host; - this.schoolId = schoolId; this.symbol = symbol; this.type = type; } @@ -89,15 +84,6 @@ public class Symbol { return this; } - public String getSchoolId() { - return this.schoolId; - } - - public Symbol setSchoolId(String schoolId) { - this.schoolId = schoolId; - return this; - } - public String getSymbol() { return this.symbol; } @@ -120,30 +106,28 @@ public class Symbol { * To-many relationship, resolved on first access (and after reset). * Changes to to-many relations are not persisted, make changes to the target entity. */ - @Generated(hash = 604366458) - public List getStudentList() { - if (studentList == null) { + @Generated(hash = 1733082867) + public List getSchoolList() { + if (schoolList == null) { final DaoSession daoSession = this.daoSession; if (daoSession == null) { throw new DaoException("Entity is detached from DAO context"); } - StudentDao targetDao = daoSession.getStudentDao(); - List studentListNew = targetDao._querySymbol_StudentList(id); + SchoolDao targetDao = daoSession.getSchoolDao(); + List schoolListNew = targetDao._querySymbol_SchoolList(id); synchronized (this) { - if (studentList == null) { - studentList = studentListNew; + if (schoolList == null) { + schoolList = schoolListNew; } } } - return studentList; + return schoolList; } - /** - * Resets a to-many relationship, making the next get call to query for a fresh result. - */ - @Generated(hash = 1628625923) - public synchronized void resetStudentList() { - studentList = null; + /** Resets a to-many relationship, making the next get call to query for a fresh result. */ + @Generated(hash = 1757777300) + public synchronized void resetSchoolList() { + schoolList = null; } /** diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/migrations/Migration27.java b/app/src/main/java/io/github/wulkanowy/data/db/dao/migrations/Migration27.java index 5c8c82f1..922079f4 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/migrations/Migration27.java +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/migrations/Migration27.java @@ -15,7 +15,7 @@ public class Migration27 implements DbHelper.Migration { } @Override - public void runMigration(Database db, SharedPrefContract sharedPref, Vulcan vulcan) throws Exception { + public void runMigration(Database db, SharedPrefContract sharedPref, Vulcan vulcan) { ExamDao.dropTable(db, true); ExamDao.createTable(db, true); diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/migrations/Migration29.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/migrations/Migration29.kt new file mode 100644 index 00000000..cb2fccb1 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/migrations/Migration29.kt @@ -0,0 +1,60 @@ +package io.github.wulkanowy.data.db.dao.migrations + +import android.database.Cursor + +import org.greenrobot.greendao.database.Database + +import io.github.wulkanowy.api.Vulcan +import io.github.wulkanowy.data.db.dao.DbHelper +import io.github.wulkanowy.data.db.shared.SharedPrefContract + +class Migration29 : DbHelper.Migration { + + override fun getVersion(): Int? { + return 29 + } + + override fun runMigration(db: Database, sharedPref: SharedPrefContract, vulcan: Vulcan) { + createSchoolsTable(db) + modifyStudents(db) + insertSchool(db, getRealSchoolId(db)) + } + + private fun createSchoolsTable(db: Database) { + db.execSQL("DROP TABLE IF EXISTS \"Schools\";") + db.execSQL("CREATE TABLE IF NOT EXISTS \"Schools\" (" + // + "\"_id\" INTEGER PRIMARY KEY AUTOINCREMENT ," + // 0: id + "\"symbol_id\" INTEGER," + // 1: symbolId + "\"current\" INTEGER NOT NULL ," + // 2: current + "\"real_id\" TEXT," + // 3: realId + "\"name\" TEXT);") // 4: name + } + + private fun modifyStudents(db: Database) { + db.execSQL("ALTER TABLE Students ADD COLUMN school_id INTEGER") + db.execSQL("UPDATE Students SET (school_id) = ('1')") + } + + private fun getRealSchoolId(db: Database): String { + var cursor: Cursor? = null + try { + cursor = db.rawQuery("SELECT school_id FROM Symbols WHERE _id=?", arrayOf("1")) + + return if (cursor!!.count > 0) { + cursor.moveToFirst() + cursor.getString(cursor.getColumnIndex("school_id")) + } else "" + } finally { + cursor!!.close() + } + } + + private fun insertSchool(db: Database, realId: String) { + db.execSQL("INSERT INTO Schools(symbol_id, current, real_id, name) VALUES(" + + "\"1\"," + + "\"1\"," + + "\"" + realId + "\"," + + "\"Uczeń\"" + + ")") + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/sync/AccountSync.java b/app/src/main/java/io/github/wulkanowy/data/sync/AccountSync.java index b9f72cb2..45f8c1f5 100644 --- a/app/src/main/java/io/github/wulkanowy/data/sync/AccountSync.java +++ b/app/src/main/java/io/github/wulkanowy/data/sync/AccountSync.java @@ -17,6 +17,8 @@ import io.github.wulkanowy.data.db.dao.entities.DaoMaster; import io.github.wulkanowy.data.db.dao.entities.DaoSession; import io.github.wulkanowy.data.db.dao.entities.Diary; import io.github.wulkanowy.data.db.dao.entities.DiaryDao; +import io.github.wulkanowy.data.db.dao.entities.School; +import io.github.wulkanowy.data.db.dao.entities.SchoolDao; import io.github.wulkanowy.data.db.dao.entities.Semester; import io.github.wulkanowy.data.db.dao.entities.Student; import io.github.wulkanowy.data.db.dao.entities.StudentDao; @@ -57,12 +59,15 @@ public class AccountSync { daoSession.getDatabase().beginTransaction(); + Timber.i("Register start"); + try { Account account = insertAccount(email, password); Symbol symbolEntity = insertSymbol(account); - insertStudents(symbolEntity); - insertDiaries(symbolEntity); - insertSemesters(); + School schoolEntity = insertSchools(symbolEntity); + Student student = insertStudents(schoolEntity); + Diary diary = insertDiaries(student); + insertSemesters(diary); sharedPref.setCurrentUserId(account.getId()); @@ -70,6 +75,8 @@ public class AccountSync { } finally { daoSession.getDatabase().endTransaction(); } + + Timber.i("Register end"); } private Account insertAccount(String email, String password) throws CryptoException { @@ -82,44 +89,64 @@ public class AccountSync { } private Symbol insertSymbol(Account account) throws VulcanException, IOException { - String schoolId = vulcan.getStudentAndParent().getSchoolID(); - Timber.d("Register symbol %s", vulcan.getSymbol()); + vulcan.getSchools(); + Timber.d("Register symbol (%s)", vulcan.getSymbol()); Symbol symbol = new Symbol() .setUserId(account.getId()) - .setSchoolId(schoolId) .setSymbol(vulcan.getSymbol()); daoSession.getSymbolDao().insert(symbol); return symbol; } - private void insertStudents(Symbol symbol) throws VulcanException, IOException { - List studentList = DataObjectConverter.studentsToStudentEntities( - vulcan.getStudentAndParent().getStudents(), + private School insertSchools(Symbol symbol) throws VulcanException, IOException { + List schoolList = DataObjectConverter.schoolsToSchoolsEntities( + vulcan.getSchools(), symbol.getId() ); - Timber.d("Register students %s", studentList.size()); - daoSession.getStudentDao().insertInTx(studentList); + Timber.d("Register schools (%s)", schoolList.size()); + daoSession.getSchoolDao().insertInTx(schoolList); + + return daoSession.getSchoolDao().queryBuilder().where( + SchoolDao.Properties.SymbolId.eq(symbol.getId()), + SchoolDao.Properties.Current.eq(true) + ).unique(); } - private void insertDiaries(Symbol symbolEntity) throws VulcanException, IOException { + private Student insertStudents(School school) throws VulcanException, IOException { + List studentList = DataObjectConverter.studentsToStudentEntities( + vulcan.getStudentAndParent().getStudents(), + school.getId() + ); + Timber.d("Register students (%s)", studentList.size()); + daoSession.getStudentDao().insertInTx(studentList); + + return daoSession.getStudentDao().queryBuilder().where( + StudentDao.Properties.SchoolId.eq(school.getId()), + StudentDao.Properties.Current.eq(true) + ).unique(); + } + + private Diary insertDiaries(Student student) throws VulcanException, IOException { List diaryList = DataObjectConverter.diariesToDiaryEntities( vulcan.getStudentAndParent().getDiaries(), - daoSession.getStudentDao().queryBuilder().where( - StudentDao.Properties.SymbolId.eq(symbolEntity.getId()), - StudentDao.Properties.Current.eq(true) - ).unique().getId()); - Timber.d("Register diaries %s", diaryList.size()); + student.getId() + ); + Timber.d("Register diaries (%s)", diaryList.size()); daoSession.getDiaryDao().insertInTx(diaryList); + + return daoSession.getDiaryDao().queryBuilder().where( + DiaryDao.Properties.StudentId.eq(student.getId()), + DiaryDao.Properties.Current.eq(true) + ).unique(); } - private void insertSemesters() throws VulcanException, IOException { + private void insertSemesters(Diary diary) throws VulcanException, IOException { List semesterList = DataObjectConverter.semestersToSemesterEntities( vulcan.getStudentAndParent().getSemesters(), - daoSession.getDiaryDao().queryBuilder().where( - DiaryDao.Properties.Current.eq(true) - ).unique().getId()); - Timber.d("Register semesters %s", semesterList.size()); + diary.getId() + ); + Timber.d("Register semesters (%s)", semesterList.size()); daoSession.getSemesterDao().insertInTx(semesterList); } @@ -138,8 +165,11 @@ public class AccountSync { Symbol symbol = daoSession.getSymbolDao().queryBuilder().where( SymbolDao.Properties.UserId.eq(account.getId())).unique(); + School school = daoSession.getSchoolDao().queryBuilder().where( + SchoolDao.Properties.SymbolId.eq(symbol.getId())).unique(); + Student student = daoSession.getStudentDao().queryBuilder().where( - StudentDao.Properties.SymbolId.eq(symbol.getId()), + StudentDao.Properties.SchoolId.eq(school.getId()), StudentDao.Properties.Current.eq(true) ).unique(); @@ -152,7 +182,7 @@ public class AccountSync { account.getEmail(), Scrambler.decrypt(account.getEmail(), account.getPassword()), symbol.getSymbol(), - symbol.getSchoolId(), + school.getRealId(), student.getRealId(), diary.getValue() ); diff --git a/app/src/main/java/io/github/wulkanowy/utils/DataObjectConverter.java b/app/src/main/java/io/github/wulkanowy/utils/DataObjectConverter.java index 1747fc26..cd4490d6 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/DataObjectConverter.java +++ b/app/src/main/java/io/github/wulkanowy/utils/DataObjectConverter.java @@ -9,6 +9,7 @@ import io.github.wulkanowy.data.db.dao.entities.Day; import io.github.wulkanowy.data.db.dao.entities.Diary; import io.github.wulkanowy.data.db.dao.entities.Exam; import io.github.wulkanowy.data.db.dao.entities.Grade; +import io.github.wulkanowy.data.db.dao.entities.School; import io.github.wulkanowy.data.db.dao.entities.Semester; import io.github.wulkanowy.data.db.dao.entities.Student; import io.github.wulkanowy.data.db.dao.entities.Subject; @@ -21,7 +22,22 @@ public final class DataObjectConverter { throw new IllegalStateException("Utility class"); } - public static List studentsToStudentEntities(List students, Long symbolId) { + public static List schoolsToSchoolsEntities(List schools, Long symbolId) { + List studentList = new ArrayList<>(); + + for (io.github.wulkanowy.api.generic.School school : schools) { + studentList.add(new School() + .setName(school.getName()) + .setCurrent(school.getCurrent()) + .setRealId(school.getId()) + .setSymbolId(symbolId) + ); + } + + return studentList; + } + + public static List studentsToStudentEntities(List students, Long schoolId) { List studentList = new ArrayList<>(); for (io.github.wulkanowy.api.generic.Student student : students) { @@ -29,7 +45,7 @@ public final class DataObjectConverter { .setName(student.getName()) .setCurrent(student.isCurrent()) .setRealId(student.getId()) - .setSymbolId(symbolId) + .setSchoolId(schoolId) ); } From b8a31c3faf2ae2da4d7d62f45f15d7c4e90baf7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Borcz?= Date: Sat, 14 Jul 2018 20:09:58 +0200 Subject: [PATCH 04/11] Upgrade android SDK (#144) --- .circleci/config.yml | 2 +- app/android-sonarqube.gradle | 2 +- app/build.gradle | 27 +++++++++++++-------------- build.gradle | 14 ++++++-------- 4 files changed, 21 insertions(+), 24 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b017fe23..387c5edd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,7 +7,7 @@ references: container_config: &container_config docker: - - image: circleci/android:api-26-alpha + - image: circleci/android:api-27-alpha working_directory: *workspace_root environment: environment: diff --git a/app/android-sonarqube.gradle b/app/android-sonarqube.gradle index 3ad2c5ff..b9284eea 100644 --- a/app/android-sonarqube.gradle +++ b/app/android-sonarqube.gradle @@ -5,7 +5,7 @@ sonarqube { //noinspection GroovyAssignabilityCheck properties { def files = fileTree("${rootProject.projectDir}/api/build/libs/").filter { it.isFile() }.files.name - def libraries = project.android.sdkDirectory.getPath() + "/platforms/android-26/android.jar," + + def libraries = project.android.sdkDirectory.getPath() + "/platforms/android-27/android.jar," + "${project.rootDir}/api/build/libs/" + files[0] property "sonar.projectName", GROUP_ID + ":app" diff --git a/app/build.gradle b/app/build.gradle index df08a23e..82d426af 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,3 +1,13 @@ +apply plugin: 'org.greenrobot.greendao' +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-kapt' // sync warning probably caused by bug https://issuetracker.google.com/issues/74537216 +apply plugin: 'io.fabric' +apply from: 'jacoco.gradle' +apply from: 'android-sonarqube.gradle' +apply plugin: 'com.google.gms.oss.licenses.plugin' +apply plugin: 'com.github.triplet.play' + buildscript { repositories { maven { url "https://plugins.gradle.org/m2/" } @@ -17,18 +27,8 @@ repositories { maven { url 'https://maven.fabric.io/public' } } -apply plugin: 'org.greenrobot.greendao' -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply plugin: 'kotlin-kapt' // sync warning probably caused by bug https://issuetracker.google.com/issues/74537216 -apply plugin: 'io.fabric' -apply from: 'jacoco.gradle' -apply from: 'android-sonarqube.gradle' -apply plugin: 'com.google.gms.oss.licenses.plugin' -apply plugin: 'com.github.triplet.play' - android { - compileSdkVersion 26 + compileSdkVersion 27 buildToolsVersion '27.0.3' playAccountConfigs { @@ -42,7 +42,7 @@ android { applicationId "io.github.wulkanowy" testApplicationId "io.github.tests.wulkanowy" minSdkVersion 15 - targetSdkVersion 26 + targetSdkVersion 27 versionCode 14 versionName "0.5.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" @@ -103,6 +103,7 @@ configurations.all { dependencies { implementation project(':api') + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation "com.android.support:support-v4:$supportVersion" implementation "com.android.support:design:$supportVersion" implementation "com.android.support:cardview-v7:$supportVersion" @@ -119,7 +120,6 @@ dependencies { implementation "com.aurelhubert:ahbottomnavigation:$ahbottom" implementation "com.jakewharton.threetenabp:threetenabp:$threeTenABP" implementation "com.google.android.gms:play-services-oss-licenses:$ossLicenses" - implementation "com.jakewharton.timber:timber:$timber" implementation "at.favre.lib:slf4j-timber:$slf4jTimber" @@ -130,7 +130,6 @@ dependencies { transitive = true } - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" kapt "com.google.dagger:dagger-compiler:$dagger2" kapt "com.google.dagger:dagger-android-processor:$dagger2" kapt "com.jakewharton:butterknife-compiler:$butterknife" diff --git a/build.gradle b/build.gradle index 2815bd0f..353dc70f 100644 --- a/build.gradle +++ b/build.gradle @@ -36,13 +36,12 @@ subprojects { ext { GROUP_ID = "io.github.wulkanowy" - supportVersion = "26.1.0" - flexibleAdapter = "5.0.2" - flexibleUi = "1.0.0-b2" - + supportVersion = "27.1.1" + flexibleAdapter = "5.0.5" + flexibleUi = "1.0.0-b5" firebaseJob = "0.8.5" apacheLang = "3.7" - apacheCollections = "4.1" + apacheCollections = "4.2" greenDao = "3.2.2" greenDaoHelper = "v2.0.2" greenDaoGradle = "3.2.2" @@ -52,8 +51,7 @@ ext { ahbottom = "2.2.0" jsoup = "1.11.3" gson = "2.8.5" - ossLicenses = "15.0.1" - + ossLicenses = "16.0.0" slf4jApi = "1.7.25" slf4jTimber = "1.0.1" timber = "4.7.1" @@ -61,7 +59,7 @@ ext { debugDb = "1.0.4" junit = "4.12" - mockito = "2.19.0" + mockito = "2.19.1" testRunner = "1.0.2" fabricGradle = "1.25.4" From 083765b02059003dbe92a86630bf93fa3933b3d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Sun, 15 Jul 2018 14:20:22 +0200 Subject: [PATCH 05/11] Adjust colors of grades in dark theme (#143) --- .../io/github/wulkanowy/utils/GradeUtils.java | 18 +++++++------- app/src/main/res/layout/grades_dialog.xml | 2 ++ app/src/main/res/layout/grades_subitem.xml | 3 +++ app/src/main/res/values/colors.xml | 16 +++++++------ .../wulkanowy/utils/GradeUtilsTest.java | 24 +++++++++---------- 5 files changed, 35 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/io/github/wulkanowy/utils/GradeUtils.java b/app/src/main/java/io/github/wulkanowy/utils/GradeUtils.java index d274da97..7b6ba193 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/GradeUtils.java +++ b/app/src/main/java/io/github/wulkanowy/utils/GradeUtils.java @@ -49,29 +49,29 @@ public final class GradeUtils { public static int getValueColor(String value) { Matcher m1 = validGradePattern.matcher(value); if (!m1.find()) { - return R.color.default_grade; + return R.color.grade_default; } Matcher m2 = simpleGradeValuePattern.matcher(m1.group()); if (!m2.find()) { - return R.color.default_grade; + return R.color.grade_default; } switch (Integer.parseInt(m2.group())) { case 6: - return R.color.six_grade; + return R.color.grade_six; case 5: - return R.color.five_grade; + return R.color.grade_five; case 4: - return R.color.four_grade; + return R.color.grade_four; case 3: - return R.color.three_grade; + return R.color.grade_three; case 2: - return R.color.two_grade; + return R.color.grade_two; case 1: - return R.color.one_grade; + return R.color.grade_one; default: - return R.color.default_grade; + return R.color.grade_default; } } diff --git a/app/src/main/res/layout/grades_dialog.xml b/app/src/main/res/layout/grades_dialog.xml index c5cf073e..aceec78f 100644 --- a/app/src/main/res/layout/grades_dialog.xml +++ b/app/src/main/res/layout/grades_dialog.xml @@ -29,6 +29,8 @@ android:layout_gravity="end" android:gravity="center" android:text="@string/app_name" + android:textColor="@color/grade_text" + android:background="@color/grade_default" android:textSize="30sp" /> #9a0007 #ff6659 #f0f0f0 - #92b53d - #66B266 - #55BBDB - #FFE68C - #CE9AD2 - #d32f2f - #cdcdcd + + #ffffff + #91b43c + #2cbd92 + #50b6d6 + #d2ab24 + #9071b3 + #d65757 + #3d5f9c #4c4c4c #333 diff --git a/app/src/test/java/io/github/wulkanowy/utils/GradeUtilsTest.java b/app/src/test/java/io/github/wulkanowy/utils/GradeUtilsTest.java index 4bf6de51..54b298f2 100644 --- a/app/src/test/java/io/github/wulkanowy/utils/GradeUtilsTest.java +++ b/app/src/test/java/io/github/wulkanowy/utils/GradeUtilsTest.java @@ -62,18 +62,18 @@ public class GradeUtilsTest { @Test public void getValueColorTest() { - assertEquals(R.color.six_grade, GradeUtils.getValueColor("-6")); - assertEquals(R.color.five_grade, GradeUtils.getValueColor("--5")); - assertEquals(R.color.four_grade, GradeUtils.getValueColor("=4")); - assertEquals(R.color.three_grade, GradeUtils.getValueColor("3-")); - assertEquals(R.color.two_grade, GradeUtils.getValueColor("2--")); - assertEquals(R.color.two_grade, GradeUtils.getValueColor("2=")); - assertEquals(R.color.one_grade, GradeUtils.getValueColor("1+")); - assertEquals(R.color.one_grade, GradeUtils.getValueColor("+1")); - assertEquals(R.color.default_grade, GradeUtils.getValueColor("6 (.XI)")); - assertEquals(R.color.default_grade, GradeUtils.getValueColor("Np")); - assertEquals(R.color.default_grade, GradeUtils.getValueColor("7")); - assertEquals(R.color.default_grade, GradeUtils.getValueColor("")); + assertEquals(R.color.grade_six, GradeUtils.getValueColor("-6")); + assertEquals(R.color.grade_five, GradeUtils.getValueColor("--5")); + assertEquals(R.color.grade_four, GradeUtils.getValueColor("=4")); + assertEquals(R.color.grade_three, GradeUtils.getValueColor("3-")); + assertEquals(R.color.grade_two, GradeUtils.getValueColor("2--")); + assertEquals(R.color.grade_two, GradeUtils.getValueColor("2=")); + assertEquals(R.color.grade_one, GradeUtils.getValueColor("1+")); + assertEquals(R.color.grade_one, GradeUtils.getValueColor("+1")); + assertEquals(R.color.grade_default, GradeUtils.getValueColor("6 (.XI)")); + assertEquals(R.color.grade_default, GradeUtils.getValueColor("Np")); + assertEquals(R.color.grade_default, GradeUtils.getValueColor("7")); + assertEquals(R.color.grade_default, GradeUtils.getValueColor("")); } @Test From d44a1dbce1da3b4248002f410b2ce881641f4e67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Sun, 15 Jul 2018 15:15:19 +0200 Subject: [PATCH 06/11] Add weight on grades list (#145) --- .../ui/main/grades/GradesSubItem.java | 6 +++++- app/src/main/res/layout/grades_dialog.xml | 2 +- app/src/main/res/layout/grades_subitem.xml | 18 +++++++++++++++--- app/src/main/res/values-pl/strings.xml | 2 +- app/src/main/res/values/strings.xml | 2 +- 5 files changed, 23 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradesSubItem.java b/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradesSubItem.java index 82b338ae..ee995040 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradesSubItem.java +++ b/app/src/main/java/io/github/wulkanowy/ui/main/grades/GradesSubItem.java @@ -88,6 +88,9 @@ public class GradesSubItem @BindView(R.id.grade_subitem_date) TextView date; + @BindView(R.id.grade_subitem_weight) + TextView weight; + @BindView(R.id.grade_subitem_alert_image) View alert; @@ -110,8 +113,9 @@ public class GradesSubItem value.setText(item.getValue()); value.setBackgroundResource(GradeUtils.getValueColor(item.getValue())); - date.setText(item.getDate()); description.setText(getDescriptionString()); + date.setText(item.getDate()); + weight.setText(String.format("%s: %s", context.getResources().getString(R.string.grade_weight_text), item.getWeight())); alert.setVisibility(item.getRead() ? View.INVISIBLE : View.VISIBLE); if (!item.getRead()) { diff --git a/app/src/main/res/layout/grades_dialog.xml b/app/src/main/res/layout/grades_dialog.xml index aceec78f..932c895e 100644 --- a/app/src/main/res/layout/grades_dialog.xml +++ b/app/src/main/res/layout/grades_dialog.xml @@ -83,7 +83,7 @@ android:layout_alignParentStart="true" android:layout_below="@+id/grade_dialog_description_value" android:layout_marginTop="10dp" - android:text="@string/dialog_weight_text" + android:text="@string/grade_weight_text" android:textSize="17sp" /> @@ -59,7 +59,19 @@ android:layout_alignBottom="@+id/grade_subitem_value" android:layout_alignLeft="@+id/grade_subitem_description" android:layout_alignStart="@+id/grade_subitem_description" - android:text="@string/grades_text" + android:text="@string/dialog_date_text" + android:textSize="12sp" /> + + - \ No newline at end of file + diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index d6f4cc7d..55eb2865 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -46,7 +46,7 @@ W obawie o bezpieczeństwo przechowywanych danych osobistych na urządzeniu z podwyższonymi uprawnieniami (root), aplikacja Wulkanowy została zablokowana Opis - Waga + Waga Brak opisu Nauczyciel Data diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 32c1efa8..e2a06e97 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -46,7 +46,7 @@ For the sake of safety of personal data stored on a device with increased authorization (root), the Wulkanowy application has been blocked. Description - Weight + Weight No description Teacher Date From 4b93a7669321b3e501fa6e27ccc3b4f01fe4cc8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Sun, 15 Jul 2018 15:40:07 +0200 Subject: [PATCH 07/11] Version 0.5.1 --- app/build.gradle | 4 ++-- app/src/main/play/pl-PL/whatsnew | 13 +++++-------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 82d426af..dae3e0e7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -43,8 +43,8 @@ android { testApplicationId "io.github.tests.wulkanowy" minSdkVersion 15 targetSdkVersion 27 - versionCode 14 - versionName "0.5.0" + versionCode 15 + versionName "0.5.1" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true playAccountConfig = playAccountConfigs.defaultAccountConfig diff --git a/app/src/main/play/pl-PL/whatsnew b/app/src/main/play/pl-PL/whatsnew index 50d65699..ff412b22 100644 --- a/app/src/main/play/pl-PL/whatsnew +++ b/app/src/main/play/pl-PL/whatsnew @@ -1,8 +1,5 @@ -Wersja 0.5.0: -- dodano podsumowanie ocen z przedmiotów -- dodano ciemny motyw (wczesna wersja) -- otwieranie aktualnego dnia w planie lekcji -- ukrywanie górnego paska przy przewijaniu -- naprawa wyświetlania zastępstw w widgecie -- poprawa wyświetlania końcowych ocen -- poprawa pierwsze logowania +Wersja 0.5.1: +- dodano wagę ocen na liście +- naprawiono błędy podczas logowania +- zmieniono nasycenie kolorów ocen +- wyłączenie synchronizacji podczas wakacji From c4792289ef2ea1c0323075db2e6b127bdcb665f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Sun, 15 Jul 2018 19:02:49 +0200 Subject: [PATCH 08/11] Fix 29 migration (#146) --- .../io/github/wulkanowy/data/db/dao/migrations/Migration29.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/migrations/Migration29.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/migrations/Migration29.kt index cb2fccb1..e318b5fd 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/migrations/Migration29.kt +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/migrations/Migration29.kt @@ -32,7 +32,7 @@ class Migration29 : DbHelper.Migration { private fun modifyStudents(db: Database) { db.execSQL("ALTER TABLE Students ADD COLUMN school_id INTEGER") - db.execSQL("UPDATE Students SET (school_id) = ('1')") + db.execSQL("UPDATE Students SET school_id = '1'") } private fun getRealSchoolId(db: Database): String { From 5dcd4f9b727b3f54e3a76b6abcbba27de393eb9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Sun, 15 Jul 2018 19:09:31 +0200 Subject: [PATCH 09/11] Version 0.5.2 --- app/build.gradle | 4 ++-- app/src/main/play/pl-PL/listing/title | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index dae3e0e7..77934331 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -43,8 +43,8 @@ android { testApplicationId "io.github.tests.wulkanowy" minSdkVersion 15 targetSdkVersion 27 - versionCode 15 - versionName "0.5.1" + versionCode 16 + versionName "0.5.2" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true playAccountConfig = playAccountConfigs.defaultAccountConfig diff --git a/app/src/main/play/pl-PL/listing/title b/app/src/main/play/pl-PL/listing/title index e5160837..e491efb9 100644 --- a/app/src/main/play/pl-PL/listing/title +++ b/app/src/main/play/pl-PL/listing/title @@ -1 +1 @@ -Wulkanowy Dziennik UONET+ +Wulkanowy Dzienniczek UONET+ From a50dfb3ea741c7740aee43efda34bb13168728c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Fri, 16 Nov 2018 01:48:03 +0100 Subject: [PATCH 10/11] Fix snp app link after uonet upgrade --- api/src/main/java/io/github/wulkanowy/api/login/StartPage.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/io/github/wulkanowy/api/login/StartPage.kt b/api/src/main/java/io/github/wulkanowy/api/login/StartPage.kt index 6f6b1490..2b8a3700 100644 --- a/api/src/main/java/io/github/wulkanowy/api/login/StartPage.kt +++ b/api/src/main/java/io/github/wulkanowy/api/login/StartPage.kt @@ -13,7 +13,7 @@ class StartPage(val client: Client) { fun getSchools(startPage: Document): MutableList { val schoolList = mutableListOf() - val snpLinks = startPage.select(".panel.linkownia.pracownik.klient a") + val snpLinks = startPage.select(".panel.linkownia.pracownik.klient .appLink a") logger.debug("SnP links: {}", snpLinks.size) From b39b9f8bba0f43661474371dc046988fd3390c7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pich?= Date: Fri, 16 Nov 2018 02:02:24 +0100 Subject: [PATCH 11/11] Fix tests --- .../io/github/wulkanowy/api/Start-multi.html | 18 ++++++++++-------- .../io/github/wulkanowy/api/Start-std.html | 14 ++++++++------ .../wulkanowy/api/login/Logowanie-success.html | 14 ++++++++------ 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/api/src/test/resources/io/github/wulkanowy/api/Start-multi.html b/api/src/test/resources/io/github/wulkanowy/api/Start-multi.html index 98d385ee..d5323677 100644 --- a/api/src/test/resources/io/github/wulkanowy/api/Start-multi.html +++ b/api/src/test/resources/io/github/wulkanowy/api/Start-multi.html @@ -10,14 +10,16 @@ diff --git a/api/src/test/resources/io/github/wulkanowy/api/Start-std.html b/api/src/test/resources/io/github/wulkanowy/api/Start-std.html index 574bd9b9..b65625cf 100644 --- a/api/src/test/resources/io/github/wulkanowy/api/Start-std.html +++ b/api/src/test/resources/io/github/wulkanowy/api/Start-std.html @@ -9,13 +9,15 @@
diff --git a/api/src/test/resources/io/github/wulkanowy/api/login/Logowanie-success.html b/api/src/test/resources/io/github/wulkanowy/api/login/Logowanie-success.html index f35e6866..b635388b 100644 --- a/api/src/test/resources/io/github/wulkanowy/api/login/Logowanie-success.html +++ b/api/src/test/resources/io/github/wulkanowy/api/login/Logowanie-success.html @@ -14,13 +14,15 @@