From d2a5489c32c4760802498bbbd4132c8f30b5f48c Mon Sep 17 00:00:00 2001 From: silas Date: Thu, 27 Sep 2018 12:32:28 +0200 Subject: [PATCH] Tutorial angefangen --- log/error.log | 19 ++ log/log.log | 19 ++ orga/test.sql | 5 +- prod.settings.js | 2 +- public/css/wordRotator.css | 2 +- public/html/application/level.html | 2 +- public/js/app.js | 314 +++++++++++------- public/js/lang/de.json | 2 +- src/js/init.js | 10 +- src/js/settings.js | 2 +- .../pwa/html/application/level.html | 9 +- .../js/Fragment/WordRotatorSettingFragment.js | 1 + .../Application/pwa/js/site/LevelSite.js | 107 +++++- .../Application/pwa/js/site/MenuSite.js | 51 ++- .../pwa/js/site/SynchronizeSite.js | 64 ---- .../pwa/js/wordrotator/Level/Level.js | 6 + .../js/wordrotator/Segment/ParentSegment.js | 2 + .../Application/pwa/translations/de.json | 7 +- src/scss/_tutorial.scss | 74 +++++ src/scss/wordRotator.scss | 7 +- test/test.testcafe.js | 2 +- 21 files changed, 491 insertions(+), 216 deletions(-) delete mode 100755 src/module/Application/pwa/js/site/SynchronizeSite.js create mode 100644 src/scss/_tutorial.scss diff --git a/log/error.log b/log/error.log index 56c196d..310fe8c 100755 --- a/log/error.log +++ b/log/error.log @@ -24,3 +24,22 @@ 2018-09-26T14:58:31+02:00 ERR (3): 2018-09-26T14:59:27+02:00 ERR (3): 2018-09-26T15:08:13+02:00 ERR (3): +2018-09-26T15:16:58+02:00 ERR (3): +2018-09-26T15:17:10+02:00 ERR (3): +2018-09-26T15:17:50+02:00 ERR (3): +2018-09-26T15:18:15+02:00 ERR (3): +2018-09-26T15:18:39+02:00 ERR (3): +2018-09-26T18:01:15+02:00 ERR (3): +2018-09-26T18:06:35+02:00 ERR (3): +2018-09-26T18:09:03+02:00 ERR (3): +2018-09-27T11:48:18+02:00 ERR (3): +2018-09-27T11:49:03+02:00 ERR (3): +2018-09-27T11:49:24+02:00 ERR (3): +2018-09-27T11:55:27+02:00 ERR (3): +2018-09-27T11:56:27+02:00 ERR (3): +2018-09-27T12:01:44+02:00 ERR (3): +2018-09-27T12:20:36+02:00 ERR (3): +2018-09-27T12:21:38+02:00 ERR (3): +2018-09-27T12:29:51+02:00 ERR (3): +2018-09-27T12:30:53+02:00 ERR (3): +2018-09-27T12:31:24+02:00 ERR (3): diff --git a/log/log.log b/log/log.log index 56c196d..310fe8c 100755 --- a/log/log.log +++ b/log/log.log @@ -24,3 +24,22 @@ 2018-09-26T14:58:31+02:00 ERR (3): 2018-09-26T14:59:27+02:00 ERR (3): 2018-09-26T15:08:13+02:00 ERR (3): +2018-09-26T15:16:58+02:00 ERR (3): +2018-09-26T15:17:10+02:00 ERR (3): +2018-09-26T15:17:50+02:00 ERR (3): +2018-09-26T15:18:15+02:00 ERR (3): +2018-09-26T15:18:39+02:00 ERR (3): +2018-09-26T18:01:15+02:00 ERR (3): +2018-09-26T18:06:35+02:00 ERR (3): +2018-09-26T18:09:03+02:00 ERR (3): +2018-09-27T11:48:18+02:00 ERR (3): +2018-09-27T11:49:03+02:00 ERR (3): +2018-09-27T11:49:24+02:00 ERR (3): +2018-09-27T11:55:27+02:00 ERR (3): +2018-09-27T11:56:27+02:00 ERR (3): +2018-09-27T12:01:44+02:00 ERR (3): +2018-09-27T12:20:36+02:00 ERR (3): +2018-09-27T12:21:38+02:00 ERR (3): +2018-09-27T12:29:51+02:00 ERR (3): +2018-09-27T12:30:53+02:00 ERR (3): +2018-09-27T12:31:24+02:00 ERR (3): diff --git a/orga/test.sql b/orga/test.sql index cfc0a4b..aa93cab 100644 --- a/orga/test.sql +++ b/orga/test.sql @@ -52,10 +52,11 @@ INSERT INTO `RoleAccess` (`RoleId`, `AccessId`) VALUES (3, 4); -- admin - admin INSERT INTO `Level` (`id`, `words`, `positions`, `renderer`, `lastUpdated`, `lang`, `deleted`, `difficulty`) VALUES -(15, '["ARCHIV","CHARME"]', '[1,1,3]', 20, '2018-07-14 17:01:18', 1, 0, 20), +(15, '["ARCHIV","CHARME"]', '[1,1,3]', 20, '2018-07-14 17:01:18', 1, 0, 2), (26, '["BODENSEE","ALARMRUF"]', '[3,2,0,3]', 40, '2018-07-14 17:01:18', 1, 0, 40), (217, '["ZEITSTRAFE","HOCHSAISON"]', '[1,0,3,3,1]', 60, '2018-07-14 17:01:18', 1, 0, 60), (220, '["FEINGUSS","R\\u00dcCKFALL","PHYSIKER","RESIDENZ","BERATUNG","HERZLAND"]', '[2,0,0,1,2,2,3,3,2,1,1,2,0,0]', 100, '2018-07-14 17:01:18', 1, 0, 100), (24, '["BETONUNG","ANBETUNG","ALLERGIE","BAUMHAUS"]', '[0,3,1,1,3,1,2,0,0,0]', 120, '2018-07-14 17:01:18', 1, 0, 120), (62, '["FEHLPROGNOSE","GEISTESKRAFT","ARBEITSPAUSE","BEREITSCHAFT","MOSAIKARBEIT","INFRAROTFILM"]', '[0,3,0,1,0,3,2,3,1,2,3,1,2,2,0,2,3,0,2,1,1]', 140, '2018-07-14 17:01:18', 1, 0, 140), -(260, '["SCHREIBTISCH","URHEBERRECHT","PFLANZENKOST","OPERNKONZERT"]', '[1,3,2,1,3,0,1,2,3,0,2,0,1,0,0]', 160, '2018-07-14 17:01:18', 1, 0, 160); \ No newline at end of file +(260, '["SCHREIBTISCH","URHEBERRECHT","PFLANZENKOST","OPERNKONZERT"]', '[1,3,2,1,3,0,1,2,3,0,2,0,1,0,0]', 160, '2018-07-14 17:01:18', 1, 0, 160), +(67,'["AHNUNG","AUSBAU"]','[0,0,1]',20,'2018-10-10 00:00:00',1,0,1); \ No newline at end of file diff --git a/prod.settings.js b/prod.settings.js index 1bd6134..d8b6874 100755 --- a/prod.settings.js +++ b/prod.settings.js @@ -1,6 +1,6 @@ import {SystemSettings, Translator} from "./lib/pwa-lib"; SystemSettings.setBasePath("/"); -Translator.supportedLanguages = ["de", "en"]; +Translator.supportedLanguages = ["de"]; Translator.markTranslations = false; Translator.markUntranslatedTranslations = false; diff --git a/public/css/wordRotator.css b/public/css/wordRotator.css index 90cebcc..ede9ceb 100755 --- a/public/css/wordRotator.css +++ b/public/css/wordRotator.css @@ -1,2 +1,2 @@ -nav.top-bar.title-bar{padding:.3rem .6rem 0}#action-bar .top-bar-right .menu .action.img a{padding-bottom:0}#action-bar .top-bar-right .menu .action.img a img{max-height:1.8rem}.dropdown.menu a,.menu a{padding:.2rem .5rem}#level-number-container{z-index:1;-webkit-transition:none;transition:none;position:absolute;left:50%;-webkit-transform:translate(-50%);transform:translate(-50%);border:3px solid #fff;border-radius:50%;visibility:hidden;display:table-cell;height:35px;width:35px;text-align:center;vertical-align:middle}#level-number-container.visible{visibility:visible}#level-number-container.in-main-menu{background:#fff;border-color:#000;height:1em;width:1em;min-height:1em;min-width:1em;max-height:1em;max-width:1em}#level-number-container #level-number{-webkit-transition:none;transition:none;position:absolute;left:50%;top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);font-weight:700}.coin-counter{display:inline-block;position:relative;font-size:1.6rem}.coin-counter :after{background-image:url(../img/coinTower.png);background-size:28px 28px;width:28px;height:28px;display:inline-block;content:""}#coin-container{height:30px}#coin-container .coin{margin-left:3px;margin-right:3px;max-width:30px;display:inline-block}@-webkit-keyframes rotate-90{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(90deg);transform:rotate(90deg)}}@keyframes rotate-90{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(90deg);transform:rotate(90deg)}}@-webkit-keyframes rotate-reverse-90{0%{-webkit-transform:rotate(180deg);transform:rotate(180deg)}to{-webkit-transform:rotate(90deg);transform:rotate(90deg)}}@keyframes rotate-reverse-90{0%{-webkit-transform:rotate(180deg);transform:rotate(180deg)}to{-webkit-transform:rotate(90deg);transform:rotate(90deg)}}@-webkit-keyframes rotate-180{0%{-webkit-transform:rotate(90deg);transform:rotate(90deg)}to{-webkit-transform:rotate(180deg);transform:rotate(180deg)}}@keyframes rotate-180{0%{-webkit-transform:rotate(90deg);transform:rotate(90deg)}to{-webkit-transform:rotate(180deg);transform:rotate(180deg)}}@-webkit-keyframes rotate-reverse-180{0%{-webkit-transform:rotate(270deg);transform:rotate(270deg)}to{-webkit-transform:rotate(180deg);transform:rotate(180deg)}}@keyframes rotate-reverse-180{0%{-webkit-transform:rotate(270deg);transform:rotate(270deg)}to{-webkit-transform:rotate(180deg);transform:rotate(180deg)}}@-webkit-keyframes rotate-270{0%{-webkit-transform:rotate(180deg);transform:rotate(180deg)}to{-webkit-transform:rotate(270deg);transform:rotate(270deg)}}@keyframes rotate-270{0%{-webkit-transform:rotate(180deg);transform:rotate(180deg)}to{-webkit-transform:rotate(270deg);transform:rotate(270deg)}}@-webkit-keyframes rotate-reverse-270{0%{-webkit-transform:rotate(1turn);transform:rotate(1turn)}to{-webkit-transform:rotate(270deg);transform:rotate(270deg)}}@keyframes rotate-reverse-270{0%{-webkit-transform:rotate(1turn);transform:rotate(1turn)}to{-webkit-transform:rotate(270deg);transform:rotate(270deg)}}@-webkit-keyframes rotate-360{0%{-webkit-transform:rotate(270deg);transform:rotate(270deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes rotate-360{0%{-webkit-transform:rotate(270deg);transform:rotate(270deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@-webkit-keyframes rotate-reverse-360{0%{-webkit-transform:rotate(450deg);transform:rotate(450deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes rotate-reverse-360{0%{-webkit-transform:rotate(450deg);transform:rotate(450deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.segment:not(.segment-row):not(.segment-triangle).rotating{z-index:10!important;overflow:hidden}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90{-webkit-animation-name:rotate-90;animation-name:rotate-90;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90>.child-container>.segment{-webkit-animation-name:rotate-360;animation-name:rotate-360;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;animation-direction:reverse;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-90;animation-name:rotate-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-180;animation-name:rotate-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-270;animation-name:rotate-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-360;animation-name:rotate-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90.reverse{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90.reverse>.child-container>.segment{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90.reverse>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90.reverse>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90.reverse>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90.reverse>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180{-webkit-animation-name:rotate-180;animation-name:rotate-180;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180>.child-container>.segment{-webkit-animation-name:rotate-270;animation-name:rotate-270;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;animation-direction:reverse;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-360;animation-name:rotate-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-90;animation-name:rotate-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-180;animation-name:rotate-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-270;animation-name:rotate-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180.reverse{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180.reverse>.child-container>.segment{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180.reverse>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180.reverse>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180.reverse>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180.reverse>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270{-webkit-animation-name:rotate-270;animation-name:rotate-270;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270>.child-container>.segment{-webkit-animation-name:rotate-180;animation-name:rotate-180;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;animation-direction:reverse;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-270;animation-name:rotate-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-360;animation-name:rotate-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-90;animation-name:rotate-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-180;animation-name:rotate-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270.reverse{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270.reverse>.child-container>.segment{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270.reverse>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270.reverse>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270.reverse>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270.reverse>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360{-webkit-animation-name:rotate-360;animation-name:rotate-360;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360>.child-container>.segment{-webkit-animation-name:rotate-90;animation-name:rotate-90;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;animation-direction:reverse;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-180;animation-name:rotate-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-270;animation-name:rotate-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-360;animation-name:rotate-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-90;animation-name:rotate-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360.reverse{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360.reverse>.child-container>.segment{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360.reverse>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360.reverse>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360.reverse>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360.reverse>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90{-webkit-transform:rotate(90deg);transform:rotate(90deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment{-webkit-transform:rotate(270deg);transform:rotate(270deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-90{-webkit-transform:rotate(1turn);transform:rotate(1turn);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-90.rotating{-webkit-animation-name:rotate-360;animation-name:rotate-360;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-90.rotating.reverse{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-180{-webkit-transform:rotate(90deg);transform:rotate(90deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-180.rotating{-webkit-animation-name:rotate-90;animation-name:rotate-90;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-180.rotating.reverse{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-270{-webkit-transform:rotate(180deg);transform:rotate(180deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-270.rotating{-webkit-animation-name:rotate-180;animation-name:rotate-180;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-270.rotating.reverse{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-360{-webkit-transform:rotate(270deg);transform:rotate(270deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-360.rotating{-webkit-animation-name:rotate-270;animation-name:rotate-270;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-360.rotating.reverse{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180,.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment{-webkit-transform:rotate(180deg);transform:rotate(180deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-90{-webkit-transform:rotate(270deg);transform:rotate(270deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-90.rotating{-webkit-animation-name:rotate-270;animation-name:rotate-270;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-90.rotating.reverse{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-180{-webkit-transform:rotate(1turn);transform:rotate(1turn);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-180.rotating{-webkit-animation-name:rotate-360;animation-name:rotate-360;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-180.rotating.reverse{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-270{-webkit-transform:rotate(90deg);transform:rotate(90deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-270.rotating{-webkit-animation-name:rotate-90;animation-name:rotate-90;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-270.rotating.reverse{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-360{-webkit-transform:rotate(180deg);transform:rotate(180deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-360.rotating{-webkit-animation-name:rotate-180;animation-name:rotate-180;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-360.rotating.reverse{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270{-webkit-transform:rotate(270deg);transform:rotate(270deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment{-webkit-transform:rotate(90deg);transform:rotate(90deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-90{-webkit-transform:rotate(180deg);transform:rotate(180deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-90.rotating{-webkit-animation-name:rotate-180;animation-name:rotate-180;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-90.rotating.reverse{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-180{-webkit-transform:rotate(270deg);transform:rotate(270deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-180.rotating{-webkit-animation-name:rotate-270;animation-name:rotate-270;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-180.rotating.reverse{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-270{-webkit-transform:rotate(1turn);transform:rotate(1turn);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-270.rotating{-webkit-animation-name:rotate-360;animation-name:rotate-360;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-270.rotating.reverse{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-360{-webkit-transform:rotate(90deg);transform:rotate(90deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-360.rotating{-webkit-animation-name:rotate-90;animation-name:rotate-90;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-360.rotating.reverse{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360{-webkit-transform:rotate(1turn);transform:rotate(1turn);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment{-webkit-transform:rotate(0deg);transform:rotate(0deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-90{-webkit-transform:rotate(90deg);transform:rotate(90deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-90.rotating{-webkit-animation-name:rotate-90;animation-name:rotate-90;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-90.rotating.reverse{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-180{-webkit-transform:rotate(180deg);transform:rotate(180deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-180.rotating{-webkit-animation-name:rotate-180;animation-name:rotate-180;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-180.rotating.reverse{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-270{-webkit-transform:rotate(270deg);transform:rotate(270deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-270.rotating{-webkit-animation-name:rotate-270;animation-name:rotate-270;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-270.rotating.reverse{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-360{-webkit-transform:rotate(1turn);transform:rotate(1turn);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-360.rotating{-webkit-animation-name:rotate-360;animation-name:rotate-360;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-360.rotating.reverse{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}#level{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;white-space:nowrap;max-width:100%;-webkit-tap-highlight-color:rgba(255,255,255,0);overflow-y:visible}#level,#level *,.segment{-webkit-transition:none;transition:none}.segment{vertical-align:top;white-space:normal;cursor:pointer;display:inline-block;text-align:center;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;z-index:1;background-color:#fff;line-height:0}.segment.segment-row{display:block;width:100%;-webkit-animation:none!important;animation:none!important;white-space:nowrap}.segment.segment-leaf{background-color:transparent;min-width:1em;padding:.8em}.segment.segment-leaf:before{content:" ";display:block;padding-top:100%}.segment.segment-leaf .leaf-element{position:absolute;width:100%;height:100%;line-height:1.5em;top:0;left:0}.segment.segment-parent{border:1px solid #a9a9a9;border-radius:3px;padding:1px}.segment.segment-parent.layer-2{border:3px solid #000}#site-content>:not(.won) .segment.locked,#site-content>:not(.won) .segment.locked>.child-container>.segment-leaf{border-color:#3adb76;background-color:#9ffbb5!important}#site-content>:not(.won) .show-when-won{display:none}.level-container{-webkit-transition:none;transition:none}.won .show-while-playing{display:none}.text-right{text-align:right}#continue-button{margin-bottom:2px} +.tutorial-blanket{display:none;position:fixed;top:0;bottom:0;left:0;right:0;z-index:9001;background:rgba(98,98,98,.51)}.tutorial .tutorial-blanket{display:block}.tutorial .tutorial-text{color:#fff;font-size:1.5rem;display:-webkit-box;display:-ms-flexbox;display:flex}.tutorial.step-1 #level .segment-row{position:inherit}.tutorial.step-1 #level .segment-parent:nth-child(3),.tutorial.step-1 #level .segment-parent:nth-child(3).rotating{z-index:9900!important}.tutorial.step-1 .tutorial-text .step-1{display:initial;z-index:9900!important;position:relative}.tutorial.step-2 #level{z-index:9900!important}.tutorial.step-2 .tutorial-text .step-2,.tutorial.step-3 .tutorial-text .step-3{display:initial;z-index:9900!important;position:relative}.tutorial.step-3 #help-button{position:relative;z-index:9900!important;overflow:visible;margin-right:10px;margin-top:10px;-webkit-box-shadow:0 0 10px 5px #fff;box-shadow:0 0 10px 5px #fff}nav.top-bar.title-bar{padding:.3rem .6rem 0}#action-bar .top-bar-right .menu .action.img a{padding-bottom:0}#action-bar .top-bar-right .menu .action.img a img{max-height:1.8rem}.dropdown.menu a,.menu a{padding:.2rem .5rem}#level-number-container{z-index:1;-webkit-transition:none;transition:none;position:absolute;left:50%;-webkit-transform:translate(-50%);transform:translate(-50%);border:3px solid #fff;border-radius:50%;visibility:hidden;display:table-cell;height:35px;width:35px;text-align:center;vertical-align:middle}#level-number-container.visible{visibility:visible}#level-number-container.in-main-menu{background:#fff;border-color:#000;height:1em;width:1em;min-height:1em;min-width:1em;max-height:1em;max-width:1em}#level-number-container #level-number{-webkit-transition:none;transition:none;position:absolute;left:50%;top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);font-weight:700}.coin-counter{display:inline-block;position:relative;font-size:1.6rem}.coin-counter :after{background-image:url(../img/coinTower.png);background-size:28px 28px;width:28px;height:28px;display:inline-block;content:""}#coin-container{height:30px}#coin-container .coin{margin-left:3px;margin-right:3px;max-width:30px;display:inline-block}@-webkit-keyframes rotate-90{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(90deg);transform:rotate(90deg)}}@keyframes rotate-90{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(90deg);transform:rotate(90deg)}}@-webkit-keyframes rotate-reverse-90{0%{-webkit-transform:rotate(180deg);transform:rotate(180deg)}to{-webkit-transform:rotate(90deg);transform:rotate(90deg)}}@keyframes rotate-reverse-90{0%{-webkit-transform:rotate(180deg);transform:rotate(180deg)}to{-webkit-transform:rotate(90deg);transform:rotate(90deg)}}@-webkit-keyframes rotate-180{0%{-webkit-transform:rotate(90deg);transform:rotate(90deg)}to{-webkit-transform:rotate(180deg);transform:rotate(180deg)}}@keyframes rotate-180{0%{-webkit-transform:rotate(90deg);transform:rotate(90deg)}to{-webkit-transform:rotate(180deg);transform:rotate(180deg)}}@-webkit-keyframes rotate-reverse-180{0%{-webkit-transform:rotate(270deg);transform:rotate(270deg)}to{-webkit-transform:rotate(180deg);transform:rotate(180deg)}}@keyframes rotate-reverse-180{0%{-webkit-transform:rotate(270deg);transform:rotate(270deg)}to{-webkit-transform:rotate(180deg);transform:rotate(180deg)}}@-webkit-keyframes rotate-270{0%{-webkit-transform:rotate(180deg);transform:rotate(180deg)}to{-webkit-transform:rotate(270deg);transform:rotate(270deg)}}@keyframes rotate-270{0%{-webkit-transform:rotate(180deg);transform:rotate(180deg)}to{-webkit-transform:rotate(270deg);transform:rotate(270deg)}}@-webkit-keyframes rotate-reverse-270{0%{-webkit-transform:rotate(1turn);transform:rotate(1turn)}to{-webkit-transform:rotate(270deg);transform:rotate(270deg)}}@keyframes rotate-reverse-270{0%{-webkit-transform:rotate(1turn);transform:rotate(1turn)}to{-webkit-transform:rotate(270deg);transform:rotate(270deg)}}@-webkit-keyframes rotate-360{0%{-webkit-transform:rotate(270deg);transform:rotate(270deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes rotate-360{0%{-webkit-transform:rotate(270deg);transform:rotate(270deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@-webkit-keyframes rotate-reverse-360{0%{-webkit-transform:rotate(450deg);transform:rotate(450deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes rotate-reverse-360{0%{-webkit-transform:rotate(450deg);transform:rotate(450deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.segment:not(.segment-row):not(.segment-triangle).rotating{z-index:10!important;overflow:hidden}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90{-webkit-animation-name:rotate-90;animation-name:rotate-90;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90>.child-container>.segment{-webkit-animation-name:rotate-360;animation-name:rotate-360;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;animation-direction:reverse;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-90;animation-name:rotate-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-180;animation-name:rotate-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-270;animation-name:rotate-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-360;animation-name:rotate-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90.reverse{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90.reverse>.child-container>.segment{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90.reverse>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90.reverse>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90.reverse>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90.reverse>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180{-webkit-animation-name:rotate-180;animation-name:rotate-180;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180>.child-container>.segment{-webkit-animation-name:rotate-270;animation-name:rotate-270;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;animation-direction:reverse;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-360;animation-name:rotate-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-90;animation-name:rotate-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-180;animation-name:rotate-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-270;animation-name:rotate-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180.reverse{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180.reverse>.child-container>.segment{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180.reverse>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180.reverse>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180.reverse>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180.reverse>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270{-webkit-animation-name:rotate-270;animation-name:rotate-270;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270>.child-container>.segment{-webkit-animation-name:rotate-180;animation-name:rotate-180;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;animation-direction:reverse;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-270;animation-name:rotate-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-360;animation-name:rotate-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-90;animation-name:rotate-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-180;animation-name:rotate-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270.reverse{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270.reverse>.child-container>.segment{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270.reverse>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270.reverse>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270.reverse>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270.reverse>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360{-webkit-animation-name:rotate-360;animation-name:rotate-360;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360>.child-container>.segment{-webkit-animation-name:rotate-90;animation-name:rotate-90;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;animation-direction:reverse;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-180;animation-name:rotate-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-270;animation-name:rotate-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-360;animation-name:rotate-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-90;animation-name:rotate-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360.reverse{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360.reverse>.child-container>.segment{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360.reverse>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360.reverse>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360.reverse>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360.reverse>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90{-webkit-transform:rotate(90deg);transform:rotate(90deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment{-webkit-transform:rotate(270deg);transform:rotate(270deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-90{-webkit-transform:rotate(1turn);transform:rotate(1turn);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-90.rotating{-webkit-animation-name:rotate-360;animation-name:rotate-360;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-90.rotating.reverse{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-180{-webkit-transform:rotate(90deg);transform:rotate(90deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-180.rotating{-webkit-animation-name:rotate-90;animation-name:rotate-90;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-180.rotating.reverse{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-270{-webkit-transform:rotate(180deg);transform:rotate(180deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-270.rotating{-webkit-animation-name:rotate-180;animation-name:rotate-180;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-270.rotating.reverse{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-360{-webkit-transform:rotate(270deg);transform:rotate(270deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-360.rotating{-webkit-animation-name:rotate-270;animation-name:rotate-270;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-360.rotating.reverse{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180,.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment{-webkit-transform:rotate(180deg);transform:rotate(180deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-90{-webkit-transform:rotate(270deg);transform:rotate(270deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-90.rotating{-webkit-animation-name:rotate-270;animation-name:rotate-270;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-90.rotating.reverse{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-180{-webkit-transform:rotate(1turn);transform:rotate(1turn);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-180.rotating{-webkit-animation-name:rotate-360;animation-name:rotate-360;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-180.rotating.reverse{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-270{-webkit-transform:rotate(90deg);transform:rotate(90deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-270.rotating{-webkit-animation-name:rotate-90;animation-name:rotate-90;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-270.rotating.reverse{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-360{-webkit-transform:rotate(180deg);transform:rotate(180deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-360.rotating{-webkit-animation-name:rotate-180;animation-name:rotate-180;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-360.rotating.reverse{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270{-webkit-transform:rotate(270deg);transform:rotate(270deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment{-webkit-transform:rotate(90deg);transform:rotate(90deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-90{-webkit-transform:rotate(180deg);transform:rotate(180deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-90.rotating{-webkit-animation-name:rotate-180;animation-name:rotate-180;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-90.rotating.reverse{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-180{-webkit-transform:rotate(270deg);transform:rotate(270deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-180.rotating{-webkit-animation-name:rotate-270;animation-name:rotate-270;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-180.rotating.reverse{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-270{-webkit-transform:rotate(1turn);transform:rotate(1turn);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-270.rotating{-webkit-animation-name:rotate-360;animation-name:rotate-360;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-270.rotating.reverse{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-360{-webkit-transform:rotate(90deg);transform:rotate(90deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-360.rotating{-webkit-animation-name:rotate-90;animation-name:rotate-90;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-360.rotating.reverse{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360{-webkit-transform:rotate(1turn);transform:rotate(1turn);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment{-webkit-transform:rotate(0deg);transform:rotate(0deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-90{-webkit-transform:rotate(90deg);transform:rotate(90deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-90.rotating{-webkit-animation-name:rotate-90;animation-name:rotate-90;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-90.rotating.reverse{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-180{-webkit-transform:rotate(180deg);transform:rotate(180deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-180.rotating{-webkit-animation-name:rotate-180;animation-name:rotate-180;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-180.rotating.reverse{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-270{-webkit-transform:rotate(270deg);transform:rotate(270deg);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-270.rotating{-webkit-animation-name:rotate-270;animation-name:rotate-270;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-270.rotating.reverse{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-360{-webkit-transform:rotate(1turn);transform:rotate(1turn);background-color:#fff;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-360.rotating{-webkit-animation-name:rotate-360;animation-name:rotate-360;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-360.rotating.reverse{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}#level{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;white-space:nowrap;max-width:100%;-webkit-tap-highlight-color:rgba(255,255,255,0);overflow-y:visible}#level,#level *,.segment{-webkit-transition:none;transition:none}.segment{vertical-align:top;white-space:normal;cursor:pointer;display:inline-block;text-align:center;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;z-index:1;background-color:#fff;line-height:0}.segment.segment-row{display:block;width:100%;-webkit-animation:none!important;animation:none!important;white-space:nowrap}.segment.segment-leaf{background-color:transparent;min-width:1em;padding:.8em}.segment.segment-leaf:before{content:" ";display:block;padding-top:100%}.segment.segment-leaf .leaf-element{position:absolute;width:100%;height:100%;line-height:1.5em;top:0;left:0}.segment.segment-parent{border:1px solid #a9a9a9;border-radius:3px;padding:1px}.segment.segment-parent.layer-2{border:3px solid #000}#site-content>:not(.won) .segment.locked,#site-content>:not(.won) .segment.locked>.child-container>.segment-leaf{border-color:#3adb76;background-color:#9ffbb5!important}#site-content>:not(.won) .show-when-won{display:none}.level-container{-webkit-transition:none;transition:none}.won .show-while-playing{display:none}.text-right{text-align:right}#continue-button{margin-bottom:2px} /*# sourceMappingURL=wordRotator.css.map */ \ No newline at end of file diff --git a/public/html/application/level.html b/public/html/application/level.html index 2f54d50..3aebe70 100755 --- a/public/html/application/level.html +++ b/public/html/application/level.html @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git a/public/js/app.js b/public/js/app.js index 24e72fc..d5d0476 100755 --- a/public/js/app.js +++ b/public/js/app.js @@ -4827,76 +4827,20 @@ InitPromise.addPromise(function (app) { app.addDeepLink("code", CodeSite); }); -class WordRotatorDb extends MyDb { - - static getInstance() { - if (Helper.isNull(WordRotatorDb.instance)) { - WordRotatorDb.instance = new WordRotatorDb(); - } - return WordRotatorDb.instance; - } - - constructor() { - super("wordRotator", 3); - } - - upgrade(db, oldVersion, newVersion, e) { - if (Helper.isNull(oldVersion) || oldVersion < 1 && newVersion >= 1) { - let levelObjectStore = db.createObjectStore(WordRotatorDb.OBJECT_STORE.LEVEL, {"keyPath": "id"}); - } - if (Helper.isNull(oldVersion) || oldVersion < 2 && newVersion >= 2) { - let levelObjectStore = e.target.transaction.objectStore(WordRotatorDb.OBJECT_STORE.LEVEL); - levelObjectStore.createIndex("played", ["deleted", "played", "difficulty", "id"], {"unique": false}); - } - if (Helper.isNull(oldVersion) || oldVersion < 3 && newVersion >= 3) { - let levelObjectStore = e.target.transaction.objectStore(WordRotatorDb.OBJECT_STORE.LEVEL); - levelObjectStore.createIndex("difficulty", "difficulty", {"unique": false}); - } - }; - - async saveManyLevels(levels) { - return this.saveMany(levels, WordRotatorDb.OBJECT_STORE.LEVEL); - } - - async loadLevel(levelId) { - return this.load(levelId, WordRotatorDb.OBJECT_STORE.LEVEL); - } - - async loadNextLevel(rendererTypes) { - const levels = await this.loadMany("difficulty", IDBKeyRange.lowerBound(0), WordRotatorDb.OBJECT_STORE.LEVEL); - - let wrongLevels = []; - let newLevels = []; - let difficulty = -1; - for (let i = 0, n = levels.length; i < n; i++) { - if ((difficulty < 0 || difficulty === levels[i]["difficulty"]) && !levels[i]["deleted"] && !levels[i]["played"] && rendererTypes.indexOf(levels[i]["rendererType"]) !== -1) { - newLevels.push(levels[i]); - difficulty = levels[i]["difficulty"]; - } - else if (levels[i]["difficulty"] !== 0 && !levels[i]["deleted"] && !levels[i]["played"] ) { - wrongLevels.push(levels[i]); - } - } - - if (newLevels.length === 0) { - return null; - } - - return newLevels[Math.round(Math.random() * newLevels.length) % newLevels.length]; - } - - async saveLevelPlayed(levelId) { - const level = await this.loadLevel(levelId); - level.played = true; - return await this.saveObj(level, WordRotatorDb.OBJECT_STORE.LEVEL); - } +class WordRotatorBaseSite extends AbstractSite { + // createActionBarMenu(menu) { + // menu = super.createActionBarMenu(menu); + // // menu.addAction(SettingsSite.settingsAction.copy()); + // // let actions = menu.actions; + // // for (let i = 0; i < actions.length; i++) { + // // if (actions[i].title === "login" || actions[i].title === "registration"){ + // // actions[i].setVisible(false); + // // } + // // } + // return menu; + // } } -WordRotatorDb.OBJECT_STORE = { - LEVEL: "level", -}; -WordRotatorDb.instance = null; - class TemplateContainer{ constructor(leafTemplate, parentTemplate, rowTemplate, triangleTemplate){ this.leafTemplate = leafTemplate; @@ -5044,6 +4988,7 @@ class ParentSegment extends Segment { this.touchendListener = function (e) { let target = document.elementFromPoint(e.changedTouches[0].pageX, e.changedTouches[0].pageY); if (e.targetTouches.length === 0 && e.changedTouches.length === 1 && self.element.contains(ParentSegment.mouseDownTarget) && self.element.contains(target)) { + self.getLevel().segmentClickedListener(self); self.rotate(ParentSegment.mouseDownTarget, target); e.stopPropagation(); e.preventDefault(); @@ -5051,6 +4996,7 @@ class ParentSegment extends Segment { }; this.mouseupListener = function (e) { if (ParentSegment.mouseDownTarget !== null && self.element.contains(ParentSegment.mouseDownTarget) && self.element.contains(e.target)) { + self.getLevel().segmentClickedListener(self); self.rotate(ParentSegment.mouseDownTarget, e.target); e.stopPropagation(); e.preventDefault(); @@ -5258,6 +5204,8 @@ class Level { self.wonResolver = resolve; self.giveUpResolver = reject; }); + + this.segmentClickedListener = () => {}; } saveAsCurrentLevel(){ @@ -5368,6 +5316,10 @@ class Level { return Level._getRotatableSegmentsFrom(this.rootSegment); } + setSegmentClickedListener(listener){ + this.segmentClickedListener = listener; + } + static _getRotatableSegmentsFrom(segment){ let rotatable = []; if (segment.canRotate()) @@ -5723,20 +5675,76 @@ LevelHelper.types = { 160: FourWordsLevel12, }; -class WordRotatorBaseSite extends AbstractSite { - // createActionBarMenu(menu) { - // menu = super.createActionBarMenu(menu); - // // menu.addAction(SettingsSite.settingsAction.copy()); - // // let actions = menu.actions; - // // for (let i = 0; i < actions.length; i++) { - // // if (actions[i].title === "login" || actions[i].title === "registration"){ - // // actions[i].setVisible(false); - // // } - // // } - // return menu; - // } +class WordRotatorDb extends MyDb { + + static getInstance() { + if (Helper.isNull(WordRotatorDb.instance)) { + WordRotatorDb.instance = new WordRotatorDb(); + } + return WordRotatorDb.instance; + } + + constructor() { + super("wordRotator", 3); + } + + upgrade(db, oldVersion, newVersion, e) { + if (Helper.isNull(oldVersion) || oldVersion < 1 && newVersion >= 1) { + let levelObjectStore = db.createObjectStore(WordRotatorDb.OBJECT_STORE.LEVEL, {"keyPath": "id"}); + } + if (Helper.isNull(oldVersion) || oldVersion < 2 && newVersion >= 2) { + let levelObjectStore = e.target.transaction.objectStore(WordRotatorDb.OBJECT_STORE.LEVEL); + levelObjectStore.createIndex("played", ["deleted", "played", "difficulty", "id"], {"unique": false}); + } + if (Helper.isNull(oldVersion) || oldVersion < 3 && newVersion >= 3) { + let levelObjectStore = e.target.transaction.objectStore(WordRotatorDb.OBJECT_STORE.LEVEL); + levelObjectStore.createIndex("difficulty", "difficulty", {"unique": false}); + } + }; + + async saveManyLevels(levels) { + return this.saveMany(levels, WordRotatorDb.OBJECT_STORE.LEVEL); + } + + async loadLevel(levelId) { + return this.load(levelId, WordRotatorDb.OBJECT_STORE.LEVEL); + } + + async loadNextLevel(rendererTypes) { + const levels = await this.loadMany("difficulty", IDBKeyRange.lowerBound(0), WordRotatorDb.OBJECT_STORE.LEVEL); + + let wrongLevels = []; + let newLevels = []; + let difficulty = -1; + for (let i = 0, n = levels.length; i < n; i++) { + if ((difficulty < 0 || difficulty === levels[i]["difficulty"]) && !levels[i]["deleted"] && !levels[i]["played"] && rendererTypes.indexOf(levels[i]["rendererType"]) !== -1) { + newLevels.push(levels[i]); + difficulty = levels[i]["difficulty"]; + } + else if (levels[i]["difficulty"] !== 0 && !levels[i]["deleted"] && !levels[i]["played"] ) { + wrongLevels.push(levels[i]); + } + } + + if (newLevels.length === 0) { + return null; + } + + return newLevels[Math.round(Math.random() * newLevels.length) % newLevels.length]; + } + + async saveLevelPlayed(levelId) { + const level = await this.loadLevel(levelId); + level.played = true; + return await this.saveObj(level, WordRotatorDb.OBJECT_STORE.LEVEL); + } } +WordRotatorDb.OBJECT_STORE = { + LEVEL: "level", +}; +WordRotatorDb.instance = null; + class EndSite extends WordRotatorBaseSite{ constructor(siteManager) { super(siteManager, "html/application/end.html"); @@ -5769,11 +5777,16 @@ class LevelSite extends WordRotatorBaseSite { aborted: false, coinCounterTimer: null, }; + this.coinPromise = Promise.resolve(); let settingsManager = SettingsManager.getInstance(); let soundManager = SoundManager.getInstance(); - soundManager.set({audio: "sound/single_coin_fall_on_concrete_.mp3", muted: !settingsManager.getSetting("play-sound", true), volume:0.7}, SoundManager.CHANNELS.SOUND); + soundManager.set({ + audio: "sound/single_coin_fall_on_concrete_.mp3", + muted: !settingsManager.getSetting("play-sound", true), + volume: 0.7 + }, SoundManager.CHANNELS.SOUND); return super.onConstruct(args); } @@ -5864,7 +5877,7 @@ class LevelSite extends WordRotatorBaseSite { this.levelScaler = await scaleHelper.scaleToFull(levelSegment, levelSegment.parentElement, false, false, 2, level.words[0].length * 2, null, 0); this.level = level; - return; + return this.tutorial(); } } catch (e) { @@ -5910,6 +5923,8 @@ class LevelSite extends WordRotatorBaseSite { this.wonParams.aborted = true; clearTimeout(this.wonParams.coinCounterTimer); + + return this.tutorial(); } catch (e) { console.error(e); @@ -5950,24 +5965,31 @@ class LevelSite extends WordRotatorBaseSite { this.coinContainer.removeAllChildren(); let coinsPerLevel = SystemSettings.get("coinsPerLevel", 5); - let coinsBefore = parseInt(Helper.nonNull(localStorage.getItem("coins"), "0")); - localStorage.setItem("coins", coinsBefore + parseInt(coinsPerLevel)); + + let coinsBefore = 0; let soundManager = SoundManager.getInstance(); let audioOptions = soundManager.get(SoundManager.CHANNELS.SOUND); - let coinPromise = Promise.all([new Promise((r) => { + this.coinPromise = Promise.all([new Promise((r) => { setTimeout(() => { r(continueButton.fadeIn()); }, 500); - }), audioOptions.loadedPromise.catch(e => {console.error(e);})]); + }), audioOptions.loadedPromise.catch(e => { + console.error(e); + }), + this.coinPromise.then(() => { + coinsBefore = parseInt(Helper.nonNull(localStorage.getItem("coins"), "0")); + localStorage.setItem("coins", coinsBefore + parseInt(coinsPerLevel)); + }) + ]); this.wonParams.aborted = false; for (let i = 0; i < coinsPerLevel; i++) { let coinElem = Helper.cloneNode(this.coinTemplate); this.coinContainer.appendChild(coinElem); - coinPromise = coinPromise.then(() => { + this.coinPromise = this.coinPromise.then(() => { return new Promise(r => { let timeout = 350; @@ -6027,8 +6049,85 @@ class LevelSite extends WordRotatorBaseSite { FlashMessenger.addMessage("not-enough-coins"); } } + + async tutorial() { + + if (this.level.id === LevelSite.TUTORIAL.FIRST_LEVEL) { + let currentStep = Helper.nonNull(localStorage.getItem("tutorial-step"), "1"); + + let scaleHelper = new ScaleHelper(); + this._siteContent.classList.add("tutorial"); + this._siteContent.classList.add("step-" + currentStep); + this.levelScaler(); + + switch (currentStep) { + case "1": { + this.level.setSegmentClickedListener(() => { + this._siteContent.classList.remove("step-1"); + localStorage.setItem("tutorial-step", "2"); + this.tutorial(); + }); + + let textElem = this.findBy(".tutorial-text .step-1"); + scaleHelper.scaleToFull(textElem, textElem.parentElement, null, true, null, 2); + + break; + } + case "2": { + this.level.setSegmentClickedListener(() => { + }); + this.level.getWonPromise().then(() => { + this._siteContent.classList.remove("tutorial"); + this._siteContent.classList.remove("step-2"); + localStorage.removeItem("tutorial-step"); + this.coinPromise = this.coinPromise.then(() => { + FlashMessenger.addMessage("extra-coins-after-first-level"); + localStorage.setItem("coins", parseInt(Helper.nonNull(localStorage.getItem("coins"), "0")) + 50); + this.coinAction.setTitle(Helper.nonNull(localStorage.getItem("coins"), "0")); + this.coinAction.redraw(); + }); + }); + + let textElem = this.findBy(".tutorial-text .step-2"); + scaleHelper.scaleToFull(textElem, textElem.parentElement, null, true, null, 2); + + break; + } + } + } + else if (this.level.id === LevelSite.TUTORIAL.SECOND_LEVEL) { + let currentStep = Helper.nonNull(localStorage.getItem("tutorial-step"), "3"); + + let scaleHelper = new ScaleHelper(); + + this._siteContent.classList.add("tutorial"); + this._siteContent.classList.add("step-" + currentStep); + this.levelScaler(); + + switch (currentStep) { + case "3": { + let eventListener = () => { + this._siteContent.classList.remove("tutorial"); + this._siteContent.classList.remove("step-2"); + localStorage.removeItem("tutorial-step"); + this.findBy("#help-button").removeEventListener("click", eventListener); + }; + this.findBy("#help-button").addEventListener("click", eventListener); + + let textElem = this.findBy(".tutorial-text .step-3"); + scaleHelper.scaleToFull(textElem, textElem.parentElement, null, true, null, 2); + break; + } + } + } + } } +LevelSite.TUTORIAL = { + FIRST_LEVEL: 67, + SECOND_LEVEL: 15, +}; + class MainMenuLevel extends FourWordsLevel{ constructor(templateContainer) { @@ -6045,7 +6144,7 @@ class MainMenuLevel extends FourWordsLevel{ class MenuSite extends WordRotatorBaseSite { constructor(siteManager) { super(siteManager, "html/application/menu.html"); - + this.loadLevelPromise = this.loadLevels(); this.listener = null; } @@ -6125,7 +6224,7 @@ class MenuSite extends WordRotatorBaseSite { let playButton = this.findBy("#play-button"); playButton.addEventListener("click", () => { - this.startSite(LevelSite); + this.startSite(LevelSite, this.loadLevelPromise); }); let leafSegmentTemplate = this.findBy("#segment-leaf-template"); @@ -6171,9 +6270,6 @@ class MenuSite extends WordRotatorBaseSite { playSoundButton.addEventListener("change", () => { settingsManager.setSetting("play-sound", playSoundButton.checked); soundManager.set({muted: !playSoundButton.checked}, SoundManager.CHANNELS.SOUND); - // if (playSoundButton.checked){ - // soundManager.play(SoundManager.CHANNELS.MUSIC); - // } }); } @@ -6182,30 +6278,6 @@ class MenuSite extends WordRotatorBaseSite { window.removeEventListener("resize", this.listener); super.onPause(args); } -} - -MenuSite.app = null; -InitPromise.addPromise(app => { - MenuSite.app = app; -}); - -class SynchronizeSite extends WordRotatorBaseSite { - - constructor(siteManager) { - super(siteManager, "html/application/sync.html"); - } - - async onConstruct(args) { - let res = await super.onConstruct(args); - await this.loadLevels(); - return res; - } - - onFirstStart() { - super.onFirstStart(); - this.startSite(MenuSite); - this.finish(); - } async loadLevels() { const dateLastSync = Helper.nonNull(localStorage.getItem("date-last-sync"), 0); @@ -6247,6 +6319,11 @@ class SynchronizeSite extends WordRotatorBaseSite { } } +MenuSite.app = null; +InitPromise.addPromise(app => { + MenuSite.app = app; +}); + class WordRotatorSettingFragment extends LocalStorageSettingsFragment { constructor(site) { super(site, "html/application/fragment/settings.html"); @@ -6280,6 +6357,7 @@ class WordRotatorSettingFragment extends LocalStorageSettingsFragment { localStorage.removeItem("currentLevel"); localStorage.removeItem("date-last-sync"); localStorage.removeItem("levelCounter"); + localStorage.removeItem("tutorial-step"); WordRotatorDb.getInstance().removeAll(WordRotatorDb.OBJECT_STORE.LEVEL); }); @@ -6298,7 +6376,7 @@ if (window.location.pathname.endsWith("publicTest/")) } SystemSettings.setBasePath(basePath); -Translator.supportedLanguages = ["de", "en"]; +Translator.supportedLanguages = ["de"]; Translator.markTranslations = false; applyPolyfills(); @@ -6341,6 +6419,6 @@ InitPromise.resolve(app).then(function(){ let soundManager = SoundManager.getInstance(); soundManager.play(SoundManager.CHANNELS.MUSIC, {audio: "sound/brightAndBeautifull__.mp3", loop: true, volume: 0.6, muted: !settingsManager.getSetting("play-music", true)}); - app.start(SynchronizeSite); + app.start(MenuSite); Translator.setLanguage("de"); }); diff --git a/public/js/lang/de.json b/public/js/lang/de.json index 585973a..8849864 100755 --- a/public/js/lang/de.json +++ b/public/js/lang/de.json @@ -1 +1 @@ -{"won":"Gewonnen!","continue":"Weiter","help":"?","not-enough-coins":"Du hast zu wenig Münzen!","sync-error":"Es gab einen Fehler beim Aktualisieren der Level. Bitte stelle sicher, dass du eine aktive Internetverbindung hast und versuche es später erneut.","game-ended":"Oh nein!
Es sieht so aus, als ob du schon alle Level gespielt hast...
Schau später noch einmal rein, evtl gibt es dann neue Level.","play":"Spielen!","Sunday":"Sonntag","Monday":"Montag","Tuesday":"Dienstag","Wednesday":"Mittwoch","Thursday":"Donnerstag","Friday":"Freitag","Saturday":"Samstag","January":"Januar","February":"Februar","March":"März","April":"April","May":"Mai","June":"Juni","July":"Juli","August":"August","September":"September","October":"Oktober","November":"November","December":"Dezember","Sun":"So","Mon":"Mo","Tue":"Di","Wed":"Mi","Thu":"Do","Fri":"Fr","Sat":"Sa","Jan":"Jan","Feb":"Feb","Mar":"Mär","Apr":"Apr","Jun":"Jun","Jul":"Jul","Aug":"Aug","Sep":"Sep","Oct":"Okt","Nov":"Nov","Dec":"Dez","code-not-valid":"Der angegebebe Code ist nicht gültig!","code-activated":"Der Code wurde erfolgreich aktiviert!","current-lang":"DE","en":"Englisch","de":"Deutsch","black":"Schwarz","red":"Rot","blue":"Blau","green":"Grün","pink":"Rosa","cancel-button":"ABBRECHEN","confirm-button":"OK","we-use-cookie-hint":"Diese Seite nutzt Cookies. Durch das weitere Benutzen dieser Seite geben Sie uns das Recht Cookies so zu benutzen, wie es in unserer Datenschutzerklärung steht.","policy-heading":"Datenschutzerklärung","area-of-validity-heading":"Geltungsbereich","area-of-validity":"Diese Datenschutzerklärung klärt Nutzer über die Art, den Umfang und Zwecke der Erhebung und Verwendung personenbezogener Daten durch den verantwortlichen Anbieter Silas Günther, Langenbusch 263b - 42897 Remscheid, matrix[at]silas.link auf dieser Website (im folgenden \"Angebot\") auf.

Die rechtlichen Grundlagen des Datenschutzes finden sich im Bundesdatenschutzgesetz (BDSG) und dem Telemediengesetz (TMG).","logfiles-heading":"Zugriffsdaten / Server-Logfiles","logfiles":"Der Anbieter (beziehungsweise sein Webspace-Provider) erhebt Daten über jeden Zugriff auf das Angebot (so genannte Serverlogfiles). Zu den Zugriffsdaten gehören:

Name der abgerufenen Webseite, Datei, Datum und Uhrzeit des Abrufs, übertragene Datenmenge, Meldung über erfolgreichen Abruf, Browsertyp nebst Version, das Betriebssystem des Nutzers, Referrer URL (die zuvor besuchte Seite), IP-Adresse und der anfragende Provider.

Der Anbieter verwendet die Protokolldaten nur für statistische Auswertungen zum Zweck des Betriebs, der Sicherheit und der Optimierung des Angebotes. Der Anbieter behält sich jedoch vor, die Protokolldaten nachträglich zu überprüfen, wenn aufgrund konkreter Anhaltspunkte der berechtigte Verdacht einer rechtswidrigen Nutzung besteht.","contact-support-heading":"Kontaktaufnahme","contact-support":"Bei der Kontaktaufnahme mit dem Anbieter (zum Beispiel per Post oder E-Mail) werden die Angaben des Nutzers zwecks Bearbeitung der Anfrage sowie für den Fall, dass Anschlussfragen entstehen, gespeichert.","cookies-heading":"Cookies","cookies":"Cookies sind kleine Dateien, die es ermöglichen, auf dem Zugriffsgerät der Nutzer (PC, Smartphone o.ä.) spezifische, auf das Gerät bezogene Informationen zu speichern. Sie dienen zum einem der Benutzerfreundlichkeit von Webseiten und damit den Nutzern (z.B. Speicherung von Logindaten). Zum anderen dienen sie, um die statistische Daten der Webseitennutzung zu erfassen und sie zwecks Verbesserung des Angebotes analysieren zu können. Die Nutzer können auf den Einsatz der Cookies Einfluss nehmen. Die meisten Browser verfügen eine Option mit der das Speichern von Cookies eingeschränkt oder komplett verhindert wird. Allerdings wird darauf hingewiesen, dass die Nutzung und insbesondere der Nutzungskomfort ohne Cookies eingeschränkt werden.

Sie können viele Online-Anzeigen-Cookies von Unternehmen über die US-amerikanische Seite http://www.aboutads.info/choices/ oder die EU-Seite http://www.youronlinechoices.com/uk/your-ad-choices/ verwalten.","google-analytics-heading":"Google Analytics","google-analytics":"Dieses Angebot benutzt Google Analytics, einen Webanalysedienst der Google Inc. („Google“). Google Analytics verwendet sog. „Cookies“, Textdateien, die auf Computer der Nutzer gespeichert werden und die eine Analyse der Benutzung der Website durch sie ermöglichen. Die durch den Cookie erzeugten Informationen über Benutzung dieser Website durch die Nutzer werden in der Regel an einen Server von Google in den USA übertragen und dort gespeichert.

Im Falle der Aktivierung der IP-Anonymisierung auf dieser Webseite, wird die IP-Adresse der Nutzer von Google jedoch innerhalb von Mitgliedstaaten der Europäischen Union oder in anderen Vertragsstaaten des Abkommens über den Europäischen Wirtschaftsraum zuvor gekürzt. Nur in Ausnahmefällen wird die volle IP-Adresse an einen Server von Google in den USA übertragen und dort gekürzt. Die IP-Anonymisierung ist auf dieser Website aktiv. Im Auftrag des Betreibers dieser Website wird Google diese Informationen benutzen, um die Nutzung der Website durch die Nutzer auszuwerten, um Reports über die Websiteaktivitäten zusammenzustellen und um weitere mit der Websitenutzung und der Internetnutzung verbundene Dienstleistungen gegenüber dem Websitebetreiber zu erbringen.

Die im Rahmen von Google Analytics von Ihrem Browser übermittelte IP-Adresse wird nicht mit anderen Daten von Google zusammengeführt. Die Nutzer können die Speicherung der Cookies durch eine entsprechende Einstellung Ihrer Browser-Software verhindern; Dieses Angebot weist die Nutzer jedoch darauf hin, dass Sie in diesem Fall gegebenenfalls nicht sämtliche Funktionen dieser Website vollumfänglich werden nutzen können. Die Nutzer können darüber hinaus die Erfassung der durch das Cookie erzeugten und auf ihre Nutzung der Website bezogenen Daten (inkl. Ihrer IP-Adresse) an Google sowie die Verarbeitung dieser Daten durch Google verhindern, indem sie das unter dem folgenden Link verfügbare Browser-Plugin herunterladen und installieren: http://tools.google.com/dlpage/gaoptout?hl=de.

Weitere Informationen zur Datennutzung zu Werbezwecken durch Google, Einstellungs- und Widerspruchsmöglichkeiten erfahren Sie auf den Webseiten von Google:
https://www.google.com/intl/de/policies/privacy/partners/ („Datennutzung durch Google bei Ihrer Nutzung von Websites oder Apps unserer Partner“),
http://www.google.com/policies/technologies/ads („Datennutzung zu Werbezwecken“),
http://www.google.de/settings/ads („Informationen verwalten, die Google verwendet, um Ihnen Werbung einzublenden“) und
http://www.google.com/ads/preferences/ („Bestimmen Sie, welche Werbung Google Ihnen zeigt“).","edited-hint":"Der generierte Text wurde vom Webseiteninhaber angepasst.","generated-hint":"Erstellt mit Datenschutz-Generator.de von RA Dr. Thomas Schwenke","google-play-services-heading":"Google Play Dienste","google-play-services":"Features wie die Bestenliste und Erfolge benötigen einen Login bei Google Play. Hierfür wird die Identität benötigt, um die entsprechenden Punktzahlen und Erfolge an das jeweilige Google Play-Konto zu knüpfen. Alle anderen Features sind weiterhin auch ohne Login bei Google Play nutzbar. Außerdem kann sich jederzeit in den Einstellungen von Google Play abgemeldet werden.","settings":"Einstellungen","close":"Schließen","other-apps":"Andere Apps","optimistic-locking-dialog":"Deine Änderungen können nicht gespeichert werden! Ein anderer Benutzer hat die Daten bereits verändert. Bitte lade die Daten neu und speichere danach.","optimistic-locking-dialog-title":"Nicht gespeichert!","not-online":"Du bist nicht mit dem Internet verbunden. Bitte überprüfe deine Verbindung.","search":"Suchen...","site":"Seite","HTTP-Exception (403) Forbidden":"Nicht erlaubt!","login":"Login","login-email":"E-Mail","login-password":"Passwort","login-automated-login":"Automatischer Login","login-submit":"Login","logout":"Ausloggen","username-or-password-wrong":"Entweder der Username oder das Passwort stimmt nicht!","login-success":"Willkommen zurück!","logged-out-successfully":"Tschüss!","registration":"Registrieren","registration-username":"Username","registration-email":"E-Mail","registration-password1":"Passwort","registration-password2":"Passwort wiederholen","registration-submit":"Registrieren","registration-success":"Ein Registrierungscode wurde an Ihre E-Mailadresse gesendet.","not-allowed-title":"Nicht erlaubt!","not-allowed":"Du hast keine Berechtigung für diese Seite. Wenn das ein Fehler ist, wende dich bitte an einen Admin.","forgot-password":"Passwort vergessen?","forgot-password-title":"Passwort vergessen","forgot-password-email":"E-Mail","forgot-password-submit":"Absenden","forgot-password-text":"Gib deine E-Mailadresse in das Feld ein. Ist die Adresse registriert, werden wir eine E-Mail mit einem Passwort-Resetcode senden.","no-user-found":"Es gibt keinen Benutzer mit dieser E-Mailadresse","new-password-code-send":"Es wurde ein Reset-Code an deine E-Mailadresse gesendet.","new-password":"Neues Passwort","new-password-password1":"Passwort","new-password-password2":"Passwort wiederholen","new-password-submit":"Passwort setzten","password-updated":"Das Passwort ist geupdated!","user-settings":"E-Mail & Username","user-settings-title":"E-Mail & Username","user-settings-form-username":"Username","user-settings-form-old-email":"Aktuelle E-Mail","user-settings-form-new-email":"Neue E-Mail","user-settings-form-submit":"Speichern","user-data-is-changed":"Die Daten wurden gespeichert.","email-code-send":"Ein Änderungscode wurde an die neue E-Mailadresse gesendet. Sobald der Code aktiviert wurde, werden Ihnen E-Mails an die neue Adresse gesendet.","change-email-new-automated-login":"Wenn die E-Mailadresse geändert wird, muss der automatische Login erneut aktiviert werden!","password-settings":"Passwort","change-password-title":"Passwort","change-password-new-automated-login":"Wenn das Passwort geändert wird, muss der automatische Login erneut aktiviert werden!","change-password-old-password":"Altes Passwort","change-password-new-password1":"Neues Passwort","change-password-new-password2":"Neues Passwort wiederholen","change-password-submit":"Speichern","password-changed":"Das Passwort wurde erfolgreich geändert!","registration-username-empty":"Der Username darf nicht leer sein.","registration-username-wrong-char":"Der Username darf nur aus Buchstaben, Zahlen oder den folgenden Zeichen bestehen: -_.&;()#!?$+\",","registration-username-already-taken":"Der Username ist schon vergeben. Bitte wähle einen anderen.","registration-password-empty":"Das Passwort darf nicht leer sein.","registration-password-short":"Das Passwort muss mindestens 8 Zeichen lang sein.","registration-password-not-identical":"Die Passwörter sind nicht identlisch.","registration-email-empty":"Die Email darf nicht leer sein.","registration-email-not-valid":"Die Emailadresse ist keine gültige Emailadresse.","registration-email-already-taken":"Es gibt bereits einen Account mit der Emailadresse.","change-password-old-password-wrong":"Das Passwort stimmt nicht!","user-roles-heading":"Benutzerrollen","user-roles-list":"Aktuelle Rollen:","available-roles-list":"Verfügbare Rollen:","name":"Name","description":"Beschreibung"} \ No newline at end of file +{"won":"Gewonnen!","continue":"Weiter","help":"?","not-enough-coins":"Du hast zu wenig Münzen!","sync-error":"Es gab einen Fehler beim Aktualisieren der Level. Bitte stelle sicher, dass du eine aktive Internetverbindung hast und versuche es später erneut.","game-ended":"Oh nein!
Es sieht so aus, als ob du schon alle Level gespielt hast...
Schau später noch einmal rein, evtl gibt es dann neue Level.","play":"Spielen!","tutorial-step-1":"Klicke auf ein Feld, um dieses rotieren zu lassen!","tutorial-step-2":"Um zu gewinnen, drehe die Segmente so, dass du zwei Wörter lesen kannst.","tutorial-step-3":"Durch die Hilfe kannst du ein Segment lösen lassen. Die Hilfe kostet aber 25 Münzen. Probiere jetzt die Hilfe aus.","extra-coins-after-first-level":"Für das erste Level gibt es 50 extra Münzen!","Sunday":"Sonntag","Monday":"Montag","Tuesday":"Dienstag","Wednesday":"Mittwoch","Thursday":"Donnerstag","Friday":"Freitag","Saturday":"Samstag","January":"Januar","February":"Februar","March":"März","April":"April","May":"Mai","June":"Juni","July":"Juli","August":"August","September":"September","October":"Oktober","November":"November","December":"Dezember","Sun":"So","Mon":"Mo","Tue":"Di","Wed":"Mi","Thu":"Do","Fri":"Fr","Sat":"Sa","Jan":"Jan","Feb":"Feb","Mar":"Mär","Apr":"Apr","Jun":"Jun","Jul":"Jul","Aug":"Aug","Sep":"Sep","Oct":"Okt","Nov":"Nov","Dec":"Dez","code-not-valid":"Der angegebebe Code ist nicht gültig!","code-activated":"Der Code wurde erfolgreich aktiviert!","current-lang":"DE","en":"Englisch","de":"Deutsch","black":"Schwarz","red":"Rot","blue":"Blau","green":"Grün","pink":"Rosa","cancel-button":"ABBRECHEN","confirm-button":"OK","we-use-cookie-hint":"Diese Seite nutzt Cookies. Durch das weitere Benutzen dieser Seite geben Sie uns das Recht Cookies so zu benutzen, wie es in unserer Datenschutzerklärung steht.","policy-heading":"Datenschutzerklärung","area-of-validity-heading":"Geltungsbereich","area-of-validity":"Diese Datenschutzerklärung klärt Nutzer über die Art, den Umfang und Zwecke der Erhebung und Verwendung personenbezogener Daten durch den verantwortlichen Anbieter Silas Günther, Langenbusch 263b - 42897 Remscheid, matrix[at]silas.link auf dieser Website (im folgenden \"Angebot\") auf.

Die rechtlichen Grundlagen des Datenschutzes finden sich im Bundesdatenschutzgesetz (BDSG) und dem Telemediengesetz (TMG).","logfiles-heading":"Zugriffsdaten / Server-Logfiles","logfiles":"Der Anbieter (beziehungsweise sein Webspace-Provider) erhebt Daten über jeden Zugriff auf das Angebot (so genannte Serverlogfiles). Zu den Zugriffsdaten gehören:

Name der abgerufenen Webseite, Datei, Datum und Uhrzeit des Abrufs, übertragene Datenmenge, Meldung über erfolgreichen Abruf, Browsertyp nebst Version, das Betriebssystem des Nutzers, Referrer URL (die zuvor besuchte Seite), IP-Adresse und der anfragende Provider.

Der Anbieter verwendet die Protokolldaten nur für statistische Auswertungen zum Zweck des Betriebs, der Sicherheit und der Optimierung des Angebotes. Der Anbieter behält sich jedoch vor, die Protokolldaten nachträglich zu überprüfen, wenn aufgrund konkreter Anhaltspunkte der berechtigte Verdacht einer rechtswidrigen Nutzung besteht.","contact-support-heading":"Kontaktaufnahme","contact-support":"Bei der Kontaktaufnahme mit dem Anbieter (zum Beispiel per Post oder E-Mail) werden die Angaben des Nutzers zwecks Bearbeitung der Anfrage sowie für den Fall, dass Anschlussfragen entstehen, gespeichert.","cookies-heading":"Cookies","cookies":"Cookies sind kleine Dateien, die es ermöglichen, auf dem Zugriffsgerät der Nutzer (PC, Smartphone o.ä.) spezifische, auf das Gerät bezogene Informationen zu speichern. Sie dienen zum einem der Benutzerfreundlichkeit von Webseiten und damit den Nutzern (z.B. Speicherung von Logindaten). Zum anderen dienen sie, um die statistische Daten der Webseitennutzung zu erfassen und sie zwecks Verbesserung des Angebotes analysieren zu können. Die Nutzer können auf den Einsatz der Cookies Einfluss nehmen. Die meisten Browser verfügen eine Option mit der das Speichern von Cookies eingeschränkt oder komplett verhindert wird. Allerdings wird darauf hingewiesen, dass die Nutzung und insbesondere der Nutzungskomfort ohne Cookies eingeschränkt werden.

Sie können viele Online-Anzeigen-Cookies von Unternehmen über die US-amerikanische Seite http://www.aboutads.info/choices/ oder die EU-Seite http://www.youronlinechoices.com/uk/your-ad-choices/ verwalten.","google-analytics-heading":"Google Analytics","google-analytics":"Dieses Angebot benutzt Google Analytics, einen Webanalysedienst der Google Inc. („Google“). Google Analytics verwendet sog. „Cookies“, Textdateien, die auf Computer der Nutzer gespeichert werden und die eine Analyse der Benutzung der Website durch sie ermöglichen. Die durch den Cookie erzeugten Informationen über Benutzung dieser Website durch die Nutzer werden in der Regel an einen Server von Google in den USA übertragen und dort gespeichert.

Im Falle der Aktivierung der IP-Anonymisierung auf dieser Webseite, wird die IP-Adresse der Nutzer von Google jedoch innerhalb von Mitgliedstaaten der Europäischen Union oder in anderen Vertragsstaaten des Abkommens über den Europäischen Wirtschaftsraum zuvor gekürzt. Nur in Ausnahmefällen wird die volle IP-Adresse an einen Server von Google in den USA übertragen und dort gekürzt. Die IP-Anonymisierung ist auf dieser Website aktiv. Im Auftrag des Betreibers dieser Website wird Google diese Informationen benutzen, um die Nutzung der Website durch die Nutzer auszuwerten, um Reports über die Websiteaktivitäten zusammenzustellen und um weitere mit der Websitenutzung und der Internetnutzung verbundene Dienstleistungen gegenüber dem Websitebetreiber zu erbringen.

Die im Rahmen von Google Analytics von Ihrem Browser übermittelte IP-Adresse wird nicht mit anderen Daten von Google zusammengeführt. Die Nutzer können die Speicherung der Cookies durch eine entsprechende Einstellung Ihrer Browser-Software verhindern; Dieses Angebot weist die Nutzer jedoch darauf hin, dass Sie in diesem Fall gegebenenfalls nicht sämtliche Funktionen dieser Website vollumfänglich werden nutzen können. Die Nutzer können darüber hinaus die Erfassung der durch das Cookie erzeugten und auf ihre Nutzung der Website bezogenen Daten (inkl. Ihrer IP-Adresse) an Google sowie die Verarbeitung dieser Daten durch Google verhindern, indem sie das unter dem folgenden Link verfügbare Browser-Plugin herunterladen und installieren: http://tools.google.com/dlpage/gaoptout?hl=de.

Weitere Informationen zur Datennutzung zu Werbezwecken durch Google, Einstellungs- und Widerspruchsmöglichkeiten erfahren Sie auf den Webseiten von Google:
https://www.google.com/intl/de/policies/privacy/partners/ („Datennutzung durch Google bei Ihrer Nutzung von Websites oder Apps unserer Partner“),
http://www.google.com/policies/technologies/ads („Datennutzung zu Werbezwecken“),
http://www.google.de/settings/ads („Informationen verwalten, die Google verwendet, um Ihnen Werbung einzublenden“) und
http://www.google.com/ads/preferences/ („Bestimmen Sie, welche Werbung Google Ihnen zeigt“).","edited-hint":"Der generierte Text wurde vom Webseiteninhaber angepasst.","generated-hint":"Erstellt mit Datenschutz-Generator.de von RA Dr. Thomas Schwenke","google-play-services-heading":"Google Play Dienste","google-play-services":"Features wie die Bestenliste und Erfolge benötigen einen Login bei Google Play. Hierfür wird die Identität benötigt, um die entsprechenden Punktzahlen und Erfolge an das jeweilige Google Play-Konto zu knüpfen. Alle anderen Features sind weiterhin auch ohne Login bei Google Play nutzbar. Außerdem kann sich jederzeit in den Einstellungen von Google Play abgemeldet werden.","settings":"Einstellungen","close":"Schließen","other-apps":"Andere Apps","optimistic-locking-dialog":"Deine Änderungen können nicht gespeichert werden! Ein anderer Benutzer hat die Daten bereits verändert. Bitte lade die Daten neu und speichere danach.","optimistic-locking-dialog-title":"Nicht gespeichert!","not-online":"Du bist nicht mit dem Internet verbunden. Bitte überprüfe deine Verbindung.","search":"Suchen...","site":"Seite","HTTP-Exception (403) Forbidden":"Nicht erlaubt!","login":"Login","login-email":"E-Mail","login-password":"Passwort","login-automated-login":"Automatischer Login","login-submit":"Login","logout":"Ausloggen","username-or-password-wrong":"Entweder der Username oder das Passwort stimmt nicht!","login-success":"Willkommen zurück!","logged-out-successfully":"Tschüss!","registration":"Registrieren","registration-username":"Username","registration-email":"E-Mail","registration-password1":"Passwort","registration-password2":"Passwort wiederholen","registration-submit":"Registrieren","registration-success":"Ein Registrierungscode wurde an Ihre E-Mailadresse gesendet.","not-allowed-title":"Nicht erlaubt!","not-allowed":"Du hast keine Berechtigung für diese Seite. Wenn das ein Fehler ist, wende dich bitte an einen Admin.","forgot-password":"Passwort vergessen?","forgot-password-title":"Passwort vergessen","forgot-password-email":"E-Mail","forgot-password-submit":"Absenden","forgot-password-text":"Gib deine E-Mailadresse in das Feld ein. Ist die Adresse registriert, werden wir eine E-Mail mit einem Passwort-Resetcode senden.","no-user-found":"Es gibt keinen Benutzer mit dieser E-Mailadresse","new-password-code-send":"Es wurde ein Reset-Code an deine E-Mailadresse gesendet.","new-password":"Neues Passwort","new-password-password1":"Passwort","new-password-password2":"Passwort wiederholen","new-password-submit":"Passwort setzten","password-updated":"Das Passwort ist geupdated!","user-settings":"E-Mail & Username","user-settings-title":"E-Mail & Username","user-settings-form-username":"Username","user-settings-form-old-email":"Aktuelle E-Mail","user-settings-form-new-email":"Neue E-Mail","user-settings-form-submit":"Speichern","user-data-is-changed":"Die Daten wurden gespeichert.","email-code-send":"Ein Änderungscode wurde an die neue E-Mailadresse gesendet. Sobald der Code aktiviert wurde, werden Ihnen E-Mails an die neue Adresse gesendet.","change-email-new-automated-login":"Wenn die E-Mailadresse geändert wird, muss der automatische Login erneut aktiviert werden!","password-settings":"Passwort","change-password-title":"Passwort","change-password-new-automated-login":"Wenn das Passwort geändert wird, muss der automatische Login erneut aktiviert werden!","change-password-old-password":"Altes Passwort","change-password-new-password1":"Neues Passwort","change-password-new-password2":"Neues Passwort wiederholen","change-password-submit":"Speichern","password-changed":"Das Passwort wurde erfolgreich geändert!","registration-username-empty":"Der Username darf nicht leer sein.","registration-username-wrong-char":"Der Username darf nur aus Buchstaben, Zahlen oder den folgenden Zeichen bestehen: -_.&;()#!?$+\",","registration-username-already-taken":"Der Username ist schon vergeben. Bitte wähle einen anderen.","registration-password-empty":"Das Passwort darf nicht leer sein.","registration-password-short":"Das Passwort muss mindestens 8 Zeichen lang sein.","registration-password-not-identical":"Die Passwörter sind nicht identlisch.","registration-email-empty":"Die Email darf nicht leer sein.","registration-email-not-valid":"Die Emailadresse ist keine gültige Emailadresse.","registration-email-already-taken":"Es gibt bereits einen Account mit der Emailadresse.","change-password-old-password-wrong":"Das Passwort stimmt nicht!","user-roles-heading":"Benutzerrollen","user-roles-list":"Aktuelle Rollen:","available-roles-list":"Verfügbare Rollen:","name":"Name","description":"Beschreibung"} \ No newline at end of file diff --git a/src/js/init.js b/src/js/init.js index 0823aa4..528bccb 100755 --- a/src/js/init.js +++ b/src/js/init.js @@ -16,14 +16,16 @@ import "./lib/pwa-assets" import "./lib/pwa-code-management" import "./lib/pwa-user-management" -import {SynchronizeSite} from "../module/Application/pwa/js/site/SynchronizeSite"; import {SettingsManager, SettingsSite} from "./lib/pwa-core"; -applyPolyfills(); +import {SoundManager} from "./lib/pwa-assets"; +import {MenuSite} from "../module/Application/pwa/js/site/MenuSite"; import {WordRotatorSettingFragment} from "../module/Application/pwa/js/Fragment/WordRotatorSettingFragment"; +applyPolyfills(); + + import './settings' -import {SoundManager} from "./lib/pwa-assets"; ThemeManager.addTheme(new Theme('red', '')); ThemeManager.addTheme(new Theme("blue", "blue")); @@ -63,7 +65,7 @@ InitPromise.resolve(app).then(function(){ let soundManager = SoundManager.getInstance(); soundManager.play(SoundManager.CHANNELS.MUSIC, {audio: "sound/brightAndBeautifull__.mp3", loop: true, volume: 0.6, muted: !settingsManager.getSetting("play-music", true)}); - app.start(SynchronizeSite); + app.start(MenuSite); Translator.setLanguage("de"); }); \ No newline at end of file diff --git a/src/js/settings.js b/src/js/settings.js index 99b7851..da43aa3 100755 --- a/src/js/settings.js +++ b/src/js/settings.js @@ -8,7 +8,7 @@ if (window.location.pathname.endsWith("publicTest/")) } SystemSettings.setBasePath(basePath); -Translator.supportedLanguages = ["de", "en"]; +Translator.supportedLanguages = ["de"]; Translator.markTranslations = false; const TRACKING_ID = ''; diff --git a/src/module/Application/pwa/html/application/level.html b/src/module/Application/pwa/html/application/level.html index 932638e..0979215 100755 --- a/src/module/Application/pwa/html/application/level.html +++ b/src/module/Application/pwa/html/application/level.html @@ -14,10 +14,14 @@
-
+
@@ -36,4 +40,7 @@
+ +
+
\ No newline at end of file diff --git a/src/module/Application/pwa/js/Fragment/WordRotatorSettingFragment.js b/src/module/Application/pwa/js/Fragment/WordRotatorSettingFragment.js index c96a19a..41f8b3a 100644 --- a/src/module/Application/pwa/js/Fragment/WordRotatorSettingFragment.js +++ b/src/module/Application/pwa/js/Fragment/WordRotatorSettingFragment.js @@ -35,6 +35,7 @@ export class WordRotatorSettingFragment extends LocalStorageSettingsFragment { localStorage.removeItem("currentLevel"); localStorage.removeItem("date-last-sync"); localStorage.removeItem("levelCounter"); + localStorage.removeItem("tutorial-step"); WordRotatorDb.getInstance().removeAll(WordRotatorDb.OBJECT_STORE.LEVEL); }); diff --git a/src/module/Application/pwa/js/site/LevelSite.js b/src/module/Application/pwa/js/site/LevelSite.js index 54be262..a9c4df0 100755 --- a/src/module/Application/pwa/js/site/LevelSite.js +++ b/src/module/Application/pwa/js/site/LevelSite.js @@ -33,11 +33,16 @@ export class LevelSite extends WordRotatorBaseSite { aborted: false, coinCounterTimer: null, }; + this.coinPromise = Promise.resolve(); let settingsManager = SettingsManager.getInstance(); let soundManager = SoundManager.getInstance(); - soundManager.set({audio: "sound/single_coin_fall_on_concrete_.mp3", muted: !settingsManager.getSetting("play-sound", true), volume:0.7}, SoundManager.CHANNELS.SOUND); + soundManager.set({ + audio: "sound/single_coin_fall_on_concrete_.mp3", + muted: !settingsManager.getSetting("play-sound", true), + volume: 0.7 + }, SoundManager.CHANNELS.SOUND); return super.onConstruct(args); } @@ -128,7 +133,7 @@ export class LevelSite extends WordRotatorBaseSite { this.levelScaler = await scaleHelper.scaleToFull(levelSegment, levelSegment.parentElement, false, false, 2, level.words[0].length * 2, null, 0); this.level = level; - return; + return this.tutorial(); } } catch (e) { @@ -174,6 +179,8 @@ export class LevelSite extends WordRotatorBaseSite { this.wonParams.aborted = true; clearTimeout(this.wonParams.coinCounterTimer); + + return this.tutorial(); } catch (e) { console.error(e); @@ -214,24 +221,31 @@ export class LevelSite extends WordRotatorBaseSite { this.coinContainer.removeAllChildren(); let coinsPerLevel = SystemSettings.get("coinsPerLevel", 5); - let coinsBefore = parseInt(Helper.nonNull(localStorage.getItem("coins"), "0")); - localStorage.setItem("coins", coinsBefore + parseInt(coinsPerLevel)); + + let coinsBefore = 0; let soundManager = SoundManager.getInstance(); let audioOptions = soundManager.get(SoundManager.CHANNELS.SOUND); - let coinPromise = Promise.all([new Promise((r) => { + this.coinPromise = Promise.all([new Promise((r) => { setTimeout(() => { r(continueButton.fadeIn()); }, 500) - }), audioOptions.loadedPromise.catch(e => {console.error(e)})]); + }), audioOptions.loadedPromise.catch(e => { + console.error(e) + }), + this.coinPromise.then(() => { + coinsBefore = parseInt(Helper.nonNull(localStorage.getItem("coins"), "0")); + localStorage.setItem("coins", coinsBefore + parseInt(coinsPerLevel)); + }) + ]); this.wonParams.aborted = false; for (let i = 0; i < coinsPerLevel; i++) { let coinElem = Helper.cloneNode(this.coinTemplate); this.coinContainer.appendChild(coinElem); - coinPromise = coinPromise.then(() => { + this.coinPromise = this.coinPromise.then(() => { return new Promise(r => { let timeout = 350; @@ -291,4 +305,81 @@ export class LevelSite extends WordRotatorBaseSite { FlashMessenger.addMessage("not-enough-coins"); } } -} \ No newline at end of file + + async tutorial() { + + if (this.level.id === LevelSite.TUTORIAL.FIRST_LEVEL) { + let currentStep = Helper.nonNull(localStorage.getItem("tutorial-step"), "1"); + + let scaleHelper = new ScaleHelper(); + this._siteContent.classList.add("tutorial"); + this._siteContent.classList.add("step-" + currentStep); + this.levelScaler(); + + switch (currentStep) { + case "1": { + this.level.setSegmentClickedListener(() => { + this._siteContent.classList.remove("step-1"); + localStorage.setItem("tutorial-step", "2"); + this.tutorial(); + }); + + let textElem = this.findBy(".tutorial-text .step-1"); + scaleHelper.scaleToFull(textElem, textElem.parentElement, null, true, null, 2); + + break; + } + case "2": { + this.level.setSegmentClickedListener(() => { + }); + this.level.getWonPromise().then(() => { + this._siteContent.classList.remove("tutorial"); + this._siteContent.classList.remove("step-2"); + localStorage.removeItem("tutorial-step"); + this.coinPromise = this.coinPromise.then(() => { + FlashMessenger.addMessage("extra-coins-after-first-level"); + localStorage.setItem("coins", parseInt(Helper.nonNull(localStorage.getItem("coins"), "0")) + 50); + this.coinAction.setTitle(Helper.nonNull(localStorage.getItem("coins"), "0")); + this.coinAction.redraw(); + }); + }); + + let textElem = this.findBy(".tutorial-text .step-2"); + scaleHelper.scaleToFull(textElem, textElem.parentElement, null, true, null, 2); + + break; + } + } + } + else if (this.level.id === LevelSite.TUTORIAL.SECOND_LEVEL) { + let currentStep = Helper.nonNull(localStorage.getItem("tutorial-step"), "3"); + + let scaleHelper = new ScaleHelper(); + + this._siteContent.classList.add("tutorial"); + this._siteContent.classList.add("step-" + currentStep); + this.levelScaler(); + + switch (currentStep) { + case "3": { + let eventListener = () => { + this._siteContent.classList.remove("tutorial"); + this._siteContent.classList.remove("step-2"); + localStorage.removeItem("tutorial-step"); + this.findBy("#help-button").removeEventListener("click", eventListener); + }; + this.findBy("#help-button").addEventListener("click", eventListener); + + let textElem = this.findBy(".tutorial-text .step-3"); + scaleHelper.scaleToFull(textElem, textElem.parentElement, null, true, null, 2); + break; + } + } + } + } +} + +LevelSite.TUTORIAL = { + FIRST_LEVEL: 67, + SECOND_LEVEL: 15, +}; \ No newline at end of file diff --git a/src/module/Application/pwa/js/site/MenuSite.js b/src/module/Application/pwa/js/site/MenuSite.js index db4a4d1..3ccfc06 100644 --- a/src/module/Application/pwa/js/site/MenuSite.js +++ b/src/module/Application/pwa/js/site/MenuSite.js @@ -3,13 +3,14 @@ import {LevelSite} from "./LevelSite"; import {ScaleHelper, SoundManager} from "../../../../../js/lib/pwa-assets"; import {TemplateContainer} from "../wordrotator/Segment/TemplateContainer"; import {MainMenuLevel} from "../wordrotator/Level/MainMenuLevel"; -import {Helper, InitPromise} from "../../../../../js/lib/pwa-lib"; -import {SettingsManager} from "../../../../../js/lib/pwa-core"; +import {FlashMessenger, Helper, InitPromise} from "../../../../../js/lib/pwa-lib"; +import {DataManager, SettingsManager} from "../../../../../js/lib/pwa-core"; +import {WordRotatorDb} from "../WordRotatorDb"; export class MenuSite extends WordRotatorBaseSite { constructor(siteManager) { super(siteManager, "html/application/menu.html"); - + this.loadLevelPromise = this.loadLevels(); this.listener = null; } @@ -89,7 +90,7 @@ export class MenuSite extends WordRotatorBaseSite { let playButton = this.findBy("#play-button"); playButton.addEventListener("click", () => { - this.startSite(LevelSite); + this.startSite(LevelSite, this.loadLevelPromise); }); let leafSegmentTemplate = this.findBy("#segment-leaf-template"); @@ -135,9 +136,6 @@ export class MenuSite extends WordRotatorBaseSite { playSoundButton.addEventListener("change", () => { settingsManager.setSetting("play-sound", playSoundButton.checked); soundManager.set({muted: !playSoundButton.checked}, SoundManager.CHANNELS.SOUND); - // if (playSoundButton.checked){ - // soundManager.play(SoundManager.CHANNELS.MUSIC); - // } }); } @@ -146,6 +144,45 @@ export class MenuSite extends WordRotatorBaseSite { window.removeEventListener("resize", this.listener); super.onPause(args); } + + async loadLevels() { + const dateLastSync = Helper.nonNull(localStorage.getItem("date-last-sync"), 0); + const db = WordRotatorDb.getInstance(); + + let newLastSync = null; + let maxRuns = 1; + let levelPromises = []; + for (let run = 0; run < maxRuns; run++) { + let res = await DataManager.load("wordRotator/levels" + DataManager.buildQuery({ + "currentRun": run, + "dateLastSync": dateLastSync + })); + if (!res["success"]) { + FlashMessenger.addMessage("sync-error", null, 6000); + newLastSync = null; + break; + } + res = res["result"]; + newLastSync = Helper.nonNull(newLastSync, res["currentSyncDate"]); + maxRuns = res["maxRuns"]; + + let levels = res["levels"]; + for (let i = 0, n = levels.length; i < n; i++) { + let currentLevel = levels[i]; + levelPromises.push(db.loadLevel(levels[i]["id"]).then(level => { + currentLevel["played"] = (Helper.nonNull(Helper.nonNull(level, {}).played, false)); + return currentLevel; + })); + } + } + let levels = await Promise.all(levelPromises); + await db.saveManyLevels(levels); + + if (newLastSync != null && newLastSync !== "null") + { + localStorage.setItem("date-last-sync", newLastSync); + } + } } MenuSite.app = null; diff --git a/src/module/Application/pwa/js/site/SynchronizeSite.js b/src/module/Application/pwa/js/site/SynchronizeSite.js deleted file mode 100755 index e0118c7..0000000 --- a/src/module/Application/pwa/js/site/SynchronizeSite.js +++ /dev/null @@ -1,64 +0,0 @@ -import {FlashMessenger, Helper} from "../../../../../js/lib/pwa-lib"; -import {DataManager} from "../../../../../js/lib/pwa-core"; -import {WordRotatorDb} from "../WordRotatorDb"; -import {LevelSite} from "./LevelSite"; -import {WordRotatorBaseSite} from "./WordRotatorBaseSite"; -import {MenuSite} from "./MenuSite"; - -export class SynchronizeSite extends WordRotatorBaseSite { - - constructor(siteManager) { - super(siteManager, "html/application/sync.html"); - } - - async onConstruct(args) { - let res = await super.onConstruct(args); - await this.loadLevels(); - return res; - } - - onFirstStart() { - super.onFirstStart(); - this.startSite(MenuSite); - this.finish(); - } - - async loadLevels() { - const dateLastSync = Helper.nonNull(localStorage.getItem("date-last-sync"), 0); - const db = WordRotatorDb.getInstance(); - - let newLastSync = null; - let maxRuns = 1; - let levelPromises = []; - for (let run = 0; run < maxRuns; run++) { - let res = await DataManager.load("wordRotator/levels" + DataManager.buildQuery({ - "currentRun": run, - "dateLastSync": dateLastSync - })); - if (!res["success"]) { - FlashMessenger.addMessage("sync-error", null, 6000); - newLastSync = null; - break; - } - res = res["result"]; - newLastSync = Helper.nonNull(newLastSync, res["currentSyncDate"]); - maxRuns = res["maxRuns"]; - - let levels = res["levels"]; - for (let i = 0, n = levels.length; i < n; i++) { - let currentLevel = levels[i]; - levelPromises.push(db.loadLevel(levels[i]["id"]).then(level => { - currentLevel["played"] = (Helper.nonNull(Helper.nonNull(level, {}).played, false)); - return currentLevel; - })); - } - } - let levels = await Promise.all(levelPromises); - await db.saveManyLevels(levels); - - if (newLastSync != null && newLastSync !== "null") - { - localStorage.setItem("date-last-sync", newLastSync); - } - } -} \ No newline at end of file diff --git a/src/module/Application/pwa/js/wordrotator/Level/Level.js b/src/module/Application/pwa/js/wordrotator/Level/Level.js index ca74c8f..43c8eb1 100755 --- a/src/module/Application/pwa/js/wordrotator/Level/Level.js +++ b/src/module/Application/pwa/js/wordrotator/Level/Level.js @@ -20,6 +20,8 @@ export class Level { self.wonResolver = resolve; self.giveUpResolver = reject; }); + + this.segmentClickedListener = () => {}; } saveAsCurrentLevel(){ @@ -130,6 +132,10 @@ export class Level { return Level._getRotatableSegmentsFrom(this.rootSegment); } + setSegmentClickedListener(listener){ + this.segmentClickedListener = listener; + } + static _getRotatableSegmentsFrom(segment){ let rotatable = []; if (segment.canRotate()) diff --git a/src/module/Application/pwa/js/wordrotator/Segment/ParentSegment.js b/src/module/Application/pwa/js/wordrotator/Segment/ParentSegment.js index 0379560..3c9cc51 100755 --- a/src/module/Application/pwa/js/wordrotator/Segment/ParentSegment.js +++ b/src/module/Application/pwa/js/wordrotator/Segment/ParentSegment.js @@ -35,6 +35,7 @@ export class ParentSegment extends Segment { this.touchendListener = function (e) { let target = document.elementFromPoint(e.changedTouches[0].pageX, e.changedTouches[0].pageY); if (e.targetTouches.length === 0 && e.changedTouches.length === 1 && self.element.contains(ParentSegment.mouseDownTarget) && self.element.contains(target)) { + self.getLevel().segmentClickedListener(self); self.rotate(ParentSegment.mouseDownTarget, target); e.stopPropagation(); e.preventDefault(); @@ -42,6 +43,7 @@ export class ParentSegment extends Segment { }; this.mouseupListener = function (e) { if (ParentSegment.mouseDownTarget !== null && self.element.contains(ParentSegment.mouseDownTarget) && self.element.contains(e.target)) { + self.getLevel().segmentClickedListener(self); self.rotate(ParentSegment.mouseDownTarget, e.target); e.stopPropagation(); e.preventDefault(); diff --git a/src/module/Application/pwa/translations/de.json b/src/module/Application/pwa/translations/de.json index 3667585..a06097d 100755 --- a/src/module/Application/pwa/translations/de.json +++ b/src/module/Application/pwa/translations/de.json @@ -8,5 +8,10 @@ "sync-error":"Es gab einen Fehler beim Aktualisieren der Level. Bitte stelle sicher, dass du eine aktive Internetverbindung hast und versuche es später erneut.", "game-ended":"Oh nein!
Es sieht so aus, als ob du schon alle Level gespielt hast...
Schau später noch einmal rein, evtl gibt es dann neue Level.", - "play":"Spielen!" + "play":"Spielen!", + + "tutorial-step-1": "Klicke auf ein Feld, um dieses rotieren zu lassen!", + "tutorial-step-2": "Um zu gewinnen, drehe die Segmente so, dass du zwei Wörter lesen kannst.", + "tutorial-step-3": "Durch die Hilfe kannst du ein Segment lösen lassen. Die Hilfe kostet aber 25 Münzen. Probiere jetzt die Hilfe aus.", + "extra-coins-after-first-level":"Für das erste Level gibt es 50 extra Münzen!" } \ No newline at end of file diff --git a/src/scss/_tutorial.scss b/src/scss/_tutorial.scss new file mode 100644 index 0000000..1d862fe --- /dev/null +++ b/src/scss/_tutorial.scss @@ -0,0 +1,74 @@ +.tutorial-blanket { + display: none; + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + + z-index: 9001; + background: rgba(98, 98, 98, 0.51); +} + +.tutorial { + .tutorial-blanket { + display: block; + } + .tutorial-text { + color: white; + font-size: 1.5rem; + display: flex; + } + + &.step-1 { + #level { + .segment-row { + position: inherit; + } + .segment-parent:nth-child(3), .segment-parent:nth-child(3).rotating { + z-index: 9900 !important; + } + } + .tutorial-text .step-1 { + display: initial; + z-index: 9900 !important; + position: relative; + } + } + + &.step-2 { + #level { + z-index: 9900 !important; + } + .tutorial-text .step-2 { + display: initial; + z-index: 9900 !important; + position: relative; + } + } + + &.step-3 { + .tutorial-text .step-3 { + display: initial; + z-index: 9900 !important; + position: relative; + } + + #help-button { + position: relative; + z-index: 9900 !important; + overflow: visible; + margin-right: 10px; + margin-top: 10px; + box-shadow: 0 0 10px 5px #fff; + //&:after { + // content: ""; + // position: absolute; + // top: 0; + // left: 0; + // bottom: 0; + // right: 0; + //} + } + } +} \ No newline at end of file diff --git a/src/scss/wordRotator.scss b/src/scss/wordRotator.scss index 1151b0f..5bd2c7e 100755 --- a/src/scss/wordRotator.scss +++ b/src/scss/wordRotator.scss @@ -1,3 +1,5 @@ +@import "tutorial"; + //ActionBar nav.top-bar.title-bar { padding: 0.3rem 0.6rem 0; @@ -286,12 +288,7 @@ $animationDuration: .25s; //Won-screen #site-content > :not(.won) { .show-when-won { - //visibility: hidden; display: none; - //transition: none; - //* { - // transition: none; - //} } } diff --git a/test/test.testcafe.js b/test/test.testcafe.js index 52df237..ea103b8 100644 --- a/test/test.testcafe.js +++ b/test/test.testcafe.js @@ -23,7 +23,7 @@ async function afterEachTest(t) { return await t.eval(() => indexedDB.deleteDatabase('wordRotator')); } -let isLocal = true; +let isLocal = false; if (isLocal) { fixture`Play` .page`https://127.0.0.1/pwa/wordRotator/publicTest/`.beforeEach(async t => {