Browse Source

MatchView

master
GAM 4 years ago
parent
commit
2179dd1a23
31 changed files with 623 additions and 212 deletions
  1. +85
    -85
      db/db_init.sql
  2. +8
    -0
      frontend/app/views/main/main-view.css
  3. +62
    -0
      frontend/app/views/match/match-view.css
  4. +0
    -6
      pom.xml
  5. +8
    -8
      src/main/java/app/data/entity/GameInfo.java
  6. +0
    -5
      src/main/java/app/data/entity/Match.java
  7. +0
    -5
      src/main/java/app/data/entity/Matchday.java
  8. +0
    -4
      src/main/java/app/data/entity/Player.java
  9. +0
    -8
      src/main/java/app/data/entity/Season.java
  10. +3
    -2
      src/main/java/app/data/service/ChessComService.java
  11. +5
    -1
      src/main/java/app/data/service/MatchService.java
  12. +3
    -5
      src/main/java/app/gameimage/GameImageService.java
  13. +6
    -4
      src/main/java/app/gameimage/GameImageUtils.java
  14. +20
    -39
      src/main/java/app/navigation/Navigation.java
  15. +1
    -1
      src/main/java/app/navigation/NavigationLevel.java
  16. +1
    -1
      src/main/java/app/navigation/NavigationService.java
  17. +23
    -10
      src/main/java/app/navigation/NavigationUtils.java
  18. +0
    -7
      src/main/java/app/navigation/UrlParameterType.java
  19. +10
    -1
      src/main/java/app/utils/ChessComUtils.java
  20. +17
    -0
      src/main/java/app/utils/EntityComponentUtils.java
  21. +48
    -0
      src/main/java/app/utils/EntityStringUtils.java
  22. +7
    -7
      src/main/java/app/utils/StringUtils.java
  23. +8
    -2
      src/main/java/app/views/match/MatchView.java
  24. +64
    -0
      src/main/java/app/views/match/components/GameComponent.java
  25. +82
    -0
      src/main/java/app/views/match/components/MatchComponent.java
  26. +151
    -0
      src/main/java/app/views/match/components/utils/GameComponentUtils.java
  27. +2
    -2
      src/main/java/app/views/matchday/MatchdayView.java
  28. +4
    -4
      src/main/java/app/views/matchday/components/MatchdayComponent.java
  29. +2
    -2
      src/main/java/app/views/navigation/NavigationViewBase.java
  30. +2
    -2
      src/main/java/app/views/table/TableView.java
  31. +1
    -1
      src/main/java/app/views/table/components/TableComponent.java

+ 85
- 85
db/db_init.sql View File

