1
0

Compare commits

..

88 Commits
0.2.1 ... 0.5.4

Author SHA1 Message Date
78849f0280 Version 0.5.4 2018-11-17 14:12:23 +01:00
78add470ba Provide back-compatibility in school discover 2018-11-17 14:02:40 +01:00
b39b9f8bba Fix tests 2018-11-16 02:02:24 +01:00
a50dfb3ea7 Fix snp app link after uonet upgrade 2018-11-16 01:48:11 +01:00
5dcd4f9b72 Version 0.5.2 2018-07-15 19:09:31 +02:00
c4792289ef Fix 29 migration (#146) 2018-07-15 19:02:49 +02:00
4b93a76693 Version 0.5.1 2018-07-15 15:40:07 +02:00
d44a1dbce1 Add weight on grades list (#145) 2018-07-15 15:15:19 +02:00
083765b020 Adjust colors of grades in dark theme (#143) 2018-07-15 14:20:22 +02:00
b8a31c3faf Upgrade android SDK (#144) 2018-07-14 20:09:58 +02:00
378aba9716 Add support for multiple SnP sites (#140) 2018-07-14 16:52:09 +02:00
5a4b8b22f3 Stop synchronization on holidays (#142) 2018-07-14 14:06:57 +02:00
8725640168 User short grade names in grades summary (#141) 2018-06-29 11:27:18 +02:00
dab1bd4ac6 Version 0.5.0 2018-06-14 14:45:32 +02:00
11578aa735 Add dark theme (#133) 2018-06-14 11:40:46 +02:00
b63e28f9a9 Separate synchronization from login (#137) 2018-06-13 18:53:42 +02:00
072c504d2b Clean data user on bad user credentials (#138) 2018-06-13 03:07:34 +02:00
7b7be1eef1 API fixes (#136) 2018-06-10 19:46:34 +02:00
81d177c270 Hide actionbar on scroll (#135) 2018-06-09 00:59:39 +02:00
8d014ab7e9 Fix displaying the replacements in widget (#134) 2018-06-07 08:13:49 +02:00
a06d114127 Add logger (#131) 2018-06-06 19:38:54 +02:00
0e16519baf Add a summary of grades (#127) 2018-06-04 21:47:46 +02:00
dde5775a41 Move ticks converter to api (#130) 2018-06-01 12:52:03 +02:00
e2003e2538 Expand current day on startup (#129) 2018-05-31 23:54:59 +02:00
228f680e5d Hide empty fields in summary (#128) 2018-05-31 23:01:52 +02:00
306092ce45 Add mobile access API (#126) 2018-05-30 11:57:29 +02:00
d4b172e022 Version 0.4.5 2018-05-28 11:32:39 +02:00
b4c765b482 [API] Fix timetable endpoint (#125) 2018-05-28 11:29:43 +02:00
3f1fff6d96 Implementation of a new Dagger injection (#103) 2018-05-26 20:44:06 +02:00
b59008a90f Version 0.4.4 2018-05-25 20:33:45 +02:00
74c0dda999 Fix lesson description from warning (#124) 2018-05-25 20:14:16 +02:00
2288ceffb8 Stop refreshing while semester switching window open (#123) 2018-05-25 19:10:34 +02:00
ffe8511e3f Add some fabric answers (#120) 2018-05-25 16:35:12 +02:00
34205e4a8b Fix autofill on api lvl 26 (#122) 2018-05-25 11:49:53 +02:00
ef648c7f8b Clear db before register (#121) 2018-05-24 22:25:24 +02:00
3592946e6f Fix api login(#119) 2018-05-23 19:21:35 +02:00
859f8dc319 Avoid null if cell second div not contain span (#118) 2018-05-23 18:44:04 +02:00
9c97962e89 Version 0.4.3 2018-05-19 23:37:32 +02:00
a4445a8a97 Fix api login error (#115) 2018-05-19 23:02:54 +02:00
3f54d13b6b Add condition to exam query (#116) 2018-05-19 21:11:04 +02:00
5685e73e46 Fix text alignment <= lv l20 (#117) 2018-05-19 19:58:33 +02:00
e9b357e92d Remove the root check (#114) 2018-05-19 12:48:12 +02:00
62bc00cd68 Delete non-existing lessons on sync (#112) 2018-05-19 12:30:17 +02:00
54e6aee82e Stop SyncJob if user is not registered in app (#113) 2018-05-16 20:43:29 +02:00
3000c077c4 Version 0.4.2 2018-05-14 22:20:17 +02:00
7d5072b529 Fix exams sync (#108) 2018-05-14 22:13:08 +02:00
052d5e3911 Stopping job when user not registered in app (#111) 2018-05-14 21:39:09 +02:00
0014b74c6b Fix certificate parsing issues (#109) 2018-05-14 21:12:45 +02:00
08dd316aee Fix adfs login (#110) 2018-05-14 20:56:17 +02:00
95caa21f2a Version 0.4.1 2018-05-13 18:16:39 +02:00
cd6e14b13b [API] Fix first login (#107) 2018-05-13 17:33:31 +02:00
2cf262130e [API] Get rid of NULL in timetable lesson descriptions (#106) 2018-05-13 16:02:51 +02:00
23183c9d7a Call of SyncJob only after user register in app (#105) 2018-05-13 15:25:56 +02:00
be8ee4c835 Fix parsing grade description with symbol containing special chars (#104) 2018-05-11 21:55:38 +02:00
3105e9e53b Version 0.4.0 2018-05-07 19:45:37 +02:00
8e855bd375 Save current tab position in exams (#102) 2018-05-07 18:18:05 +02:00
67f83a4d2f Mark current week (#100) 2018-05-07 17:57:58 +02:00
d7f0fcad30 Remove backup rules (#101) 2018-05-07 17:44:28 +02:00
f29689c6cd Add about section in settings (#99) 2018-05-07 16:05:57 +02:00
dd2c69601a Change description date in exam and fix styles (#98) 2018-05-06 21:16:03 +02:00
bfaa3d196b Fix animations on expand and collapse (#97) 2018-05-06 20:28:24 +02:00
ffd20c94dd Add exams (#87)
* [API/exams] Fix parsing empty list
* [API/exams] Fix date format
* [API/exams] Set day name from api
2018-05-03 19:47:34 +02:00
1740047aea [API] Add support for adfs login (#76) 2018-05-03 14:14:47 +02:00
cb2d4a905d Add option to hide present in attendance (#96) 2018-05-03 12:49:33 +02:00
89350e5793 Update dependencies (#95) 2018-05-03 12:29:10 +02:00
4ef3334bf7 Add semester switch in grades (#94) 2018-05-02 21:51:23 +02:00
cb6d39fe15 Fix widget state change during update (#93) 2018-04-29 19:47:01 +02:00
09a8cc38f9 Refactor model layout (#92) 2018-04-29 12:45:05 +02:00
3443b01b9a Fix grade regex (#91) 2018-04-27 01:36:40 +02:00
7dde13585c Add info about predicted and final ratings (#88) 2018-04-27 00:03:37 +02:00
176d17e1ec Fix notification intent (#89) 2018-04-24 23:52:53 +02:00
119e38254a Refactor entites (#86) 2018-04-24 22:05:46 +02:00
6fcf09e2b7 Add timetable widget (#84) 2018-04-24 21:27:45 +02:00
6927ac0e4f Version 0.3.1 2018-04-20 20:39:18 +02:00
2fd5b0f6ee [API] Improve login (#83) 2018-04-20 20:30:39 +02:00
b7a6b71a4d Change message after sync completed (#85) 2018-04-20 14:07:40 +02:00
ce00c7025a Version 0.3.0 2018-04-08 20:16:52 +02:00
5c558ae1f9 Show fully name on expand header (#82) 2018-04-08 18:05:41 +02:00
0708d84b98 Log non-fatal exceptions with fabric (#80) 2018-04-08 17:34:18 +02:00
b22d95392b Update CI config (#81) 2018-04-08 17:14:59 +02:00
78d57ca746 Notifications improvements (#78)
* Refactor notifications
* Change grade notify icon
2018-04-08 16:37:27 +02:00
0aa8c5605d Add setttings (#74) 2018-04-08 16:15:05 +02:00
cb6afb137f Hide actionbar during login (#79) 2018-04-08 15:54:46 +02:00
c72e7748e2 Migrate to ThreeTenABP (#77) 2018-04-05 21:56:08 +02:00
5c9f10fa50 Update gradle to 4.4 (#75) 2018-04-03 16:10:56 +02:00
cdd3d6a53b Version 0.2.2 2018-03-22 22:54:11 +01:00
8431661d54 Fix resuming states in fragments (#72)
* Downgrade sdk version
* Update dependencies
* Fix infinite loading on restore states
* Fix crash when loading loaded fragments
2018-03-22 22:42:08 +01:00
3dabb11473 [API] Add error messages to exceptions (#71) 2018-03-20 23:10:20 +01:00
320 changed files with 10064 additions and 4020 deletions

View File

@ -31,9 +31,18 @@ jobs:
- run:
name: Setup environment
command: ./gradlew dependencies --no-daemon --stacktrace --console=plain -PdisablePreDex || true
- run:
name: Decrypt keys
command: |
openssl aes-256-cbc -d -in ./app/key-encrypted.p12 -k $ENCRYPT_KEY >> ./app/key.p12
openssl aes-256-cbc -d -in ./app/upload-key-encrypted.jks -k $ENCRYPT_KEY >> ./app/upload-key.jks
- run:
name: Initial build
command: ./gradlew build assembleDebug -x test -x lint -x fabricGenerateResourcesRelease --no-daemon --stacktrace --console=plain -PdisablePreDex
- run:
name: Clear keys
command: |
rm ./app/key.p12 ./app/upload-key.jks
- store_artifacts:
path: ./app/build/outputs/apk/
destination: apks/
@ -78,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:
@ -103,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:
@ -121,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
@ -172,30 +175,69 @@ jobs:
name: Run sonarqube runner
command: ./gradlew -x test -x lint sonarqube -Dsonar.host.url=$SONAR_HOST -Dsonar.organization=$SONAR_ORG -Dsonar.login=$SONAR_KEY -Dsonar.branch.name=$CIRCLE_BRANCH --no-daemon --stacktrace --console=plain -PdisablePreDex
deploy:
<<: *container_config
steps:
- *attach_workspace
- restore_cache:
<<: *general_cache_key
- run:
name: Decrypt keys
command: |
openssl aes-256-cbc -d -in ./app/key-encrypted.p12 -k $ENCRYPT_KEY >> ./app/key.p12
openssl aes-256-cbc -d -in ./app/upload-key-encrypted.jks -k $ENCRYPT_KEY >> ./app/upload-key.jks
- run:
name: Publish release
command: ./gradlew publishRelease --no-daemon --stacktrace --console=plain -PdisablePreDex
workflows:
version: 2
build_check_tests:
build-test-deploy:
jobs:
- build
- build:
filters:
tags:
only: /.*/
- lint:
filters:
tags:
only: /.*/
requires:
- build
- app-test:
filters:
tags:
only: /.*/
requires:
- build
- api-test:
filters:
tags:
only: /.*/
requires:
- build
- instrumented:
requires:
- build
filters:
tags:
only: /.*/
requires:
- build
- sonarcube:
filters:
tags:
only: /.*/
requires:
- build
- lint
- app-test
- api-test
- instrumented
- deploy:
requires:
- instrumented
filters:
tags:
only: /\d+\.\d+\.\d+/
branches:
ignore: /.*/

6
.gitignore vendored
View File

@ -32,6 +32,8 @@ local.properties
.idea/tasks.xml
.idea/vcs.xml
.idea/workspace.xml
.idea/caches/
.idea/codeStyles/
*.iml
# OS-specific files
@ -42,3 +44,7 @@ local.properties
.Trashes
ehthumbs.db
Thumbs.db
.idea/codeStyles/
.idea/caches/
app/key.p12
app/upload-key.jks

View File

@ -12,7 +12,7 @@ build:
script:
- ./gradlew --no-daemon --stacktrace dependencies || true
- ./gradlew --no-daemon --stacktrace assembleDebug
- mv app/build/outputs/apk/app-debug.apk .
- mv app/build/outputs/apk/debug/app-debug.apk .
artifacts:
name: "${CI_PROJECT_NAME}_${CI_BUILD_REF_NAME}-${CI_BUILD_ID}"
paths:
@ -26,7 +26,7 @@ tests:
- .gradle
policy: pull
script:
- ./gradlew --no-daemon --stacktrace test
- ./gradlew --no-daemon --stacktrace -x fabricGenerateResourcesRelease test
artifacts:
paths:
- app/build/reports/tests
@ -39,7 +39,7 @@ lint:
- .gradle
policy: pull
script:
- ./gradlew --no-daemon --stacktrace lint
- ./gradlew --no-daemon --stacktrace -x fabricGenerateResourcesRelease lint
artifacts:
paths:
- app/build/reports

View File

@ -4,9 +4,12 @@
[![Bitrise](https://img.shields.io/bitrise/daeff1893f3c8128/master.svg?token=Hjm1ACamk86JDeVVJHOeqQ&style=flat-square)](https://www.bitrise.io/app/daeff1893f3c8128)
[![Codecov](https://img.shields.io/codecov/c/github/wulkanowy/wulkanowy/master.svg?style=flat-square)](https://codecov.io/gh/wulkanowy/wulkanowy)
[![BCH compliance](https://bettercodehub.com/edge/badge/wulkanowy/wulkanowy?branch=master)](https://bettercodehub.com/)
[![Known Vulnerabilities](https://snyk.io/test/github/wulkanowy/wulkanowy/badge.svg?targetFile=app%2Fbuild.gradle&style=flat-square)](https://snyk.io/test/github/wulkanowy/wulkanowy?targetFile=app%2Fbuild.gradle)
[![Scrutinizer](https://img.shields.io/scrutinizer/g/wulkanowy/wulkanowy.svg?style=flat-square)](https://scrutinizer-ci.com/g/wulkanowy/wulkanowy/?branch=master)
[![Bintray](https://img.shields.io/bintray/v/wulkanowy/wulkanowy/api.svg?style=flat-square)](https://bintray.com/wulkanowy/wulkanowy/api)
[![Discord](https://img.shields.io/discord/390889354199040011.svg?style=flat-square)](https://discord.gg/vccAQBr)
[Pobierz wersję rozwojową](https://bitrise-redirector.herokuapp.com/v0.1/apps/daeff1893f3c8128/builds/master/artifacts/app-debug-bitrise-signed.apk)
[Pobierz wersję beta](https://play.google.com/store/apps/details?id=io.github.wulkanowy&amp;utm_source=vcs)
Wulkanowy to aplikacja na androida polepszająca wygodę używania dziennika UONET+.
[Pobierz wersję DEV](https://bitrise-redirector.herokuapp.com/v0.1/apps/daeff1893f3c8128/builds/master/artifacts/0)
Androidowy klient dziennika VULCAN UONET+.

View File

@ -1,4 +1,5 @@
apply plugin: 'java-library'
apply plugin: 'kotlin'
apply plugin: 'org.sonarqube'
apply plugin: 'jacoco'
apply plugin: 'com.jfrog.bintray'
@ -28,12 +29,15 @@ jacocoTestReport {
}
dependencies {
implementation 'org.jsoup:jsoup:1.10.3'
implementation 'org.apache.commons:commons-lang3:3.7'
implementation 'com.google.code.gson:gson:2.8.2'
implementation "org.jsoup:jsoup:$jsoup"
implementation "org.apache.commons:commons-lang3:$apacheLang"
implementation "com.google.code.gson:gson:$gson"
implementation "org.slf4j:slf4j-api:$slf4jApi"
testImplementation 'junit:junit:4.12'
testImplementation 'org.mockito:mockito-core:2.13.0'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
testImplementation "junit:junit:$junit"
testImplementation "org.mockito:mockito-core:$mockito"
}
version = PUBLISH_VERSION

View File

@ -3,12 +3,16 @@ package io.github.wulkanowy.api;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.slf4j.Logger;
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 {
@ -21,18 +25,23 @@ public class Client {
private String password;
private String symbol = "Default";
private String symbol;
private Login login;
private String schoolId;
private Date lastSuccessRequest = new Date();
private List<School> schools;
private Date lastSuccessRequest;
private Cookies cookies = new Cookies();
Client(String email, String password, String symbol) {
private static final Logger logger = LoggerFactory.getLogger(Client.class);
Client(String email, String password, String symbol, String schoolId) {
this.email = email;
this.password = password;
this.symbol = symbol;
this.schoolId = schoolId;
setFullEndpointInfo(email);
}
@ -46,7 +55,11 @@ public class Client {
String[] url = creds[0].split("://");
protocol = url[0];
host = url[1];
String[] path = url[1].split("/");
host = path[0];
if (path.length > 1) {
symbol = path[1];
}
email = creds[2];
}
}
@ -56,23 +69,22 @@ public class Client {
return;
}
this.symbol = getLogin().login(email, password, symbol);
logger.info("Not logged. Login...");
clearCookies();
new Login(this).login(email, password, symbol);
lastSuccessRequest = new Date();
logger.info("Login successful on {} at {}", getHost(), new Date());
}
private boolean isLoggedIn() {
return getCookies().size() > 0 &&
29 > TimeUnit.MILLISECONDS.toMinutes(new Date().getTime() - lastSuccessRequest.getTime());
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());
Login getLogin() {
if (null != login) {
return login;
}
login = new Login(this);
return login;
}
public String getSymbol() {
@ -87,32 +99,79 @@ public class Client {
return cookies.getItems();
}
String getHost() {
public void clearCookies() {
cookies = new Cookies();
}
public String getHost() {
return host;
}
public void setSchools(List<School> schools) {
this.schools = schools;
this.schoolId = schools.get(0).getId();
}
public List<School> 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 : "");
}
Document getPageByUrl(String url) throws IOException, VulcanException {
login();
public Document getPageByUrl(String url) throws IOException, VulcanException {
return getPageByUrl(url, true, null);
}
Connection.Response response = Jsoup.connect(getFilledUrl(url))
public Document getPageByUrl(String url, boolean loginBefore) throws IOException, VulcanException {
return getPageByUrl(url, loginBefore, null);
}
public synchronized Document getPageByUrl(String url, boolean loginBefore, Map<String, String> cookies) throws IOException, VulcanException {
if (loginBefore) {
login();
}
if (null != cookies) {
this.cookies.addItems(cookies);
}
url = getFilledUrl(url);
logger.debug("GET {}", url);
Connection.Response response = Jsoup.connect(url)
.followRedirects(true)
.cookies(getCookies())
.execute();
this.cookies.addItems(response.cookies());
return checkForErrors(response.parse());
Document doc = checkForErrors(response.parse(), response.statusCode());
if (loginBefore) {
lastSuccessRequest = new Date();
}
return doc;
}
public Document postPageByUrl(String url, String[][] params) throws IOException, VulcanException {
Connection connection = Jsoup.connect(getFilledUrl(url));
public synchronized Document postPageByUrl(String url, String[][] params) throws IOException, VulcanException {
url = getFilledUrl(url);
logger.debug("POST {}", url);
Connection connection = Jsoup.connect(url);
for (String[] data : params) {
connection.data(data[0], data[1]);
@ -126,13 +185,19 @@ public class Client {
this.cookies.addItems(response.cookies());
return checkForErrors(response.parse());
response.bufferUp(); // fixes cert parsing issues #109
return checkForErrors(response.parse(), response.statusCode());
}
public String getJsonStringByUrl(String url) throws IOException, VulcanException {
login();
Connection.Response response = Jsoup.connect(getFilledUrl(url))
url = getFilledUrl(url);
logger.debug("GET {}", url);
Connection.Response response = Jsoup.connect(url)
.followRedirects(true)
.ignoreContentType(true)
.cookies(getCookies())
@ -146,7 +211,11 @@ public class Client {
public String postJsonStringByUrl(String url, String[][] params) throws IOException, VulcanException {
login();
Connection connection = Jsoup.connect(getFilledUrl(url));
url = getFilledUrl(url);
logger.debug("POST {}", url);
Connection connection = Jsoup.connect(url);
for (String[] data : params) {
connection.data(data[0], data[1]);
@ -164,16 +233,22 @@ public class Client {
return response.body();
}
Document checkForErrors(Document doc) throws VulcanException {
if ("Przerwa techniczna".equals(doc.select("title").text())) {
throw new VulcanOfflineException();
Document checkForErrors(Document doc, int code) throws VulcanException {
lastSuccessRequest = null;
String title = doc.select("title").text();
if ("Przerwa techniczna".equals(title)) {
throw new VulcanOfflineException(title);
}
if ("Zaloguj się".equals(doc.select(".loginButton").text())) {
throw new NotLoggedInErrorException();
String singIn = doc.select(".loginButton").text();
if ("Zaloguj się".equals(singIn)) {
throw new NotLoggedInErrorException(singIn);
}
lastSuccessRequest = new Date();
if ("Błąd strony".equals(title)) {
throw new NotLoggedInErrorException(title + " " + doc.body() + ", status: " + code);
}
return doc;
}

View File

@ -0,0 +1,53 @@
package io.github.wulkanowy.api
import java.text.SimpleDateFormat
import java.util.*
const val LOG_DATE_PATTERN = "dd.MM.yyyy"
const val API_DATE_PATTERN = "yyyy-MM-dd"
const val TICKS_AT_EPOCH = 621355968000000000L
const val TICKS_PER_MILLISECOND = 10000
fun getFormattedDate(date: String): String {
return getFormattedDate(date, API_DATE_PATTERN)
}
fun getFormattedDate(date: String, format: String): String {
return getFormattedDate(date, LOG_DATE_PATTERN, format)
}
fun getFormattedDate(date: String, fromFormat: String, toFormat: String): String {
val sdf = SimpleDateFormat(fromFormat, Locale.ROOT)
val d = sdf.parse(date)
sdf.applyPattern(toFormat)
return sdf.format(d)
}
fun getDateAsTick(dateString: String?): String {
if (dateString.isNullOrEmpty()) {
return ""
}
return getDateAsTick(dateString as String, API_DATE_PATTERN).toString()
}
fun getDateAsTick(dateString: String, dateFormat: String): Long {
val format = SimpleDateFormat(dateFormat, Locale.ROOT)
format.timeZone = TimeZone.getTimeZone("UTC")
val dateObject = format.parse(dateString)
return getDateAsTick(dateObject)
}
fun getDateAsTick(date: Date): Long {
val calendar = Calendar.getInstance()
calendar.time = date
return calendar.timeInMillis * TICKS_PER_MILLISECOND + TICKS_AT_EPOCH
}
fun getDate(netTicks: Long): Date {
return Date((netTicks - TICKS_AT_EPOCH) / TICKS_PER_MILLISECOND)
}

View File

@ -1,4 +1,8 @@
package io.github.wulkanowy.api;
public class NotLoggedInErrorException extends VulcanException {
public NotLoggedInErrorException(String message) {
super(message);
}
}

View File

@ -1,37 +0,0 @@
package io.github.wulkanowy.api;
public class Semester {
private String number = "";
private String id = "";
private boolean isCurrent = false;
public String getNumber() {
return number;
}
public Semester setNumber(String number) {
this.number = number;
return this;
}
public String getId() {
return id;
}
public Semester setId(String id) {
this.id = id;
return this;
}
public boolean isCurrent() {
return isCurrent;
}
public Semester setCurrent(boolean current) {
isCurrent = current;
return this;
}
}

View File

@ -6,19 +6,30 @@ import org.jsoup.nodes.Element;
import java.io.IOException;
import java.util.List;
import io.github.wulkanowy.api.generic.Diary;
import io.github.wulkanowy.api.generic.ParamItem;
import io.github.wulkanowy.api.generic.Semester;
import io.github.wulkanowy.api.generic.Student;
public interface SnP {
String getId();
void setDiaryID(String id);
StudentAndParent storeContextCookies() throws IOException, VulcanException;
String getStudentID();
List<Student> getStudents() throws IOException, VulcanException;
StudentAndParent setUp() throws IOException, VulcanException;
String getRowDataChildValue(Element e, int index);
Document getSnPPageDocument(String url) throws IOException, VulcanException;
List<Diary> getDiaries() throws IOException, VulcanException;
List<Semester> getSemesters() throws IOException, VulcanException;
List<Semester> getSemesters(Document gradesPage);
Semester getCurrentSemester(List<Semester> semesterList);
<T> T getCurrent(List<? extends ParamItem> list);
}

View File

@ -3,77 +3,105 @@ package io.github.wulkanowy.api;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.github.wulkanowy.api.generic.Diary;
import io.github.wulkanowy.api.generic.ParamItem;
import io.github.wulkanowy.api.generic.Semester;
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 id;
private String studentID;
StudentAndParent(Client client, String id) {
private String diaryID;
private static final Logger logger = LoggerFactory.getLogger(StudentAndParent.class);
StudentAndParent(Client client, String studentID, String diaryID) {
this.client = client;
this.id = id;
this.studentID = studentID;
this.diaryID = diaryID;
}
private String getBaseUrl() {
return BASE_URL.replace("{ID}", getId());
}
public StudentAndParent setUp() throws IOException, VulcanException {
if (null == getStudentID() || "".equals(getStudentID())) {
Document doc = client.getPageByUrl(BASE_URL);
public String getId() {
return id;
}
if (doc.select("#idSection").isEmpty()) {
logger.error("Expected SnP page, got page with title: {} {}", doc.title(), doc.selectFirst("body"));
throw new VulcanException("Nieznany błąd podczas pobierania danych. Strona: " + doc.title());
}
Student student = getCurrent(getStudents(doc));
studentID = student.getId();
Diary diary = getCurrent(getDiaries(doc));
diaryID = diary.getId();
}
public StudentAndParent storeContextCookies() throws IOException, VulcanException {
client.getPageByUrl(getSnpHomePageUrl());
return this;
}
String getSnpHomePageUrl() throws IOException, VulcanException {
if (null != getId()) {
return getBaseUrl();
}
// get url to uonetplus-opiekun.vulcan.net.pl
Document startPage = client.getPageByUrl(START_PAGE_URL);
Element studentTileLink = startPage.select(".panel.linkownia.pracownik.klient > a").first();
if (null == studentTileLink) {
throw new NotLoggedInErrorException();
}
String snpPageUrl = studentTileLink.attr("href");
this.id = getExtractedIdFromUrl(snpPageUrl);
return snpPageUrl;
}
String getExtractedIdFromUrl(String snpPageUrl) throws NotLoggedInErrorException {
String[] path = snpPageUrl.split(client.getHost())[1].split("/");
if (5 != path.length) {
throw new NotLoggedInErrorException();
}
return path[2];
public String getStudentID() {
return studentID;
}
public String getRowDataChildValue(Element e, int index) {
return e.select(".daneWiersz .wartosc").get(index - 1).text();
}
public void setDiaryID(String id) {
this.diaryID = id;
}
public Document getSnPPageDocument(String url) throws IOException, VulcanException {
return client.getPageByUrl(getBaseUrl() + url);
Map<String, String> cookies = new HashMap<>();
cookies.put("idBiezacyDziennik", diaryID);
cookies.put("idBiezacyUczen", studentID);
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"));
throw new VulcanException("Nieznany błąd podczas pobierania danych. Strona: " + doc.title());
}
if (doc.title().endsWith("Strona główna")) {
throw new VulcanException("Sesja została nieprawidłowo zainicjowana");
}
return doc;
}
public List<Diary> getDiaries() throws IOException, VulcanException {
return getDiaries(client.getPageByUrl(BASE_URL));
}
private List<Diary> getDiaries(Document doc) throws IOException, VulcanException {
return getList(doc.select("#dziennikDropDownList option"), Diary.class);
}
public List<Student> getStudents() throws IOException, VulcanException {
return getStudents(client.getPageByUrl(BASE_URL));
}
private List<Student> getStudents(Document doc) throws IOException, VulcanException {
return getList(doc.select("#uczenDropDownList option"), Student.class);
}
public List<Semester> getSemesters() throws IOException, VulcanException {
@ -87,10 +115,10 @@ public class StudentAndParent implements SnP {
for (Element e : semesterOptions) {
Semester semester = new Semester()
.setId(e.text())
.setNumber(e.attr("value"));
.setId(e.attr("value"))
.setName(e.text());
if ("selected".equals(e.attr("selected"))) {
if (isCurrent(e)) {
semester.setCurrent(true);
}
@ -100,15 +128,44 @@ public class StudentAndParent implements SnP {
return semesters;
}
public Semester getCurrentSemester(List<Semester> semesterList) {
Semester current = null;
for (Semester s : semesterList) {
@SuppressWarnings("unchecked")
private <T> List<T> getList(Elements options, Class<? extends ParamItem> type) throws IOException, VulcanException {
List<T> list = new ArrayList<>();
for (Element e : options) {
URL url = new URL(e.val());
try {
ParamItem item = type.newInstance()
.setId(url.getQuery().split("=")[1])
.setName(e.text());
if (isCurrent(e)) {
item.setCurrent(true);
}
list.add((T) item);
} catch (Exception ex) {
throw new VulcanException("Error while trying to parse params list", ex);
}
}
return list;
}
@SuppressWarnings("unchecked")
public <T> T getCurrent(List<? extends ParamItem> list) {
ParamItem current = null;
for (ParamItem s : list) {
if (s.isCurrent()) {
current = s;
break;
}
}
return current;
return (T) current;
}
private boolean isCurrent(Element e) {
return "selected".equals(e.attr("selected"));
}
}

View File

@ -1,13 +1,20 @@
package io.github.wulkanowy.api;
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;
import io.github.wulkanowy.api.mobile.RegisterDevice;
import io.github.wulkanowy.api.mobile.RegisteredDevices;
import io.github.wulkanowy.api.notes.AchievementsList;
import io.github.wulkanowy.api.notes.NotesList;
import io.github.wulkanowy.api.school.SchoolInfo;
@ -18,21 +25,28 @@ import io.github.wulkanowy.api.user.FamilyInformation;
public class Vulcan {
private String id;
private SnP snp;
private Client client;
public void setCredentials(String email, String password, String symbol, String id) {
client = new Client(email, password, symbol);
private String studentId;
this.id = id;
private String diaryId;
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.studentId = studentId;
this.diaryId = diaryId;
client = new Client(email, password, symbol, schoolId);
logger.debug("Client created with symbol " + symbol);
}
public Client getClient() throws NotLoggedInErrorException {
if (null == client) {
throw new NotLoggedInErrorException();
throw new NotLoggedInErrorException("Vulcan must be initialized by calling setCredentials() prior to fetch data");
}
return client;
@ -40,23 +54,23 @@ public class Vulcan {
public String getSymbol() throws NotLoggedInErrorException {
return getClient().getSymbol();
}
public SnP getStudentAndParent() throws IOException, VulcanException {
public List<School> getSchools() throws VulcanException, IOException {
return getClient().getSchools();
}
public SnP getStudentAndParent() throws VulcanException, IOException {
if (null != this.snp) {
return this.snp;
}
this.snp = new StudentAndParent(getClient(), id).storeContextCookies();
this.snp = new StudentAndParent(getClient(), studentId, diaryId)
.setUp();
return this.snp;
}
public String getId() throws IOException, VulcanException {
return getStudentAndParent().getId();
}
public AttendanceTable getAttendanceTable() throws IOException, VulcanException {
return new AttendanceTable(getStudentAndParent());
}
@ -105,6 +119,14 @@ public class Vulcan {
return new FamilyInformation(getStudentAndParent());
}
public RegisteredDevices getRegisteredDevices() throws VulcanException, IOException {
return new RegisteredDevices(getStudentAndParent());
}
public RegisterDevice getRegisterDevice() throws VulcanException, IOException {
return new RegisterDevice(getStudentAndParent());
}
public Messages getMessages() throws VulcanException {
return new Messages(getClient());
}

View File

@ -1,4 +1,12 @@
package io.github.wulkanowy.api;
public abstract class VulcanException extends Exception {
public class VulcanException extends Exception {
public VulcanException(String message) {
super(message);
}
protected VulcanException(String message, Exception e) {
super(message, e);
}
}

View File

@ -1,4 +1,8 @@
package io.github.wulkanowy.api;
public class VulcanOfflineException extends VulcanException {
VulcanOfflineException(String message) {
super(message);
}
}

View File

@ -4,12 +4,8 @@ import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import io.github.wulkanowy.api.SnP;
import io.github.wulkanowy.api.VulcanException;
@ -17,6 +13,9 @@ import io.github.wulkanowy.api.generic.Day;
import io.github.wulkanowy.api.generic.Lesson;
import io.github.wulkanowy.api.generic.Week;
import static io.github.wulkanowy.api.DateTimeUtilsKt.getDateAsTick;
import static io.github.wulkanowy.api.DateTimeUtilsKt.getFormattedDate;
public class AttendanceTable {
private final static String ATTENDANCE_PAGE_URL = "Frekwencja.mvc?data=";
@ -27,13 +26,12 @@ public class AttendanceTable {
this.snp = snp;
}
public Week<Day> getWeekTable() throws IOException, ParseException, VulcanException {
public Week<Day> getWeekTable() throws IOException, VulcanException {
return getWeekTable("");
}
public Week<Day> getWeekTable(String tick) throws IOException, ParseException, VulcanException {
Element table = snp.getSnPPageDocument(ATTENDANCE_PAGE_URL + tick)
public Week<Day> getWeekTable(String date) throws IOException, VulcanException {
Element table = snp.getSnPPageDocument(ATTENDANCE_PAGE_URL + getDateAsTick(date))
.select(".mainContainer .presentData").first();
Elements headerCells = table.select("thead th");
@ -42,14 +40,10 @@ public class AttendanceTable {
for (int i = 1; i < headerCells.size(); i++) {
String[] dayHeaderCell = headerCells.get(i).html().split("<br>");
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy", Locale.ROOT);
Date d = sdf.parse(dayHeaderCell[1].trim());
sdf.applyPattern("yyyy-MM-dd");
Day day = new Day();
day.setDayName(dayHeaderCell[0]);
day.setDate(sdf.format(d));
days.add(day);
days.add(new Day()
.setDayName(dayHeaderCell[0])
.setDate(getFormattedDate(dayHeaderCell[1].trim()))
);
}
Elements hoursInDays = table.select("tbody tr");
@ -63,7 +57,7 @@ public class AttendanceTable {
for (int i = 1; i < size; i++) {
Lesson lesson = new Lesson();
lesson.setDate(days.get(i - 1).getDate());
lesson.setNumber(hours.get(0).text());
lesson.setNumber(Integer.valueOf(hours.get(0).text()));
addLessonDetails(lesson, hours.get(i));

View File

@ -1,5 +1,6 @@
package io.github.wulkanowy.api.exams;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
@ -12,6 +13,9 @@ import io.github.wulkanowy.api.SnP;
import io.github.wulkanowy.api.VulcanException;
import io.github.wulkanowy.api.generic.Week;
import static io.github.wulkanowy.api.DateTimeUtilsKt.getDateAsTick;
import static io.github.wulkanowy.api.DateTimeUtilsKt.getFormattedDate;
public class ExamsWeek {
private static final String EXAMS_PAGE_URL = "Sprawdziany.mvc/Terminarz?rodzajWidoku=2&data=";
@ -26,8 +30,8 @@ public class ExamsWeek {
return getWeek("", true);
}
public Week<ExamDay> getWeek(String tick, final boolean onlyNotEmpty) throws IOException, VulcanException {
Document examsPage = snp.getSnPPageDocument(EXAMS_PAGE_URL + tick);
public Week<ExamDay> getWeek(String date, final boolean onlyNotEmpty) throws IOException, VulcanException {
Document examsPage = snp.getSnPPageDocument(EXAMS_PAGE_URL + getDateAsTick(date));
Elements examsDays = examsPage.select(".mainContainer > div:not(.navigation)");
List<ExamDay> days = new ArrayList<>();
@ -41,7 +45,9 @@ public class ExamsWeek {
}
if (null != dayHeading) {
day.setDate(dayHeading.text().split(", ")[1]);
String[] dateHeader = dayHeading.text().split(", ");
day.setDayName(StringUtils.capitalize(dateHeader[0]));
day.setDate(getFormattedDate(dateHeader[1]));
}
Elements exams = item.select("article");
@ -51,15 +57,17 @@ public class ExamsWeek {
.setType(snp.getRowDataChildValue(e, 2))
.setDescription(snp.getRowDataChildValue(e, 3))
.setTeacher(snp.getRowDataChildValue(e, 4).split(", ")[0])
.setEntryDate(snp.getRowDataChildValue(e, 4).split(", ")[1])
.setEntryDate(getFormattedDate(snp.getRowDataChildValue(e, 4).split(", ")[1]))
);
}
days.add(day);
}
return new Week<ExamDay>()
.setStartDayDate(examsDays.select("h2").first().text().split(" ")[1])
.setStartDayDate(getFormattedDate(examsPage.select(".mainContainer > h2")
.first().text().split(" ")[1]))
.setDays(days);
}
}

View File

@ -11,10 +11,6 @@ public class Day {
private String dayName = "";
private boolean isFreeDay = false;
private String freeDayName = "";
public Lesson getLesson(int index) {
return lessons.get(index);
}
@ -41,23 +37,8 @@ public class Day {
return dayName;
}
public void setDayName(String dayName) {
public Day setDayName(String dayName) {
this.dayName = dayName;
}
public boolean isFreeDay() {
return isFreeDay;
}
public void setFreeDay(boolean freeDay) {
isFreeDay = freeDay;
}
public String getFreeDayName() {
return freeDayName;
}
public void setFreeDayName(String freeDayName) {
this.freeDayName = freeDayName;
return this;
}
}

View File

@ -0,0 +1,38 @@
package io.github.wulkanowy.api.generic;
public class Diary implements ParamItem {
private String id = "";
private String name = "";
private boolean current = false;
public String getId() {
return id;
}
public Diary setId(String id) {
this.id = id;
return this;
}
public String getName() {
return name;
}
public Diary setName(String name) {
this.name = name;
return this;
}
@Override
public boolean isCurrent() {
return current;
}
public Diary setCurrent(boolean current) {
this.current = current;
return this;
}
}

View File

@ -2,7 +2,7 @@ package io.github.wulkanowy.api.generic;
public class Lesson {
private String number = "";
private int number = 0;
private String subject = "";
@ -48,12 +48,13 @@ public class Lesson {
private boolean isExemption = false;
public String getNumber() {
public int getNumber() {
return number;
}
public void setNumber(String number) {
public Lesson setNumber(int number) {
this.number = number;
return this;
}
public String getSubject() {

View File

@ -0,0 +1,12 @@
package io.github.wulkanowy.api.generic;
public interface ParamItem {
ParamItem setId(String id);
ParamItem setName(String name);
ParamItem setCurrent(boolean isCurrent);
boolean isCurrent();
}

View File

@ -0,0 +1,7 @@
package io.github.wulkanowy.api.generic
data class School(
val name: String,
val id: String,
val current: Boolean
)

View File

@ -0,0 +1,37 @@
package io.github.wulkanowy.api.generic;
public class Semester implements ParamItem {
private String id = "";
private String name = "";
private boolean current = false;
public String getId() {
return id;
}
public Semester setId(String id) {
this.id = id;
return this;
}
public String getName() {
return name;
}
public Semester setName(String number) {
this.name = number;
return this;
}
public boolean isCurrent() {
return current;
}
public Semester setCurrent(boolean current) {
this.current = current;
return this;
}
}

View File

@ -0,0 +1,37 @@
package io.github.wulkanowy.api.generic;
public class Student implements ParamItem {
private String id = "";
private String name = "";
private boolean current = false;
public String getId() {
return id;
}
public Student setId(String id) {
this.id = id;
return this;
}
public String getName() {
return name;
}
public Student setName(String name) {
this.name = name;
return this;
}
public boolean isCurrent() {
return current;
}
public Student setCurrent(boolean current) {
this.current = current;
return this;
}
}

View File

@ -18,8 +18,6 @@ public class Grade {
private String teacher = "";
private String semester = "";
public String getSubject() {
return subject;
}
@ -99,14 +97,4 @@ public class Grade {
return this;
}
public String getSemester() {
return semester;
}
public Grade setSemester(String semester) {
this.semester = semester;
return this;
}
}

View File

@ -5,79 +5,71 @@ import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import io.github.wulkanowy.api.Semester;
import io.github.wulkanowy.api.SnP;
import io.github.wulkanowy.api.VulcanException;
import static io.github.wulkanowy.api.DateTimeUtilsKt.getFormattedDate;
public class GradesList {
private static final String GRADES_PAGE_URL = "Oceny/Wszystkie?details=2&okres=";
private SnP snp = null;
private List<Grade> grades = new ArrayList<>();
private SnP snp;
public GradesList(SnP snp) {
this.snp = snp;
}
private String getGradesPageUrl() {
return GRADES_PAGE_URL;
}
public List<Grade> getAll() throws IOException, ParseException, VulcanException {
return getAll("");
}
public List<Grade> getAll(String semester) throws IOException, ParseException, VulcanException {
Document gradesPage = snp.getSnPPageDocument(getGradesPageUrl() + semester);
public List<Grade> getAll(String semester) throws IOException, VulcanException {
Document gradesPage = snp.getSnPPageDocument(GRADES_PAGE_URL + semester);
Elements gradesRows = gradesPage.select(".ocenySzczegoly-table > tbody > tr");
Semester currentSemester = snp.getCurrentSemester(snp.getSemesters(gradesPage));
List<Grade> grades = new ArrayList<>();
for (Element row : gradesRows) {
if ("Brak ocen".equals(row.select("td:nth-child(2)").text())) {
continue;
}
String descriptions = row.select("td:nth-child(3)").text();
String symbol = descriptions.split(", ")[0];
String description = descriptions.replaceFirst(symbol, "").replaceFirst(", ", "");
Pattern pattern = Pattern.compile("#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})");
Matcher matcher = pattern.matcher(row.select("td:nth-child(2) span.ocenaCzastkowa")
.attr("style"));
String color = "";
while (matcher.find()) {
color = matcher.group(1);
}
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy", Locale.ROOT);
Date d = sdf.parse(row.select("td:nth-child(5)").text());
sdf.applyPattern("yyyy-MM-dd");
grades.add(new Grade()
.setSubject(row.select("td:nth-child(1)").text())
.setValue(row.select("td:nth-child(2)").text())
.setColor(color)
.setSymbol(symbol)
.setDescription(description)
.setWeight(row.select("td:nth-child(4)").text())
.setDate(sdf.format(d))
.setTeacher(row.select("td:nth-child(6)").text())
.setSemester(currentSemester.getNumber())
);
grades.add(getGrade(row));
}
return grades;
}
private Grade getGrade(Element row) {
String descriptions = row.select("td:nth-child(3)").text();
String symbol = descriptions.split(", ")[0];
String description = descriptions.replaceFirst(Pattern.quote(symbol), "").replaceFirst(", ", "");
String color = getColor(row.select("td:nth-child(2) span.ocenaCzastkowa").attr("style"));
String date = getFormattedDate(row.select("td:nth-child(5)").text());
return new Grade()
.setSubject(row.select("td:nth-child(1)").text())
.setValue(row.select("td:nth-child(2)").text())
.setColor(color)
.setSymbol(symbol)
.setDescription(description)
.setWeight(row.select("td:nth-child(4)").text())
.setDate(date)
.setTeacher(row.select("td:nth-child(6)").text());
}
private String getColor(String styleAttr) {
Pattern pattern = Pattern.compile("#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})");
Matcher matcher = pattern.matcher(styleAttr);
String color = "";
while (matcher.find()) {
color = matcher.group(1);
}
return color;
}
}

View File

@ -13,16 +13,21 @@ import io.github.wulkanowy.api.VulcanException;
public class SubjectsList {
private static final String SUBJECTS_PAGE_URL = "Oceny/Wszystkie?details=1";
private static final String SUBJECTS_PAGE_URL = "Oceny/Wszystkie?details=1&okres=";
private SnP snp = null;
private SnP snp;
public SubjectsList(SnP snp) {
this.snp = snp;
}
public List<Subject> getAll() throws IOException, VulcanException {
Document subjectPage = snp.getSnPPageDocument(SUBJECTS_PAGE_URL);
return getAll("");
}
public List<Subject> getAll(String semester) throws IOException, VulcanException {
Document subjectPage = snp.getSnPPageDocument(SUBJECTS_PAGE_URL + semester);
Elements rows = subjectPage.select(".ocenyZwykle-table > tbody > tr");

View File

@ -3,4 +3,8 @@ package io.github.wulkanowy.api.login;
import io.github.wulkanowy.api.VulcanException;
public class AccountPermissionException extends VulcanException {
AccountPermissionException(String message) {
super(message);
}
}

View File

@ -3,4 +3,8 @@ package io.github.wulkanowy.api.login;
import io.github.wulkanowy.api.VulcanException;
public class BadCredentialsException extends VulcanException {
BadCredentialsException(String message) {
super(message);
}
}

View File

@ -2,74 +2,125 @@ package io.github.wulkanowy.api.login;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.parser.Parser;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import io.github.wulkanowy.api.Client;
import io.github.wulkanowy.api.NotLoggedInErrorException;
import io.github.wulkanowy.api.VulcanException;
public class Login {
private 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";
private static final String LOGIN_ENDPOINT_PAGE_URL =
"{schema}://uonetplus.{host}/{symbol}/LoginEndpoint.aspx";
private Client client;
private String symbol;
private static final Logger logger = LoggerFactory.getLogger(Login.class);
public Login(Client client) {
this.client = client;
}
public String login(String email, String password, String symbol) throws VulcanException, IOException {
String certificate = sendCredentials(email, password, symbol);
public void login(String email, String password, String symbol) throws VulcanException, IOException {
Document certDoc = sendCredentials(email, password);
return sendCertificate(certificate, symbol);
}
String sendCredentials(String email, String password, String symbol) throws IOException, VulcanException {
this.symbol = symbol;
Document html = client.postPageByUrl(LOGIN_PAGE_URL, new String[][]{
{"LoginName", email},
{"Password", password}
});
if (null != html.select(".ErrorMessage").first()) {
throw new BadCredentialsException();
if ("Błąd".equals(certDoc.title())) {
client.clearCookies();
throw new NotLoggedInErrorException(certDoc.body().text());
}
return html.select("input[name=wresult]").attr("value");
sendCertificate(certDoc, symbol);
}
String sendCertificate(String certificate, String defaultSymbol) throws IOException, VulcanException {
this.symbol = findSymbol(defaultSymbol, certificate);
client.setSymbol(this.symbol);
Document sendCredentials(String email, String password) throws IOException, VulcanException {
String[][] credentials = new String[][]{
{"LoginName", email},
{"Password", password}
};
String title = client.postPageByUrl(LOGIN_ENDPOINT_PAGE_URL, new String[][]{
{"wa", "wsignin1.0"},
{"wresult", certificate}
}).select("title").text();
Document nextDoc = sendCredentialsData(credentials, LOGIN_PAGE_URL + LOGIN_PAGE_URL_QUERY.replace(":", "%253A"));
Element errorMessage = nextDoc.selectFirst(".ErrorMessage, #ErrorTextLabel");
if (null != errorMessage) {
throw new BadCredentialsException(errorMessage.text());
}
return nextDoc;
}
private Document sendCredentialsData(String[][] credentials, String nextUrl) throws IOException, VulcanException {
Element formFirst = client.getPageByUrl(nextUrl, false).selectFirst("#form1");
if (null != formFirst) { // only on adfs login
Document formSecond = client.postPageByUrl(
formFirst.attr("abs:action"),
getFormStateParams(formFirst, "", "")
);
credentials = getFormStateParams(formSecond, credentials[0][1], credentials[1][1]);
nextUrl = formSecond.selectFirst("#form1").attr("abs:action");
}
return client.postPageByUrl(nextUrl, credentials);
}
private String[][] getFormStateParams(Element form, String email, String password) {
return new String[][]{
{"__VIEWSTATE", form.select("#__VIEWSTATE").val()},
{"__VIEWSTATEGENERATOR", form.select("#__VIEWSTATEGENERATOR").val()},
{"__EVENTVALIDATION", form.select("#__EVENTVALIDATION").val()},
{"__db", form.select("input[name=__db]").val()},
{"PassiveSignInButton.x", "0"},
{"PassiveSignInButton.y", "0"},
{"SubmitButton.x", "0"},
{"SubmitButton.y", "0"},
{"UsernameTextBox", email},
{"PasswordTextBox", password},
};
}
void sendCertificate(Document doc, String defaultSymbol) throws IOException, VulcanException {
client.setSymbol(findSymbol(defaultSymbol, doc.select("input[name=wresult]").val()));
Document targetDoc = sendCertData(doc);
String title = targetDoc.title();
if ("Working...".equals(title)) { // on adfs login
logger.info("ADFS login");
title = sendCertData(targetDoc).title();
}
if ("Logowanie".equals(title)) {
throw new AccountPermissionException();
throw new AccountPermissionException("No account access. Try another symbol");
}
if (!"Uonet+".equals(title)) {
throw new LoginErrorException();
logger.debug("Login failed. Body: {}", targetDoc.body());
throw new LoginErrorException("Expected page title `UONET+`, got " + title);
}
return this.symbol;
client.setSchools(new StartPage(client).getSchools(targetDoc));
}
private String findSymbol(String symbol, String certificate) {
private Document sendCertData(Document doc) throws IOException, VulcanException {
String url = doc.select("form[name=hiddenform]").attr("action");
return client.postPageByUrl(url.replaceFirst("Default", "{symbol}"), new String[][]{
{"wa", "wsignin1.0"},
{"wresult", doc.select("input[name=wresult]").val()},
{"wctx", doc.select("input[name=wctx]").val()}
});
}
private String findSymbol(String symbol, String certificate) throws AccountPermissionException {
if ("Default".equals(symbol)) {
return findSymbolInCertificate(certificate);
}
@ -77,15 +128,19 @@ public class Login {
return symbol;
}
String findSymbolInCertificate(String certificate) {
Elements els = Jsoup
String findSymbolInCertificate(String certificate) throws AccountPermissionException {
Elements instances = Jsoup
.parse(certificate.replaceAll(":", ""), "", Parser.xmlParser())
.select("[AttributeName=\"UserInstance\"] samlAttributeValue");
if (els.isEmpty()) {
if (instances.isEmpty()) { // on adfs login
return "";
}
return els.get(1).text();
if (instances.size() < 2) { // 1st index is always `Default`
throw new AccountPermissionException("First login detected, specify symbol");
}
return instances.get(1).text();
}
}

View File

@ -2,5 +2,9 @@ package io.github.wulkanowy.api.login;
import io.github.wulkanowy.api.NotLoggedInErrorException;
public class LoginErrorException extends NotLoggedInErrorException {
class LoginErrorException extends NotLoggedInErrorException {
LoginErrorException(String message) {
super(message);
}
}

View File

@ -0,0 +1,46 @@
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
import java.net.URL
class StartPage(val client: Client) {
private val logger = LoggerFactory.getLogger(StartPage::class.java)
fun getSchools(startPage: Document): MutableList<School> {
val schoolList = mutableListOf<School>()
val snpLinks = startPage.select(".panel.linkownia.pracownik.klient a[href*=\"uonetplus-opiekun\"]")
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(),
getExtractedSchoolSymbolFromUrl(it.attr("href")),
it == snpLinks.first()
))
}
return schoolList
}
internal fun getExtractedSchoolSymbolFromUrl(snpPageUrl: String): String {
val path = URL(snpPageUrl).path.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]
}
}

View File

@ -3,4 +3,8 @@ package io.github.wulkanowy.api.messages;
import io.github.wulkanowy.api.VulcanException;
class BadRequestException extends VulcanException {
BadRequestException(String message) {
super(message);
}
}

View File

@ -59,10 +59,10 @@ public class Messages {
messages = new Gson().fromJson(res, MessagesContainer.class).data;
} catch (JsonParseException e) {
if (res.contains(ERROR_TITLE)) {
throw new BadRequestException();
throw new BadRequestException(ERROR_TITLE);
}
throw new NotLoggedInErrorException();
throw new NotLoggedInErrorException("You are probably not logged in");
}
return messages;
@ -80,10 +80,10 @@ public class Messages {
message = new Gson().fromJson(res, MessageContainer.class).data;
} catch (JsonParseException e) {
if (res.contains(ERROR_TITLE)) {
throw new BadRequestException();
throw new BadRequestException(ERROR_TITLE);
}
throw new NotLoggedInErrorException();
throw new NotLoggedInErrorException("You are probably not logged in. Force login");
}
return message;

View File

@ -0,0 +1,33 @@
package io.github.wulkanowy.api.mobile
import io.github.wulkanowy.api.SnP
import org.jsoup.nodes.Element
class RegisterDevice(private val snp: SnP) {
companion object {
const val REGISTER_URL = "DostepMobilny.mvc/Rejestruj"
}
data class Token(
val token: String,
val symbol: String,
val pin: String
)
fun getToken(): Token {
val form = snp.getSnPPageDocument(REGISTER_URL).selectFirst("#rejestracja-formularz")
val fields = form.select(".blockElement")
return Token(
getValue(fields[1]),
getValue(fields[2]),
getValue(fields[3])
)
}
fun getValue(e: Element): String {
return e.text().split(":")[1].trim()
}
}

View File

@ -0,0 +1,38 @@
package io.github.wulkanowy.api.mobile
import io.github.wulkanowy.api.SnP
import io.github.wulkanowy.api.getFormattedDate
class RegisteredDevices(private val snp: SnP) {
companion object {
const val DEVICES_LIST_URL = "DostepMobilny.mvc"
}
data class Device(
val name: String,
val system: String,
val date: String,
val id: Int
)
fun getList(): List<Device> {
val items = snp.getSnPPageDocument(DEVICES_LIST_URL).select("table tbody tr")
val devices: MutableList<Device> = mutableListOf()
for (item in items) {
val cells = item.select("td")
val system = cells[0].text().split("(").last().removeSuffix(")")
devices.add(Device(
cells[0].text().replace(" ($system)", ""),
system,
getFormattedDate(cells[1].text(), "dd.MM.yyyy 'godz:' HH:mm:ss", "yyyy-MM-dd HH:mm:ss"),
cells[2].select("a").attr("href")
.split("/").last().toInt()
))
}
return devices
}
}

View File

@ -14,9 +14,7 @@ public class AchievementsList {
private static final String NOTES_PAGE_URL = "UwagiOsiagniecia.mvc/Wszystkie";
private SnP snp = null;
private List<String> achievements = new ArrayList<>();
private SnP snp;
public AchievementsList(SnP snp) {
this.snp = snp;
@ -27,6 +25,8 @@ public class AchievementsList {
.select(".mainContainer > div").get(1);
Elements items = pageFragment.select("article");
List<String> achievements = new ArrayList<>();
for (Element item : items) {
achievements.add(item.text());
}

View File

@ -10,13 +10,13 @@ import java.util.List;
import io.github.wulkanowy.api.SnP;
import io.github.wulkanowy.api.VulcanException;
import static io.github.wulkanowy.api.DateTimeUtilsKt.getFormattedDate;
public class NotesList {
private static final String NOTES_PAGE_URL = "UwagiOsiagniecia.mvc/Wszystkie";
private SnP snp = null;
private List<Note> notes = new ArrayList<>();
private SnP snp;
public NotesList(SnP snp) {
this.snp = snp;
@ -28,10 +28,12 @@ public class NotesList {
Elements items = pageFragment.select("article");
Elements dates = pageFragment.select("h2");
List<Note> notes = new ArrayList<>();
int index = 0;
for (Element item : items) {
notes.add(new Note()
.setDate(dates.get(index++).text())
.setDate(getFormattedDate(dates.get(index++).text()))
.setTeacher(snp.getRowDataChildValue(item, 1))
.setCategory(snp.getRowDataChildValue(item, 2))
.setContent(snp.getRowDataChildValue(item, 3))

View File

@ -11,7 +11,7 @@ public class SchoolInfo {
private static final String SCHOOL_PAGE_URL = "Szkola.mvc/Nauczyciele";
private SnP snp = null;
private SnP snp;
public SchoolInfo(SnP snp) {
this.snp = snp;

View File

@ -15,7 +15,7 @@ public class TeachersInfo {
private static final String SCHOOL_PAGE_URL = "Szkola.mvc/Nauczyciele";
private SnP snp = null;
private SnP snp;
public TeachersInfo(SnP snp) {
this.snp = snp;

View File

@ -3,61 +3,64 @@ package io.github.wulkanowy.api.timetable;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import io.github.wulkanowy.api.SnP;
import io.github.wulkanowy.api.VulcanException;
import io.github.wulkanowy.api.generic.Day;
import io.github.wulkanowy.api.generic.Lesson;
import io.github.wulkanowy.api.generic.Week;
import static io.github.wulkanowy.api.DateTimeUtilsKt.getDateAsTick;
import static io.github.wulkanowy.api.DateTimeUtilsKt.getFormattedDate;
public class Timetable {
private static final String TIMETABLE_PAGE_URL = "Lekcja.mvc/PlanLekcji?data=";
private static final String TIMETABLE_PAGE_URL = "Lekcja.mvc/PlanZajec?data=";
private SnP snp;
private static final Logger logger = LoggerFactory.getLogger(Timetable.class);
public Timetable(SnP snp) {
this.snp = snp;
}
public Week<Day> getWeekTable() throws IOException, ParseException, VulcanException {
public Week<TimetableDay> getWeekTable() throws IOException, VulcanException {
return getWeekTable("");
}
public Week<Day> getWeekTable(final String tick) throws IOException, ParseException, VulcanException {
Element table = snp.getSnPPageDocument(TIMETABLE_PAGE_URL + tick)
public Week<TimetableDay> getWeekTable(final String date) throws IOException, VulcanException {
Element table = snp.getSnPPageDocument(TIMETABLE_PAGE_URL + getDateAsTick(date))
.select(".mainContainer .presentData").first();
List<Day> days = getDays(table.select("thead th"));
List<TimetableDay> days = getDays(table.select("thead th"));
setLessonToDays(table, days);
return new Week<Day>()
return new Week<TimetableDay>()
.setStartDayDate(days.get(0).getDate())
.setDays(days);
}
private List<Day> getDays(Elements tableHeaderCells) throws ParseException {
List<Day> days = new ArrayList<>();
private List<TimetableDay> getDays(Elements tableHeaderCells) {
List<TimetableDay> days = new ArrayList<>();
int numberOfDays = tableHeaderCells.size();
for (int i = 2; i < 7; i++) {
if (numberOfDays > 7) {
logger.info("Number of days: {}", numberOfDays);
}
for (int i = 2; i < numberOfDays; i++) {
String[] dayHeaderCell = tableHeaderCells.get(i).html().split("<br>");
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy", Locale.ROOT);
Date d = sdf.parse(dayHeaderCell[1].trim());
sdf.applyPattern("yyyy-MM-dd");
Day day = new Day();
TimetableDay day = new TimetableDay();
day.setDayName(dayHeaderCell[0]);
day.setDate(sdf.format(d));
day.setDate(getFormattedDate(dayHeaderCell[1].trim()));
if (tableHeaderCells.get(i).hasClass("free-day")) {
day.setFreeDay(true);
@ -70,7 +73,7 @@ public class Timetable {
return days;
}
private void setLessonToDays(Element table, List<Day> days) {
private void setLessonToDays(Element table, List<TimetableDay> days) {
for (Element row : table.select("tbody tr")) {
Elements hours = row.select("td");
@ -82,7 +85,7 @@ public class Timetable {
lesson.setStartTime(startEndEnd[0]);
lesson.setEndTime(startEndEnd[1]);
lesson.setDate(days.get(i - 2).getDate());
lesson.setNumber(hours.get(0).text());
lesson.setNumber(Integer.valueOf(hours.get(0).text()));
addLessonDetails(lesson, hours.get(i).select("div"));
@ -99,7 +102,16 @@ public class Timetable {
addLessonInfoFromElement(lesson, e.first());
break;
case 2:
addLessonInfoFromElement(lesson, e.last());
Element span = e.last().selectFirst("span");
if (null == span) {
addLessonInfoFromElement(lesson, e.first());
} else if (span.hasClass(LessonTypes.CLASS_MOVED_OR_CANCELED)) {
lesson.setNewMovedInOrChanged(true);
lesson.setDescription("poprzednio: " + getLessonAndGroupInfoFromSpan(span)[0]);
addLessonInfoFromElement(lesson, e.first());
} else {
addLessonInfoFromElement(lesson, e.last());
}
break;
case 3:
addLessonInfoFromElement(lesson, e.get(1));
@ -114,7 +126,9 @@ public class Timetable {
Elements warn = e.select(".uwaga-panel");
if (!warn.isEmpty()) {
e.select(".x-treelabel-rlz").last().text("(" + warn.text() + ")");
e.select("span").last()
.addClass("x-treelabel-rlz")
.text(warn.text());
e.remove(1);
}
}
@ -122,6 +136,11 @@ public class Timetable {
private void addLessonInfoFromElement(Lesson lesson, Element e) {
Elements spans = e.select("span");
if (spans.isEmpty()) {
logger.warn("Lesson span is empty");
return;
}
addTypeInfo(lesson, spans);
addNormalLessonInfo(lesson, spans);
addChangesInfo(lesson, spans);
@ -165,7 +184,8 @@ public class Timetable {
lesson.setRoom(spans.get(5).text());
lesson.setMovedOrCanceled(false);
lesson.setNewMovedInOrChanged(true);
lesson.setDescription(StringUtils.substringBetween(spans.last().text(), "(", ")")
lesson.setDescription(StringUtils.defaultString(StringUtils.substringBetween(
spans.last().text(), "(", ")"), spans.last().text())
+ " (poprzednio: " + spans.get(0).text() + ")");
} else if (9 == spans.size()) {
String[] subjectAndGroupInfo = getLessonAndGroupInfoFromSpan(spans.get(4));
@ -176,13 +196,15 @@ public class Timetable {
lesson.setMovedOrCanceled(false);
lesson.setNewMovedInOrChanged(true);
lesson.setDivisionIntoGroups(true);
lesson.setDescription(StringUtils.substringBetween(spans.last().text(), "(", ")")
lesson.setDescription(StringUtils.defaultString(StringUtils.substringBetween(
spans.last().text(), "(", ")"), spans.last().text())
+ " (poprzednio: " + getLessonAndGroupInfoFromSpan(spans.get(0))[0] + ")");
} else if (4 <= spans.size()) {
lesson.setSubject(spans.get(0).text());
lesson.setTeacher(spans.get(1).text());
lesson.setRoom(spans.get(2).text());
lesson.setDescription(StringUtils.substringBetween(spans.last().text(), "(", ")"));
lesson.setDescription(StringUtils.defaultString(StringUtils.substringBetween(
spans.last().text(), "(", ")"), spans.last().text()));
}
}
@ -205,12 +227,17 @@ public class Timetable {
}
private String[] getLessonAndGroupInfoFromSpan(Element span) {
if (!span.text().contains("[")) {
return new String[] {span.text(), ""};
}
String[] subjectNameArray = span.text().split(" ");
String groupName = subjectNameArray[subjectNameArray.length - 1];
return new String[]{
span.text().replace(" " + groupName, ""),
StringUtils.substringBetween(groupName, "[", "]")
StringUtils.defaultString(StringUtils.substringBetween(
groupName, "[", "]"), groupName)
};
}
}

View File

@ -0,0 +1,26 @@
package io.github.wulkanowy.api.timetable;
import io.github.wulkanowy.api.generic.Day;
public class TimetableDay extends Day {
private boolean isFreeDay = false;
private String freeDayName = "";
public boolean isFreeDay() {
return isFreeDay;
}
public void setFreeDay(boolean freeDay) {
isFreeDay = freeDay;
}
public String getFreeDayName() {
return freeDayName;
}
public void setFreeDayName(String freeDayName) {
this.freeDayName = freeDayName;
}
}

View File

@ -1,13 +1,10 @@
package io.github.wulkanowy.api;
import org.hamcrest.CoreMatchers;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.junit.Assert;
import org.junit.Test;
import io.github.wulkanowy.api.login.Login;
public class ClientTest {
private String getFixtureAsString(String fixtureFileName) {
@ -15,66 +12,67 @@ 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"));
Assert.assertEquals(doc, client.checkForErrors(doc));
Assert.assertEquals(doc, client.checkForErrors(doc, 200));
}
@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"));
client.checkForErrors(doc);
client.checkForErrors(doc, 200);
}
@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"));
client.checkForErrors(doc);
}
@Test
public void getClientTest() throws Exception {
Client client = new Client("", "", "");
Assert.assertThat(client.getLogin(), CoreMatchers.instanceOf(Login.class));
}
@Test
public void getClientTwiceTest() throws Exception {
Client client = new Client("", "", "");
Assert.assertEquals(client.getLogin(), client.getLogin());
client.checkForErrors(doc, 200);
}
@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());
}
}

View File

@ -0,0 +1,53 @@
package io.github.wulkanowy.api
import org.junit.Assert
import org.junit.Test
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.*
class DateTimeUtilsTest {
@Test
fun getTicksDateObjectTest() {
val format = SimpleDateFormat("dd.MM.yyyy", Locale.ROOT)
format.timeZone = TimeZone.getTimeZone("UTC")
val date = format.parse("31.07.2017")
Assert.assertEquals(636370560000000000L, getDateAsTick(date))
val calendar = Calendar.getInstance()
calendar.time = date
calendar.add(Calendar.DAY_OF_YEAR, -14)
val dateTwoWeekBefore = calendar.time
Assert.assertEquals(636358464000000000L, getDateAsTick(dateTwoWeekBefore))
}
@Test(expected = ParseException::class)
fun getTicsStringInvalidFormatTest() {
Assert.assertEquals(636370560000000000L, getDateAsTick("31.07.2017", "dd.MMM.yyyy"))
}
@Test
fun getTicsStringFormatTest() {
Assert.assertEquals(636370560000000000L, getDateAsTick("31.07.2017", "dd.MM.yyyy"))
}
@Test
fun getTicsStringTest() {
Assert.assertEquals("636370560000000000", getDateAsTick("2017-07-31"))
Assert.assertEquals("636334272000000000", getDateAsTick("2017-06-19"))
Assert.assertEquals("636189120000000000", getDateAsTick("2017-01-02"))
Assert.assertEquals("636080256000000000", getDateAsTick("2016-08-29"))
}
@Test
fun getDateTest() {
val format = SimpleDateFormat("dd.MM.yyyy", Locale.ROOT)
format.timeZone = TimeZone.getTimeZone("UTC")
val date = format.parse("31.07.2017")
Assert.assertEquals(date, getDate(636370560000000000L))
}
}

View File

@ -7,9 +7,12 @@ import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import io.github.wulkanowy.api.generic.Semester;
public class StudentAndParentTest {
private Client client;
@ -22,102 +25,79 @@ public class StudentAndParentTest {
client = Mockito.mock(Client.class);
Mockito.when(client.getPageByUrl(Mockito.anyString())).thenReturn(gradesPageDocument);
Mockito.when(client.getPageByUrl(
Mockito.anyString(),
Mockito.anyBoolean(), Mockito.anyMap())).thenReturn(gradesPageDocument);
}
@Test
public void snpTest() throws Exception {
StudentAndParent snp = new StudentAndParent(client, "id123");
Assert.assertEquals("id123", snp.getId());
}
@Test
public void getSnpPageUrlWithIdTest() throws Exception {
Assert.assertEquals("{schema}://uonetplus-opiekun.{host}/{symbol}/123456/",
(new StudentAndParent(client, "123456")).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);
Assert.assertEquals("https://uonetplus-opiekun.vulcan.net.pl/symbol/534213/Start/Index/",
snp.getSnpHomePageUrl());
}
@Test(expected = NotLoggedInErrorException.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);
snp.getSnpHomePageUrl();
}
@Test
public void getExtractedIDStandardTest() throws Exception {
Mockito.when(client.getHost()).thenReturn("vulcan.net.pl");
StudentAndParent snp = new StudentAndParent(client, "symbol");
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");
Assert.assertEquals("demo12345",
snp.getExtractedIdFromUrl("https://uonetplus-opiekun.vulcan.net.pl/demoupowiat/demo12345/Start/Index/"));
}
@Test(expected = NotLoggedInErrorException.class)
public void getExtractedIDNotLoggedTest() throws Exception {
Mockito.when(client.getHost()).thenReturn("vulcan.net.pl");
StudentAndParent snp = new StudentAndParent(client, "symbol");
Assert.assertEquals("123",
snp.getExtractedIdFromUrl("https://uonetplus.vulcan.net.pl/powiat/"));
public void snpTest() {
StudentAndParent snp = new StudentAndParent(client, "1234", null);
Assert.assertEquals("1234", snp.getStudentID());
}
@Test
public void getSemestersTest() throws Exception {
SnP snp = new StudentAndParent(client, "123456");
SnP snp = new StudentAndParent(client, null, null);
List<Semester> semesters = snp.getSemesters();
Assert.assertEquals(2, semesters.size());
Assert.assertEquals("1", semesters.get(0).getId());
Assert.assertEquals("1234", semesters.get(0).getNumber());
Assert.assertEquals("1", semesters.get(0).getName());
Assert.assertEquals("1234", semesters.get(0).getId());
Assert.assertFalse(semesters.get(0).isCurrent());
Assert.assertEquals("2", semesters.get(1).getId());
Assert.assertEquals("1235", semesters.get(1).getNumber());
Assert.assertEquals("2", semesters.get(1).getName());
Assert.assertEquals("1235", semesters.get(1).getId());
Assert.assertTrue(semesters.get(1).isCurrent());
}
@Test
public void getCurrentSemesterTest() throws Exception {
public void getCurrentSemesterTest() {
List<Semester> semesters = new ArrayList<>();
semesters.add(new Semester().setNumber("1500100900").setId("1").setCurrent(false));
semesters.add(new Semester().setNumber("1500100901").setId("2").setCurrent(true));
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, "");
Assert.assertTrue(snp.getCurrentSemester(semesters).isCurrent());
Assert.assertEquals("2", snp.getCurrentSemester(semesters).getId());
Assert.assertEquals("1500100901", snp.getCurrentSemester(semesters).getNumber());
SnP snp = new StudentAndParent(client, null, null);
Semester semester = snp.getCurrent(semesters);
Assert.assertTrue(semester.isCurrent());
Assert.assertEquals("2", semester.getId());
Assert.assertEquals("1500100901", semester.getName());
}
@Test
public void getCurrentSemesterFromEmptyTest() throws Exception {
SnP snp = new StudentAndParent(client, "");
public void getCurrentSemesterFromEmptyTest() {
SnP snp = new StudentAndParent(client, null, null);
List<Semester> semesters = new ArrayList<>();
Assert.assertNull(snp.getCurrentSemester(semesters));
Assert.assertNull(snp.getCurrent(semesters));
}
@Test
public void getDiariesAndStudentTest() throws IOException, VulcanException {
String input = FixtureHelper.getAsString(getClass().getResourceAsStream("WitrynaUczniaIRodzica.html"));
Document snpHome = Jsoup.parse(input);
client = Mockito.mock(Client.class);
Mockito.when(client.getPageByUrl(Mockito.anyString())).thenReturn(snpHome);
SnP snp = new StudentAndParent(client, null, null);
snp.setUp();
Assert.assertEquals("3Ti 2017", snp.getDiaries().get(0).getName());
Assert.assertEquals("2Ti 2016", snp.getDiaries().get(1).getName());
Assert.assertEquals("1Ti 2015", snp.getDiaries().get(2).getName());
Assert.assertEquals("1300", snp.getDiaries().get(0).getId());
Assert.assertEquals("1200", snp.getDiaries().get(1).getId());
Assert.assertEquals("1100", snp.getDiaries().get(2).getId());
Assert.assertTrue(snp.getDiaries().get(0).isCurrent());
Assert.assertFalse(snp.getDiaries().get(1).isCurrent());
Assert.assertFalse(snp.getDiaries().get(2).isCurrent());
Assert.assertEquals("Jan Kowal", snp.getStudents().get(0).getName());
Assert.assertEquals("100", snp.getStudents().get(0).getId());
}
}

View File

@ -5,6 +5,8 @@ import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.mockito.Mockito;
import io.github.wulkanowy.api.generic.Semester;
public abstract class StudentAndParentTestCase {
protected StudentAndParent getSnp(String fixtureFileName) throws Exception {
@ -16,7 +18,7 @@ public abstract class StudentAndParentTestCase {
Mockito.when(snp.getSnPPageDocument(Mockito.anyString()))
.thenReturn(tablePageDocument);
Mockito.when(snp.getSemesters(Mockito.any(Document.class))).thenCallRealMethod();
Mockito.when(snp.getCurrentSemester(Mockito.<Semester>anyList()))
Mockito.when(snp.getCurrent(Mockito.<Semester>anyList()))
.thenCallRealMethod();
Mockito.when(snp.getRowDataChildValue(Mockito.any(Element.class),
Mockito.anyInt())).thenCallRealMethod();

View File

@ -16,7 +16,7 @@ public class VulcanTest {
@Test
public void getClientTest() throws Exception {
Vulcan vulcan = new Vulcan();
vulcan.setCredentials("email", "password", "symbol", null);
vulcan.setCredentials("email", "password", "symbol", null, null, null);
Assert.assertThat(vulcan.getClient(), CoreMatchers.instanceOf(Client.class));
}
@ -24,7 +24,7 @@ public class VulcanTest {
@Test
public void getClientTwiceTest() throws Exception {
Vulcan vulcan = new Vulcan();
vulcan.setCredentials("email", "password", "symbol", null);
vulcan.setCredentials("email", "password", "symbol", null, null, null);
Assert.assertEquals(vulcan.getClient(), vulcan.getClient());
}

View File

@ -12,20 +12,25 @@ public class ExamsWeekTest extends StudentAndParentTestCase {
private ExamsWeek onePerDay;
private ExamsWeek empty;
@Before
public void getCurrent() throws Exception {
onePerDay = new ExamsWeek(getSnp("Sprawdziany-one-per-day.html"));
empty = new ExamsWeek(getSnp("Sprawdziany-empty.html"));
}
@Test
public void getWeekTest() throws Exception {
Assert.assertEquals("23.10.2017", onePerDay.getCurrent().getStartDayDate());
Assert.assertEquals("2017-10-23", onePerDay.getCurrent().getStartDayDate());
Assert.assertEquals("2018-04-30", empty.getCurrent().getStartDayDate());
}
@Test
public void getDaysListTest() throws Exception {
Assert.assertEquals(3, onePerDay.getCurrent().getDays().size());
Assert.assertEquals(7, onePerDay.getWeek("", false).getDays().size());
Assert.assertEquals(0, empty.getCurrent().getDays().size());
}
@Test
@ -45,9 +50,18 @@ public class ExamsWeekTest extends StudentAndParentTestCase {
public void getDayDateTest() throws Exception {
List<ExamDay> dayList = onePerDay.getCurrent().getDays();
Assert.assertEquals("23.10.2017", dayList.get(0).getDate());
Assert.assertEquals("24.10.2017", dayList.get(1).getDate());
Assert.assertEquals("27.10.2017", dayList.get(2).getDate());
Assert.assertEquals("2017-10-23", dayList.get(0).getDate());
Assert.assertEquals("2017-10-24", dayList.get(1).getDate());
Assert.assertEquals("2017-10-27", dayList.get(2).getDate());
}
@Test
public void getDayNameTest() throws Exception {
List<ExamDay> dayList = onePerDay.getCurrent().getDays();
Assert.assertEquals("Poniedziałek", dayList.get(0).getDayName());
Assert.assertEquals("Wtorek", dayList.get(1).getDayName());
Assert.assertEquals("Piątek", dayList.get(2).getDayName());
}
@Test
@ -90,8 +104,8 @@ public class ExamsWeekTest extends StudentAndParentTestCase {
public void getExamEntryDateTest() throws Exception {
List<ExamDay> dayList = onePerDay.getCurrent().getDays();
Assert.assertEquals("16.10.2017", dayList.get(0).getExamList().get(0).getEntryDate());
Assert.assertEquals("17.10.2017", dayList.get(1).getExamList().get(0).getEntryDate());
Assert.assertEquals("16.10.2017", dayList.get(2).getExamList().get(0).getEntryDate());
Assert.assertEquals("2017-10-16", dayList.get(0).getExamList().get(0).getEntryDate());
Assert.assertEquals("2017-10-17", dayList.get(1).getExamList().get(0).getEntryDate());
Assert.assertEquals("2017-10-16", dayList.get(2).getExamList().get(0).getEntryDate());
}
}

View File

@ -19,12 +19,12 @@ public class GradesListTest extends StudentAndParentTestCase {
@Test
public void getAllTest() throws Exception {
Assert.assertEquals(6, filled.getAll().size()); // 2 items are skipped
Assert.assertEquals(7, filled.getAll("").size()); // 2 items are skipped
}
@Test
public void getSubjectTest() throws Exception {
List<Grade> list = filled.getAll();
List<Grade> list = filled.getAll("");
Assert.assertEquals("Zajęcia z wychowawcą", list.get(0).getSubject());
Assert.assertEquals("Język angielski", list.get(3).getSubject());
@ -34,7 +34,7 @@ public class GradesListTest extends StudentAndParentTestCase {
@Test
public void getValueTest() throws Exception {
List<Grade> list = filled.getAll();
List<Grade> list = filled.getAll("");
Assert.assertEquals("5", list.get(0).getValue());
Assert.assertEquals("5", list.get(3).getValue());
@ -44,7 +44,7 @@ public class GradesListTest extends StudentAndParentTestCase {
@Test
public void getColorTest() throws Exception {
List<Grade> list = filled.getAll();
List<Grade> list = filled.getAll("");
Assert.assertEquals("000000", list.get(0).getColor());
Assert.assertEquals("1289F7", list.get(3).getColor());
@ -54,27 +54,29 @@ public class GradesListTest extends StudentAndParentTestCase {
@Test
public void getSymbolTest() throws Exception {
List<Grade> list = filled.getAll();
List<Grade> list = filled.getAll("");
Assert.assertEquals("A1", list.get(0).getSymbol());
Assert.assertEquals("BW3", list.get(3).getSymbol());
Assert.assertEquals("STR", list.get(4).getSymbol());
Assert.assertEquals("K", list.get(5).getSymbol());
Assert.assertEquals("+Odp", list.get(6).getSymbol());
}
@Test
public void getDescriptionTest() throws Exception {
List<Grade> list = filled.getAll();
List<Grade> list = filled.getAll("");
Assert.assertEquals("Dzień Kobiet w naszej klasie", list.get(0).getDescription());
Assert.assertEquals("Writing", list.get(3).getDescription());
Assert.assertEquals("", list.get(4).getDescription());
Assert.assertEquals("Kordian", list.get(5).getDescription());
Assert.assertEquals("Kordian", list.get(6).getDescription());
}
@Test
public void getWeightTest() throws Exception {
List<Grade> list = filled.getAll();
List<Grade> list = filled.getAll("");
Assert.assertEquals("1,00", list.get(0).getWeight());
Assert.assertEquals("3,00", list.get(3).getWeight());
@ -84,7 +86,7 @@ public class GradesListTest extends StudentAndParentTestCase {
@Test
public void getDateTest() throws Exception {
List<Grade> list = filled.getAll();
List<Grade> list = filled.getAll("");
Assert.assertEquals("2017-03-21", list.get(0).getDate());
Assert.assertEquals("2017-06-02", list.get(3).getDate());
@ -94,21 +96,11 @@ public class GradesListTest extends StudentAndParentTestCase {
@Test
public void getTeacherTest() throws Exception {
List<Grade> list = filled.getAll();
List<Grade> list = filled.getAll("");
Assert.assertEquals("Patryk Maciejewski", list.get(0).getTeacher());
Assert.assertEquals("Oliwia Woźniak", list.get(3).getTeacher());
Assert.assertEquals("Klaudia Dziedzic", list.get(4).getTeacher());
Assert.assertEquals("Amelia Stępień", list.get(5).getTeacher());
}
@Test
public void getSemesterTest() throws Exception {
List<Grade> list = filled.getAll();
Assert.assertEquals("7654321", list.get(0).getSemester());
Assert.assertEquals("7654321", list.get(3).getSemester());
Assert.assertEquals("7654321", list.get(4).getSemester());
Assert.assertEquals("7654321", list.get(5).getSemester());
}
}

View File

@ -11,86 +11,121 @@ import io.github.wulkanowy.api.FixtureHelper;
public class LoginTest {
private Document getFixtureAsDocument(String fixtureFileName) {
return Jsoup.parse(getFixtureAsString(fixtureFileName));
}
private String getFixtureAsString(String fixtureFileName) {
return FixtureHelper.getAsString(getClass().getResourceAsStream(fixtureFileName));
}
private Client getClient(String fixtureFileName) throws Exception {
Document doc = Jsoup.parse(getFixtureAsString(fixtureFileName));
Document doc = getFixtureAsDocument(fixtureFileName);
Client client = Mockito.mock(Client.class);
Mockito.when(client.postPageByUrl(Mockito.anyString(), Mockito.any(String[][].class))).thenReturn(doc);
Mockito.when(client.getPageByUrl(Mockito.anyString(), Mockito.anyBoolean())).thenReturn(doc);
return client;
}
@Test
public void loginTest() throws Exception {
Login login = new Login(getClient("Logowanie-success.html"));
Client client = getClient("Logowanie-success.html");
Mockito.when(client.getPageByUrl(Mockito.anyString(), Mockito.anyBoolean()))
.thenReturn(getFixtureAsDocument("Logowanie-error.html"));
Mockito.when(client.postPageByUrl(Mockito.eq(Login.LOGIN_PAGE_URL), Mockito.any(String[][].class)))
.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)
public void sendWrongCredentialsTest() throws Exception {
Login login = new Login(getClient("Logowanie-error.html"));
Client client = getClient("Logowanie-error.html");
Mockito.when(client.getPageByUrl(Mockito.anyString(), Mockito.anyBoolean()))
.thenReturn(getFixtureAsDocument("Logowanie-error.html")); // -error.html because it html with form used by
Login login = new Login(client);
login.sendCredentials("a@a", "pswd", "d123");
login.sendCredentials("a@a", "pswd");
}
@Test
public void sendCredentialsCertificateTest() throws Exception {
Login login = new Login(getClient("Logowanie-certyfikat.html"));
Client client = getClient("Logowanie-certyfikat.html");
Mockito.when(client.getPageByUrl(Mockito.anyString(), Mockito.anyBoolean()))
.thenReturn(getFixtureAsDocument("Logowanie-error.html")); // -error.html because it html with form used by
Login login = new Login(client);
Assert.assertEquals(
getFixtureAsString("cert.xml").replaceAll("\\s+",""),
login.sendCredentials("a@a", "passwd", "d123").replaceAll("\\s+","")
getFixtureAsString("cert-stock.xml").replaceAll("\\s+", ""),
login.sendCredentials("a@a", "passwd")
.select("input[name=wresult]")
.attr("value")
.replaceAll("\\s+", "")
);
}
@Test
public void sendCertificateNotDefaultSymbolSuccessTest() throws Exception {
Login login = new Login(getClient("Logowanie-success.html"));
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("", "wulkanowyschool321"));
login.sendCertificate(getFixtureAsDocument("Logowanie-certyfikat.html"), "wulkanowyschool321");
Assert.assertEquals("wulkanowyschool321", client.getSymbol());
}
@Test
public void sendCertificateDefaultSymbolSuccessTest() throws Exception {
Login login = new Login(getClient("Logowanie-success.html"));
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(getFixtureAsString("cert.xml"), "Default"));
login.sendCertificate(getFixtureAsDocument("Logowanie-certyfikat.html"), "Default");
Assert.assertEquals("demo12345", client.getSymbol());
}
@Test(expected = AccountPermissionException.class)
public void sendCertificateAccountPermissionTest() throws Exception {
Login login = new Login(getClient("Logowanie-brak-dostepu.html"));
Client client = getClient("Logowanie-brak-dostepu.html");
login.sendCertificate(getFixtureAsString("cert.xml"), "demo123");
Login login = new Login(client);
login.sendCertificate(getFixtureAsDocument("Logowanie-certyfikat.html"), "demo123");
}
@Test(expected = LoginErrorException.class)
public void sendCertificateLoginErrorTest() throws Exception {
Login login = new Login(getClient("Logowanie-certyfikat.html")); // change to other document
login.sendCertificate(getFixtureAsString("cert.xml"), "demo123");
login.sendCertificate(getFixtureAsDocument("Logowanie-certyfikat.html"), "demo123");
}
@Test
public void findSymbolInCertificateTest() throws Exception {
Login login = new Login(getClient("Logowanie-certyfikat.html"));
String certificate = getFixtureAsString("cert.xml");
String certificate = getFixtureAsString("cert-stock.xml");
Assert.assertEquals("demo12345", login.findSymbolInCertificate(certificate));
}
@Test
public void findSymbolInInvalidCertificateTest() throws Exception {
@Test(expected = AccountPermissionException.class)
public void findSymbolInCertificateWithoutSecondInstanceTest() throws Exception {
Login login = new Login(getClient("Logowanie-certyfikat.html"));
Assert.assertEquals("", login.findSymbolInCertificate("<xml></xml>")); // change to real cert with empty symbols
login.findSymbolInCertificate(getFixtureAsString("cert-no-symbols.xml"));
}
}

View File

@ -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)
.getExtractedSchoolSymbolFromUrl("https://uonetplus-opiekun.fakelog.cf/powiat/123456/Start/Index/"))
}
@Test
fun getExtractedIDDemoTest() {
assertEquals("demo12345", StartPage(client)
.getExtractedSchoolSymbolFromUrl("https://uonetplus-opiekun.fakelog.cf/demoupowiat/demo12345/Start/Index/"))
}
@Test(expected = VulcanException::class)
fun getExtractedIDNotLoggedTest() {
assertEquals("123", StartPage(client)
.getExtractedSchoolSymbolFromUrl("https://uonetplus.NOTfakelog.cf/powiat/"))
}
}

View File

@ -0,0 +1,17 @@
package io.github.wulkanowy.api.mobile
import io.github.wulkanowy.api.StudentAndParentTestCase
import org.junit.Assert.assertEquals
import org.junit.Test
class RegisterDeviceTest : StudentAndParentTestCase() {
@Test
fun getTokenTest() {
val registration = RegisterDevice(getSnp("Rejestruj.html"))
assertEquals("3S1A1B2C", registration.getToken().token)
assertEquals("Default", registration.getToken().symbol)
assertEquals("1234567", registration.getToken().pin)
}
}

View File

@ -0,0 +1,37 @@
package io.github.wulkanowy.api.mobile
import io.github.wulkanowy.api.StudentAndParentTestCase
import org.junit.Assert.assertEquals
import org.junit.Test
class RegisteredDevicesListTest : StudentAndParentTestCase() {
private val filled = RegisteredDevices(getSnp("DostepMobilny-filled.html"))
@Test
fun getListTest() {
assertEquals(2, filled.getList().size)
}
@Test
fun getNameTest() {
assertEquals("google Android SDK built for x86", filled.getList()[0].name)
assertEquals("google (Android SDK) built for x86", filled.getList()[1].name)
}
@Test
fun getSystemTest() {
assertEquals("Android 8.1.0", filled.getList()[0].system)
assertEquals("Android 8.1.0", filled.getList()[1].system)
}
@Test
fun getDateTest() {
assertEquals("2018-01-20 22:35:30", filled.getList()[0].date)
}
@Test
fun getIdTest() {
assertEquals(321, filled.getList()[0].id)
}
}

View File

@ -30,8 +30,8 @@ public class NotesListTest extends StudentAndParentTestCase {
public void getDateTest() throws Exception {
List<Note> filledList = filled.getAllNotes();
Assert.assertEquals("06.06.2017", filledList.get(0).getDate());
Assert.assertEquals("01.10.2016", filledList.get(2).getDate());
Assert.assertEquals("2017-06-06", filledList.get(0).getDate());
Assert.assertEquals("2016-10-01", filledList.get(2).getDate());
}
@Test

View File

@ -83,11 +83,11 @@ public class TimetableTest extends StudentAndParentTestCase {
@Test
public void getLessonNumberTest() throws Exception {
Assert.assertEquals("2", std.getWeekTable().getDay(0).getLesson(1).getNumber());
Assert.assertEquals("5", std.getWeekTable().getDay(2).getLesson(4).getNumber());
Assert.assertEquals("0", full.getWeekTable().getDay(0).getLesson(0).getNumber());
Assert.assertEquals("13", full.getWeekTable().getDay(4).getLesson(13).getNumber());
Assert.assertEquals("3", holidays.getWeekTable().getDay(3).getLesson(3).getNumber());
Assert.assertEquals(2, std.getWeekTable().getDay(0).getLesson(1).getNumber());
Assert.assertEquals(5, std.getWeekTable().getDay(2).getLesson(4).getNumber());
Assert.assertEquals(0, full.getWeekTable().getDay(0).getLesson(0).getNumber());
Assert.assertEquals(13, full.getWeekTable().getDay(4).getLesson(13).getNumber());
Assert.assertEquals(3, holidays.getWeekTable().getDay(3).getLesson(3).getNumber());
}
@Test
@ -105,11 +105,13 @@ public class TimetableTest extends StudentAndParentTestCase {
Assert.assertEquals("Zajęcia techniczne", std.getWeekTable().getDay(2).getLesson(4).getSubject());
Assert.assertEquals("Wychowanie fizyczne", std.getWeekTable().getDay(1).getLesson(1).getSubject());
Assert.assertEquals("Język angielski", full.getWeekTable().getDay(0).getLesson(1).getSubject());
Assert.assertEquals("Wychowanie fizyczne", full.getWeekTable().getDay(0).getLesson(9).getSubject());
Assert.assertEquals("Wychowanie do życia w rodzinie", full.getWeekTable().getDay(2).getLesson(0).getSubject());
Assert.assertEquals("Wychowanie fizyczne", full.getWeekTable().getDay(3).getLesson(1).getSubject());
Assert.assertEquals("Uroczyste zakończenie roku szkolnego", full.getWeekTable().getDay(4).getLesson(0).getSubject());
Assert.assertEquals("Fizyka", full.getWeekTable().getDay(0).getLesson(0).getSubject());
Assert.assertEquals("Metodologia programowania", full.getWeekTable().getDay(1).getLesson(0).getSubject());
Assert.assertEquals("Język niemiecki", full.getWeekTable().getDay(4).getLesson(2).getSubject());
Assert.assertEquals("", holidays.getWeekTable().getDay(3).getLesson(3).getSubject());
}
@ -122,6 +124,7 @@ public class TimetableTest extends StudentAndParentTestCase {
Assert.assertEquals("Nowak Jadwiga", full.getWeekTable().getDay(2).getLesson(0).getTeacher());
Assert.assertEquals("Nowicka Irena", full.getWeekTable().getDay(3).getLesson(1).getTeacher());
Assert.assertEquals("Baran Małgorzata", full.getWeekTable().getDay(4).getLesson(0).getTeacher());
Assert.assertEquals("", full.getWeekTable().getDay(4).getLesson(1).getTeacher());
Assert.assertEquals("", holidays.getWeekTable().getDay(3).getLesson(3).getTeacher());
}
@ -148,7 +151,13 @@ public class TimetableTest extends StudentAndParentTestCase {
Assert.assertEquals("zastępstwo (poprzednio: Religia)", full.getWeekTable().getDay(2).getLesson(0).getDescription());
Assert.assertEquals("zastępstwo (poprzednio: Wychowanie fizyczne)", full.getWeekTable().getDay(3).getLesson(1).getDescription());
Assert.assertEquals("", full.getWeekTable().getDay(4).getLesson(0).getDescription());
Assert.assertEquals("", full.getWeekTable().getDay(4).getLesson(1).getDescription());
Assert.assertEquals("bez nawiasów (poprzednio: Religia)", full.getWeekTable().getDay(4).getLesson(3).getDescription());
Assert.assertEquals("poprzednio: Wychowanie fizyczne", full.getWeekTable().getDay(4).getLesson(2).getDescription());
Assert.assertEquals("egzamin", full.getWeekTable().getDay(3).getLesson(0).getDescription());
Assert.assertEquals("", full.getWeekTable().getDay(4).getLesson(1).getDescription());
Assert.assertEquals("poprzednio: Zajęcia z wychowawcą", full.getWeekTable().getDay(4).getLesson(5).getDescription());
Assert.assertEquals("opis w uwadze bez klasy w spanie", full.getWeekTable().getDay(4).getLesson(4).getDescription());
Assert.assertEquals("", holidays.getWeekTable().getDay(3).getLesson(3).getDescription());
}
@ -237,6 +246,8 @@ public class TimetableTest extends StudentAndParentTestCase {
Assert.assertTrue(full.getWeekTable().getDay(1).getLesson(2).isNewMovedInOrChanged());
Assert.assertTrue(full.getWeekTable().getDay(1).getLesson(3).isNewMovedInOrChanged());
Assert.assertTrue(full.getWeekTable().getDay(3).getLesson(1).isNewMovedInOrChanged());
Assert.assertFalse(full.getWeekTable().getDay(4).getLesson(1).isNewMovedInOrChanged());
Assert.assertTrue(full.getWeekTable().getDay(4).getLesson(2).isNewMovedInOrChanged());
Assert.assertFalse(holidays.getWeekTable().getDay(3).getLesson(3).isNewMovedInOrChanged());
}
}

View File

@ -15,7 +15,8 @@
<option selected="selected" value="1235">2</option>
</select>
</div>
</main>
</div>
</main>
<footer>wersja: 17.05.0000.24042</footer>
</body>
</html>

View File

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Uonet+</title>
</head>
<body>
<div class="startScreen">
<div class="holder">
<div class="content">
<div class="panel linkownia pracownik klient">
<div id="idAppUczen" class="subDiv">
<div class="appLink">
<a href="https://uonetplus-opiekun.fakelog.cf/symbol/123456/Start/Index/">
<span class="header directLink">GIMBB</span>
</a>
<br>
<a href="https://uonetplus-opiekun.fakelog.cf/symbol/123457/Start/Index/">
<span class="header directLink">SPBB</span>
</a>
<br>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Uonet+</title>
</head>
<body>
<div class="startScreen">
<div class="holder">
<div class="content">
<div class="panel linkownia pracownik klient">
<div class="appLink">
<a href="http://uonetplus-opiekun.fakelog.localhost:3000/default/534213/Start/Index/">
<div class="imagedHeader directLink">
<div id="idEmptyAppUczen">
<div class="name">Uczeń</div>
</div>
</div>
</a>
</div>
<div class="newAppLink">
<div class="link">
<a href="http://uonetplus-uczen.fakelog.localhost:3000/default/012345/">
<div class="imagedHeader directLink">
<div id="idEmptyAppUczenExt">
<div class="name">Uczeń</div>
</div>
</div>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@ -1,24 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Uonet+</title>
</head>
<body>
<div class="startScreen">
<div class="holder">
<div class="content">
<div class="panel linkownia pracownik klient">
<a href="https://uonetplus-opiekun.vulcan.net.pl/symbol/534213/Start/Index/">
<div class="imagedHeader directLink">
<div id="idEmptyAppUczeń">
<div class="name">Uczeń</div>
</div>
</div>
</a>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="utf-8">
<title>Witryna ucznia i rodzica Strona gł&#243;wna</title>
</head>
<body>
<ul id="idSection">
<li>
<label for="uczenDropDownList">Uczeń:</label>
<select id="uczenDropDownList" name="uczenDropDownList">
<option selected="selected"
value="https://uonetplus-opiekun.fakelog.cf/Default/123456/Uczen/UczenOnChange?&amp;id=100">
Jan Kowal
</option>
</select>
</li>
<li>
<label for="dziennikDropDownList">Dziennik:</label>
<select id="dziennikDropDownList" name="dziennikDropDownList">
<option selected="selected"
value="https://uonetplus-opiekun.fakelog.cf/Default/123456/Dziennik/DziennikOnChange?&amp;id=1300">
3Ti 2017
</option>
<option value="https://uonetplus-opiekun.fakelog.cf/Default/123456/Dziennik/DziennikOnChange?&amp;id=1200">
2Ti 2016
</option>
<option value="https://uonetplus-opiekun.fakelog.cf/Default/123456/Dziennik/DziennikOnChange?&amp;id=1100">
1Ti 2015
</option>
</select>
</li>
</ul>
<footer>wersja: 17.09.0008.26553</footer>
</body>
</html>

View File

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Witryna ucznia i rodzica Terminarz sprawdzian&#243;w</title>
</head>
<body>
<main class="mainContainer">
<h1>Sprawdziany</h1>
<h2>Tydzień 30.04.2018 - 06.05.2018</h2>
<h2>Nie zaplanowano żadnych sprawdzian&#243;w na wybrany tydzień</h2>
<div class="navigation">
<a href="/symbol/123456/Sprawdziany.mvc/Terminarz?data=636600384000000000&amp;rokSzkolny=2017&amp;rodzajWidoku=2" class="button-prev">Poprzedni tydzień</a>
<a href="/symbol/123456/Sprawdziany.mvc/Terminarz?data=636612480000000000&amp;rokSzkolny=2017&amp;rodzajWidoku=2" class="button-next">Następny tydzień</a>
</div>
</main>
<footer>wersja: 17.09.0009.26859</footer>
</body>
</html>

View File

@ -100,6 +100,14 @@
<td>06.02.2017</td>
<td>Amelia Stępień</td>
</tr>
<tr>
<td>Język polski</td>
<td class="break-word"><span class="ocenaCzastkowa" style="color:#6ECD07;">5</span></td>
<td class="break-word">+Odp, Kordian</td>
<td>5,00</td>
<td>11.05.2017</td>
<td>Amelia Stępień</td>
</tr>
</tbody>
</table>
</main>

View File

@ -3,10 +3,10 @@
<title>Working...</title>
</head>
<body>
<form method="POST" name="hiddenform" action="https://fake-log.com/Default/LoginEndpoint.aspx">
<form method="POST" name="hiddenform" action="https://fakelog.cf/Default/LoginEndpoint.aspx">
<input type="hidden" name="wa" value="wsignin1.0">
<input type="hidden" name="wresult" value="<trust:RequestSecurityTokenResponseCollection xmlns:trust=&quot;http://docs.oasis-open.org/ws-sx/ws-trust/200512&quot;><trust:RequestSecurityTokenResponse Context=&quot;https://uonetplus.fake-log.com/Default/LoginEndpoint.aspx&quot;><trust:RequestedSecurityToken><saml:Assertion AssertionID=&quot;_12345678-1234-1234-1234-1234567890ab&quot; IssueInstant=&quot;2017-10-18T22:00:29.006Z&quot; Issuer=&quot;CUFSTokenService&quot; MajorVersion=&quot;1&quot; MinorVersion=&quot;1&quot; xmlns:saml=&quot;urn:oasis:names:tc:SAML:1.0:assertion&quot;><saml:AttributeStatement><saml:Attribute AttributeName=&quot;UserInstance&quot; AttributeNamespace=&quot;http://schemas.fake-log.com/ws/identity/claims&quot;><saml:AttributeValue>Default</saml:AttributeValue><saml:AttributeValue>demo12345</saml:AttributeValue><saml:AttributeValue>incorrect value</saml:AttributeValue><saml:AttributeValue>warszawa</saml:AttributeValue><saml:AttributeValue>asdf</saml:AttributeValue><saml:AttributeValue>asdfsdf</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion></trust:RequestedSecurityToken></trust:RequestSecurityTokenResponse></trust:RequestSecurityTokenResponseCollection>">
<input type="hidden" name="wctx" value="https://fake-log.com/Default/LoginEndpoint.aspx">
<input type="hidden" name="wresult" value="<trust:RequestSecurityTokenResponseCollection xmlns:trust=&quot;http://docs.oasis-open.org/ws-sx/ws-trust/200512&quot;><trust:RequestSecurityTokenResponse Context=&quot;https://uonetplus.fakelog.cf/Default/LoginEndpoint.aspx&quot;><trust:RequestedSecurityToken><saml:Assertion AssertionID=&quot;_12345678-1234-1234-1234-1234567890ab&quot; IssueInstant=&quot;2017-10-18T22:00:29.006Z&quot; Issuer=&quot;CUFSTokenService&quot; MajorVersion=&quot;1&quot; MinorVersion=&quot;1&quot; xmlns:saml=&quot;urn:oasis:names:tc:SAML:1.0:assertion&quot;><saml:AttributeStatement><saml:Attribute AttributeName=&quot;UserInstance&quot; AttributeNamespace=&quot;http://schemas.fakelog.cf/ws/identity/claims&quot;><saml:AttributeValue>Default</saml:AttributeValue><saml:AttributeValue>demo12345</saml:AttributeValue><saml:AttributeValue>incorrect value</saml:AttributeValue><saml:AttributeValue>warszawa</saml:AttributeValue><saml:AttributeValue>asdf</saml:AttributeValue><saml:AttributeValue>asdfsdf</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion></trust:RequestedSecurityToken></trust:RequestSecurityTokenResponse></trust:RequestSecurityTokenResponseCollection>">
<input type="hidden" name="wctx" value="https://fakelog.cf/Default/LoginEndpoint.aspx">
<noscript>
<p>Script is disabled. Click Submit to continue.</p>
<input type="submit" value="Submit">

View File

@ -6,6 +6,9 @@
<body>
<div id="MainDiv">
<form>
<div class="LogOnBoard">
<h1 id="h1Default">Logowanie</h1>
</div>
<div class="ErrorMessage center">
Zła nazwa użytkownika lub hasło
</div>

View File

@ -11,6 +11,21 @@
<span class="userdata">example@wulkanowy.io (<a href="/demo123/LoginEndpoint.aspx?logout=true">wyloguj</a>)</span>
</div>
</div>
<div class="holder">
<div class="content">
<div class="panel linkownia pracownik klient">
<div class="appLink">
<a href="https://uonetplus-opiekun.fakelog.cf/symbol/534213/Start/Index/">
<div class="imagedHeader directLink">
<div id="idEmptyAppUczeń">
<div class="name">Uczeń</div>
</div>
</div>
</a>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,13 @@
<trust:RequestSecurityTokenResponseCollection xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
<trust:RequestSecurityTokenResponse Context="https://uonetplus.fakelog.cf/Default/LoginEndpoint.aspx">
<trust:RequestedSecurityToken>
<saml:Assertion AssertionID="_12345678-1234-1234-1234-1234567890ab" IssueInstant="2017-10-18T22:00:29.006Z" Issuer="CUFSTokenService" MajorVersion="1" MinorVersion="1" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion">
<saml:AttributeStatement>
<saml:Attribute AttributeName="UserInstance" AttributeNamespace="http://schemas.fakelog.cf/ws/identity/claims">
<saml:AttributeValue>Default</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
</trust:RequestedSecurityToken>
</trust:RequestSecurityTokenResponse>
</trust:RequestSecurityTokenResponseCollection>

View File

@ -1,9 +1,9 @@
<trust:RequestSecurityTokenResponseCollection xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
<trust:RequestSecurityTokenResponse Context="https://uonetplus.fake-log.com/Default/LoginEndpoint.aspx">
<trust:RequestSecurityTokenResponse Context="https://uonetplus.fakelog.cf/Default/LoginEndpoint.aspx">
<trust:RequestedSecurityToken>
<saml:Assertion AssertionID="_12345678-1234-1234-1234-1234567890ab" IssueInstant="2017-10-18T22:00:29.006Z" Issuer="CUFSTokenService" MajorVersion="1" MinorVersion="1" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion">
<saml:AttributeStatement>
<saml:Attribute AttributeName="UserInstance" AttributeNamespace="http://schemas.fake-log.com/ws/identity/claims">
<saml:Attribute AttributeName="UserInstance" AttributeNamespace="http://schemas.fakelog.cf/ws/identity/claims">
<saml:AttributeValue>Default</saml:AttributeValue>
<saml:AttributeValue>demo12345</saml:AttributeValue>
<saml:AttributeValue>incorrect value</saml:AttributeValue>

View File

@ -0,0 +1,44 @@
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="utf-8">
<title>Witryna ucznia i rodzica dostęp mobilny</title>
</head>
<body>
<main class="mainContainer">
<h1>Dostęp mobilny</h1>
<article>
<h2>Zarejestrowane urządzenia</h2>
</article>
<table>
<thead>
<tr>
<th>Urządzenie</th>
<th>Data rejestracji</th>
<th></th>
</tr>
</thead>
<tbody>
<tr class="text-center">
<td>google Android SDK built for x86 (Android 8.1.0)</td>
<td>20.01.2018 godz: 22:35:30</td>
<td class="cellWithButton">
<a href="/Default/123456/DostepMobilny.mvc/Wyrejestruj/321" class="button">Wyrejestruj</a>
</td>
</tr>
<tr class="text-center">
<td>google (Android SDK) built for x86 (Android 8.1.0)</td>
<td>20.01.2018 godz: 22:35:30</td>
<td class="cellWithButton">
<a href="/Default/123456/DostepMobilny.mvc/Wyrejestruj/213" class="button">Wyrejestruj</a>
</td>
</tr>
</tbody>
</table>
</main>
<footer>wersja: 18.01.0001.27311</footer>
</body>
</html>

View File

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="utf-8">
<title>Witryna ucznia i rodzica Rejestracja urządzenia mobilnego</title>
<style>
.blockElement {
display: block;
}
</style>
</head>
<body>
<main class="mainContainer">
<h1>Rejestracja urządzenia mobilnego</h1>
<article class="text-center" id="rejestracja-formularz">
<span class="blockElement">Za pomocą aplikacji &quot;Dzienniczek+&quot; zeskanuj kod QR.</span>
<img src=" data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gUdCTohm9rlswAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAFKklEQVR42u3dYYqDQAyA0abk/lfO/l+6LLZYksx7J3C09SPgaFRVPQDgoqdTAICAACAgAAgIAAICAAICgIAAICAACAgAAgIAAgKAgAAgIAAICAACAgACAoCAACAgAAgIAAICAAICgIAAICAACAgAAgIAAgKAgAAgIAAICAACAgACAoCAACAgAAgIAAICAFdltwOKiNUnvKqOXj/4/9y3fhMIACMICAACAoCAACAgAAgIAAgIAJ/IaQfc7Tno3+5+Dr37+sH/p+/6TSAACAgAAgKAgACAgAAgIAAICADj5bYF2YcBuH+YQAAQEAAEBAAEBAABAUBAABAQAAQEAAQEAAEBQEAAEBAABAQABAQAAQFAQAAQEAAEBAAEBAABAUBAABAQAAQEAP6R2xZUVa4q4P5hAgFAQAAQEAAQEAAEBAABAUBAANho3D6QiHDVAPcPEwgAAgKAgACAgAAgIAAICAACAsCJ2u0D8T5+wP3DBAKAgACAgAAgIAAICAACAoCAAMBL7faBeF8/4P7wWrd9LiYQAAQEAAEBQEAAEBAAEBAABASAr8tpB+x9/7DX6f/vaftcTCAACAgAAgKAgAAgIAAgIAAICAACAoCAACAgACAgAAgIAAICgIAAICAAICAACAgAAgKAgAAgIAAgIAAICAACAoCAACAgACAgAAgIAAICgIAAICAAICAACAgAAgKAgAAgIAAgIAAICAACAoCAAICAACAgAAgIAAICgIAAgIAAICAACAgAAgKAgACAgAAgIAAICAACAoCAAICAACAgAAgIAAICgIAAgIAAICAACAgAAgKAgACAgAAgIAAICAACAoCAAICAACAgAAgIAAICgIA4BQAICAACAoCAACAgACAgAAgIAAICgIAAICAAICAACAgAAgKAgAAgIAAgIAAICAACAoCAACAgACAgAAgIAAICgIAAICAAICAACAgAAgKAgAAgIAAgIAAICAACAoCAACAgACAgAAgIAAICgIAAgIAAICAACAgAAgKAgACAgAAgIAAICAACAoCAAICAACAgAAgIAAICgIAAgIAAICAACAgAAgKAgACAgAAgIAAICAACAoCAAICAACAgAAgIAAICgIAAgIAAICAACAgAAgKAgACAgAAgIAAICAACAgACAoCAACAgAAgIAAICAAICgIAAICAACAgAAgIAAgKAgAAgIAAICAACAgACAoCAACAgAAgIAAICAAICgIAAICAACAgAAgIAAgKAgAAgIAAICAACAgACAoCAANBWTjvgiDj6glWVXy1gAgFAQAAQEAAQEAAEBAABAUBAuOb0x5CBPdrtAzl9n4PAACYQAAQEAAQEAAEBQEAAEBAABAQA/tBuH8j2fRC+5wGYQAAQEAAQEAAEBAABAUBAAEBAAHhTTjvg7vsofM8DMIEAgIAAICAACAgAAgKAgACAgABwk9y2oLv3YfieB4AJBAABAUBAABAQAAQEAAQEAAEBQEAAEBAABAQABAQAAQFAQAAQEAAEBAAEBAABAUBAABAQAAQEAAQEAAEBQEAAGC+3LaiqXFUAEwgAAgKAgACAgAAgIAAICAACAsBG4/aBRMTRF+z09QMmEAAEBAABAQABAUBAABAQAAQEgINF+YAGACYQAAQEAAEBQEAAQEAAEBAABAQAAQFAQABAQAAQEAAEBAABAUBAAEBAABAQAAQEAAEBQEAAQEAAEBAABAQAAQFAQABAQAAQEAAEBAABAUBAAEBAABAQAAQEAAEBQEAAQEAA+IYf8fZKNX0RrMQAAAAASUVORK5CYII="
alt="Kod QR" title="Kod QR" height="400" width="400"/>
<span class="blockElement">Token: 3S1A1B2C</span>
<span class="blockElement">Symbol: Default</span>
<span class="blockElement">PIN: 1234567</span>
</article>
</main>
<footer>wersja: 18.01.0001.27311</footer>
</body>
</html>

View File

@ -3,6 +3,40 @@
<head>
<meta charset="utf-8">
<title>Witryna ucznia i rodzica Plan lekcji</title>
<style>
table, th, td {
border: 1px solid;
border-collapse: collapse;
}
table td > div:not(:last-child) {
border-bottom: 5px solid silver;
padding-bottom: 5px;
margin-bottom: 5px;
}
table td div span:nth-child(1) {
display: block;
}
table span {
font-size: smaller;
}
.x-treelabel-ppl {
background: #99f;
font-style: italic;
}
.x-treelabel-rlz {
background: #f3a;
}
.x-treelabel-inv {
background: #f00;
}
.x-treelabel-zas {
background: #0f0;
}
table span:not([class]),
table span[class=""] {
background: #999;
}
</style>
</head>
<body>
<main class="mainContainer">
@ -82,13 +116,6 @@
</div>
</td>
<td>
<div>
<span class="x-treelabel-ppl x-treelabel-inv">Metodologia programowania [zaw2]</span>
<span class="x-treelabel-ppl x-treelabel-inv"></span>
<span class="x-treelabel-ppl x-treelabel-inv">Baran Małgorzata</span>
<span class="x-treelabel-ppl x-treelabel-inv">36</span>
<span class="x-treelabel-rlz">(zmiana organizacji zajęć)</span>
</div>
<div>
<span class="x-treelabel-ppl x-treelabel-zas">Wychowanie fizyczne [zaw2]</span>
<span class="x-treelabel-ppl x-treelabel-zas"></span>
@ -96,6 +123,13 @@
<span class="x-treelabel-ppl x-treelabel-zas">G3</span>
<span class="x-treelabel-rlz">(przeniesiona z lekcji 7, 01.12.2017)</span>
</div>
<div>
<span class="x-treelabel-ppl x-treelabel-inv">Metodologia programowania [zaw2]</span>
<span class="x-treelabel-ppl x-treelabel-inv"></span>
<span class="x-treelabel-ppl x-treelabel-inv">Baran Małgorzata</span>
<span class="x-treelabel-ppl x-treelabel-inv">36</span>
<span class="x-treelabel-rlz">(zmiana organizacji zajęć)</span>
</div>
</td>
<td>
<div>
@ -118,7 +152,18 @@
<span class="x-treelabel-rlz">(zastępstwo)</span>
</div>
</td>
<td></td>
<td>
<div>
<span class="">Uroczyste rozpoczecie roku szkolnego 2017/2018</span>
<span class=""></span>
<span class=""></span>
</div>
<div>
<span class="x-treelabel-ppl">Uroczyste rozpoczecie roku szkolnego 2017/2018</span>
<span class="x-treelabel-ppl"></span>
<span class="x-treelabel-ppl"></span>
</div>
</td>
</tr>
<tr>
<td>2</td>
@ -165,7 +210,20 @@
<span></span>
</div>
</td>
<td></td>
<td>
<div>
<span class="">Język niemiecki [wf_grupa_2]</span>
<span class=""></span>
<span class=""></span>
<span class=""></span>
</div>
<div>
<span class="x-treelabel-ppl x-treelabel-inv">Wychowanie fizyczne [wf_grupa_2]</span>
<span class="x-treelabel-ppl x-treelabel-inv"></span>
<span class="x-treelabel-ppl x-treelabel-inv">Nauczycielel</span>
<span class="x-treelabel-ppl x-treelabel-inv">106</span>
</div>
</td>
</tr>
<tr>
<td>3</td>
@ -214,7 +272,17 @@
<span></span>
</div>
</td>
<td></td>
<td>
<div>
<span class="x-treelabel-inv">Religia</span>
<span class="x-treelabel-inv">Cyranka Krystian</span>
<span class="x-treelabel-inv">3</span>
<span class="x-treelabel-ppl x-treelabel-zas">Wychowanie do życia w rodzinie</span>
<span class="x-treelabel-ppl x-treelabel-zas">Nowak Jadwiga</span>
<span class="x-treelabel-ppl x-treelabel-zas">3</span>
<span class="x-treelabel-rlz">bez nawiasów</span>
</div>
</td>
</tr>
<tr>
<td>4</td>
@ -251,7 +319,16 @@
<span></span>
</div>
</td>
<td></td>
<td>
<div>
<span class="x-treelabel-ppl x-treelabel-inv">Język polski</span>
<span class="x-treelabel-ppl x-treelabel-inv"> </span>
<span class="x-treelabel-ppl x-treelabel-inv">16</span>
<span class="random-class">(oddział nieobecny)</span>
</div>
<button type="button" class="uwaga-btn">Uwaga</button>
<div class="uwaga-panel">opis w uwadze bez klasy w spanie</div>
</td>
</tr>
<tr>
<td>5</td>
@ -287,7 +364,20 @@
<span></span>
</div>
</td>
<td></td>
<td>
<div>
<span class="">Tworzenie i administrowanie bazami danych [zaw2]</span>
<span class=""></span>
<span class=""></span>
<span class=""></span>
</div>
<div>
<span class="x-treelabel-ppl x-treelabel-inv">Zajęcia z wychowawcą</span>
<span class="x-treelabel-ppl x-treelabel-inv">Małgorzata Kowal</span>
<span class="x-treelabel-ppl x-treelabel-inv">43</span>
<span class="x-treelabel-rlz">(zmiana organizacji zajęć)</span>
</div>
</td>
</tr>
<tr>
<td>6</td>
@ -393,7 +483,18 @@
<tr>
<td>9</td>
<td>14:50 15:35</td>
<td></td>
<td>
<div>
<span class="x-treelabel-ppl x-treelabel-zas">Wychowanie fizyczne [zaw2]</span>
<span class="x-treelabel-ppl x-treelabel-zas"></span>
<span class="x-treelabel-ppl x-treelabel-zas"></span>
<span class="x-treelabel-ppl x-treelabel-zas">G3</span>
<span class="x-treelabel-rlz">(przeniesiona z lekcji 7, 01.12.2017)</span>
</div>
<div>
<!--<span>WTF</span>-->
</div>
</td>
<td>
<div>
<span class="x-treelabel-ppl x-treelabel-inv">Język niemiecki [J1]</span>

View File

@ -1,12 +1,25 @@
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/" }
maven { url 'https://maven.fabric.io/public' }
google()
}
dependencies {
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2'
classpath 'io.fabric.tools:gradle:1.25.1'
classpath "org.greenrobot:greendao-gradle-plugin:$greenDaoGradle"
classpath "io.fabric.tools:gradle:$fabricGradle"
classpath "com.google.gms:oss-licenses:0.9.2"
classpath "com.github.triplet.gradle:play-publisher:$playPublisher"
}
}
@ -14,33 +27,46 @@ repositories {
maven { url 'https://maven.fabric.io/public' }
}
apply plugin: 'com.android.application'
apply plugin: 'org.greenrobot.greendao'
apply plugin: 'io.fabric'
apply from: '../jacoco.gradle'
apply from: '../android-sonarqube.gradle'
android {
compileSdkVersion 27
buildToolsVersion "27.0.3"
buildToolsVersion '27.0.3'
playAccountConfigs {
defaultAccountConfig {
serviceAccountEmail = System.getenv("PLAY_SERVICE_ACCOUNT_EMAIL")
pk12File = file('key.p12')
}
}
defaultConfig {
applicationId "io.github.wulkanowy"
testApplicationId "io.github.tests.wulkanowy"
minSdkVersion 15
targetSdkVersion 27
versionCode 4
versionName "0.2.1"
versionCode 18
versionName "0.5.4"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
playAccountConfig = playAccountConfigs.defaultAccountConfig
manifestPlaceholders = [
fabricApiKey: System.getenv("FABRIC_API_KEY") ?: "null"
]
}
signingConfigs {
release {
storeFile file("upload-key.jks")
storePassword System.getenv("PLAY_STORE_PASSWORD")
keyAlias System.getenv("PLAY_KEY_ALIAS")
keyPassword System.getenv("PLAY_KEY_PASSWORD")
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
debug {
applicationIdSuffix ".dev"
@ -61,49 +87,58 @@ android {
}
}
play {
track = 'alpha'
uploadImages = true
}
greendao {
schemaVersion 22
schemaVersion 29
generateTests = true
}
configurations.all {
resolutionStrategy.force "com.android.support:support-annotations:$supportVersion"
}
dependencies {
implementation project(':api')
implementation 'com.android.support:appcompat-v7:27.1.0'
implementation 'com.android.support:design:27.1.0'
implementation 'com.android.support:support-v4:27.1.0'
implementation 'com.android.support:recyclerview-v7:27.1.0'
implementation 'com.android.support:cardview-v7:27.1.0'
implementation 'com.android.support:customtabs:27.1.0'
implementation 'com.firebase:firebase-jobdispatcher:0.8.5'
implementation 'org.apache.commons:commons-lang3:3.7'
implementation 'eu.davidea:flexible-adapter:5.0.0-rc4'
implementation 'eu.davidea:flexible-adapter-ui:1.0.0-b1'
implementation 'org.apache.commons:commons-collections4:4.1'
implementation 'org.greenrobot:greendao:3.2.2'
implementation 'com.github.yuweiguocn:GreenDaoUpgradeHelper:v2.0.2'
implementation 'com.jakewharton:butterknife:8.8.1'
implementation 'joda-time:joda-time:2.9.9'
implementation 'com.google.dagger:dagger-android:2.14.1'
implementation 'com.google.dagger:dagger-android-support:2.14.1'
implementation 'com.aurelhubert:ahbottomnavigation:2.1.0'
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"
implementation "com.android.support:customtabs:$supportVersion"
implementation "com.android.support:preference-v14:$supportVersion"
implementation "com.firebase:firebase-jobdispatcher:$firebaseJob"
implementation "org.apache.commons:commons-lang3:$apacheLang"
implementation "org.apache.commons:commons-collections4:$apacheCollections"
implementation "eu.davidea:flexible-adapter:$flexibleAdapter"
implementation "eu.davidea:flexible-adapter-ui:$flexibleUi"
implementation "org.greenrobot:greendao:$greenDao"
implementation "com.jakewharton:butterknife:$butterknife"
implementation "com.google.dagger:dagger-android-support:$dagger2"
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"
implementation('com.crashlytics.sdk.android:crashlytics:2.8.0@aar') {
implementation("com.crashlytics.sdk.android:crashlytics:$crashlyticsSdk@aar") {
transitive = true
}
implementation('com.crashlytics.sdk.android:answers:1.4.1@aar') {
implementation("com.crashlytics.sdk.android:answers:$crashlyticsAnswers@aar") {
transitive = true
}
annotationProcessor 'com.google.dagger:dagger-android-processor:2.14.1'
annotationProcessor 'com.google.dagger:dagger-compiler:2.14.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
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:1.0.1'
debugImplementation 'net.zetetic:android-database-sqlcipher:3.5.9'
debugImplementation "com.amitshekhar.android:debug-db:$debugDb"
testImplementation 'junit:junit:4.12'
testImplementation 'org.mockito:mockito-core:2.13.0'
testImplementation "junit:junit:$junit"
testImplementation "org.mockito:mockito-core:$mockito"
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'org.mockito:mockito-android:2.13.0'
androidTestImplementation "com.android.support.test:runner:$testRunner"
androidTestImplementation "org.mockito:mockito-android:$mockito"
}

56
app/jacoco.gradle Normal file
View File

@ -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"]
)
}

BIN
app/key-encrypted.p12 Normal file

Binary file not shown.

View File

@ -2,9 +2,6 @@ package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
import io.github.wulkanowy.data.db.dao.entities.AttendanceLesson;
import io.github.wulkanowy.data.db.dao.entities.AttendanceLessonDao;
public class AttendanceLessonTest extends AbstractDaoTestLongPk<AttendanceLessonDao, AttendanceLesson> {
public AttendanceLessonTest() {
@ -15,13 +12,13 @@ public class AttendanceLessonTest extends AbstractDaoTestLongPk<AttendanceLesson
protected AttendanceLesson createEntity(Long key) {
AttendanceLesson entity = new AttendanceLesson();
entity.setId(key);
entity.setIsPresence(false);
entity.setIsAbsenceUnexcused(false);
entity.setIsAbsenceExcused(false);
entity.setIsUnexcusedLateness(false);
entity.setIsAbsenceForSchoolReasons(false);
entity.setIsExcusedLateness(false);
entity.setIsExemption(false);
entity.setPresence(false);
entity.setAbsenceUnexcused(false);
entity.setAbsenceExcused(false);
entity.setUnexcusedLateness(false);
entity.setAbsenceForSchoolReasons(false);
entity.setExcusedLateness(false);
entity.setExemption(false);
return entity;
}

View File

@ -12,7 +12,7 @@ public class DayTest extends AbstractDaoTestLongPk<DayDao, Day> {
protected Day createEntity(Long key) {
Day entity = new Day();
entity.setId(key);
entity.setIsFreeDay(false);
entity.setFreeDay(false);
return entity;
}

View File

@ -0,0 +1,19 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
public class DiaryTest extends AbstractDaoTestLongPk<DiaryDao, Diary> {
public DiaryTest() {
super(DiaryDao.class);
}
@Override
protected Diary createEntity(Long key) {
Diary entity = new Diary();
entity.setId(key);
entity.setCurrent(false);
return entity;
}
}

View File

@ -0,0 +1,18 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
public class ExamTest extends AbstractDaoTestLongPk<ExamDao, Exam> {
public ExamTest() {
super(ExamDao.class);
}
@Override
protected Exam createEntity(Long key) {
Exam entity = new Exam();
entity.setId(key);
return entity;
}
}

View File

@ -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<SchoolDao, School> {
public SchoolTest() {
super(SchoolDao.class);
}
@Override
protected School createEntity(Long key) {
School entity = new School();
entity.setId(key);
entity.setCurrent(false);
return entity;
}
}

View File

@ -0,0 +1,21 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
import io.github.wulkanowy.data.db.dao.entities.Semester;
import io.github.wulkanowy.data.db.dao.entities.SemesterDao;
public class SemesterTest extends AbstractDaoTestLongPk<SemesterDao, Semester> {
public SemesterTest() {
super(SemesterDao.class);
}
@Override
protected Semester createEntity(Long key) {
Semester entity = new Semester();
entity.setId(key);
return entity;
}
}

View File

@ -0,0 +1,21 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
import io.github.wulkanowy.data.db.dao.entities.Student;
import io.github.wulkanowy.data.db.dao.entities.StudentDao;
public class StudentTest extends AbstractDaoTestLongPk<StudentDao, Student> {
public StudentTest() {
super(StudentDao.class);
}
@Override
protected Student createEntity(Long key) {
Student entity = new Student();
entity.setId(key);
return entity;
}
}

View File

@ -0,0 +1,21 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
import io.github.wulkanowy.data.db.dao.entities.Symbol;
import io.github.wulkanowy.data.db.dao.entities.SymbolDao;
public class SymbolTest extends AbstractDaoTestLongPk<SymbolDao, Symbol> {
public SymbolTest() {
super(SymbolDao.class);
}
@Override
protected Symbol createEntity(Long key) {
Symbol entity = new Symbol();
entity.setId(key);
return entity;
}
}

View File

@ -2,9 +2,6 @@ package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
import io.github.wulkanowy.data.db.dao.entities.TimetableLesson;
import io.github.wulkanowy.data.db.dao.entities.TimetableLessonDao;
public class TimetableLessonTest extends AbstractDaoTestLongPk<TimetableLessonDao, TimetableLesson> {
public TimetableLessonTest() {
@ -15,12 +12,12 @@ public class TimetableLessonTest extends AbstractDaoTestLongPk<TimetableLessonDa
protected TimetableLesson createEntity(Long key) {
TimetableLesson entity = new TimetableLesson();
entity.setId(key);
entity.setIsEmpty(false);
entity.setIsDivisionIntoGroups(false);
entity.setIsPlanning(false);
entity.setIsRealized(false);
entity.setIsMovedOrCanceled(false);
entity.setIsNewMovedInOrChanged(false);
entity.setEmpty(false);
entity.setDivisionIntoGroups(false);
entity.setPlanning(false);
entity.setRealized(false);
entity.setMovedOrCanceled(false);
entity.setNewMovedInOrChanged(false);
return entity;
}

View File

@ -10,12 +10,10 @@
<application
android:name=".WulkanowyApp"
android:allowBackup="true"
android:fullBackupContent="@xml/backup_rules"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/WulkanowyTheme">
<activity
android:name=".ui.splash.SplashActivity"
@ -32,19 +30,40 @@
android:name=".ui.login.LoginActivity"
android:configChanges="orientation|screenSize"
android:label="@string/title_activity_login"
android:theme="@style/WulkanowyTheme.DarkActionBar"
android:windowSoftInputMode="adjustResize" />
<activity
android:name=".ui.main.MainActivity"
android:configChanges="orientation|screenSize"
android:label="@string/activity_dashboard_text" />
android:label="@string/activity_dashboard_text"
android:launchMode="singleTop"
/>
<activity
android:name="com.google.android.gms.oss.licenses.OssLicensesMenuActivity"
android:theme="@style/WulkanowyTheme.DarkActionBar" />
<activity
android:name="com.google.android.gms.oss.licenses.OssLicensesActivity"
android:theme="@style/WulkanowyTheme.DarkActionBar" />
<service
android:name=".services.SyncJob"
android:name=".services.jobs.SyncJob"
android:exported="false">
<intent-filter>
<action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE" />
</intent-filter>
</service>
<service
android:name=".services.widgets.TimetableWidgetServices"
android:permission="android.permission.BIND_REMOTEVIEWS" />
<receiver android:name=".ui.widgets.TimetableWidgetProvider">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_provider" />
</receiver>
<meta-data
android:name="io.fabric.ApiKey"

View File

@ -1,26 +1,25 @@
package io.github.wulkanowy;
import android.app.Application;
import com.crashlytics.android.Crashlytics;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.core.CrashlyticsCore;
import com.jakewharton.threetenabp.AndroidThreeTen;
import org.greenrobot.greendao.query.QueryBuilder;
import javax.inject.Inject;
import dagger.android.AndroidInjector;
import dagger.android.support.DaggerApplication;
import eu.davidea.flexibleadapter.FlexibleAdapter;
import eu.davidea.flexibleadapter.utils.Log;
import io.fabric.sdk.android.Fabric;
import io.github.wulkanowy.data.RepositoryContract;
import io.github.wulkanowy.di.component.ApplicationComponent;
import io.github.wulkanowy.di.component.DaggerApplicationComponent;
import io.github.wulkanowy.di.modules.ApplicationModule;
import io.github.wulkanowy.utils.LogUtils;
import io.github.wulkanowy.di.DaggerAppComponent;
import io.github.wulkanowy.utils.FabricUtils;
import io.github.wulkanowy.utils.LoggerUtils;
import timber.log.Timber;
public class WulkanowyApp extends Application {
protected ApplicationComponent applicationComponent;
public class WulkanowyApp extends DaggerApplication {
@Inject
RepositoryContract repository;
@ -28,11 +27,7 @@ public class WulkanowyApp extends Application {
@Override
public void onCreate() {
super.onCreate();
applicationComponent = DaggerApplicationComponent
.builder()
.applicationModule(new ApplicationModule(this))
.build();
applicationComponent.inject(this);
AndroidThreeTen.init(this);
if (BuildConfig.DEBUG) {
enableDebugLog();
@ -42,30 +37,38 @@ public class WulkanowyApp extends Application {
}
private void initializeUserSession() {
if (repository.getCurrentUserId() != 0) {
if (repository.getSharedRepo().isUserLoggedIn()) {
try {
repository.initLastUser();
repository.getSyncRepo().initLastUser();
FabricUtils.logLogin("Open app", true);
} catch (Exception e) {
LogUtils.error("An error occurred when the application was started", e);
FabricUtils.logLogin("Open app", false);
Timber.e(e, "An error occurred when the application was started");
}
}
}
private void enableDebugLog() {
QueryBuilder.LOG_VALUES = true;
FlexibleAdapter.enableLogs(Log.Level.DEBUG);
FlexibleAdapter.enableLogs(eu.davidea.flexibleadapter.utils.Log.Level.DEBUG);
Timber.plant(new LoggerUtils.DebugLogTree());
}
private void initializeFabric() {
Fabric.with(new Fabric.Builder(this)
.kits(new Crashlytics.Builder()
.core(new CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build())
.build())
.kits(
new Crashlytics.Builder()
.core(new CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build())
.build(),
new Answers()
)
.debuggable(BuildConfig.DEBUG)
.build());
Timber.plant(new LoggerUtils.CrashlyticsTree());
}
public ApplicationComponent getApplicationComponent() {
return applicationComponent;
@Override
protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
return DaggerAppComponent.builder().create(this);
}
}

View File

@ -1,159 +1,56 @@
package io.github.wulkanowy.data;
import java.io.IOException;
import java.text.ParseException;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
import io.github.wulkanowy.api.VulcanException;
import io.github.wulkanowy.data.db.dao.entities.Account;
import io.github.wulkanowy.data.db.dao.entities.AttendanceLesson;
import io.github.wulkanowy.data.db.dao.entities.DaoSession;
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.Week;
import io.github.wulkanowy.data.db.dao.entities.WeekDao;
import io.github.wulkanowy.data.db.dao.DbContract;
import io.github.wulkanowy.data.db.resources.ResourcesContract;
import io.github.wulkanowy.data.db.shared.SharedPrefContract;
import io.github.wulkanowy.data.sync.SyncContract;
import io.github.wulkanowy.data.sync.account.AccountSyncContract;
import io.github.wulkanowy.data.sync.attendance.AttendanceSyncContract;
import io.github.wulkanowy.data.sync.timetable.TimetableSyncContract;
import io.github.wulkanowy.di.annotations.SyncGrades;
import io.github.wulkanowy.di.annotations.SyncSubjects;
import io.github.wulkanowy.utils.security.CryptoException;
@Singleton
public class Repository implements RepositoryContract {
private final SharedPrefContract sharedPref;
private final DbContract database;
private final ResourcesContract resources;
private final DaoSession daoSession;
private final SharedPrefContract sharedPref;
private final AccountSyncContract accountSync;
private final AttendanceSyncContract attendanceSync;
private final TimetableSyncContract timetableSync;
private final SyncContract gradeSync;
private final SyncContract subjectSync;
private final SyncContract synchronization;
@Inject
Repository(SharedPrefContract sharedPref,
ResourcesContract resources,
DaoSession daoSession,
AccountSyncContract accountSync,
AttendanceSyncContract attendanceSync,
TimetableSyncContract timetableSync,
@SyncGrades SyncContract gradeSync,
@SyncSubjects SyncContract subjectSync) {
this.sharedPref = sharedPref;
Repository(DbContract database, ResourcesContract resources, SharedPrefContract sharedPref,
SyncContract synchronization) {
this.database = database;
this.resources = resources;
this.daoSession = daoSession;
this.accountSync = accountSync;
this.attendanceSync = attendanceSync;
this.timetableSync = timetableSync;
this.gradeSync = gradeSync;
this.subjectSync = subjectSync;
this.sharedPref = sharedPref;
this.synchronization = synchronization;
}
@Override
public long getCurrentUserId() {
return sharedPref.getCurrentUserId();
public SharedPrefContract getSharedRepo() {
return sharedPref;
}
@Override
public String[] getSymbolsKeysArray() {
return resources.getSymbolsKeysArray();
public ResourcesContract getResRepo() {
return resources;
}
@Override
public String[] getSymbolsValuesArray() {
return resources.getSymbolsValuesArray();
public DbContract getDbRepo() {
return database;
}
@Override
public String getErrorLoginMessage(Exception e) {
return resources.getErrorLoginMessage(e);
public SyncContract getSyncRepo() {
return synchronization;
}
@Override
public String getAttendanceLessonDescription(AttendanceLesson lesson) {
return resources.getAttendanceLessonDescription(lesson);
}
@Override
public void registerUser(String email, String password, String symbol) throws VulcanException,
IOException, CryptoException {
accountSync.registerUser(email, password, symbol);
}
@Override
public void initLastUser() throws VulcanException, IOException, CryptoException {
accountSync.initLastUser();
}
@Override
public void syncGrades() throws VulcanException, IOException, ParseException {
gradeSync.sync();
}
@Override
public void syncSubjects() throws VulcanException, IOException, ParseException {
subjectSync.sync();
}
@Override
public void syncAttendance() throws ParseException, IOException, VulcanException {
attendanceSync.syncAttendance();
}
@Override
public void syncAttendance(String date) throws ParseException, IOException, VulcanException {
attendanceSync.syncAttendance(date);
}
@Override
public void syncTimetable() throws VulcanException, IOException, ParseException {
timetableSync.syncTimetable();
}
@Override
public void syncTimetable(String date) throws VulcanException, IOException, ParseException {
timetableSync.syncTimetable(date);
}
@Override
public void syncAll() throws VulcanException, IOException, ParseException {
syncSubjects();
syncGrades();
syncAttendance();
syncTimetable();
}
@Override
public Account getCurrentUser() {
return daoSession.getAccountDao().load(sharedPref.getCurrentUserId());
}
@Override
public Week getWeek(String date) {
return daoSession.getWeekDao().queryBuilder()
.where(WeekDao.Properties.StartDayDate.eq(date),
WeekDao.Properties.UserId.eq(getCurrentUserId()))
.unique();
}
@Override
public List<Grade> getNewGrades() {
return daoSession.getGradeDao().queryBuilder()
.where(GradeDao.Properties.IsNew.eq(1))
.list();
public void cleanAllData() {
sharedPref.cleanSharedPref();
database.recreateDatabase();
}
}

View File

@ -1,35 +1,22 @@
package io.github.wulkanowy.data;
import java.io.IOException;
import java.text.ParseException;
import java.util.List;
import javax.inject.Singleton;
import io.github.wulkanowy.api.VulcanException;
import io.github.wulkanowy.data.db.dao.entities.Account;
import io.github.wulkanowy.data.db.dao.entities.Grade;
import io.github.wulkanowy.data.db.dao.entities.Week;
import io.github.wulkanowy.data.db.dao.DbContract;
import io.github.wulkanowy.data.db.resources.ResourcesContract;
import io.github.wulkanowy.data.sync.account.AccountSyncContract;
import io.github.wulkanowy.data.sync.attendance.AttendanceSyncContract;
import io.github.wulkanowy.data.sync.timetable.TimetableSyncContract;
import io.github.wulkanowy.data.db.shared.SharedPrefContract;
import io.github.wulkanowy.data.sync.SyncContract;
@Singleton
public interface RepositoryContract extends ResourcesContract, AccountSyncContract,
AttendanceSyncContract, TimetableSyncContract {
public interface RepositoryContract {
long getCurrentUserId();
SharedPrefContract getSharedRepo();
void syncGrades() throws VulcanException, IOException, ParseException;
ResourcesContract getResRepo();
void syncSubjects() throws VulcanException, IOException, ParseException;
DbContract getDbRepo();
void syncAll() throws VulcanException, IOException, ParseException;
SyncContract getSyncRepo();
Account getCurrentUser();
Week getWeek(String date);
List<Grade> getNewGrades();
void cleanAllData();
}

View File

@ -0,0 +1,37 @@
package io.github.wulkanowy.data.db.dao;
import java.util.List;
import io.github.wulkanowy.data.db.dao.entities.Grade;
import io.github.wulkanowy.data.db.dao.entities.Subject;
import io.github.wulkanowy.data.db.dao.entities.Symbol;
import io.github.wulkanowy.data.db.dao.entities.Week;
public interface DbContract {
Week getWeek(String date);
Week getWeek(long diaryId, String date);
List<Subject> getSubjectList(int semesterName);
List<Grade> getNewGrades(int semesterName);
long getCurrentSchoolId();
long getCurrentStudentId();
long getCurrentSymbolId();
Symbol getCurrentSymbol();
long getCurrentDiaryId();
long getSemesterId(int name);
long getCurrentSemesterId();
int getCurrentSemesterName();
void recreateDatabase();
}

View File

@ -3,59 +3,100 @@ package io.github.wulkanowy.data.db.dao;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import com.github.yuweiguocn.library.greendao.MigrationHelper;
import org.greenrobot.greendao.database.Database;
import org.greenrobot.greendao.database.StandardDatabase;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import io.github.wulkanowy.BuildConfig;
import io.github.wulkanowy.data.db.dao.entities.AccountDao;
import io.github.wulkanowy.api.Vulcan;
import io.github.wulkanowy.data.db.dao.entities.DaoMaster;
import io.github.wulkanowy.data.db.dao.entities.GradeDao;
import io.github.wulkanowy.data.db.dao.entities.SubjectDao;
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 io.github.wulkanowy.di.annotations.ApplicationContext;
import io.github.wulkanowy.di.annotations.DatabaseInfo;
import io.github.wulkanowy.utils.LogUtils;
import timber.log.Timber;
@Singleton
public class DbHelper extends DaoMaster.OpenHelper {
private SharedPrefContract sharedPref;
private final SharedPrefContract sharedPref;
private final Vulcan vulcan;
@Inject
DbHelper(@ApplicationContext Context context, @DatabaseInfo String dbName,
SharedPrefContract sharedPref) {
DbHelper(Context context, @Named("dbName") String dbName,
SharedPrefContract sharedPref, Vulcan vulcan) {
super(context, dbName);
this.sharedPref = sharedPref;
}
@Override
@SuppressWarnings("unchecked")
public void onUpgrade(Database db, int oldVersion, int newVersion) {
MigrationHelper.DEBUG = BuildConfig.DEBUG;
MigrationHelper.migrate(db, new MigrationHelper.ReCreateAllTableListener() {
@Override
public void onCreateAllTables(Database db, boolean ifNotExists) {
DaoMaster.createAllTables(db, ifNotExists);
}
@Override
public void onDropAllTables(Database db, boolean ifExists) {
DaoMaster.dropAllTables(db, ifExists);
}
}, AccountDao.class, SubjectDao.class, GradeDao.class);
this.vulcan = vulcan;
}
@Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Timber.i("Cleaning user data oldVersion=%s newVersion=%s", oldVersion, newVersion);
Database database = new StandardDatabase(db);
DaoMaster.dropAllTables(database, true);
onCreate(database);
sharedPref.setCurrentUserId(0);
recreateDatabase(database);
}
LogUtils.info("Cleaning user data oldVersion=" + oldVersion + " newVersion=" + newVersion);
@Override
public void onUpgrade(Database db, int oldVersion, int newVersion) {
List<Migration> migrations = getMigrations();
// Only run migrations past the old version
for (Migration migration : migrations) {
if (oldVersion < migration.getVersion()) {
try {
Timber.i("Applying migration to db schema v%s...", migration.getVersion());
migration.runMigration(db, sharedPref, vulcan);
Timber.i("Migration %s complete", migration.getVersion());
} catch (Exception e) {
Timber.e(e, "Failed to apply migration");
recreateDatabase(db);
break;
}
}
}
}
private void recreateDatabase(Database db) {
Timber.i("Database is recreating...");
sharedPref.setCurrentUserId(0);
DaoMaster.dropAllTables(db, true);
onCreate(db);
}
private List<Migration> getMigrations() {
List<Migration> migrations = new ArrayList<>();
migrations.add(new Migration23());
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<Migration> migrationComparator = new Comparator<Migration>() {
@Override
public int compare(Migration m1, Migration m2) {
return m1.getVersion().compareTo(m2.getVersion());
}
};
Collections.sort(migrations, migrationComparator);
return migrations;
}
public interface Migration {
Integer getVersion();
void runMigration(Database db, SharedPrefContract sharedPref, Vulcan vulcan) throws Exception;
}
}

View File

@ -0,0 +1,132 @@
package io.github.wulkanowy.data.db.dao;
import org.greenrobot.greendao.database.Database;
import java.util.List;
import javax.inject.Inject;
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.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;
import io.github.wulkanowy.data.db.dao.entities.Subject;
import io.github.wulkanowy.data.db.dao.entities.Symbol;
import io.github.wulkanowy.data.db.dao.entities.SymbolDao;
import io.github.wulkanowy.data.db.dao.entities.Week;
import io.github.wulkanowy.data.db.dao.entities.WeekDao;
import io.github.wulkanowy.data.db.shared.SharedPrefContract;
public class DbRepository implements DbContract {
private final DaoSession daoSession;
private final SharedPrefContract sharedPref;
@Inject
DbRepository(DaoSession daoSession, SharedPrefContract sharedPrefContract) {
this.daoSession = daoSession;
this.sharedPref = sharedPrefContract;
}
@Override
public Week getWeek(String date) {
return getWeek(getCurrentDiaryId(), date);
}
@Override
public Week getWeek(long diaryId, String date) {
return daoSession.getWeekDao().queryBuilder().where(
WeekDao.Properties.StartDayDate.eq(date),
WeekDao.Properties.DiaryId.eq(diaryId)
).unique();
}
@Override
public List<Subject> getSubjectList(int semesterName) {
return daoSession.getSemesterDao().load(getSemesterId(semesterName)).getSubjectList();
}
@Override
public List<Grade> getNewGrades(int semesterName) {
return daoSession.getGradeDao().queryBuilder().where(
GradeDao.Properties.IsNew.eq(1),
GradeDao.Properties.SemesterId.eq(getSemesterId(semesterName))
).list();
}
@Override
public Symbol getCurrentSymbol() {
return daoSession.getSymbolDao().queryBuilder().where(
SymbolDao.Properties.UserId.eq(sharedPref.getCurrentUserId())
).unique();
}
@Override
public long getCurrentSymbolId() {
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.SchoolId.eq(getCurrentSchoolId()),
StudentDao.Properties.Current.eq(true)
).unique().getId();
}
@Override
public long getCurrentDiaryId() {
return daoSession.getDiaryDao().queryBuilder().where(
DiaryDao.Properties.StudentId.eq(getCurrentStudentId()),
DiaryDao.Properties.Current.eq(true)
).unique().getId();
}
@Override
public long getSemesterId(int name) {
return daoSession.getSemesterDao().queryBuilder().where(
SemesterDao.Properties.DiaryId.eq(getCurrentDiaryId()),
SemesterDao.Properties.Name.eq(String.valueOf(name))
).unique().getId();
}
@Override
public long getCurrentSemesterId() {
return getCurrentSemester().getId();
}
@Override
public int getCurrentSemesterName() {
return Integer.valueOf(getCurrentSemester().getName());
}
private Semester getCurrentSemester() {
return daoSession.getSemesterDao().queryBuilder().where(
SemesterDao.Properties.DiaryId.eq(getCurrentDiaryId()),
SemesterDao.Properties.Current.eq(true)
).unique();
}
@Override
public void recreateDatabase() {
Database database = daoSession.getDatabase();
DaoMaster.dropAllTables(database, true);
DaoMaster.createAllTables(database, true);
}
}

View File

@ -6,6 +6,7 @@ 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 org.greenrobot.greendao.annotation.Unique;
import java.util.List;
@ -18,29 +19,15 @@ public class Account {
@Id(autoincrement = true)
private Long id;
@Property(nameInDb = "NAME")
private String name;
@Property(nameInDb = "E-MAIL")
@Unique
@Property(nameInDb = "email")
private String email;
@Property(nameInDb = "PASSWORD")
@Property(nameInDb = "password")
private String password;
@Property(nameInDb = "SYMBOL")
private String symbol;
@Property(nameInDb = "SNPID")
private String snpId;
@ToMany(referencedJoinProperty = "userId")
private List<Subject> subjectList;
@ToMany(referencedJoinProperty = "userId")
private List<Grade> gradeList;
@ToMany(referencedJoinProperty = "userId")
private List<Day> dayList;
private List<Symbol> symbolList;
/**
* Used to resolve relations
@ -54,15 +41,11 @@ public class Account {
@Generated(hash = 335469827)
private transient AccountDao myDao;
@Generated(hash = 735765217)
public Account(Long id, String name, String email, String password, String symbol,
String snpId) {
@Generated(hash = 1104194311)
public Account(Long id, String email, String password) {
this.id = id;
this.name = name;
this.email = email;
this.password = password;
this.symbol = symbol;
this.snpId = snpId;
}
@Generated(hash = 882125521)
@ -70,25 +53,15 @@ public class Account {
}
public Long getId() {
return id;
return this.id;
}
public Account setId(Long id) {
public void setId(Long id) {
this.id = id;
return this;
}
public String getName() {
return name;
}
public Account setName(String name) {
this.name = name;
return this;
}
public String getEmail() {
return email;
return this.email;
}
public Account setEmail(String email) {
@ -97,7 +70,7 @@ public class Account {
}
public String getPassword() {
return password;
return this.password;
}
public Account setPassword(String password) {
@ -105,82 +78,34 @@ public class Account {
return this;
}
public String getSymbol() {
return symbol;
}
public Account setSymbol(String symbol) {
this.symbol = symbol;
return this;
}
public String getSnpId() {
return this.snpId;
}
public Account setSnpId(String snpId) {
this.snpId = snpId;
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 = 1800750450)
public List<Subject> getSubjectList() {
if (subjectList == null) {
@Generated(hash = 822972496)
public List<Symbol> getSymbolList() {
if (symbolList == null) {
final DaoSession daoSession = this.daoSession;
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
SubjectDao targetDao = daoSession.getSubjectDao();
List<Subject> subjectListNew = targetDao._queryAccount_SubjectList(id);
SymbolDao targetDao = daoSession.getSymbolDao();
List<Symbol> symbolListNew = targetDao._queryAccount_SymbolList(id);
synchronized (this) {
if (subjectList == null) {
subjectList = subjectListNew;
if (symbolList == null) {
symbolList = symbolListNew;
}
}
}
return subjectList;
return symbolList;
}
/**
* Resets a to-many relationship, making the next get call to query for a fresh result.
*/
@Generated(hash = 594294258)
public synchronized void resetSubjectList() {
subjectList = null;
}
/**
* 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 = 1040074549)
public List<Grade> getGradeList() {
if (gradeList == null) {
final DaoSession daoSession = this.daoSession;
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
GradeDao targetDao = daoSession.getGradeDao();
List<Grade> gradeListNew = targetDao._queryAccount_GradeList(id);
synchronized (this) {
if (gradeList == null) {
gradeList = gradeListNew;
}
}
}
return gradeList;
}
/**
* Resets a to-many relationship, making the next get call to query for a fresh result.
*/
@Generated(hash = 1939990047)
public synchronized void resetGradeList() {
gradeList = null;
@Generated(hash = 1716801695)
public synchronized void resetSymbolList() {
symbolList = null;
}
/**
@ -219,36 +144,6 @@ public class Account {
myDao.update(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 = 300459794)
public List<Day> getDayList() {
if (dayList == null) {
final DaoSession daoSession = this.daoSession;
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
DayDao targetDao = daoSession.getDayDao();
List<Day> dayListNew = targetDao._queryAccount_DayList(id);
synchronized (this) {
if (dayList == null) {
dayList = dayListNew;
}
}
}
return dayList;
}
/**
* Resets a to-many relationship, making the next get call to query for a fresh result.
*/
@Generated(hash = 1010399236)
public synchronized void resetDayList() {
dayList = null;
}
/** called by internal mechanisms, do not call yourself. */
@Generated(hash = 1812283172)
public void __setDaoSession(DaoSession daoSession) {

View File

@ -20,38 +20,38 @@ public class AttendanceLesson implements Serializable {
@Id(autoincrement = true)
private Long id;
@Property(nameInDb = "DAY_ID")
@Property(nameInDb = "day_id")
private Long dayId;
@Property(nameInDb = "DATE")
@Property(nameInDb = "date")
private String date = "";
@Property(nameInDb = "NUMBER_OF_LESSON")
@Property(nameInDb = "number_of_lesson")
private int number = 0;
@Property(nameInDb = "SUBJECT_NAME")
@Property(nameInDb = "subject")
private String subject = "";
@Property(nameInDb = "IS_PRESENCE")
private boolean isPresence = false;
@Property(nameInDb = "presence")
private boolean presence = false;
@Property(nameInDb = "IS_ABSENCE_UNEXCUSED")
private boolean isAbsenceUnexcused = false;
@Property(nameInDb = "absence_unexcused")
private boolean absenceUnexcused = false;
@Property(nameInDb = "IS_ABSENCE_EXCUSED")
private boolean isAbsenceExcused = false;
@Property(nameInDb = "absence_excused")
private boolean absenceExcused = false;
@Property(nameInDb = "IS_UNEXCUSED_LATENESS")
private boolean isUnexcusedLateness = false;
@Property(nameInDb = "unexcused_lateness")
private boolean unexcusedLateness = false;
@Property(nameInDb = "IS_ABSENCE_FOR_SCHOOL_REASONS")
private boolean isAbsenceForSchoolReasons = false;
@Property(nameInDb = "absence_for_school_reasons")
private boolean absenceForSchoolReasons = false;
@Property(nameInDb = "IS_EXCUSED_LATENESS")
private boolean isExcusedLateness = false;
@Property(nameInDb = "excused_lateness")
private boolean excusedLateness = false;
@Property(nameInDb = "IS_EXEMPTION")
private boolean isExemption = false;
@Property(nameInDb = "exemption")
private boolean exemption = false;
@Transient
private String description = "";
@ -70,24 +70,24 @@ public class AttendanceLesson implements Serializable {
@Generated(hash = 1936953859)
private transient AttendanceLessonDao myDao;
@Generated(hash = 1428129046)
@Generated(hash = 1741231228)
public AttendanceLesson(Long id, Long dayId, String date, int number,
String subject, boolean isPresence, boolean isAbsenceUnexcused,
boolean isAbsenceExcused, boolean isUnexcusedLateness,
boolean isAbsenceForSchoolReasons, boolean isExcusedLateness,
boolean isExemption) {
String subject, boolean presence, boolean absenceUnexcused,
boolean absenceExcused, boolean unexcusedLateness,
boolean absenceForSchoolReasons, boolean excusedLateness,
boolean exemption) {
this.id = id;
this.dayId = dayId;
this.date = date;
this.number = number;
this.subject = subject;
this.isPresence = isPresence;
this.isAbsenceUnexcused = isAbsenceUnexcused;
this.isAbsenceExcused = isAbsenceExcused;
this.isUnexcusedLateness = isUnexcusedLateness;
this.isAbsenceForSchoolReasons = isAbsenceForSchoolReasons;
this.isExcusedLateness = isExcusedLateness;
this.isExemption = isExemption;
this.presence = presence;
this.absenceUnexcused = absenceUnexcused;
this.absenceExcused = absenceExcused;
this.unexcusedLateness = unexcusedLateness;
this.absenceForSchoolReasons = absenceForSchoolReasons;
this.excusedLateness = excusedLateness;
this.exemption = exemption;
}
@Generated(hash = 921806575)
@ -137,66 +137,66 @@ public class AttendanceLesson implements Serializable {
return this;
}
public boolean getIsPresence() {
return this.isPresence;
public boolean getPresence() {
return this.presence;
}
public AttendanceLesson setIsPresence(boolean isPresence) {
this.isPresence = isPresence;
public AttendanceLesson setPresence(boolean presence) {
this.presence = presence;
return this;
}
public boolean getIsAbsenceUnexcused() {
return this.isAbsenceUnexcused;
public boolean getAbsenceUnexcused() {
return this.absenceUnexcused;
}
public AttendanceLesson setIsAbsenceUnexcused(boolean isAbsenceUnexcused) {
this.isAbsenceUnexcused = isAbsenceUnexcused;
public AttendanceLesson setAbsenceUnexcused(boolean absenceUnexcused) {
this.absenceUnexcused = absenceUnexcused;
return this;
}
public boolean getIsAbsenceExcused() {
return this.isAbsenceExcused;
public boolean getAbsenceExcused() {
return this.absenceExcused;
}
public AttendanceLesson setIsAbsenceExcused(boolean isAbsenceExcused) {
this.isAbsenceExcused = isAbsenceExcused;
public AttendanceLesson setAbsenceExcused(boolean absenceExcused) {
this.absenceExcused = absenceExcused;
return this;
}
public boolean getIsUnexcusedLateness() {
return this.isUnexcusedLateness;
public boolean getUnexcusedLateness() {
return this.unexcusedLateness;
}
public AttendanceLesson setIsUnexcusedLateness(boolean isUnexcusedLateness) {
this.isUnexcusedLateness = isUnexcusedLateness;
public AttendanceLesson setUnexcusedLateness(boolean unexcusedLateness) {
this.unexcusedLateness = unexcusedLateness;
return this;
}
public boolean getIsAbsenceForSchoolReasons() {
return this.isAbsenceForSchoolReasons;
public boolean getAbsenceForSchoolReasons() {
return this.absenceForSchoolReasons;
}
public AttendanceLesson setIsAbsenceForSchoolReasons(boolean isAbsenceForSchoolReasons) {
this.isAbsenceForSchoolReasons = isAbsenceForSchoolReasons;
public AttendanceLesson setAbsenceForSchoolReasons(boolean absenceForSchoolReasons) {
this.absenceForSchoolReasons = absenceForSchoolReasons;
return this;
}
public boolean getIsExcusedLateness() {
return this.isExcusedLateness;
public boolean getExcusedLateness() {
return this.excusedLateness;
}
public AttendanceLesson setIsExcusedLateness(boolean isExcusedLateness) {
this.isExcusedLateness = isExcusedLateness;
public AttendanceLesson setExcusedLateness(boolean excusedLateness) {
this.excusedLateness = excusedLateness;
return this;
}
public boolean getIsExemption() {
return this.isExemption;
public boolean getExemption() {
return this.exemption;
}
public AttendanceLesson setIsExemption(boolean isExemption) {
this.isExemption = isExemption;
public AttendanceLesson setExemption(boolean exemption) {
this.exemption = exemption;
return this;
}

View File

@ -14,59 +14,57 @@ import java.util.List;
@Entity(
nameInDb = "Days",
active = true,
indexes = {@Index(value = "userId,weekId,date", unique = true)}
indexes = {@Index(value = "weekId,date", unique = true)}
)
public class Day {
@Id(autoincrement = true)
private Long id;
@Property(nameInDb = "USER_ID")
private Long userId;
@Property(nameInDb = "WEEK_ID")
@Property(nameInDb = "week_id")
private Long weekId;
@Property(nameInDb = "DATE")
@Property(nameInDb = "date")
private String date = "";
@Property(nameInDb = "DAY_NAME")
@Property(nameInDb = "day_name")
private String dayName = "";
@Property(nameInDb = "IS_FREE_DAY")
private boolean isFreeDay = false;
@Property(nameInDb = "free_day")
private boolean freeDay = false;
@Property(nameInDb = "FREE_DAY_NAME")
@Property(nameInDb = "free_day_name")
private String freeDayName = "";
@OrderBy("number ASC")
@ToMany(referencedJoinProperty = "dayId")
private List<TimetableLesson> timetableLessons;
@ToMany(referencedJoinProperty = "dayId")
@OrderBy("number ASC")
@ToMany(referencedJoinProperty = "dayId")
private List<AttendanceLesson> attendanceLessons;
@ToMany(referencedJoinProperty = "dayId")
private List<Exam> exams;
/**
* Used to resolve relations
*/
@Generated(hash = 2040040024)
private transient DaoSession daoSession;
/**
* Used for active entity operations.
*/
/** Used for active entity operations. */
@Generated(hash = 312167767)
private transient DayDao myDao;
@Generated(hash = 723729681)
public Day(Long id, Long userId, Long weekId, String date, String dayName,
boolean isFreeDay, String freeDayName) {
@Generated(hash = 523139020)
public Day(Long id, Long weekId, String date, String dayName, boolean freeDay,
String freeDayName) {
this.id = id;
this.userId = userId;
this.weekId = weekId;
this.date = date;
this.dayName = dayName;
this.isFreeDay = isFreeDay;
this.freeDay = freeDay;
this.freeDayName = freeDayName;
}
@ -82,26 +80,16 @@ public class Day {
this.id = id;
}
public Long getUserId() {
return userId;
}
public Long getWeekId() {
return weekId;
return this.weekId;
}
public Day setWeekId(Long weekId) {
public void setWeekId(Long weekId) {
this.weekId = weekId;
return this;
}
public Day setUserId(Long userId) {
this.userId = userId;
return this;
}
public String getDate() {
return date;
return this.date;
}
public Day setDate(String date) {
@ -110,7 +98,7 @@ public class Day {
}
public String getDayName() {
return dayName;
return this.dayName;
}
public Day setDayName(String dayName) {
@ -118,17 +106,17 @@ public class Day {
return this;
}
public boolean getIsFreeDay() {
return this.isFreeDay;
public boolean getFreeDay() {
return this.freeDay;
}
public Day setIsFreeDay(boolean isFreeDay) {
this.isFreeDay = isFreeDay;
public Day setFreeDay(boolean freeDay) {
this.freeDay = freeDay;
return this;
}
public String getFreeDayName() {
return freeDayName;
return this.freeDayName;
}
public Day setFreeDayName(String freeDayName) {
@ -159,7 +147,9 @@ public class Day {
return timetableLessons;
}
/** Resets a to-many relationship, making the next get call to query for a fresh result. */
/**
* Resets a to-many relationship, making the next get call to query for a fresh result.
*/
@Generated(hash = 1687683740)
public synchronized void resetTimetableLessons() {
timetableLessons = null;
@ -188,12 +178,44 @@ public class Day {
return attendanceLessons;
}
/** Resets a to-many relationship, making the next get call to query for a fresh result. */
/**
* Resets a to-many relationship, making the next get call to query for a fresh result.
*/
@Generated(hash = 1343075564)
public synchronized void resetAttendanceLessons() {
attendanceLessons = null;
}
/**
* 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 = 1231531946)
public List<Exam> getExams() {
if (exams == null) {
final DaoSession daoSession = this.daoSession;
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
ExamDao targetDao = daoSession.getExamDao();
List<Exam> examsNew = targetDao._queryDay_Exams(id);
synchronized (this) {
if (exams == null) {
exams = examsNew;
}
}
}
return exams;
}
/**
* Resets a to-many relationship, making the next get call to query for a fresh result.
*/
@Generated(hash = 841969952)
public synchronized void resetExams() {
exams = null;
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
* Entity must attached to an entity context.
@ -236,4 +258,6 @@ public class Day {
this.daoSession = daoSession;
myDao = daoSession != null ? daoSession.getDayDao() : null;
}
}

View File

@ -0,0 +1,177 @@
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 = "Diaries",
active = true
)
public class Diary {
@Id(autoincrement = true)
private Long id;
@Property(nameInDb = "student_id")
private Long studentId;
@Property(nameInDb = "current")
private boolean current;
@Property(nameInDb = "name")
private String name;
@Property(nameInDb = "value")
private String value;
@ToMany(referencedJoinProperty = "diaryId")
private List<Semester> semesterList;
/**
* Used to resolve relations
*/
@Generated(hash = 2040040024)
private transient DaoSession daoSession;
/**
* Used for active entity operations.
*/
@Generated(hash = 21166549)
private transient DiaryDao myDao;
@Generated(hash = 277096196)
public Diary(Long id, Long studentId, boolean current, String name, String value) {
this.id = id;
this.studentId = studentId;
this.current = current;
this.name = name;
this.value = value;
}
@Generated(hash = 112123061)
public Diary() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public Long getStudentId() {
return this.studentId;
}
public Diary setStudentId(Long studentId) {
this.studentId = studentId;
return this;
}
public String getName() {
return this.name;
}
public Diary setName(String name) {
this.name = name;
return this;
}
public String getValue() {
return this.value;
}
public Diary setValue(String value) {
this.value = value;
return this;
}
public boolean getCurrent() {
return this.current;
}
public Diary setCurrent(boolean current) {
this.current = current;
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 = 1738383053)
public List<Semester> getSemesterList() {
if (semesterList == null) {
final DaoSession daoSession = this.daoSession;
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
SemesterDao targetDao = daoSession.getSemesterDao();
List<Semester> semesterListNew = targetDao._queryDiary_SemesterList(id);
synchronized (this) {
if (semesterList == null) {
semesterList = semesterListNew;
}
}
}
return semesterList;
}
/**
* Resets a to-many relationship, making the next get call to query for a fresh result.
*/
@Generated(hash = 995060657)
public synchronized void resetSemesterList() {
semesterList = 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 = 629297785)
public void __setDaoSession(DaoSession daoSession) {
this.daoSession = daoSession;
myDao = daoSession != null ? daoSession.getDiaryDao() : null;
}
}

View File

@ -0,0 +1,177 @@
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.Index;
import org.greenrobot.greendao.annotation.Property;
import java.io.Serializable;
@Entity(
nameInDb = "Exams",
active = true,
indexes = {@Index(value = "dayId,entryDate,subjectAndGroup,type,teacher", unique = true)}
)
public class Exam implements Serializable {
@Id(autoincrement = true)
private Long id;
@Property(nameInDb = "day_id")
private Long dayId;
@Property(nameInDb = "subject_and_group")
private String subjectAndGroup = "";
@Property(nameInDb = "type")
private String type = "";
@Property(nameInDb = "description")
private String description = "";
@Property(nameInDb = "teacher")
private String teacher = "";
@Property(nameInDb = "entry_date")
private String entryDate = "";
private static final long serialVersionUID = 42L;
/**
* Used to resolve relations
*/
@Generated(hash = 2040040024)
private transient DaoSession daoSession;
/**
* Used for active entity operations.
*/
@Generated(hash = 973692038)
private transient ExamDao myDao;
@Generated(hash = 998653360)
public Exam(Long id, Long dayId, String subjectAndGroup, String type, String description,
String teacher, String entryDate) {
this.id = id;
this.dayId = dayId;
this.subjectAndGroup = subjectAndGroup;
this.type = type;
this.description = description;
this.teacher = teacher;
this.entryDate = entryDate;
}
@Generated(hash = 945526930)
public Exam() {
}
public Long getId() {
return id;
}
public Exam setId(Long id) {
this.id = id;
return this;
}
public Long getDayId() {
return this.dayId;
}
public Exam setDayId(Long dayId) {
this.dayId = dayId;
return this;
}
public String getSubjectAndGroup() {
return subjectAndGroup;
}
public Exam setSubjectAndGroup(String subjectAndGroup) {
this.subjectAndGroup = subjectAndGroup;
return this;
}
public String getType() {
return type;
}
public Exam setType(String type) {
this.type = type;
return this;
}
public String getDescription() {
return description;
}
public Exam setDescription(String description) {
this.description = description;
return this;
}
public String getTeacher() {
return teacher;
}
public Exam setTeacher(String teacher) {
this.teacher = teacher;
return this;
}
public String getEntryDate() {
return entryDate;
}
public Exam setEntryDate(String entryDate) {
this.entryDate = entryDate;
return this;
}
/**
* 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 = 1730563422)
public void __setDaoSession(DaoSession daoSession) {
this.daoSession = daoSession;
myDao = daoSession != null ? daoSession.getExamDao() : null;
}
}

View File

@ -10,8 +10,6 @@ import org.greenrobot.greendao.annotation.Property;
import java.io.Serializable;
import io.github.wulkanowy.R;
@Entity(
nameInDb = "Grades",
active = true
@ -21,72 +19,44 @@ public class Grade implements Serializable {
@Id(autoincrement = true)
protected Long id;
@Property(nameInDb = "SUBJECT_ID")
@Property(nameInDb = "semester_id")
private Long semesterId;
@Property(nameInDb = "subject_id")
private Long subjectId;
@Property(nameInDb = "USER_ID")
private Long userId;
@Property(nameInDb = "SUBJECT")
@Property(nameInDb = "subject")
private String subject = "";
@Property(nameInDb = "VALUE")
@Property(nameInDb = "value")
protected String value = "";
@Property(nameInDb = "COLOR")
private String color = "";
@Property(nameInDb = "SYMBOL")
private String symbol = "";
@Property(nameInDb = "DESCRIPTION")
private String description = "";
@Property(nameInDb = "WEIGHT")
@Property(nameInDb = "weight")
private String weight = "";
@Property(nameInDb = "DATE")
@Property(nameInDb = "date")
private String date = "";
@Property(nameInDb = "TEACHER")
@Property(nameInDb = "symbol")
private String symbol = "";
@Property(nameInDb = "color")
private String color = "";
@Property(nameInDb = "description")
private String description = "";
@Property(nameInDb = "teacher")
private String teacher = "";
@Property(nameInDb = "SEMESTER")
private String semester = "";
@Property(nameInDb = "IS_NEW")
@Property(nameInDb = "is_new")
private boolean isNew = false;
@Property(nameInDb = "READ")
@Property(nameInDb = "read")
private boolean read = true;
private static final long serialVersionUID = 42L;
@Generated(hash = 568899968)
public Grade(Long id, Long subjectId, Long userId, String subject, String value,
String color, String symbol, String description, String weight,
String date, String teacher, String semester, boolean isNew,
boolean read) {
this.id = id;
this.subjectId = subjectId;
this.userId = userId;
this.subject = subject;
this.value = value;
this.color = color;
this.symbol = symbol;
this.description = description;
this.weight = weight;
this.date = date;
this.teacher = teacher;
this.semester = semester;
this.isNew = isNew;
this.read = read;
}
@Generated(hash = 2042976393)
public Grade() {
}
/**
* Used to resolve relations
*/
@ -99,29 +69,27 @@ public class Grade implements Serializable {
@Generated(hash = 681281562)
private transient GradeDao myDao;
public int getValueColor() {
@Generated(hash = 2042976393)
public Grade() {
}
String replacedString = value.replaceAll("[^0-9]", "");
if (!"".equals(replacedString)) {
switch (Integer.parseInt(replacedString)) {
case 6:
return R.color.six_grade;
case 5:
return R.color.five_grade;
case 4:
return R.color.four_grade;
case 3:
return R.color.three_grade;
case 2:
return R.color.two_grade;
case 1:
return R.color.one_grade;
default:
return R.color.default_grade;
}
}
return R.color.default_grade;
@Generated(hash = 619853992)
public Grade(Long id, Long semesterId, Long subjectId, String subject, String value,
String weight, String date, String symbol, String color, String description,
String teacher, boolean isNew, boolean read) {
this.id = id;
this.semesterId = semesterId;
this.subjectId = subjectId;
this.subject = subject;
this.value = value;
this.weight = weight;
this.date = date;
this.symbol = symbol;
this.color = color;
this.description = description;
this.teacher = teacher;
this.isNew = isNew;
this.read = read;
}
@Override
@ -133,6 +101,7 @@ public class Grade implements Serializable {
Grade grade = (Grade) o;
return new EqualsBuilder()
.append(semesterId, grade.semesterId)
.append(subject, grade.subject)
.append(value, grade.value)
.append(color, grade.color)
@ -141,13 +110,13 @@ public class Grade implements Serializable {
.append(weight, grade.weight)
.append(date, grade.date)
.append(teacher, grade.teacher)
.append(semester, grade.semester)
.isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(semesterId)
.append(subject)
.append(value)
.append(color)
@ -156,48 +125,19 @@ public class Grade implements Serializable {
.append(weight)
.append(date)
.append(teacher)
.append(semester)
.toHashCode();
}
public Long getId() {
return id;
return this.id;
}
public Grade setId(Long id) {
public void setId(Long id) {
this.id = id;
return this;
}
public Long getSubjectId() {
return subjectId;
}
public Grade setSubjectId(Long subjectId) {
this.subjectId = subjectId;
return this;
}
public Long getUserId() {
return userId;
}
public Grade setUserId(Long userId) {
this.userId = userId;
return this;
}
public String getSubject() {
return subject;
}
public Grade setSubject(String subject) {
this.subject = subject;
return this;
}
public String getValue() {
return value;
return this.value;
}
public Grade setValue(String value) {
@ -205,8 +145,26 @@ public class Grade implements Serializable {
return this;
}
public Long getSemesterId() {
return this.semesterId;
}
public Grade setSemesterId(Long semesterId) {
this.semesterId = semesterId;
return this;
}
public String getSubject() {
return this.subject;
}
public Grade setSubject(String subject) {
this.subject = subject;
return this;
}
public String getColor() {
return color;
return this.color;
}
public Grade setColor(String color) {
@ -215,7 +173,7 @@ public class Grade implements Serializable {
}
public String getSymbol() {
return symbol;
return this.symbol;
}
public Grade setSymbol(String symbol) {
@ -224,7 +182,7 @@ public class Grade implements Serializable {
}
public String getDescription() {
return description;
return this.description;
}
public Grade setDescription(String description) {
@ -233,7 +191,7 @@ public class Grade implements Serializable {
}
public String getWeight() {
return weight;
return this.weight;
}
public Grade setWeight(String weight) {
@ -242,7 +200,7 @@ public class Grade implements Serializable {
}
public String getDate() {
return date;
return this.date;
}
public Grade setDate(String date) {
@ -251,7 +209,7 @@ public class Grade implements Serializable {
}
public String getTeacher() {
return teacher;
return this.teacher;
}
public Grade setTeacher(String teacher) {
@ -259,22 +217,12 @@ public class Grade implements Serializable {
return this;
}
public String getSemester() {
return semester;
}
public Grade setSemester(String semester) {
this.semester = semester;
return this;
}
public boolean getIsNew() {
return this.isNew;
}
public Grade setIsNew(boolean isNew) {
public void setIsNew(boolean isNew) {
this.isNew = isNew;
return this;
}
public boolean getRead() {
@ -286,6 +234,17 @@ public class Grade implements Serializable {
return this;
}
public Long getSubjectId() {
return this.subjectId;
}
public void setSubjectId(Long subjectId) {
this.subjectId = subjectId;
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
* Entity must attached to an entity context.
@ -298,6 +257,7 @@ public class Grade implements Serializable {
myDao.delete(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}.
* Entity must attached to an entity context.
@ -310,6 +270,7 @@ public class Grade implements Serializable {
myDao.refresh(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}.
* Entity must attached to an entity context.
@ -322,6 +283,7 @@ public class Grade implements Serializable {
myDao.update(this);
}
/** called by internal mechanisms, do not call yourself. */
@Generated(hash = 1187286414)
public void __setDaoSession(DaoSession daoSession) {

View File

@ -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<Student> 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<Student> 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<Student> 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;
}
}

View File

@ -0,0 +1,208 @@
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 = "Semesters",
active = true
)
public class Semester {
@Id(autoincrement = true)
private Long id;
@Property(nameInDb = "diary_id")
private Long diaryId;
@Property(nameInDb = "current")
private boolean current;
@Property(nameInDb = "name")
private String name;
@Property(nameInDb = "value")
private String value;
@ToMany(referencedJoinProperty = "semesterId")
private List<Subject> subjectList;
@ToMany(referencedJoinProperty = "semesterId")
private List<Grade> gradeList;
/**
* Used to resolve relations
*/
@Generated(hash = 2040040024)
private transient DaoSession daoSession;
/**
* Used for active entity operations.
*/
@Generated(hash = 282930393)
private transient SemesterDao myDao;
@Generated(hash = 1661077309)
public Semester(Long id, Long diaryId, boolean current, String name, String value) {
this.id = id;
this.diaryId = diaryId;
this.current = current;
this.name = name;
this.value = value;
}
@Generated(hash = 58335877)
public Semester() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public Long getDiaryId() {
return this.diaryId;
}
public Semester setDiaryId(Long diaryId) {
this.diaryId = diaryId;
return this;
}
public String getName() {
return this.name;
}
public Semester setName(String name) {
this.name = name;
return this;
}
public String getValue() {
return this.value;
}
public Semester setValue(String value) {
this.value = value;
return this;
}
public boolean getCurrent() {
return this.current;
}
public Semester setCurrent(boolean current) {
this.current = current;
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 = 723353662)
public List<Subject> getSubjectList() {
if (subjectList == null) {
final DaoSession daoSession = this.daoSession;
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
SubjectDao targetDao = daoSession.getSubjectDao();
List<Subject> subjectListNew = targetDao._querySemester_SubjectList(id);
synchronized (this) {
if (subjectList == null) {
subjectList = subjectListNew;
}
}
}
return subjectList;
}
/**
* Resets a to-many relationship, making the next get call to query for a fresh result.
*/
@Generated(hash = 594294258)
public synchronized void resetSubjectList() {
subjectList = 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);
}
/**
* 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 = 390330007)
public List<Grade> getGradeList() {
if (gradeList == null) {
final DaoSession daoSession = this.daoSession;
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
GradeDao targetDao = daoSession.getGradeDao();
List<Grade> gradeListNew = targetDao._querySemester_GradeList(id);
synchronized (this) {
if (gradeList == null) {
gradeList = gradeListNew;
}
}
}
return gradeList;
}
/** Resets a to-many relationship, making the next get call to query for a fresh result. */
@Generated(hash = 1939990047)
public synchronized void resetGradeList() {
gradeList = null;
}
/** called by internal mechanisms, do not call yourself. */
@Generated(hash = 676204164)
public void __setDaoSession(DaoSession daoSession) {
this.daoSession = daoSession;
myDao = daoSession != null ? daoSession.getSemesterDao() : null;
}
}

View File

@ -0,0 +1,178 @@
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 = "Students",
active = true
)
public class Student {
@Id(autoincrement = true)
private Long id;
@Property(nameInDb = "school_id")
private Long schoolId;
@Property(nameInDb = "current")
private boolean current;
@Property(nameInDb = "real_id")
private String realId;
@Property(nameInDb = "name")
private String name;
@ToMany(referencedJoinProperty = "studentId")
private List<Diary> diaryList;
/**
* Used to resolve relations
*/
@Generated(hash = 2040040024)
private transient DaoSession daoSession;
/**
* Used for active entity operations.
*/
@Generated(hash = 1943931642)
private transient StudentDao myDao;
@Generated(hash = 470181623)
public Student(Long id, Long schoolId, boolean current, String realId, String name) {
this.id = id;
this.schoolId = schoolId;
this.current = current;
this.realId = realId;
this.name = name;
}
@Generated(hash = 1556870573)
public Student() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public Long getSchoolId() {
return this.schoolId;
}
public Student setSchoolId(Long schoolId) {
this.schoolId = schoolId;
return this;
}
public String getRealId() {
return this.realId;
}
public Student setRealId(String realId) {
this.realId = realId;
return this;
}
public String getName() {
return this.name;
}
public Student setName(String name) {
this.name = name;
return this;
}
public boolean getCurrent() {
return this.current;
}
public Student setCurrent(boolean current) {
this.current = current;
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 = 508305571)
public List<Diary> getDiaryList() {
if (diaryList == null) {
final DaoSession daoSession = this.daoSession;
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
DiaryDao targetDao = daoSession.getDiaryDao();
List<Diary> diaryListNew = targetDao._queryStudent_DiaryList(id);
synchronized (this) {
if (diaryList == null) {
diaryList = diaryListNew;
}
}
}
return diaryList;
}
/**
* Resets a to-many relationship, making the next get call to query for a fresh result.
*/
@Generated(hash = 1078514341)
public synchronized void resetDiaryList() {
diaryList = 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 = 1701634981)
public void __setDaoSession(DaoSession daoSession) {
this.daoSession = daoSession;
myDao = daoSession != null ? daoSession.getStudentDao() : null;
}
}

View File

@ -18,21 +18,18 @@ public class Subject {
@Id(autoincrement = true)
private Long id;
@Property(nameInDb = "USER_ID")
private Long userId;
@Property(nameInDb = "semester_id")
private Long semesterId;
@Property(nameInDb = "NAME")
@Property(nameInDb = "name")
private String name;
@Property(nameInDb = "PREDICTED_RATING")
@Property(nameInDb = "predicted_rating")
private String predictedRating;
@Property(nameInDb = "FINAL_RATING")
@Property(nameInDb = "final_rating")
private String finalRating;
@Property(nameInDb = "SEMESTER")
private String semester;
@ToMany(referencedJoinProperty = "subjectId")
private List<Grade> gradeList;
@ -48,15 +45,14 @@ public class Subject {
@Generated(hash = 1644932788)
private transient SubjectDao myDao;
@Generated(hash = 396325764)
public Subject(Long id, Long userId, String name, String predictedRating,
String finalRating, String semester) {
@Generated(hash = 1817932538)
public Subject(Long id, Long semesterId, String name, String predictedRating,
String finalRating) {
this.id = id;
this.userId = userId;
this.semesterId = semesterId;
this.name = name;
this.predictedRating = predictedRating;
this.finalRating = finalRating;
this.semester = semester;
}
@Generated(hash = 1617906264)
@ -64,25 +60,24 @@ public class Subject {
}
public Long getId() {
return id;
return this.id;
}
public Subject setId(Long id) {
public void setId(Long id) {
this.id = id;
return this;
}
public Long getUserId() {
return userId;
public Long getSemesterId() {
return this.semesterId;
}
public Subject setUserId(Long userId) {
this.userId = userId;
public Subject setSemesterId(Long semesterId) {
this.semesterId = semesterId;
return this;
}
public String getName() {
return name;
return this.name;
}
public Subject setName(String name) {
@ -91,7 +86,7 @@ public class Subject {
}
public String getPredictedRating() {
return predictedRating;
return this.predictedRating;
}
public Subject setPredictedRating(String predictedRating) {
@ -100,7 +95,7 @@ public class Subject {
}
public String getFinalRating() {
return finalRating;
return this.finalRating;
}
public Subject setFinalRating(String finalRating) {
@ -108,45 +103,6 @@ public class Subject {
return this;
}
public String getSemester() {
return semester;
}
public Subject setSemester(String semester) {
this.semester = semester;
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 = 1358847893)
public List<Grade> getGradeList() {
if (gradeList == null) {
final DaoSession daoSession = this.daoSession;
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
GradeDao targetDao = daoSession.getGradeDao();
List<Grade> gradeListNew = targetDao._querySubject_GradeList(id);
synchronized (this) {
if (gradeList == null) {
gradeList = gradeListNew;
}
}
}
return gradeList;
}
/**
* Resets a to-many relationship, making the next get call to query for a fresh result.
*/
@Generated(hash = 1939990047)
public synchronized void resetGradeList() {
gradeList = null;
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
* Entity must attached to an entity context.
@ -183,6 +139,34 @@ public class Subject {
myDao.update(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 = 1358847893)
public List<Grade> getGradeList() {
if (gradeList == null) {
final DaoSession daoSession = this.daoSession;
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
GradeDao targetDao = daoSession.getGradeDao();
List<Grade> gradeListNew = targetDao._querySubject_GradeList(id);
synchronized (this) {
if (gradeList == null) {
gradeList = gradeListNew;
}
}
}
return gradeList;
}
/** Resets a to-many relationship, making the next get call to query for a fresh result. */
@Generated(hash = 1939990047)
public synchronized void resetGradeList() {
gradeList = null;
}
/** called by internal mechanisms, do not call yourself. */
@Generated(hash = 937984622)
public void __setDaoSession(DaoSession daoSession) {

View File

@ -0,0 +1,175 @@
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 = "Symbols",
active = true
)
public class Symbol {
@Id(autoincrement = true)
private Long id;
@Property(nameInDb = "user_id")
private Long userId;
@Property(nameInDb = "host")
private String host;
@Property(nameInDb = "symbol")
private String symbol;
@Property(nameInDb = "type")
private String type;
@ToMany(referencedJoinProperty = "symbolId")
private List<School> schoolList;
/**
* Used to resolve relations
*/
@Generated(hash = 2040040024)
private transient DaoSession daoSession;
/**
* Used for active entity operations.
*/
@Generated(hash = 684907977)
private transient SymbolDao myDao;
@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.symbol = symbol;
this.type = type;
}
@Generated(hash = 460475327)
public Symbol() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public Long getUserId() {
return this.userId;
}
public Symbol setUserId(Long userId) {
this.userId = userId;
return this;
}
public String getHost() {
return this.host;
}
public Symbol setHost(String host) {
this.host = host;
return this;
}
public String getSymbol() {
return this.symbol;
}
public Symbol setSymbol(String symbol) {
this.symbol = symbol;
return this;
}
public String getType() {
return this.type;
}
public Symbol setType(String type) {
this.type = type;
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 = 1733082867)
public List<School> getSchoolList() {
if (schoolList == null) {
final DaoSession daoSession = this.daoSession;
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
SchoolDao targetDao = daoSession.getSchoolDao();
List<School> schoolListNew = targetDao._querySymbol_SchoolList(id);
synchronized (this) {
if (schoolList == null) {
schoolList = schoolListNew;
}
}
}
return schoolList;
}
/** 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;
}
/**
* 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 = 632145708)
public void __setDaoSession(DaoSession daoSession) {
this.daoSession = daoSession;
myDao = daoSession != null ? daoSession.getSymbolDao() : null;
}
}

Some files were not shown because too many files have changed in this diff Show More