@ -42,7 +42,7 @@ CREATE TABLE "game" (
CREATE TABLE "game_info" ( CREATE TABLE "game_info" (
"id" SERIAL PRIMARY KEY, "id" SERIAL PRIMARY KEY,
"time_control" varchar, "time_control" varchar,
"url" varchar
"chess_com_id" varchar
); );
@ -357,137 +357,137 @@ INSERT INTO "match" ("player1", "player2", "matchday") VALUES ( 9, 5, 26);
INSERT INTO "match" ("player1", "player2", "matchday") VALUES ( 7, 13, 26); INSERT INTO "match" ("player1", "player2", "matchday") VALUES ( 7, 13, 26);
INSERT INTO "match" ("player1", "player2", "matchday") VALUES (14, 2, 26); INSERT INTO "match" ("player1", "player2", "matchday") VALUES (14, 2, 26);
INSERT INTO "game_info" (time_control, url)VALUES ('600', 'https://www.chess.com/game/live/8722014513');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=2 AND player2=9 AND matchday=1), TRUE, 1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8722014513'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('600', '8722014513');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=2 AND player2=9 AND matchday=1), TRUE, 1, (SELECT id from game_info WHERE chess_com_id='8722014513'));
INSERT INTO "game_info" (time_control, url)VALUES ('600', 'https://www.chess.com/game/live/8723231941');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=2 AND player2=9 AND matchday=1), FALSE, 1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8723231941'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('600', '8723231941');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=2 AND player2=9 AND matchday=1), FALSE, 1, (SELECT id from game_info WHERE chess_com_id='8723231941'));
INSERT INTO "game_info" (time_control, url)VALUES ('300', 'https://www.chess.com/game/live/8724907847');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=2 AND player2=9 AND matchday=1), TRUE, -1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8724907847'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('300', '8724907847');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=2 AND player2=9 AND matchday=1), TRUE, -1, (SELECT id from game_info WHERE chess_com_id='8724907847'));
INSERT INTO "game_info" (time_control, url)VALUES ('300', 'https://www.chess.com/game/live/8725036665');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=2 AND player2=9 AND matchday=1), FALSE, 1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8725036665'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('300', '8725036665');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=2 AND player2=9 AND matchday=1), FALSE, 1, (SELECT id from game_info WHERE chess_com_id='8725036665'));
INSERT INTO "game_info" (time_control, url)VALUES ('180', 'https://www.chess.com/game/live/8725614379');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=2 AND player2=9 AND matchday=1), TRUE, 1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8725614379'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('180', '8725614379');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=2 AND player2=9 AND matchday=1), TRUE, 1, (SELECT id from game_info WHERE chess_com_id='8725614379'));
INSERT INTO "game_info" (time_control, url)VALUES ('180', 'https://www.chess.com/game/live/8726184583');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=2 AND player2=9 AND matchday=1), FALSE, 1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8726184583'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('180', '8726184583');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=2 AND player2=9 AND matchday=1), FALSE, 1, (SELECT id from game_info WHERE chess_com_id='8726184583'));
INSERT INTO "game_info" (time_control, url)VALUES ('600', 'https://www.chess.com/game/live/8616485043');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=14 AND player2=7 AND matchday=1), TRUE, 1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8616485043'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('600', '8616485043');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=14 AND player2=7 AND matchday=1), TRUE, 1, (SELECT id from game_info WHERE chess_com_id='8616485043'));
INSERT INTO "game_info" (time_control, url)VALUES ('600', 'https://www.chess.com/game/live/8618149677');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=14 AND player2=7 AND matchday=1), FALSE, -1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8618149677'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('600', '8618149677');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=14 AND player2=7 AND matchday=1), FALSE, -1, (SELECT id from game_info WHERE chess_com_id='8618149677'));
INSERT INTO "game_info" (time_control, url)VALUES ('300', 'https://www.chess.com/game/live/8702757001');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=14 AND player2=7 AND matchday=1), FALSE, -1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8702757001'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('300', '8702757001');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=14 AND player2=7 AND matchday=1), FALSE, -1, (SELECT id from game_info WHERE chess_com_id='8702757001'));
INSERT INTO "game_info" (time_control, url)VALUES ('300', 'https://www.chess.com/game/live/8705204521');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=14 AND player2=7 AND matchday=1), TRUE, 1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8705204521'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('300', '8705204521');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=14 AND player2=7 AND matchday=1), TRUE, 1, (SELECT id from game_info WHERE chess_com_id='8705204521'));
INSERT INTO "game_info" (time_control, url)VALUES ('180', 'https://www.chess.com/game/live/8705796221');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=14 AND player2=7 AND matchday=1), FALSE, -1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8705796221'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('180', '8705796221');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=14 AND player2=7 AND matchday=1), FALSE, -1, (SELECT id from game_info WHERE chess_com_id='8705796221'));
INSERT INTO "game_info" (time_control, url)VALUES ('180', 'https://www.chess.com/game/live/8706438057');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=14 AND player2=7 AND matchday=1), TRUE, 1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8706438057'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('180', '8706438057');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=14 AND player2=7 AND matchday=1), TRUE, 1, (SELECT id from game_info WHERE chess_com_id='8706438057'));
INSERT INTO "game_info" (time_control, url)VALUES ('600', 'https://www.chess.com/game/live/8617630129');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=10 AND player2=4 AND matchday=1), TRUE, 1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8617630129'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('600', '8617630129');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=10 AND player2=4 AND matchday=1), TRUE, 1, (SELECT id from game_info WHERE chess_com_id='8617630129'));
INSERT INTO "game_info" (time_control, url)VALUES ('600', 'https://www.chess.com/game/live/8618225533');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=10 AND player2=4 AND matchday=1), FALSE, 1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8618225533'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('600', '8618225533');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=10 AND player2=4 AND matchday=1), FALSE, 1, (SELECT id from game_info WHERE chess_com_id='8618225533'));
INSERT INTO "game_info" (time_control, url)VALUES ('300', 'https://www.chess.com/game/live/8619306585');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=10 AND player2=4 AND matchday=1), TRUE, -1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8619306585'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('300', '8619306585');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=10 AND player2=4 AND matchday=1), TRUE, -1, (SELECT id from game_info WHERE chess_com_id='8619306585'));
INSERT INTO "game_info" (time_control, url)VALUES ('300', 'https://www.chess.com/game/live/8619471075');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=10 AND player2=4 AND matchday=1), FALSE, 1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8619471075'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('300', '8619471075');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=10 AND player2=4 AND matchday=1), FALSE, 1, (SELECT id from game_info WHERE chess_com_id='8619471075'));
INSERT INTO "game_info" (time_control, url)VALUES ('180', 'https://www.chess.com/game/live/8620078695');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=10 AND player2=4 AND matchday=1), TRUE, -1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8620078695'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('180', '8620078695');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=10 AND player2=4 AND matchday=1), TRUE, -1, (SELECT id from game_info WHERE chess_com_id='8620078695'));
INSERT INTO "game_info" (time_control, url)VALUES ('180', 'https://www.chess.com/game/live/8620568591');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=10 AND player2=4 AND matchday=1), FALSE, 1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8620568591'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('180', '8620568591');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=10 AND player2=4 AND matchday=1), FALSE, 1, (SELECT id from game_info WHERE chess_com_id='8620568591'));
INSERT INTO "game_info" (time_control, url)VALUES ('600', 'https://www.chess.com/game/live/8504667551');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=13 AND player2=6 AND matchday=1), TRUE, 0, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8504667551'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('600', '8504667551');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=13 AND player2=6 AND matchday=1), TRUE, 0, (SELECT id from game_info WHERE chess_com_id='8504667551'));
INSERT INTO "game_info" (time_control, url)VALUES ('600', 'https://www.chess.com/game/live/8505882389');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=13 AND player2=6 AND matchday=1), FALSE, -1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8505882389'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('600', '8505882389');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=13 AND player2=6 AND matchday=1), FALSE, -1, (SELECT id from game_info WHERE chess_com_id='8505882389'));
INSERT INTO "game_info" (time_control, url)VALUES ('300', 'https://www.chess.com/game/live/8507004247');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=13 AND player2=6 AND matchday=1), TRUE, -1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8507004247'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('300', '8507004247');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=13 AND player2=6 AND matchday=1), TRUE, -1, (SELECT id from game_info WHERE chess_com_id='8507004247'));
INSERT INTO "game_info" (time_control, url)VALUES ('300', 'https://www.chess.com/game/live/8507617133');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=13 AND player2=6 AND matchday=1), FALSE, -1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8507617133'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('300', '8507617133');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=13 AND player2=6 AND matchday=1), FALSE, -1, (SELECT id from game_info WHERE chess_com_id='8507617133'));
INSERT INTO "game_info" (time_control, url)VALUES ('180', 'https://www.chess.com/game/live/8508203475');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=13 AND player2=6 AND matchday=1), TRUE, 1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8508203475'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('180', '8508203475');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=13 AND player2=6 AND matchday=1), TRUE, 1, (SELECT id from game_info WHERE chess_com_id='8508203475'));
INSERT INTO "game_info" (time_control, url)VALUES ('180', 'https://www.chess.com/game/live/8508297031');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=13 AND player2=6 AND matchday=1), FALSE, -1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8508297031'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('180', '8508297031');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=13 AND player2=6 AND matchday=1), FALSE, -1, (SELECT id from game_info WHERE chess_com_id='8508297031'));
INSERT INTO "game_info" (time_control, url)VALUES ('600', 'https://www.chess.com/game/live/8624735639');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=11 AND player2=8 AND matchday=1), FALSE, 1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8624735639'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('600', '8624735639');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=11 AND player2=8 AND matchday=1), FALSE, 1, (SELECT id from game_info WHERE chess_com_id='8624735639'));
INSERT INTO "game_info" (time_control, url)VALUES ('600', 'https://www.chess.com/game/live/8625353555');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=11 AND player2=8 AND matchday=1), TRUE, -1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8625353555'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('600', '8625353555');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=11 AND player2=8 AND matchday=1), TRUE, -1, (SELECT id from game_info WHERE chess_com_id='8625353555'));
INSERT INTO "game_info" (time_control, url)VALUES ('300', 'https://www.chess.com/game/live/8625963087');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=11 AND player2=8 AND matchday=1), FALSE, 1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8625963087'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('300', '8625963087');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=11 AND player2=8 AND matchday=1), FALSE, 1, (SELECT id from game_info WHERE chess_com_id='8625963087'));
INSERT INTO "game_info" (time_control, url)VALUES ('300', 'https://www.chess.com/game/live/8853361491');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=11 AND player2=8 AND matchday=1), TRUE, -1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8853361491'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('300', '8853361491');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=11 AND player2=8 AND matchday=1), TRUE, -1, (SELECT id from game_info WHERE chess_com_id='8853361491'));
INSERT INTO "game_info" (time_control, url)VALUES ('180', 'https://www.chess.com/game/live/8853455035');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=11 AND player2=8 AND matchday=1), FALSE, 1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8853455035'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('180', '8853455035');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=11 AND player2=8 AND matchday=1), FALSE, 1, (SELECT id from game_info WHERE chess_com_id='8853455035'));
INSERT INTO "game_info" (time_control, url)VALUES ('180', 'https://www.chess.com/game/live/8854002505');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=11 AND player2=8 AND matchday=1), TRUE, -1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8854002505'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('180', '8854002505');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=11 AND player2=8 AND matchday=1), TRUE, -1, (SELECT id from game_info WHERE chess_com_id='8854002505'));
INSERT INTO "game_info" (time_control, url)VALUES ('600', 'https://www.chess.com/game/live/8858219835');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=12 AND player2=1 AND matchday=1), FALSE, -1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8858219835'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('600', '8858219835');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=12 AND player2=1 AND matchday=1), FALSE, -1, (SELECT id from game_info WHERE chess_com_id='8858219835'));
INSERT INTO "game_info" (time_control, url)VALUES ('600', 'https://www.chess.com/game/live/8859375675');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=12 AND player2=1 AND matchday=1), TRUE, 1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8859375675'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('600', '8859375675');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=12 AND player2=1 AND matchday=1), TRUE, 1, (SELECT id from game_info WHERE chess_com_id='8859375675'));
INSERT INTO "game_info" (time_control, url)VALUES ('300', 'https://www.chess.com/game/live/8859976305');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=12 AND player2=1 AND matchday=1), FALSE, 1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8859976305'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('300', '8859976305');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=12 AND player2=1 AND matchday=1), FALSE, 1, (SELECT id from game_info WHERE chess_com_id='8859976305'));
INSERT INTO "game_info" (time_control, url)VALUES ('300', 'https://www.chess.com/game/live/8860591347');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=12 AND player2=1 AND matchday=1), TRUE, 1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8860591347'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('300', '8860591347');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=12 AND player2=1 AND matchday=1), TRUE, 1, (SELECT id from game_info WHERE chess_com_id='8860591347'));
INSERT INTO "game_info" (time_control, url)VALUES ('180', 'https://www.chess.com/game/live/8860675419');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=12 AND player2=1 AND matchday=1), FALSE, -1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8860675419'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('180', '8860675419');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=12 AND player2=1 AND matchday=1), FALSE, -1, (SELECT id from game_info WHERE chess_com_id='8860675419'));
INSERT INTO "game_info" (time_control, url)VALUES ('180', 'https://www.chess.com/game/live/8861228997');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=12 AND player2=1 AND matchday=1), TRUE, 1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8861228997'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('180', '8861228997');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=12 AND player2=1 AND matchday=1), TRUE, 1, (SELECT id from game_info WHERE chess_com_id='8861228997'));
INSERT INTO "game_info" (time_control, url)VALUES ('600', 'https://www.chess.com/game/live/8877523129');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=5 AND player2=3 AND matchday=1), FALSE, 1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8877523129'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('600', '8877523129');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=5 AND player2=3 AND matchday=1), FALSE, 1, (SELECT id from game_info WHERE chess_com_id='8877523129'));
INSERT INTO "game_info" (time_control, url)VALUES ('600', 'https://www.chess.com/game/live/8878652939');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=5 AND player2=3 AND matchday=1), TRUE, 1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8878652939'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('600', '8878652939');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=5 AND player2=3 AND matchday=1), TRUE, 1, (SELECT id from game_info WHERE chess_com_id='8878652939'));
INSERT INTO "game_info" (time_control, url)VALUES ('300', 'https://www.chess.com/game/live/8879853665');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=5 AND player2=3 AND matchday=1), FALSE, 1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8879853665'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('300', '8879853665');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=5 AND player2=3 AND matchday=1), FALSE, 1, (SELECT id from game_info WHERE chess_com_id='8879853665'));
INSERT INTO "game_info" (time_control, url)VALUES ('300', 'https://www.chess.com/game/live/8880469509');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=5 AND player2=3 AND matchday=1), TRUE, 1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8880469509'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('300', '8880469509');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=5 AND player2=3 AND matchday=1), TRUE, 1, (SELECT id from game_info WHERE chess_com_id='8880469509'));
INSERT INTO "game_info" (time_control, url)VALUES ('180', 'https://www.chess.com/game/live/8881562307');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=5 AND player2=3 AND matchday=1), FALSE, -1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8881562307'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('180', '8881562307');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=5 AND player2=3 AND matchday=1), FALSE, -1, (SELECT id from game_info WHERE chess_com_id='8881562307'));
INSERT INTO "game_info" (time_control, url)VALUES ('180', 'https://www.chess.com/game/live/8881610243');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=5 AND player2=3 AND matchday=1), TRUE, -1, (SELECT id from game_info WHERE url='https://www.chess.com/game/live/8881610243'));
INSERT INTO "game_info" (time_control, chess_com_id) VALUES ('180', '8881610243');
INSERT INTO "game" (match, player1_is_white, result, info) VALUES ((SELECT id from match WHERE player1=5 AND player2=3 AND matchday=1), TRUE, -1, (SELECT id from game_info WHERE chess_com_id='8881610243'));


+ 8
- 0
frontend/app/views/main/main-view.css View File

@ -22,6 +22,14 @@
padding: var(--lumo-space-m); padding: var(--lumo-space-m);
} }
.bold-label {
font-weight: bold;
}
.nickname-label {
margin-left: var(--lumo-space-xs);
}
/*//////////////////*/ /*//////////////////*/
/* APP-LAYOUT-STUFF */ /* APP-LAYOUT-STUFF */
/*//////////////////*/ /*//////////////////*/


+ 62
- 0
frontend/app/views/match/match-view.css View File

@ -0,0 +1,62 @@
.match-view .match-header-players {
width: 100%;
font-size: x-large;
justify-content: center;
}
.match-view .match-header-result {
width: 100%;
font-weight: bolder;
font-size: x-large;
text-align: center;
}
.match-view .game-card {
margin-top: var(--lumo-space-m);
margin-left: var(--lumo-space-m);
}
.match-view .player {
border-radius: var(--lumo-border-radius);
padding: var(--lumo-space-xs) 0;
width: 100%;
text-align: center;
align-content: center;
}
.match-view .black-player {
background-color: var(--lumo-shade);
}
.match-view .vs-label {
margin-top: 0;
}
.match-view .white-player {
margin-top: var(--lumo-space-xs);
margin-bottom: var(--lumo-space-m);
background-color: var(--lumo-tint);
color: var(--lumo-shade);
}
.match-view .game-info-div {
padding-top: 0;
padding-bottom: 0;
}
.match-view .game-image-div {
min-width: 300px;
max-width: 300px;
min-height: 300px;
max-height: 300px;
}
.match-view .game-header {
font-weight: bolder;
font-size: large;
margin-bottom: var(--lumo-space-s);
}
.match-view .time-control {
margin-bottom: var(--lumo-space-s);
}

+ 0
- 6
pom.xml View File

@ -126,12 +126,6 @@
<version>3.0.0</version> <version>3.0.0</version>
</dependency> </dependency>
<!-- <dependency>-->
<!-- <groupId>com.google.code.gson</groupId>-->
<!-- <artifactId>gson</artifactId>-->
<!-- <version>2.3.1</version>-->
<!-- </dependency>-->
<dependency> <dependency>
<groupId>com.h2database</groupId> <groupId>com.h2database</groupId>
<artifactId>h2</artifactId> <artifactId>h2</artifactId>


+ 8
- 8
src/main/java/app/data/entity/GameInfo.java View File

@ -7,7 +7,7 @@ import java.util.Objects;
@Table(name = "game_info", schema = "public", catalog = "chessleague") @Table(name = "game_info", schema = "public", catalog = "chessleague")
public class GameInfo { public class GameInfo {
private Integer id; private Integer id;
private String url;
private String chessComId;
private Game game; private Game game;
private String timeControl; private String timeControl;
@ -23,13 +23,13 @@ public class GameInfo {
} }
@Basic @Basic
@Column(name = "url", length = -1)
public String getUrl() {
return url;
@Column(name = "chess_com_id", length = -1)
public String getChessComId() {
return chessComId;
} }
public void setUrl(String url) {
this.url = url;
public void setChessComId(String chessComId) {
this.chessComId = chessComId;
} }
@Basic @Basic
@ -47,12 +47,12 @@ public class GameInfo {
if (this == o) return true; if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false; if (o == null || getClass() != o.getClass()) return false;
GameInfo that = (GameInfo) o; GameInfo that = (GameInfo) o;
return Objects.equals(id, that.id) && Objects.equals(url, that.url) && Objects.equals(timeControl, that.timeControl);
return Objects.equals(id, that.id) && Objects.equals(chessComId, that.chessComId) && Objects.equals(timeControl, that.timeControl);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(id, url, timeControl);
return Objects.hash(id, chessComId, timeControl);
} }
@OneToOne(mappedBy = "gameInfo") @OneToOne(mappedBy = "gameInfo")


+ 0
- 5
src/main/java/app/data/entity/Match.java View File

@ -75,9 +75,4 @@ public class Match {
public void setMatchday(Matchday matchday) { public void setMatchday(Matchday matchday) {
this.matchday = matchday; this.matchday = matchday;
} }
@Override
public String toString() {
return String.format("%s-vs-%s", player1.getNickname().toLowerCase(), player2.getNickname().toLowerCase());
}
} }

+ 0
- 5
src/main/java/app/data/entity/Matchday.java View File

@ -64,9 +64,4 @@ public class Matchday {
public void setSeason(Season season) { public void setSeason(Season season) {
this.season = season; this.season = season;
} }
@Override
public String toString() {
return number.toString();
}
} }

+ 0
- 4
src/main/java/app/data/entity/Player.java View File

@ -86,8 +86,4 @@ public class Player {
this.playerInfo = playerInfo; this.playerInfo = playerInfo;
} }
@Override
public String toString() {
return name + " (" + nickname + ")";
}
} }

+ 0
- 8
src/main/java/app/data/entity/Season.java View File

@ -65,12 +65,4 @@ public class Season {
this.matchdays = matchdays; this.matchdays = matchdays;
} }
@Override
public String toString() {
String s = yearStart.toString();
if (!yearEnd.equals(yearStart)) {
s += "-" + yearEnd.toString();
}
return s;
}
} }

+ 3
- 2
src/main/java/app/data/service/ChessComService.java View File

@ -85,7 +85,7 @@ public class ChessComService {
game.setResult(ChessComUtils.getResult(chessComGame)); game.setResult(ChessComUtils.getResult(chessComGame));
game.setGameInfo(gameInfo); game.setGameInfo(gameInfo);
gameInfo.setUrl(chessComGame.getUrl());
gameInfo.setChessComId(chessComGame.getUrl());
gameInfo.setTimeControl(chessComGame.getTimeControl()); gameInfo.setTimeControl(chessComGame.getTimeControl());
gameInfo.setGame(game); gameInfo.setGame(game);
@ -108,11 +108,12 @@ public class ChessComService {
} }
List<ChessComGame> chessComGames = chessComArchive.get().getGames(); List<ChessComGame> chessComGames = chessComArchive.get().getGames();
for (ChessComGame chessComGame : chessComGames) { for (ChessComGame chessComGame : chessComGames) {
if (chessComGame.getUrl().equals(game.getGameInfo().getUrl())) {
if (chessComGame.getUrl().equals(game.getGameInfo().getChessComId())) {
return Optional.of(chessComGame); return Optional.of(chessComGame);
} }
} }
} }
return Optional.empty(); return Optional.empty();
} }
} }

+ 5
- 1
src/main/java/app/data/service/MatchService.java View File

@ -43,10 +43,14 @@ public class MatchService extends CrudService<Match, Integer> {
public List<CalculatedMatch> getCalculatedMatches(Matchday matchday) { public List<CalculatedMatch> getCalculatedMatches(Matchday matchday) {
return getMatches(matchday).stream() return getMatches(matchday).stream()
.map(match -> new CalculatedMatch(match, match.getPlayer1(), match.getPlayer2(), getScore1(match), getScore2(match)))
.map(this::getCalculatedMatch)
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
public CalculatedMatch getCalculatedMatch(Match match) {
return new CalculatedMatch(match, match.getPlayer1(), match.getPlayer2(), getScore1(match), getScore2(match));
}
private static double getScore1(Match match) { private static double getScore1(Match match) {
double score = 0; double score = 0;
for (Game game : match.getGames()) { for (Game game : match.getGames()) {


src/main/java/app/gameimage/service/GameImageService.java → src/main/java/app/gameimage/GameImageService.java View File

@ -1,10 +1,8 @@
package app.gameimage.service;
package app.gameimage;
import app.data.chesscom.ChessComGame; import app.data.chesscom.ChessComGame;
import app.data.entity.Game; import app.data.entity.Game;
import app.data.service.ChessComService; import app.data.service.ChessComService;
import app.gameimage.GameImageGenerator;
import app.gameimage.GameImageUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -25,7 +23,7 @@ public class GameImageService {
} }
public Optional<String> getImagePath(Game game) { public Optional<String> getImagePath(Game game) {
String path = GameImageUtils.IMAGE_DEST_PATH + getGameNumber(game) + GameImageUtils.EXTENSION;
String path = GameImageUtils.IMAGE_DEST_PATH_SERVER + getGameNumber(game) + GameImageUtils.EXTENSION;
File f = new File(path); File f = new File(path);
if(f.isFile()) { if(f.isFile()) {
return Optional.of(path); return Optional.of(path);
@ -40,7 +38,7 @@ public class GameImageService {
} }
private String getGameNumber(Game game) { private String getGameNumber(Game game) {
String[] url = game.getGameInfo().getUrl().split("/");
String[] url = game.getGameInfo().getChessComId().split("/");
return url[url.length -1]; return url[url.length -1];
} }

+ 6
- 4
src/main/java/app/gameimage/GameImageUtils.java View File

@ -6,9 +6,11 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
public class GameImageUtils { public class GameImageUtils {
public static final String IMAGE_SOURCE_PATH = "src/main/resources/META-INF/resources/images/chess-sources/";
public static final String IMAGE_DEST_PATH = "src/main/resources/META-INF/resources/images/games/";
public static final String IMAGE_PATH_CLIENT = "images/games/";
public static final String EXTENSION = ".png"; public static final String EXTENSION = ".png";
static final String IMAGE_SOURCE_PATH_SERVER = "src/main/resources/META-INF/resources/images/chess-sources/";
static final String IMAGE_DEST_PATH_SERVER = "src/main/resources/META-INF/resources/images/games/";
private static final String EXTENSION_WITHOUT_DOT = "png"; private static final String EXTENSION_WITHOUT_DOT = "png";
private GameImageUtils() {} private GameImageUtils() {}
@ -16,7 +18,7 @@ public class GameImageUtils {
public static BufferedImage readImage(String fileNameWithoutExtension) { public static BufferedImage readImage(String fileNameWithoutExtension) {
BufferedImage img = null; BufferedImage img = null;
try { try {
String path = IMAGE_SOURCE_PATH + fileNameWithoutExtension + EXTENSION;
String path = IMAGE_SOURCE_PATH_SERVER + fileNameWithoutExtension + EXTENSION;
img = ImageIO.read(new File(path)); img = ImageIO.read(new File(path));
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
@ -26,7 +28,7 @@ public class GameImageUtils {
public static void writeImage(BufferedImage img, String fileNameWithoutExtension) { public static void writeImage(BufferedImage img, String fileNameWithoutExtension) {
try { try {
String path = IMAGE_DEST_PATH + fileNameWithoutExtension + EXTENSION;
String path = IMAGE_DEST_PATH_SERVER + fileNameWithoutExtension + EXTENSION;
File outputFile = new File(path); File outputFile = new File(path);
ImageIO.write(img, EXTENSION_WITHOUT_DOT, outputFile); ImageIO.write(img, EXTENSION_WITHOUT_DOT, outputFile);
} catch (IOException e) { } catch (IOException e) {


+ 20
- 39
src/main/java/app/navigation/Navigation.java View File

@ -7,11 +7,12 @@ import app.data.entity.Season;
import app.data.service.MatchService; import app.data.service.MatchService;
import app.data.service.MatchdayService; import app.data.service.MatchdayService;
import app.data.service.SeasonService; import app.data.service.SeasonService;
import app.navigation.service.NavigationLevel;
import com.vaadin.flow.component.AbstractField;
import com.vaadin.flow.component.HasValue;
import com.vaadin.flow.component.UI;
import app.utils.EntityStringUtils;
import com.vaadin.flow.component.*;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.select.Select; import com.vaadin.flow.component.select.Select;
import com.vaadin.flow.data.renderer.ComponentRenderer;
import com.vaadin.flow.function.SerializableFunction;
import com.vaadin.flow.router.BeforeEvent; import com.vaadin.flow.router.BeforeEvent;
import com.vaadin.flow.router.HasUrlParameter; import com.vaadin.flow.router.HasUrlParameter;
import com.vaadin.flow.router.WildcardParameter; import com.vaadin.flow.router.WildcardParameter;
@ -59,6 +60,10 @@ public class Navigation implements HasUrlParameter<String> {
seasonSelect.addValueChangeListener(seasonSelectValueChangeListener()); seasonSelect.addValueChangeListener(seasonSelectValueChangeListener());
matchdaySelect.addValueChangeListener(matchdaySelectValueChangeListener()); matchdaySelect.addValueChangeListener(matchdaySelectValueChangeListener());
matchSelect.addValueChangeListener(matchSelectValueChangeListener()); matchSelect.addValueChangeListener(matchSelectValueChangeListener());
seasonSelect.setItemLabelGenerator(EntityStringUtils::getSeasonString);
matchdaySelect.setItemLabelGenerator(EntityStringUtils::getMatchdayString);
matchSelect.setItemLabelGenerator(EntityStringUtils::getMatchString);
} }
public void setRoute(String route) { public void setRoute(String route) {
@ -98,9 +103,12 @@ public class Navigation implements HasUrlParameter<String> {
String seasonParam = null; String seasonParam = null;
String matchdayParam = null; String matchdayParam = null;
String matchParam = null; String matchParam = null;
if (seasonEnabled() && seasonSelect.getOptionalValue().isPresent()) seasonParam = seasonSelect.getValue().toString();
if (matchdayEnabled() && matchdaySelect.getOptionalValue().isPresent()) matchdayParam = matchdaySelect.getValue().toString();
if (matchEnabled() && matchSelect.getOptionalValue().isPresent()) matchParam = matchSelect.getValue().toString();
if (seasonEnabled() && seasonSelect.getOptionalValue().isPresent())
seasonParam = EntityStringUtils.getSeasonStringForURL(seasonSelect.getValue());
if (matchdayEnabled() && matchdaySelect.getOptionalValue().isPresent())
matchdayParam = EntityStringUtils.getMatchdayStringForURL(matchdaySelect.getValue());
if (matchEnabled() && matchSelect.getOptionalValue().isPresent())
matchParam = EntityStringUtils.getMatchStringForURL(matchSelect.getValue());
String params = NavigationUtils.getWildcardParam(seasonParam, matchdayParam, matchParam); String params = NavigationUtils.getWildcardParam(seasonParam, matchdayParam, matchParam);
UI.getCurrent().getPage().getHistory().pushState(null, String.format("%s/%s", getRoute(), params)); UI.getCurrent().getPage().getHistory().pushState(null, String.format("%s/%s", getRoute(), params));
@ -197,54 +205,27 @@ public class Navigation implements HasUrlParameter<String> {
@Override @Override
public void setParameter(BeforeEvent event, @WildcardParameter String param) { public void setParameter(BeforeEvent event, @WildcardParameter String param) {
Map<UrlParameterType, Optional<String>> map = NavigationUtils.getParameterMap(param);
navigate(map.get(UrlParameterType.SEASON), map.get(UrlParameterType.MATCHDAY), map.get(UrlParameterType.MATCH));
Map<NavigationLevel, Optional<String>> map = NavigationUtils.getParameterMap(param);
navigate(map.get(NavigationLevel.SEASON), map.get(NavigationLevel.MATCHDAY), map.get(NavigationLevel.MATCH));
} }
private void navigate(Optional<String> seasonParam, Optional<String> matchdayParam, Optional<String> matchParam) { private void navigate(Optional<String> seasonParam, Optional<String> matchdayParam, Optional<String> matchParam) {
if (!seasonEnabled()) return; if (!seasonEnabled()) return;
Optional<Season> season = getSeasonFromParam(seasonParam);
Optional<Season> season = NavigationUtils.getObjectFromParam(seasonList, seasonParam);
if (season.isPresent()) seasonSelect.setValue(season.get()); if (season.isPresent()) seasonSelect.setValue(season.get());
else autoselectSeason(); else autoselectSeason();
if (!matchdayEnabled()) return; if (!matchdayEnabled()) return;
Optional<Matchday> matchday = getMatchdayFromParam(matchdayParam);
Optional<Matchday> matchday = NavigationUtils.getObjectFromParam(matchdayList, matchdayParam);
if (matchday.isPresent()) matchdaySelect.setValue(matchday.get()); if (matchday.isPresent()) matchdaySelect.setValue(matchday.get());
else autoselectMatchday(); else autoselectMatchday();
if (!matchEnabled()) return; if (!matchEnabled()) return;
Optional<Match> match = getMatchFromParam(matchParam);
Optional<Match> match = NavigationUtils.getObjectFromParam(matchList, matchParam);
if (match.isPresent()) matchSelect.setValue(match.get()); if (match.isPresent()) matchSelect.setValue(match.get());
else autoselectMatch(); else autoselectMatch();
} }
private Optional<Season> getSeasonFromParam(Optional<String> seasonParam) {
if (seasonParam.isEmpty()) {
return Optional.empty();
}
return seasonList.stream()
.filter(season -> season.toString().equals(seasonParam.get()))
.findFirst();
}
private Optional<Matchday> getMatchdayFromParam(Optional<String> matchdayParam) {
if (matchdayParam.isEmpty()) {
return Optional.empty();
}
return matchdayList.stream()
.filter(matchday -> matchday.toString().equals(matchdayParam.get()))
.findFirst();
}
private Optional<Match> getMatchFromParam(Optional<String> matchParam) {
if (matchParam.isEmpty()) {
return Optional.empty();
}
return matchList.stream()
.filter(match -> match.toString().equals(matchParam.get()))
.findFirst();
}
public ValidationLabel getValidationLabel() { public ValidationLabel getValidationLabel() {
return validationLabel; return validationLabel;
} }


src/main/java/app/navigation/service/NavigationLevel.java → src/main/java/app/navigation/NavigationLevel.java View File

@ -1,4 +1,4 @@
package app.navigation.service;
package app.navigation;
public enum NavigationLevel { public enum NavigationLevel {
NONE, NONE,

src/main/java/app/navigation/service/NavigationService.java → src/main/java/app/navigation/NavigationService.java View File

@ -1,4 +1,4 @@
package app.navigation.service;
package app.navigation;
import app.data.service.MatchService; import app.data.service.MatchService;
import app.data.service.MatchdayService; import app.data.service.MatchdayService;

+ 23
- 10
src/main/java/app/navigation/NavigationUtils.java View File

@ -4,34 +4,38 @@ import com.vaadin.flow.router.WildcardParameter;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
public class NavigationUtils {
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
class NavigationUtils {
private NavigationUtils() {
}
@NonNull @NonNull
public static Map<UrlParameterType, Optional<String>> getParameterMap(@WildcardParameter String param) {
Map<UrlParameterType, Optional<String>> map = new HashMap<>();
static Map<NavigationLevel, Optional<String>> getParameterMap(@WildcardParameter String param) {
Map<NavigationLevel, Optional<String>> map = new HashMap<>();
String[] params = param.split("/"); String[] params = param.split("/");
switch (params.length) { switch (params.length) {
case 3: case 3:
map.put(UrlParameterType.MATCH, Optional.of(params[2]));
map.put(NavigationLevel.MATCH, Optional.of(params[2]));
case 2: case 2:
map.put(UrlParameterType.MATCHDAY, Optional.of(params[1]));
map.put(NavigationLevel.MATCHDAY, Optional.of(params[1]));
case 1: case 1:
map.put(UrlParameterType.SEASON, Optional.of(params[0]));
map.put(NavigationLevel.SEASON, Optional.of(params[0]));
default: default:
break; break;
} }
map.putIfAbsent(UrlParameterType.MATCH, Optional.empty());
map.putIfAbsent(UrlParameterType.MATCHDAY, Optional.empty());
map.putIfAbsent(UrlParameterType.SEASON, Optional.empty());
map.putIfAbsent(NavigationLevel.MATCH, Optional.empty());
map.putIfAbsent(NavigationLevel.MATCHDAY, Optional.empty());
map.putIfAbsent(NavigationLevel.SEASON, Optional.empty());
return map; return map;
} }
@NonNull @NonNull
public static String getWildcardParam(String... params) {
static String getWildcardParam(String... params) {
StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder = new StringBuilder();
for (String param : params) { for (String param : params) {
if (param == null || param.equals("")) { if (param == null || param.equals("")) {
@ -41,4 +45,13 @@ public class NavigationUtils {
} }
return stringBuilder.toString(); return stringBuilder.toString();
} }
static <T> Optional<T> getObjectFromParam(List<T> objectList, Optional<String> param) {
if (param.isEmpty()) {
return Optional.empty();
}
return objectList.stream()
.filter(match -> match.toString().equals(param.get()))
.findFirst();
}
} }

+ 0
- 7
src/main/java/app/navigation/UrlParameterType.java View File

@ -1,7 +0,0 @@
package app.navigation;
public enum UrlParameterType {
SEASON,
MATCHDAY,
MATCH
}

+ 10
- 1
src/main/java/app/utils/ChessComUtils.java View File

@ -1,12 +1,17 @@
package app.utils; package app.utils;
import app.data.chesscom.ChessComGame; import app.data.chesscom.ChessComGame;
import app.data.entity.Game;
import app.data.entity.Match; import app.data.entity.Match;
import app.data.entity.Player; import app.data.entity.Player;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
public class ChessComUtils { public class ChessComUtils {
private ChessComUtils() {}
private static final String GAME_LINK = "https://www.chess.com/live/game/{gameId}";
private ChessComUtils() {
}
public static String getPreparedArchiveJson(String unpreparedArchiveJson) { public static String getPreparedArchiveJson(String unpreparedArchiveJson) {
return unpreparedArchiveJson return unpreparedArchiveJson
@ -46,4 +51,8 @@ public class ChessComUtils {
return false; return false;
} }
public static String getGameLink(Game game) {
String gameId = game.getGameInfo().getChessComId();
return GAME_LINK.replace("{gameId}", gameId);
}
} }

+ 17
- 0
src/main/java/app/utils/EntityComponentUtils.java View File

@ -0,0 +1,17 @@
package app.utils;
import app.data.entity.Player;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
public class EntityComponentUtils {
private EntityComponentUtils(){}
public static HorizontalLayout getPlayerLabel(Player player) {
Label name = new Label(player.getName());
name.addClassName("bold-label");
Label nickname = new Label(String.format("(%s)", player.getNickname()));
nickname.addClassName("nickname-label");
return new HorizontalLayout(name, nickname);
}
}

+ 48
- 0
src/main/java/app/utils/EntityStringUtils.java View File

@ -0,0 +1,48 @@
package app.utils;
import app.data.entity.Match;
import app.data.entity.Matchday;
import app.data.entity.Player;
import app.data.entity.Season;
public class EntityStringUtils {
private EntityStringUtils() {
}
public static String getPlayerString(Player player) {
return String.format("%s (%s)", player.getName(), player.getNickname());
}
public static String getPlayerStringForURL(Player player) {
return player.getNickname().toLowerCase();
}
public static String getSeasonString(Season season) {
String string = season.getYearStart().toString();
if (!season.getYearEnd().equals(season.getYearStart())) {
string += "-" + season.getYearEnd().toString();
}
return string;
}
public static String getSeasonStringForURL(Season season) {
return getSeasonString(season);
}
public static String getMatchdayString(Matchday matchday ) {
return matchday.getNumber().toString();
}
public static String getMatchdayStringForURL(Matchday matchday) {
return matchday.getNumber().toString();
}
public static String getMatchString(Match match) {
return String.format("%s vs. %s", match.getPlayer1().getNickname(), match.getPlayer2().getNickname());
}
public static String getMatchStringForURL(Match match) {
return String.format("%s-vs-%s", match.getPlayer1().getNickname().toLowerCase(), match.getPlayer2().getNickname().toLowerCase());
}
}

+ 7
- 7
src/main/java/app/utils/StringUtils.java View File

@ -9,15 +9,15 @@ public class StringUtils {
private StringUtils() { private StringUtils() {
} }
////////////////
// Formatting //
////////////////
////////////////////////
// SPECIAL FORMATTING //
////////////////////////
public static String getResultString(Double first, Double second) {
public static String getResultString(String delimiter, Double first, Double second) {
String firstString = first.toString().replace(".0", ""); String firstString = first.toString().replace(".0", "");
String secondString = second.toString().replace(".0", ""); String secondString = second.toString().replace(".0", "");
String result = firstString + " : " + secondString;
if (result.equals("0 : 0")) {
String result = String.format("%s %s %s", firstString, delimiter, secondString);
if (result.equals("0 : 0")) { // TODO: care about delimiter
return "- : -"; return "- : -";
} }
return result; return result;
@ -41,7 +41,7 @@ public class StringUtils {
} }
//////////////// ////////////////
// Randomness //
// RANDOMNESS //
//////////////// ////////////////
private static final int RANDOM_STRING_LENGTH = 10; private static final int RANDOM_STRING_LENGTH = 10;


+ 8
- 2
src/main/java/app/views/match/MatchView.java View File

@ -1,9 +1,10 @@
package app.views.match; package app.views.match;
import app.data.service.MatchService; import app.data.service.MatchService;
import app.navigation.service.NavigationLevel;
import app.navigation.service.NavigationService;
import app.navigation.NavigationLevel;
import app.navigation.NavigationService;
import app.views.main.MainView; import app.views.main.MainView;
import app.views.match.components.MatchComponent;
import app.views.navigation.NavigationViewBase; import app.views.navigation.NavigationViewBase;
import com.vaadin.flow.component.dependency.CssImport; import com.vaadin.flow.component.dependency.CssImport;
import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.PageTitle;
@ -17,6 +18,8 @@ public class MatchView extends NavigationViewBase {
private final MatchService matchService; private final MatchService matchService;
private MatchComponent matchComponent;
public MatchView(@Autowired NavigationService navigationService, public MatchView(@Autowired NavigationService navigationService,
@Autowired MatchService matchService) { @Autowired MatchService matchService) {
super(navigationService, "match", NavigationLevel.MATCH); super(navigationService, "match", NavigationLevel.MATCH);
@ -32,6 +35,8 @@ public class MatchView extends NavigationViewBase {
//////////// ////////////
private void configureLayout() { private void configureLayout() {
matchComponent = new MatchComponent(navigation);
add(matchComponent);
} }
///////////// /////////////
@ -40,5 +45,6 @@ public class MatchView extends NavigationViewBase {
@Override @Override
protected void configureContent() { protected void configureContent() {
matchComponent.configureContent();
} }
} }

+ 64
- 0
src/main/java/app/views/match/components/GameComponent.java View File

@ -0,0 +1,64 @@
package app.views.match.components;
import app.data.entity.Game;
import app.views.match.components.utils.GameComponentUtils;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Image;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
public class GameComponent extends Div {
private final Game game;
private final HorizontalLayout inner = new HorizontalLayout();
private final VerticalLayout left = new VerticalLayout();
private final Div right = new Div();
public GameComponent(Game game) {
this.game = game;
addClassName("wrapper");
addClassName("game-card");
configureInner();
}
private void configureInner() {
add(inner);
inner.add(left, right);
inner.setAlignItems(FlexComponent.Alignment.CENTER);
configureLeft();
configureRight();
}
private void configureLeft() {
Label header = GameComponentUtils.getHeader(game);
Div timeControlDiv = GameComponentUtils.getTimeControlDiv(game);
Div blackDiv = GameComponentUtils.getPlayerDiv(game, false);
Label vsLabel = GameComponentUtils.getVsLabel();
Div whiteDiv = GameComponentUtils.getPlayerDiv(game, true);
Button button = GameComponentUtils.getChessComButton(game);
left.add(header, timeControlDiv, blackDiv, vsLabel, whiteDiv, button);
left.addClassName("game-info-div");
left.setAlignItems(FlexComponent.Alignment.CENTER);
left.setHeightFull();
}
private void configureRight() {
right.addClassName("game-image-div");
Image image = new Image(GameComponentUtils.getImagePath(game), "Could not find game image.");
right.add(image);
image.setWidthFull();
image.setHeightFull();
}
}

+ 82
- 0
src/main/java/app/views/match/components/MatchComponent.java View File

@ -0,0 +1,82 @@
package app.views.match.components;
import app.data.bean.CalculatedMatch;
import app.data.entity.Game;
import app.data.entity.Match;
import app.navigation.Navigation;
import app.utils.EntityComponentUtils;
import app.utils.StringUtils;
import app.views.navigation.interfaces.ContentConfigurable;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.FlexLayout;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import java.util.NoSuchElementException;
public class MatchComponent extends Div implements ContentConfigurable {
private final Navigation navigation;
private final VerticalLayout headerLayout = new VerticalLayout();
private final HorizontalLayout headerPlayersLayout = new HorizontalLayout();
private final Label headerResultLabel = new Label();
private final FlexLayout gamesLayout = new FlexLayout();
public MatchComponent(Navigation navigation) {
this.navigation = navigation;
add(headerLayout, gamesLayout);
configureHeaderLayout();
configureGamesLayout();
}
private void configureHeaderLayout() {
headerLayout.add(headerPlayersLayout, headerResultLabel);
headerPlayersLayout.addClassName("match-header-players");
headerResultLabel.addClassName("match-header-result");
headerResultLabel.addClassName("bold-header");
}
private void configureGamesLayout() {
gamesLayout.setFlexWrap(FlexLayout.FlexWrap.WRAP);
gamesLayout.setJustifyContentMode(FlexComponent.JustifyContentMode.CENTER);
}
@Override
public void configureContent() {
try {
Match match = navigation.getSelectedMatch().orElseThrow();
configureHeaderContent(match);
gamesLayout.removeAll();
for (Game game : match.getGames()) {
gamesLayout.add(new GameComponent(game));
}
} catch (NoSuchElementException e) {
gamesLayout.removeAll();
add(navigation.getValidationLabel());
}
}
private void configureHeaderContent(Match match) {
CalculatedMatch calculatedMatch = navigation.getMatchService().getCalculatedMatch(match);
HorizontalLayout player1 = EntityComponentUtils.getPlayerLabel(calculatedMatch.getPlayer1());
HorizontalLayout player2 = EntityComponentUtils.getPlayerLabel(calculatedMatch.getPlayer2());
Label vs = new Label("vs.");
headerPlayersLayout.removeAll();
headerPlayersLayout.add(player1, vs, player2);
headerResultLabel.setText(String.format("%s",
StringUtils.getResultString("-", calculatedMatch.getScore1(), calculatedMatch.getScore2())));
}
}

+ 151
- 0
src/main/java/app/views/match/components/utils/GameComponentUtils.java View File

@ -0,0 +1,151 @@
package app.views.match.components.utils;
import app.data.entity.Game;
import app.data.entity.Player;
import app.gameimage.GameImageUtils;
import app.utils.ChessComUtils;
import app.utils.EntityComponentUtils;
import com.vaadin.flow.component.ClickEvent;
import com.vaadin.flow.component.ComponentEventListener;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class GameComponentUtils {
private GameComponentUtils() {
}
public static int getGameNumber(Game game) {
List<Game> games = new ArrayList<>(game.getMatch().getGames());
int index = games.indexOf(game);
if (index < 0) throw new IllegalStateException("The match associated with the Game does not contain the Game!");
return games.indexOf(game) + 1;
}
public static String getImagePath(Game game) {
String[] urlParts = game.getGameInfo().getChessComId().split("/");
return GameImageUtils.IMAGE_PATH_CLIENT + urlParts[urlParts.length - 1] + GameImageUtils.EXTENSION;
}
public static Player getWhitePlayer(Game game) {
return game.getPlayer1IsWhite() ? game.getMatch().getPlayer1() : game.getMatch().getPlayer2();
}
public static Player getBlackPlayer(Game game) {
return game.getPlayer1IsWhite() ? game.getMatch().getPlayer2() : game.getMatch().getPlayer1();
}
public static Div getPlayerDiv(Game game, boolean white) {
Player player = white ? getWhitePlayer(game) : getBlackPlayer(game);
Div div = new Div();
div.addClassName("player");
div.addClassName(white ? "white-player" : "black-player");
HorizontalLayout playerLabel = EntityComponentUtils.getPlayerLabel(player);
playerLabel.setWidthFull();
playerLabel.setJustifyContentMode(FlexComponent.JustifyContentMode.CENTER);
Label resultLabel = getResultLabel(game, white);
playerLabel.add(resultLabel);
div.add(playerLabel);
return div;
}
private static Label getResultLabel(Game game, boolean white) {
String resultString;
switch (game.getResult()) {
case -1:
resultString = white ? "0" : "1";
break;
case 0:
resultString = "0.5";
break;
case 1:
resultString = white ? "1" : "0";
break;
default:
throw new IllegalStateException(String.format("Game result must be either -1, 0, or 1, but it is %d!", game.getResult()));
}
Label resultLabel = new Label(resultString);
resultLabel.addClassName("bold-label");
return resultLabel;
}
public static Div getTimeControlDiv(Game game) {
String timeControl = game.getGameInfo().getTimeControl();
Icon icon;
String string;
switch (timeControl) {
case "600":
icon = new Icon(VaadinIcon.STOPWATCH);
string = "10 min";
break;
case "300":
icon = new Icon(VaadinIcon.BOLT);
string = "5 min";
break;
case "180":
icon = new Icon(VaadinIcon.BOMB);
string = "3 min";
break;
default:
icon = new Icon(VaadinIcon.QUESTION);
string = String.format("Unknown Time Control: %s", timeControl);
break;
}
Div div = new Div();
div.addClassName("time-control");
HorizontalLayout horizontalLayout = new HorizontalLayout();
horizontalLayout.setWidthFull();
horizontalLayout.setJustifyContentMode(FlexComponent.JustifyContentMode.CENTER);
horizontalLayout.add(icon, new Label(string));
div.add(horizontalLayout);
return div;
}
public static Label getHeader(Game game) {
Label label = new Label();
label.setText(String.format("Game %d", getGameNumber(game)));
label.addClassName("game-header");
return label;
}
public static Button getChessComButton(Game game) {
String string = "Watch on Chess.com";
Icon icon = new Icon(VaadinIcon.EYE);
Button button = new Button(string, icon);
button.setWidthFull();
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
button.addClickListener(event ->
button.getUI().ifPresent(ui ->
ui.getPage().open(ChessComUtils.getGameLink(game), "_blank")));
return button;
}
public static Label getVsLabel() {
Label label = new Label("vs.");
label.addClassName("vs-label");
return label;
}
}

+ 2
- 2
src/main/java/app/views/matchday/MatchdayView.java View File

@ -1,7 +1,7 @@
package app.views.matchday; package app.views.matchday;
import app.navigation.service.NavigationLevel;
import app.navigation.service.NavigationService;
import app.navigation.NavigationLevel;
import app.navigation.NavigationService;
import app.views.main.MainView; import app.views.main.MainView;
import app.views.matchday.components.MatchdayComponent; import app.views.matchday.components.MatchdayComponent;
import app.views.navigation.NavigationViewBase; import app.views.navigation.NavigationViewBase;


+ 4
- 4
src/main/java/app/views/matchday/components/MatchdayComponent.java View File

@ -5,6 +5,7 @@ import app.data.entity.Matchday;
import app.navigation.Navigation; import app.navigation.Navigation;
import app.navigation.components.button.NextMatchdayButton; import app.navigation.components.button.NextMatchdayButton;
import app.navigation.components.button.PrevMatchdayButton; import app.navigation.components.button.PrevMatchdayButton;
import app.utils.EntityStringUtils;
import app.utils.StringUtils; import app.utils.StringUtils;
import app.utils.VaadinUtils; import app.utils.VaadinUtils;
import app.views.navigation.interfaces.ContentConfigurable; import app.views.navigation.interfaces.ContentConfigurable;
@ -23,8 +24,6 @@ public class MatchdayComponent extends Div implements ContentConfigurable {
private final Navigation navigation; private final Navigation navigation;
private final VerticalLayout inner = new VerticalLayout();
private final HorizontalLayout header = new HorizontalLayout(); private final HorizontalLayout header = new HorizontalLayout();
private final Label headerLabel = new Label(); private final Label headerLabel = new Label();
private final Grid<CalculatedMatch> grid = new Grid<>(); private final Grid<CalculatedMatch> grid = new Grid<>();
@ -33,6 +32,7 @@ public class MatchdayComponent extends Div implements ContentConfigurable {
this.navigation = navigation; this.navigation = navigation;
addClassName("wrapper"); addClassName("wrapper");
VerticalLayout inner = new VerticalLayout();
add(inner); add(inner);
inner.add(header, grid); inner.add(header, grid);
@ -79,14 +79,14 @@ public class MatchdayComponent extends Div implements ContentConfigurable {
} }
private String getResultString(CalculatedMatch match) { private String getResultString(CalculatedMatch match) {
return StringUtils.getResultString(match.getScore1(), match.getScore2());
return StringUtils.getResultString(":", match.getScore1(), match.getScore2());
} }
@Override @Override
public void configureContent() { public void configureContent() {
try { try {
Matchday matchday = navigation.getSelectedMatchday().orElseThrow(); Matchday matchday = navigation.getSelectedMatchday().orElseThrow();
headerLabel.setText(String.format("Matchday %s", matchday.toString())); // TODO: add dates
headerLabel.setText(String.format("Matchday %s", EntityStringUtils.getMatchdayString(matchday))); // TODO: add dates
grid.setItems(navigation.getMatchService().getCalculatedMatches(matchday)); grid.setItems(navigation.getMatchService().getCalculatedMatches(matchday));
} catch (NoSuchElementException e) { } catch (NoSuchElementException e) {
removeAll(); removeAll();


+ 2
- 2
src/main/java/app/views/navigation/NavigationViewBase.java View File

@ -2,8 +2,8 @@ package app.views.navigation;
import app.navigation.Navigation; import app.navigation.Navigation;
import app.navigation.components.NavigationHeader; import app.navigation.components.NavigationHeader;
import app.navigation.service.NavigationLevel;
import app.navigation.service.NavigationService;
import app.navigation.NavigationLevel;
import app.navigation.NavigationService;
import com.vaadin.flow.component.orderedlayout.FlexComponent; import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.BeforeEvent; import com.vaadin.flow.router.BeforeEvent;


+ 2
- 2
src/main/java/app/views/table/TableView.java View File

@ -1,8 +1,8 @@
package app.views.table; package app.views.table;
import app.data.service.PlayerService; import app.data.service.PlayerService;
import app.navigation.service.NavigationLevel;
import app.navigation.service.NavigationService;
import app.navigation.NavigationLevel;
import app.navigation.NavigationService;
import app.views.main.MainView; import app.views.main.MainView;
import app.views.navigation.NavigationViewBase; import app.views.navigation.NavigationViewBase;
import app.views.table.components.TableComponent; import app.views.table.components.TableComponent;


+ 1
- 1
src/main/java/app/views/table/components/TableComponent.java View File

@ -113,7 +113,7 @@ public class TableComponent extends Div implements ContentConfigurable {
} }
private String getResultString(PlayerForTable player) { private String getResultString(PlayerForTable player) {
return StringUtils.getResultString(player.getGamePointsForSelf(), player.getGamePointsForOpponents());
return StringUtils.getResultString(":", player.getGamePointsForSelf(), player.getGamePointsForOpponents());
} }
@Override @Override


Loading…
Cancel
Save