new version

This commit is contained in:
silas
2020-10-17 16:42:59 +02:00
parent 0d70067fe4
commit db76378425
388 changed files with 47326 additions and 19804 deletions

8
src/client/globals.d.ts vendored Normal file
View File

@@ -0,0 +1,8 @@
declare var require: {
<T>(path: string): T;
(paths: string[], callback: (...modules: any[]) => void): void;
ensure: (
paths: string[],
callback: (require: <T>(path: string) => T) => void
) => void;
};

View File

@@ -0,0 +1,7 @@
<div>
<div id='theme-choose-container'>
<div id='choose-theme-template' class = 'setting-row row'>
<div class='name column small-12'></div>
</div>
</div>
</div>

View File

@@ -0,0 +1,3 @@
<article>
<section id = 'persistance-info-message'></section>
</article>

View File

@@ -0,0 +1 @@
<div class = 'max-width center'></div>

View File

@@ -0,0 +1,57 @@
<div class='max-height fill-me'>
<div class='grid-x max-width grow flex-center'>
<div class='columns small-centered small-12 smedium-11 medium-9 large-7'>
<label class="switch grid-x setting-row">
<span class='columns small-6 translation'>sound</span>
<span class='columns small-6 text-right'>
<input type="checkbox" class="setting" id="play-sound" name='play-sound' value="1"
data-default="1">
<span class="slider"></span>
</span>
</label>
<label class="switch grid-x setting-row">
<span class='columns small-6 translation' >music</span>
<span class='columns small-6 text-right'>
<input type="checkbox" class="setting" id="play-music" name='play-music' value="1"
data-default="1">
<span class="slider"></span>
</span>
</label>
<div class='grid-x setting-row' id='credits-button'>
<span class='columns small-6 translation' >credits</span>
<span class='columns small-6 text-right translation'>&gt;</span>
</div>
<div class='grid-x setting-row' id='privacy-policy-button'>
<span class='columns small-6 translation'>privacy-policy</span>
<span class='columns small-6 text-right translation'>&gt;</span>
</div>
<div class='grid-x setting-row' id='impressum-button'>
<span class='columns small-6 translation' >impressum</span>
<span class='columns small-6 text-right translation'>&gt;</span>
</div>
<div class='grid-x setting-row' id='contact-button'>
<span class='columns small-6 translation'>contact</span>
<span class='columns small-6 text-right translation'>&gt;</span>
</div>
<label class="switch grid-x setting-row">
<span class='columns small-6 translation'>track</span>
<span class='columns small-6 text-right'>
<input type="checkbox" class="setting" id="track-switch" name='matomoShouldTrack' value="1"
data-default="1" data-raw="1">
<span class="slider"></span>
</span>
</label>
<div class='grid-x setting-row hidden' >
<span class = "column small-10" id='storage-info'></span>
<span class='columns small-2 text-right translation'>&gt;</span>
</div>
<div class='grid-x setting-row' >
<span class = "column small-6 translation">version-label</span>
<span class = "column small-6 text-right" id='version-info'></span>
</div>
<button id='reset-levels' class="button hidden">reset-levels</button>
</div>
</div>
</div>

View File

@@ -0,0 +1,21 @@
<h1 class = "translation">contact</h1>
<p id = "contactText">
</p>
<form class="grid-x" id = "contact-form">
<label class="small-12 medium-6 right">
<input type="checkbox" value="1" required name="policy">
<span>
<a class = "link translation" href="/?s=privacyPolicy">privacy-policy</a>
<span class = "translation">privacy policy accepted</span>
</span>
</label>
<label class = "small-12 medium-6">
<input type="email" required name="email">
<span class="translation">e-mail</span>
</label>
<label class="small-12">
<textarea required name="message"></textarea>
<span class="translation">message</span>
</label>
<button class="small-12 button translation">send</button>
</form>

View File

@@ -0,0 +1,5 @@
<div>
<p class="translation" data-translation="credits-sister-text"></p>
<p class="translation" data-translation="credits-coin-text" data-translation-args='["https://www.freesfx.co.uk/"]'></p>
<p class="translation" data-translation="credits-music-text" data-translation-args='["https://audeeyah.de", "http://creativecommons.org/licenses/by/4.0/"]'></p>
</div>

View File

@@ -0,0 +1,13 @@
<div>
<div id = "level-template" class = "row">
<div class = "columns small-3">id:</div><div class="column small-6 id"></div><div class = 'column small-3'><button class = 'clickable margin-0 delete-button'>X</button></div>
<div class = "columns small-3">words:</div><div class="column small-9 words"></div>
<div class = "columns small-3">rotations:</div><div class="column small-9 positions"></div>
<div class = "columns small-12" style = 'border-bottom: 1px solid black'>&nbsp;</div>
</div>
<div id = "word-template" style="margin-bottom: 1.5rem">
<span class = "name"></span>:<br/>
<div class = "level-container"></div>
</div>
<div id = "word-container"></div>
</div>

View File

@@ -0,0 +1,3 @@
<div class = 'max-height flex-center'>
<div data-translation="game-ended" class = 'center translation'></div>
</div>

View File

@@ -0,0 +1,11 @@
<div>
<h2>Impressum</h2>
<p>Silas Günther<br />
Mariabrunnstraße 48<br />
52064 Aachen<br/>
Deutschland
</p>
<p>E-Mail: <a href="mailto:wordRotator@silas.link">wordRotator@silas.link</a><br />
<a href = "?s=contact" class = "link" target="_blank">Kontaktformular</a>
</p>
</div>

View File

@@ -0,0 +1,54 @@
<div class='max-height overflow-hidden'>
<!-- Templates for segments-->
<div id='segment-leaf-template' class='segment segment-leaf'>
<div class='leaf-element'></div>
</div>
<div id='segment-parent-template' class='segment segment-parent'>
<div class='child-container'></div>
</div>
<div id='segment-row-template' class='segment segment-row'>
<div class='child-container'></div>
</div>
<div id='segment-column-template' class='segment segment-column'>
<div class='child-container'></div>
</div>
<div id='segment-triangle-template' class='segment segment-triangle'>
<div class='child-container'></div>
</div>
<div id = 'tutorial-pointer'></div>
<!-- Site Content -->
<div class='max-height fill-me'>
<!-- <div class="text-right max-width">-->
<!-- <button class="button show-while-playing" id='help-button'>-->
<!-- <img src = "../../img/help.png"/>-->
<!-- </button>-->
<!-- </div>-->
<div class = 'height-20 no-transition tutorial-text center flex-center hidden'>
<div class = 'step-1 hidden translation' data-translation="tutorial-step-1"></div>
<div class = 'step-2 hidden translation' data-translation="tutorial-step-2"></div>
<div class = 'step-3 hidden translation' data-translation="tutorial-step-3"></div>
<div class = 'step-4 hidden translation' data-translation="tutorial-step-4"></div>
</div>
<div class='height-20 show-when-won center flex-center fill-me' style = 'min-height: 45px'>
<div class = 'grow max-width'>
<b class="translation" data-translation="won" id="won-text"></b>
</div>
<div id='coin-container'>
<div id='coin-template' class='coin' style="opacity: 0">
<img src='../../img/coin.png'/>
</div>
</div>
</div>
<div class="flex-center level-container grow">
<div id='level'>
</div>
</div>
<div class='show-when-won flex-center height-20'>
<button class='button max-width translation' id='continue-button' data-translation="continue"></button>
</div>
</div>
<div class = 'tutorial-blanket'></div>
</div>

View File

@@ -0,0 +1,39 @@
<div class='max-height flex-center'>
<!--<b>WordRotator</b>-->
<div id='segment-leaf-template' class='segment segment-leaf'>
<div class='leaf-element'></div>
</div>
<div id='segment-parent-template' class='segment segment-parent'>
<div class='child-container'></div>
</div>
<div id='segment-row-template' class='segment segment-row'>
<div class='child-container'></div>
</div>
<div id='segment-triangle-template' class='segment segment-triangle'>
<div class='child-container'></div>
</div>
<div class='height-60 max-width flex-center relative-level-number'>
<div id='level'></div>
<span id='level-number-container' class='visible in-main-menu'>
<span id='level-number'>1</span>
</span>
</div>
<div class='height-30 flex-center fill-me'>
<button class='button grow text-center' id='play-button'><span class="translation" data-translation="play"></span></button>
<div class='max-width line-height-1 fill-me vertical'>
<label class="switch">
<div data-view="../../img/speaker.svg"></div>
<input type="checkbox" class="setting" id="play-sound">
<span class="slider"></span>
</label>
<div class="grow center" id = "share-button"><span data-view="../../img/share.svg"></span></div>
<label class="switch right">
<div data-view="../../img/music.svg"></div>
<input type="checkbox" class="setting" id="play-music">
<span class="slider"></span>
</label>
</div>
</div>
</div>

View File

@@ -0,0 +1,233 @@
<div class="max-height">
<h2>Datenschutzerklärung</h2>
<h3 id="dsg-general-intro"></h3>
<p>Diese Datenschutzerklärung klärt Sie über die Art, den Umfang und Zweck der Verarbeitung von personenbezogenen
Daten (nachfolgend kurz „Daten“) im Rahmen der Erbringung unserer Leistungen sowie innerhalb unseres
Onlineangebotes und der mit ihm verbundenen Webseiten, Funktionen und Inhalte sowie externen Onlinepräsenzen
(nachfolgend gemeinsam bezeichnet als „Onlineangebot“). Im Hinblick auf
die verwendeten Begrifflichkeiten, wie z.B. „Verarbeitung“ oder „Verantwortlicher“ verweisen wir auf die
Definitionen im Art. 4 der Datenschutzgrundverordnung (DSGVO). <br>
<br>
</p>
<h3 id="dsg-general-controller">Verantwortlicher</h3>
<p><span class="tsmcontroller">Silas Günther<br>
Mariabrunnstraße 48<br>
52064 Aachen<br>
Deutschland<br>
<br>
E-Mailadresse: wordRotator@silas.link<br>
Link zum Impressum: <a class = "link" href = "https://wordrotator.silas.link/impressum">https://wordrotator.silas.link/impressum</a></span></p>
<h3 id="dsg-general-datatype">Arten der verarbeiteten Daten</h3>
<p>
- Bestandsdaten (z.B., Personen-Stammdaten, Namen oder Adressen).<br>
- Kontaktdaten (z.B., E-Mail, Telefonnummern).<br>
- Nutzungsdaten (z.B., besuchte Webseiten, Interesse an Inhalten, Zugriffszeiten).<br>
- Meta-/Kommunikationsdaten (z.B., Geräte-Informationen, Anonymisierte IP-Adressen).</p>
<h3 id="dsg-general-datasubjects">Kategorien betroffener Personen</h3>
<p>Besucher und Nutzer des Onlineangebotes (Nachfolgend bezeichnen wir die betroffenen Personen zusammenfassend auch
als „Nutzer“).<br>
</p>
<h3 id="dsg-general-purpose">Zweck der Verarbeitung</h3>
<p>- Zurverfügungstellung des Onlineangebotes, seiner Funktionen und Inhalte.<br>
- Beantwortung von Kontaktanfragen und Kommunikation mit Nutzern.<br>
- Sicherheitsmaßnahmen.<br>
- Reichweitenmessung/Marketing<br>
<span class="tsmcom"></span></p>
<h3 id="dsg-general-terms">Verwendete Begrifflichkeiten </h3>
<p>„Personenbezogene Daten“ sind alle Informationen, die sich auf eine identifizierte oder identifizierbare
natürliche Person (im Folgenden „betroffene Person“) beziehen; als identifizierbar wird eine natürliche Person
angesehen, die direkt oder indirekt, insbesondere mittels Zuordnung zu einer Kennung wie einem Namen, zu einer
Kennnummer, zu Standortdaten, zu einer Online-Kennung (z.B. Cookie) oder zu einem oder mehreren besonderen
Merkmalen identifiziert werden kann, die Ausdruck der physischen, physiologischen, genetischen, psychischen,
wirtschaftlichen, kulturellen oder sozialen Identität dieser natürlichen Person sind.<br>
<br>
„Verarbeitung“ ist jeder mit oder ohne Hilfe automatisierter Verfahren ausgeführte Vorgang oder jede solche
Vorgangsreihe im Zusammenhang mit personenbezogenen Daten. Der Begriff reicht weit und umfasst praktisch jeden
Umgang mit Daten.<br>
<br>
„Pseudonymisierung“ die Verarbeitung personenbezogener Daten in einer Weise, dass die personenbezogenen Daten
ohne Hinzuziehung zusätzlicher Informationen nicht mehr einer spezifischen betroffenen Person zugeordnet werden
können, sofern diese zusätzlichen Informationen gesondert aufbewahrt werden und technischen und
organisatorischen Maßnahmen unterliegen, die gewährleisten, dass die personenbezogenen Daten nicht einer
identifizierten oder identifizierbaren natürlichen Person zugewiesen werden.<br>
<br>
„Profiling“ jede Art der automatisierten Verarbeitung personenbezogener Daten, die darin besteht, dass diese
personenbezogenen Daten verwendet werden, um bestimmte persönliche Aspekte, die sich auf eine natürliche Person
beziehen, zu bewerten, insbesondere um Aspekte bezüglich Arbeitsleistung, wirtschaftliche Lage, Gesundheit,
persönliche Vorlieben, Interessen, Zuverlässigkeit, Verhalten, Aufenthaltsort oder Ortswechsel dieser
natürlichen Person zu analysieren oder vorherzusagen.<br>
<br>
Als „Verantwortlicher“ wird die natürliche oder juristische Person, Behörde, Einrichtung oder andere Stelle, die
allein oder gemeinsam mit anderen über die Zwecke und Mittel der Verarbeitung von personenbezogenen Daten
entscheidet, bezeichnet.<br>
<br>
„Auftragsverarbeiter“ eine natürliche oder juristische Person, Behörde, Einrichtung oder andere Stelle, die
personenbezogene Daten im Auftrag des Verantwortlichen verarbeitet.<br>
</p>
<h3 id="dsg-general-legalbasis">Maßgebliche Rechtsgrundlagen</h3>
<p>Nach Maßgabe des Art. 13 DSGVO teilen wir Ihnen die Rechtsgrundlagen unserer Datenverarbeitungen mit. Für Nutzer
aus dem Geltungsbereich der Datenschutzgrundverordnung (DSGVO), d.h. der EU und des EWG gilt, sofern die
Rechtsgrundlage in der Datenschutzerklärung nicht genannt wird, Folgendes: <br>
Die Rechtsgrundlage für die Einholung von Einwilligungen ist Art. 6 Abs. 1 lit. a und Art. 7 DSGVO;<br>
Die Rechtsgrundlage für die Verarbeitung zur Erfüllung unserer Leistungen und Durchführung vertraglicher
Maßnahmen sowie Beantwortung von Anfragen ist Art. 6 Abs. 1 lit. b DSGVO;<br>
Die Rechtsgrundlage für die Verarbeitung zur Erfüllung unserer rechtlichen Verpflichtungen ist Art. 6 Abs. 1
lit. c DSGVO;<br>
Für den Fall, dass lebenswichtige Interessen der betroffenen Person oder einer anderen natürlichen Person eine
Verarbeitung personenbezogener Daten erforderlich machen, dient Art. 6 Abs. 1 lit. d DSGVO als
Rechtsgrundlage.<br>
Die Rechtsgrundlage für die erforderliche Verarbeitung zur Wahrnehmung einer Aufgabe, die im öffentlichen
Interesse liegt oder in Ausübung öffentlicher Gewalt erfolgt, die dem Verantwortlichen übertragen wurde ist Art.
6 Abs. 1 lit. e DSGVO. <br>
Die Rechtsgrundlage für die Verarbeitung zur Wahrung unserer berechtigten Interessen ist Art. 6 Abs. 1 lit. f
DSGVO. <br>
Die Verarbeitung von Daten zu anderen Zwecken als denen, zu denen sie ehoben wurden, bestimmt sich nach den
Vorgaben des Art 6 Abs. 4 DSGVO. <br>
Die Verarbeitung von besonderen Kategorien von Daten (entsprechend Art. 9 Abs. 1 DSGVO) bestimmt sich nach den
Vorgaben des Art. 9 Abs. 2 DSGVO. <br>
</p>
<h3 id="dsg-general-securitymeasures">Sicherheitsmaßnahmen</h3>
<p>Wir treffen nach Maßgabe der gesetzlichen Vorgabenunter Berücksichtigung des Stands der Technik, der
Implementierungskosten und der Art, des Umfangs, der Umstände und der Zwecke der Verarbeitung sowie der
unterschiedlichen Eintrittswahrscheinlichkeit und Schwere des Risikos für die Rechte und Freiheiten natürlicher
Personen, geeignete technische und organisatorische Maßnahmen, um ein dem Risiko angemessenes Schutzniveau zu
gewährleisten.<br>
<br>
Zu den Maßnahmen gehören insbesondere die Sicherung der Vertraulichkeit, Integrität und Verfügbarkeit von Daten
durch Kontrolle des physischen Zugangs zu den Daten, als auch des sie betreffenden Zugriffs, der Eingabe,
Weitergabe, der Sicherung der Verfügbarkeit und ihrer Trennung. Des Weiteren haben wir Verfahren eingerichtet,
die eine Wahrnehmung von Betroffenenrechten, Löschung von Daten und Reaktion auf Gefährdung der Daten
gewährleisten. Ferner berücksichtigen wir den Schutz personenbezogener Daten bereits bei der Entwicklung, bzw.
Auswahl von Hardware, Software sowie Verfahren, entsprechend dem Prinzip des Datenschutzes durch
Technikgestaltung und durch datenschutzfreundliche Voreinstellungen.<br>
</p>
<h3 id="dsg-general-coprocessing">Zusammenarbeit mit Auftragsverarbeitern, gemeinsam Verantwortlichen und
Dritten</h3>
<p>Sofern wir im Rahmen unserer Verarbeitung Daten gegenüber anderen Personen und Unternehmen (Auftragsverarbeitern,
gemeinsam Verantwortlichen oder Dritten) offenbaren, sie an diese übermitteln oder ihnen sonst Zugriff auf die
Daten gewähren, erfolgt dies nur auf Grundlage einer gesetzlichen Erlaubnis (z.B. wenn eine Übermittlung der
Daten an Dritte, wie an Zahlungsdienstleister, zur Vertragserfüllung erforderlich ist), Nutzer eingewilligt
haben, eine rechtliche Verpflichtung dies vorsieht oder auf Grundlage unserer berechtigten Interessen (z.B. beim
Einsatz von Beauftragten, Webhostern, etc.). <br>
<br>
Sofern wir Daten anderen Unternehmen unserer Unternehmensgruppe offenbaren, übermitteln oder ihnen sonst den
Zugriff gewähren, erfolgt dies insbesondere zu administrativen Zwecken als berechtigtes Interesse und
darüberhinausgehend auf einer den gesetzlichen Vorgaben entsprechenden Grundlage. <br>
</p>
<!--<h3 id="dsg-general-thirdparty">Übermittlungen in Drittländer</h3>-->
<!--<p>Sofern wir Daten in einem Drittland (d.h. außerhalb der Europäischen Union (EU), des Europäischen-->
<!--Wirtschaftsraums (EWR) oder der Schweizer Eidgenossenschaft) verarbeiten oder dies im Rahmen der Inanspruchnahme-->
<!--von Diensten Dritter oder Offenlegung, bzw. Übermittlung von Daten an andere Personen oder Unternehmen-->
<!--geschieht, erfolgt dies nur, wenn es zur Erfüllung unserer (vor)vertraglichen Pflichten, auf Grundlage Ihrer-->
<!--Einwilligung, aufgrund einer rechtlichen Verpflichtung oder auf Grundlage unserer berechtigten Interessen-->
<!--geschieht. Vorbehaltlich gesetzlicher oder vertraglicher Erlaubnisse, verarbeiten oder lassen wir die Daten in-->
<!--einem Drittland nur beim Vorliegen der gesetzlichen Voraussetzungen. D.h. die Verarbeitung erfolgt z.B. auf-->
<!--Grundlage besonderer Garantien, wie der offiziell anerkannten Feststellung eines der EU entsprechenden-->
<!--Datenschutzniveaus (z.B. für die USA durch das „Privacy Shield“) oder Beachtung offiziell anerkannter spezieller-->
<!--vertraglicher Verpflichtungen.</p>-->
<h3 id="dsg-general-rightssubject">Rechte der betroffenen Personen</h3>
<p>Sie haben das Recht, eine Bestätigung darüber zu verlangen, ob betreffende Daten verarbeitet werden und auf
Auskunft über diese Daten sowie auf weitere Informationen und Kopie der Daten entsprechend den gesetzlichen
Vorgaben.<br>
<br>
Sie haben entsprechend. den gesetzlichen Vorgaben das Recht, die Vervollständigung der Sie betreffenden Daten
oder die Berichtigung der Sie betreffenden unrichtigen Daten zu verlangen.<br>
<br>
Sie haben nach Maßgabe der gesetzlichen Vorgaben das Recht zu verlangen, dass betreffende Daten unverzüglich
gelöscht werden, bzw. alternativ nach Maßgabe der gesetzlichen Vorgaben eine Einschränkung der Verarbeitung der
Daten zu verlangen.<br>
<br>
Sie haben das Recht zu verlangen, dass die Sie betreffenden Daten, die Sie uns bereitgestellt haben nach Maßgabe
der gesetzlichen Vorgaben zu erhalten und deren Übermittlung an andere Verantwortliche zu fordern. <br>
<br>
Sie haben ferner nach Maßgabe der gesetzlichen Vorgaben das Recht, eine Beschwerde bei der zuständigen
Aufsichtsbehörde einzureichen.<br>
</p>
<h3 id="dsg-general-revokeconsent">Widerrufsrecht</h3>
<p>Sie haben das Recht, erteilte Einwilligungen mit Wirkung für die Zukunft zu widerrufen.</p>
<h3 id="dsg-general-object">Widerspruchsrecht</h3>
<p><strong>Sie können der künftigen Verarbeitung der Sie betreffenden Daten nach Maßgabe der gesetzlichen Vorgaben
jederzeit widersprechen. Der Widerspruch kann insbesondere gegen die Verarbeitung für Zwecke der Direktwerbung
erfolgen.</strong></p>
<h3 id="dsg-general-cookies">Cookies und Widerspruchsrecht bei Direktwerbung</h3>
<p>Als „Cookies“ werden kleine Dateien bezeichnet, die auf Rechnern der Nutzer gespeichert werden. Innerhalb der
Cookies können unterschiedliche Angaben gespeichert werden. Ein Cookie dient primär dazu, die Angaben zu einem
Nutzer (bzw. dem Gerät auf dem das Cookie gespeichert ist) während oder auch nach seinem Besuch innerhalb eines
Onlineangebotes zu speichern. Als temporäre Cookies, bzw. „Session-Cookies“ oder „transiente Cookies“, werden
Cookies bezeichnet, die gelöscht werden, nachdem ein Nutzer ein Onlineangebot verlässt und seinen Browser
schließt. In einem solchen Cookie kann z.B. der Inhalt eines Warenkorbs in einem Onlineshop oder ein
Login-Status gespeichert werden. Als „permanent“ oder „persistent“ werden Cookies bezeichnet, die auch nach dem
Schließen des Browsers gespeichert bleiben. So kann z.B. der Login-Status gespeichert werden, wenn die Nutzer
diese nach mehreren Tagen aufsuchen. Ebenso können in einem solchen Cookie die Interessen der Nutzer gespeichert
werden, die für Reichweitenmessung oder Marketingzwecke verwendet werden. Als „Third-Party-Cookie“ werden
Cookies bezeichnet, die von anderen Anbietern als dem Verantwortlichen, der das Onlineangebot betreibt,
angeboten werden (andernfalls, wenn es nur dessen Cookies sind spricht man von „First-Party Cookies“).<br>
<br>
Wir können temporäre und permanente Cookies einsetzen und klären hierüber im Rahmen unserer Datenschutzerklärung
auf.<br>
<br>
Falls die Nutzer nicht möchten, dass Cookies auf ihrem Rechner gespeichert werden, werden sie gebeten die
entsprechende Option in den Systemeinstellungen ihres Browsers zu deaktivieren. Gespeicherte Cookies können in
den Systemeinstellungen des Browsers gelöscht werden. Der Ausschluss von Cookies kann zu
Funktionseinschränkungen dieses Onlineangebotes führen.<br>
<h3 id="dsg-general-erasure">Löschung von Daten</h3>
<p>Die von uns verarbeiteten Daten werden nach Maßgabe der gesetzlichen Vorgaben gelöscht oder in ihrer Verarbeitung
eingeschränkt. Sofern nicht im Rahmen dieser Datenschutzerklärung ausdrücklich angegeben, werden die bei uns
gespeicherten Daten gelöscht, sobald sie für ihre Zweckbestimmung nicht mehr erforderlich sind und der Löschung
keine gesetzlichen Aufbewahrungspflichten entgegenstehen. <br>
<br>
Sofern die Daten nicht gelöscht werden, weil sie für andere und gesetzlich zulässige Zwecke erforderlich sind,
wird deren Verarbeitung eingeschränkt. D.h. die Daten werden gesperrt und nicht für andere Zwecke verarbeitet.
Das gilt z.B. für Daten, die aus handels- oder steuerrechtlichen Gründen aufbewahrt werden müssen.</p>
<h3 id="dsg-general-changes">Änderungen und Aktualisierungen der Datenschutzerklärung</h3>
<p>Wir bitten Sie sich regelmäßig über den Inhalt unserer Datenschutzerklärung zu informieren. Wir passen die
Datenschutzerklärung an, sobald die Änderungen der von uns durchgeführten Datenverarbeitungen dies erforderlich
machen. Wir informieren Sie, sobald durch die Änderungen eine Mitwirkungshandlung Ihrerseits (z.B. Einwilligung)
oder eine sonstige individuelle Benachrichtigung erforderlich wird.</p>
<p></p>
<h3 id="dsg-hostingprovider">Hosting und E-Mail-Versand</h3>
<p></p>
<p><span class="ts-muster-content">Die von uns in Anspruch genommenen Hosting-Leistungen dienen der Zurverfügungstellung der folgenden Leistungen: Infrastruktur- und Plattformdienstleistungen, Rechenkapazität, Speicherplatz und Datenbankdienste, E-Mail-Versand, Sicherheitsleistungen sowie technische Wartungsleistungen, die wir zum Zwecke des Betriebs dieses Onlineangebotes einsetzen. <br>
<br>
Hierbei verarbeiten wir, bzw. unser Hostinganbieter Bestandsdaten, Kontaktdaten, Vertragsdaten, Nutzungsdaten, Meta- und Kommunikationsdaten von Kunden, Interessenten und Besuchern dieses Onlineangebotes auf Grundlage unserer berechtigten Interessen an einer effizienten und sicheren Zurverfügungstellung dieses Onlineangebotes gem. Art. 6 Abs. 1 lit. f DSGVO i.V.m. Art. 28 DSGVO (Abschluss Auftragsverarbeitungsvertrag).</span>
</p>
<p></p>
<h3 id="dsg-logfiles">Erhebung von Zugriffsdaten und Logfiles</h3>
<p></p>
<p><span class="ts-muster-content">Wir, bzw. unser Hostinganbieter, erhebt auf Grundlage unserer berechtigten Interessen
im Sinne des Art. 6 Abs. 1 lit. f. DSGVO Daten über jeden Zugriff auf den Server, auf dem sich dieser Dienst befindet
(sogenannte 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.<br>
<br>
Logfile-Informationen werden aus Sicherheitsgründen (z.B. zur Aufklärung von Missbrauchs- oder Betrugshandlungen) für die
Dauer von maximal 5 Wochen gespeichert und danach gelöscht. Daten, deren weitere Aufbewahrung zu Beweiszwecken erforderlich ist, sind bis zur endgültigen Klärung des jeweiligen Vorfalls von der Löschung ausgenommen.</span>
</p>
<p></p>
<h3 id="dsg-matomo">Reichweitenmessung mit Matomo</h3>
<p></p>
<p><span class="ts-muster-content">Im Rahmen der Reichweitenanalyse von Matomo werden auf Grundlage unserer berechtigten Interessen (d.h. Interesse an der Analyse, Optimierung und wirtschaftlichem Betrieb unseres Onlineangebotes im Sinne des Art. 6 Abs. 1 lit. f. DSGVO) die folgenden Daten verarbeitet: der von Ihnen verwendete Browsertyp und die Browserversion, das von Ihnen verwendete Betriebssystem, Ihr Herkunftsland, Datum und Uhrzeit der Serveranfrage, die Anzahl der Besuche, Ihre Verweildauer auf der Website sowie die von Ihnen betätigten externen Links. Die IP-Adresse der Nutzer wird anonymisiert, bevor sie gespeichert wird. <br>
<br>
Matomo verwendet Cookies, die auf dem Computer der Nutzer gespeichert werden und die eine Analyse der Benutzung unseres Onlineangebotes durch die Nutzer ermöglichen. Dabei können aus den verarbeiteten Daten pseudonyme Nutzungsprofile der Nutzer erstellt werden. Die Cookies haben eine Speicherdauer von einer Woche. Die durch das Cookie erzeugten Informationen über Ihre Benutzung dieser Webseite werden nur auf unserem Server gespeichert und nicht an Dritte weitergegeben.<br>
<br>
Nutzer können der anonymisierten Datenerhebung durch das Programm Matomo jederzeit mit Wirkung für die Zukunft widersprechen,
indem sie den unten befindlichen Schalter nutzen. In diesem Fall wird in ihrem Browser ein sog. Opt-Out-Cookie abgelegt,
was zur Folge hat, dass Matomo keinerlei Sitzungsdaten mehr erhebt.
Wenn Nutzer ihre Cookies löschen, so hat dies jedoch zur Folge, dass auch das Opt-Out-Cookie gelöscht wird und daher
von den Nutzern erneut aktiviert werden muss.<br>
<br>
Die Logs mit den Daten der Nutzer werden nach spätestens einem Jahr gelöscht.<br>
<br></span>
</p>
<label class="switch row setting-row">
<span class='columns small-6 translation' data-translation="track"></span>
<span class='columns small-6 text-right'>
<input type="checkbox" class="setting" id="track-switch" name='matomoShouldTrack' value="1"
data-default="1" data-raw="1">
<span class="slider"></span>
</span>
</label>
<a href="https://datenschutz-generator.de" class="dsg1-6" rel="nofollow" target="_blank">Erstellt mit
Datenschutz-Generator.de von RA Dr. Thomas Schwenke</a><br/>
und angepasst vom Webseitenbetreiber
</div>

View File

@@ -0,0 +1,27 @@
<div>
<div class="row">
<div class="column small-6">Noch nicht geprüft:</div>
<div class="column small-6" id='not-checked'></div>
<div class="column small-6">Gecheckt:</div>
<div class="column small-6" id='checked'></div>
<div class="column small-6">Unsicher:</div>
<div class="column small-6" id='not-sure'></div>
<div class="column small-6">Gelöscht:</div>
<div class="column small-6" id='deleted'></div>
<div class="column small-6">Unbenutzt:</div>
<div class="column small-6" id='unused'></div>
</div>
<br/><br/>
<div id="word-container">
<div id="word-template" class='row'>
<div class="column small-12">
<span class='word'></span>
<span class="right">
<button class='button button-ok'>OK</button>
<button class='button button-unsure'>Unsicher</button>
<button class='button button-delete'>Entf.</button>
</span>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,17 @@
<div>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<div id = "wordRotatorSettings"></div>
</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 494 KiB

Binary file not shown.

BIN
src/client/img/coin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

BIN
src/client/img/help.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 B

BIN
src/client/img/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

BIN
src/client/img/icon1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
src/client/img/icon1.xcf Normal file

Binary file not shown.

BIN
src/client/img/icon10.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
src/client/img/icon10.xcf Normal file

Binary file not shown.

BIN
src/client/img/icon11.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
src/client/img/icon11.xcf Normal file

Binary file not shown.

BIN
src/client/img/icon12,.xcf Normal file

Binary file not shown.

BIN
src/client/img/icon12.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
src/client/img/icon13.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
src/client/img/icon13.xcf Normal file

Binary file not shown.

BIN
src/client/img/icon14.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
src/client/img/icon14.xcf Normal file

Binary file not shown.

BIN
src/client/img/icon2.xcf Normal file

Binary file not shown.

BIN
src/client/img/icon3.xcf Normal file

Binary file not shown.

BIN
src/client/img/icon4.xcf Normal file

Binary file not shown.

BIN
src/client/img/icon5.xcf Normal file

Binary file not shown.

Binary file not shown.

BIN
src/client/img/icon6.xcf Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="img/icons/mstile-150x150.png"/>
<TileColor>#da532c</TileColor>
</tile>
</msapplication>
</browserconfig>

Binary file not shown.

After

Width:  |  Height:  |  Size: 639 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -0,0 +1,69 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="512.000000pt" height="512.000000pt" viewBox="0 0 512.000000 512.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.11, written by Peter Selinger 2001-2013
</metadata>
<g transform="translate(0.000000,512.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M2425 5114 c-435 -33 -824 -153 -1173 -361 -336 -200 -675 -539 -875
-875 -242 -405 -360 -838 -360 -1313 0 -475 118 -908 360 -1313 200 -336 539
-675 875 -875 405 -242 838 -360 1313 -360 399 0 739 75 1093 244 274 130 484
279 708 503 410 410 652 900 730 1477 21 150 23 470 5 614 -75 595 -337 1126
-757 1535 -400 389 -892 628 -1449 704 -113 15 -381 27 -470 20z m-1410 -1566
c3 -13 10 -32 15 -43 9 -22 55 -233 66 -302 4 -24 11 -43 16 -43 6 0 8 -9 5
-20 -3 -10 -2 -20 2 -22 7 -3 71 -293 71 -321 0 -10 4 -17 9 -17 5 0 11 -12
13 -27 17 -100 63 -299 71 -304 6 -4 7 -14 4 -23 -4 -9 -3 -16 1 -16 5 0 16
-45 27 -100 16 -92 35 -140 35 -91 0 11 4 22 9 25 5 3 7 15 4 26 -3 11 -1 20
5 20 5 0 12 17 15 38 8 54 47 235 54 252 3 8 5 21 4 29 -1 8 2 17 7 20 5 3 24
81 42 174 19 92 37 167 41 167 4 0 5 9 2 21 -3 12 -1 24 4 28 9 5 44 155 61
254 2 15 8 27 12 27 5 0 6 9 3 20 -3 11 -1 26 5 33 5 6 17 48 26 92 9 44 19
90 22 103 l4 22 260 0 c143 0 260 -1 260 -3 0 -23 24 -125 32 -134 6 -7 8 -20
4 -28 -3 -8 -2 -15 2 -15 5 0 21 -64 36 -142 16 -79 33 -149 38 -155 6 -7 8
-19 5 -27 -3 -8 -2 -16 2 -18 7 -3 59 -233 69 -305 2 -18 8 -33 14 -33 5 0 8
-8 6 -17 -1 -10 0 -22 4 -28 3 -5 20 -80 38 -165 18 -85 35 -157 39 -160 4 -3
13 -39 21 -80 14 -82 23 -77 36 20 4 27 10 50 15 50 5 0 6 7 2 16 -3 9 -1 19
4 23 5 3 25 78 43 166 18 88 36 162 39 165 7 6 71 297 71 323 0 10 4 17 10 17
5 0 7 7 4 15 -4 8 -2 21 4 28 5 6 24 82 42 167 18 85 36 160 41 166 5 6 6 14
3 17 -3 3 -2 12 2 19 5 7 14 36 19 63 l10 50 250 0 c470 0 718 -10 843 -35 61
-13 112 -27 112 -31 0 -5 5 -9 11 -9 5 0 40 -14 77 -32 79 -37 174 -135 193
-199 7 -21 16 -39 22 -39 5 0 7 -6 4 -14 -3 -8 -1 -16 6 -19 18 -6 17 -339 -1
-345 -6 -2 -10 -7 -7 -11 2 -5 -7 -31 -20 -60 -14 -28 -25 -55 -25 -60 0 -6
-10 -17 -22 -25 -12 -9 -19 -16 -16 -16 4 0 -10 -18 -32 -40 -22 -22 -43 -40
-48 -40 -4 0 -18 -9 -30 -20 -12 -12 -22 -17 -22 -13 0 4 -4 3 -8 -3 -4 -5
-34 -21 -67 -35 -45 -18 -54 -25 -37 -27 12 -2 22 -7 22 -10 0 -4 17 -16 38
-27 46 -24 124 -101 146 -143 8 -16 22 -36 29 -44 7 -7 29 -44 47 -83 19 -38
38 -72 42 -73 5 -2 6 -8 2 -13 -3 -5 0 -9 5 -9 6 0 11 -6 11 -14 0 -19 60
-150 71 -154 5 -2 9 -9 9 -15 0 -7 8 -28 18 -47 11 -19 22 -47 25 -62 4 -15
15 -34 25 -44 9 -10 16 -19 14 -21 -1 -2 4 -16 12 -32 13 -24 56 -131 56 -138
0 -2 -122 -3 -271 -3 l-270 0 -21 50 c-11 27 -25 50 -30 50 -5 0 -6 5 -3 10 3
6 1 10 -4 10 -6 0 -11 8 -11 17 0 15 -40 100 -177 380 -56 113 -130 203 -168
203 -8 0 -15 5 -15 11 0 5 -4 7 -10 4 -5 -3 -10 -2 -10 3 0 17 -53 22 -301 28
l-247 6 -16 -74 c-8 -40 -23 -111 -32 -158 -10 -47 -20 -87 -24 -90 -4 -3 -22
-79 -41 -170 -18 -91 -36 -166 -40 -168 -4 -2 -5 -12 -2 -22 3 -11 0 -20 -6
-20 -6 0 -11 -11 -11 -25 l0 -25 -308 0 -308 0 -24 115 c-13 63 -28 115 -33
115 -5 0 -7 10 -6 23 2 12 1 27 -3 32 -3 6 -20 80 -38 165 -18 85 -37 158 -43
161 -5 4 -7 16 -4 27 2 12 1 22 -3 24 -4 2 -20 64 -35 138 -15 74 -32 138 -37
141 -6 4 -8 16 -5 28 3 12 2 21 -2 21 -4 0 -11 24 -17 53 -41 205 -59 283 -67
288 -6 4 -7 14 -4 23 4 9 3 16 -2 16 -5 0 -12 19 -16 43 -8 42 -8 41 -27 -53
-11 -52 -23 -97 -27 -100 -4 -3 -22 -79 -41 -170 -19 -91 -37 -166 -41 -168
-4 -2 -4 -12 -2 -24 3 -11 1 -23 -4 -27 -9 -5 -50 -179 -61 -258 -2 -18 -8
-33 -12 -33 -5 0 -6 -9 -3 -21 3 -12 1 -24 -4 -28 -9 -6 -83 -330 -83 -364 0
-8 -4 -17 -8 -19 -5 -1 -15 -34 -23 -73 l-15 -70 -306 -3 -306 -2 -13 65 c-7
36 -17 65 -22 65 -5 0 -7 9 -4 20 3 11 2 20 -3 20 -4 0 -10 15 -12 33 -10 67
-61 302 -68 307 -6 4 -54 221 -68 303 -2 15 -8 27 -13 27 -5 0 -9 7 -9 16 0
30 -70 348 -81 371 -6 11 -9 26 -5 31 3 6 2 12 -2 14 -4 1 -21 65 -37 141 -15
75 -32 137 -38 137 -5 0 -7 14 -5 30 3 17 2 30 -2 30 -3 0 -21 74 -40 165 -19
91 -38 165 -42 165 -4 0 -8 11 -8 25 l0 25 254 0 255 0 6 -22z"/>
<path d="M3315 3192 c-43 -4 -55 -14 -55 -49 0 -13 -4 -23 -9 -23 -5 0 -7 -9
-4 -20 3 -11 1 -26 -5 -33 -6 -7 -23 -73 -38 -147 -15 -74 -31 -136 -35 -138
-4 -2 -5 -12 -2 -22 3 -11 0 -20 -6 -20 -6 0 -11 -8 -11 -18 0 -17 13 -19 158
-25 363 -15 426 -7 493 63 21 22 35 40 31 40 -4 0 0 4 8 10 17 11 27 191 12
230 -5 14 -9 27 -9 30 0 3 -11 18 -26 34 -15 16 -27 33 -27 38 0 5 -4 6 -10 3
-5 -3 -10 -1 -10 4 0 6 -3 10 -7 9 -5 -1 -21 4 -37 11 -16 6 -48 14 -70 16
-57 7 -293 11 -341 7z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
src/client/img/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

2
src/client/img/music.svg Normal file
View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" version="1.1" x="0px" y="0px" viewBox="0 0 32 32" enable-background="new 0 0 32 32" xml:space="preserve" id="svg2" inkscape:version="0.48.4 r9939" sodipodi:docname="music.svg"><defs id="defs13"/><sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-width="640" inkscape:window-height="480" id="namedview11" showgrid="false" inkscape:zoom="7.375" inkscape:cx="16" inkscape:cy="16" inkscape:window-x="53" inkscape:window-y="31" inkscape:window-maximized="0" inkscape:current-layer="svg2"/><metadata id="metadata3"><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/><dc:title>PICOL Icon</dc:title><dc:date>2009-03-15</dc:date><dc:creator><cc:Agent><dc:title>Melih Bilgil</dc:title></cc:Agent></dc:creator><dc:rights><cc:Agent><dc:title>Creative Commons BY-SA</dc:title></cc:Agent></dc:rights><dc:publisher><cc:Agent><dc:title>PICOL - Pictorial Communication Language</dc:title></cc:Agent></dc:publisher><dc:identifier>http://blog.picol.org</dc:identifier><dc:source>http://blog.picol.org</dc:source><dc:language>en</dc:language><dc:subject><rdf:Bag><rdf:li>PICOL</rdf:li><rdf:li>icon</rdf:li><rdf:li>icons</rdf:li><rdf:li>sign</rdf:li><rdf:li>GUI</rdf:li><rdf:li>vector</rdf:li><rdf:li>interface</rdf:li></rdf:Bag></dc:subject><dc:description>This is one icon out of all PICOL icons</dc:description><dc:contributor><cc:Agent><dc:title>Melih Bilgil (www.lonja.de), Christopher Adjei (www.boffer.net)</dc:title></cc:Agent></dc:contributor><cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/3.0/"/></cc:Work><cc:License rdf:about="http://creativecommons.org/licenses/by-sa/3.0/"><cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/><cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/><cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/><cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/><cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/><cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/></cc:License></rdf:RDF></metadata><g id="background"><rect fill="none" width="32" height="32" id="rect6"/></g><path id="path9" d="M 8,0 V 16.35 C 7.373,16.127 6.702,16 6,16 c -3.316,0 -6,2.691 -6,6 0,3.314 2.684,6 6,6 3.311,0 6,-2.686 6,-6 V 6 L 24,8 V 20.35 C 23.373,20.127 22.703,20 22,20 c -3.316,0 -6,2.691 -6,6 0,3.314 2.684,6 6,6 3.309,0 6,-2.686 6,-6 V 4 L 8,0 z"/></svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
src/client/img/settings.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

4
src/client/img/share.svg Normal file
View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
<!--<path d="M0 0h48v48h-48z" fill="none" />-->
<path class="fill-color" d="M36 32.17c-1.52 0-2.89.59-3.93 1.54l-14.25-8.31c.11-.45.18-.92.18-1.4s-.07-.95-.18-1.4l14.1-8.23c1.07 1 2.5 1.62 4.08 1.62 3.31 0 6-2.69 6-6s-2.69-6-6-6-6 2.69-6 6c0 .48.07.95.18 1.4l-14.1 8.23c-1.07-1-2.5-1.62-4.08-1.62-3.31 0-6 2.69-6 6s2.69 6 6 6c1.58 0 3.01-.62 4.08-1.62l14.25 8.31c-.1.42-.16.86-.16 1.31 0 3.22 2.61 5.83 5.83 5.83s5.83-2.61 5.83-5.83-2.61-5.83-5.83-5.83z"/>
</svg>

After

Width:  |  Height:  |  Size: 533 B

52
src/client/img/sms.svg Normal file
View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 596.02863 624.86049"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="sms.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
/>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-96.271606,-161.35864)">
<path class="fill-color"
d="m 226.78571,717.53552 0,-68.68386 -4.88516,-4.70867 c -6.42608,-6.19391 -9.23116,-6.71523 -36.9412,-6.86548 -24.78746,-0.1344 -32.98397,-1.22152 -43.95079,-5.82929 -15.56012,-6.53766 -29.88171,-19.84926 -37.02898,-34.4176 -8.389993,-17.10139 -7.693873,0.8413 -7.693873,-198.31128 l 0,-177.00001 3.30919,-9.5 c 4.257043,-12.22109 10.306203,-21.86381 18.862433,-30.06785 11.61523,-11.1371 24.97171,-17.63265 40.92353,-19.90201 5.72478,-0.81442 72.02563,-1.03614 240.40485,-0.80395 261.45563,0.36054 235.55345,-0.46199 253,8.03402 7.01459,3.41591 10.16895,5.80822 18.05026,13.68953 7.8784,7.8784 10.27528,11.03826 13.69183,18.05026 8.46606,17.37539 7.75791,-0.69816 7.75791,198.00001 0,198.69816 0.70815,180.62461 -7.75791,198 -3.41655,7.012 -5.81343,10.17186 -13.69183,18.05026 -7.88131,7.88131 -11.03567,10.27362 -18.05026,13.68953 -16.96959,8.26374 -5.62767,7.61008 -142.59678,8.21816 -105.14414,0.46679 -122.36103,0.74554 -124,2.00762 -3.09839,2.3859 -36.06645,33.0732 -145.876,135.78421 -6.61497,6.1873 -12.36472,11.2498 -12.77722,11.25 -0.4125,10e-5 -0.75,-30.9075 -0.75,-68.6836 z"
id="path3353"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://web.resource.org/cc/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" version="1.0" id="layer1" viewBox="0 0 75 75"><metadata id="metadata1"><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/></cc:Work></rdf:RDF></metadata>
<g id="g1"><polygon id="polygon1" points="39.389,13.769 22.235,28.606 6,28.606 6,47.699 21.989,47.699 39.389,62.75 39.389,13.769" style="stroke:currentColor;stroke-width:5;stroke-linejoin:round;fill:currentColor;"/><path id="path1" d="M 48.128,49.03 C 50.057,45.934 51.19,42.291 51.19,38.377 C 51.19,34.399 50.026,30.703 48.043,27.577" style="fill:none;stroke:currentColor;stroke-width:5;stroke-linecap:round"/>
<path id="path2" d="M 55.082,20.537 C 58.777,25.523 60.966,31.694 60.966,38.377 C 60.966,44.998 58.815,51.115 55.178,56.076" style="fill:none;stroke:currentColor;stroke-width:5;stroke-linecap:round"/>
<path id="path1" d="M 61.71,62.611 C 66.977,55.945 70.128,47.531 70.128,38.378 C 70.128,29.161 66.936,20.696 61.609,14.01" style="fill:none;stroke:currentColor;stroke-width:5;stroke-linecap:round"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,17 @@
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 240 240">
<defs>
<linearGradient id="b" x1="0.6667" y1="0.1667" x2="0.4167" y2="0.75">
<stop stop-color="#000" offset="0"/>
<stop stop-color="#000" offset="1"/>
</linearGradient>
<linearGradient id="w" x1="0.6597" y1="0.4369" x2="0.8512" y2="0.8024">
<stop stop-color="#fff" offset="0"/>
<stop stop-color="#fff" offset="1"/>
</linearGradient>
</defs>
<circle cx="120" cy="120" r="120" class = "fill-color"/>
<path class = "fill-background" fill-opacity="0.5" d="m98 175c-3.8876 0-3.227-1.4679-4.5678-5.1695L82 132.2059 170 80"/>
<path class = "fill-background" fill-opacity="0.5" d="m98 175c3 0 4.3255-1.372 6-3l16-15.558-19.958-12.035"/>
<path class = "fill-background" d="m100.04 144.41 48.36 35.729c5.5185 3.0449 9.5014 1.4684 10.876-5.1235l19.685-92.763c2.0154-8.0802-3.0801-11.745-8.3594-9.3482l-115.59 44.571c-7.8901 3.1647-7.8441 7.5666-1.4382 9.528l29.663 9.2583 68.673-43.325c3.2419-1.9659 6.2173-0.90899 3.7752 1.2584"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Layer_1"
x="0px"
y="0px"
viewBox="0 0 194.9763 194.49711"
enable-background="new 0 0 405.661 316.98"
xml:space="preserve"
inkscape:version="0.91 r13725"
sodipodi:docname="whatsapp.svg"><metadata
id="metadata3422"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs3420" /><sodipodi:namedview
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1855"
inkscape:window-height="1056"
id="namedview3418"
showgrid="false"
inkscape:zoom="2.8992364"
inkscape:cx="90.564335"
inkscape:cy="48.01468"
inkscape:window-x="1985"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0" /><rect
y="-12.951568"
width="203.44708"
height="209.61963"
id="rect3408"
x="-3.27195"
style="fill:#ffffff00" /><g
id="g3410"
transform="translate(-112.956,-10.627894)"><path
d="m 112.956,205.125 c 5.281,-17.05 11.402,-33.26 16.998,-49.994 -37.095,-64.878 8.812,-137.915 70.991,-143.982 58.707,-5.729 106.841,36.439 106.987,93.988 0.153,60.723 -58.74,111.713 -124.985,90.988 -4.997,-1.563 -11.18,-6.657 -16.998,-6.999 -8.131,-0.479 -18.787,5.359 -26.997,7.999 -8.999,2.895 -16.824,5.796 -25.996,8 z m 54.993,-33.996 c 53.495,32.466 117.551,-3.949 122.985,-56.993 4.918,-48.019 -33.424,-90.745 -84.99,-86.989 -58.87,4.287 -94.232,74.559 -57.993,125.984 -3.208,8.791 -6.21,17.788 -8.999,26.997 9.822,-2.844 18.876,-6.455 28.997,-8.999 z"
id="path3412"
inkscape:connector-curvature="0"
style="clip-rule:evenodd;fill-rule:evenodd" /><!--<path--><!--d="m 138.953,180.128 c 2.789,-9.209 5.791,-18.206 8.999,-26.997 -36.24,-51.425 -0.877,-121.697 57.993,-125.984 51.566,-3.756 89.908,38.97 84.99,86.989 -5.434,53.043 -69.49,89.458 -122.985,56.993 -10.122,2.544 -19.176,6.155 -28.997,8.999 z M 165.95,95.139 c 8.578,24.126 44.126,56.803 69.991,57.993 12.26,0.564 26.755,-5.796 25.996,-22.997 -7.382,-5.283 -15.892,-9.438 -24.996,-12.998 -4.358,4.307 -7.783,9.548 -12.999,12.998 -15.685,-6.979 -27.717,-17.61 -34.995,-32.996 14.331,-7.816 5.627,-25.226 0,-36.996 -22.233,-6.699 -28.087,20.681 -22.997,34.996 z"--><!--id="path3414"--><!--inkscape:connector-curvature="0"--><!--style="clip-rule:evenodd;fill:#ffffff;fill-rule:evenodd" />--><path
d="m 188.947,60.143 c 5.627,11.77 14.331,29.179 0,36.996 7.278,15.386 19.311,26.017 34.995,32.996 5.216,-3.45 8.641,-8.691 12.999,-12.998 9.104,3.561 17.614,7.715 24.996,12.998 0.759,17.201 -13.736,23.562 -25.996,22.997 -25.865,-1.19 -61.414,-33.867 -69.991,-57.993 -5.09,-14.315 0.764,-41.695 22.997,-34.996 z"
id="path3416"
inkscape:connector-curvature="0"
style="clip-rule:evenodd;fill-rule:evenodd" /></g></svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

42
src/client/index.html Normal file
View File

@@ -0,0 +1,42 @@
<!DOCTYPE html>
<html>
<head>
<link rel="icon" type="image/png" href="img/logo.png">
<meta charset="utf-8"/>
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
<meta name="viewport"
content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
<meta http-equiv="Content-Security-Policy"
content="default-src 'self' data: gap: cdvfile: * 'unsafe-eval';
style-src 'self' 'unsafe-inline';
media-src *; img-src 'self' * data: cdvfile: content:;
script-src 'self' data: 'unsafe-eval'" ;>
<!--Element, mit dem Foundation die ViewQueries mitteilt-->
<meta class='foundation-mq'>
<link rel="stylesheet" type="text/css" href="index.css">
<title>WordRotator</title>
<script src="scripts/sql-wasm.js"></script>
<script src="scripts/localforage.js"></script>
</head>
<body class="default">
<div id="toast-container">
<div class='toast toast-template' style="opacity: 0">
<span class='message'></span>
</div>
</div>
<div id='site'>
<div class="loader overlay">
<svg viewBox="0 0 32 32" width="32" height="32">
<circle class="spinner" cx="16" cy="16" r="14" fill="none" style="stroke: black;"></circle>
</svg>
</div>
</div>
<!--<script src='https://vjs.zencdn.net/7.4.1/video.js'></script>-->
<script type="text/javascript" src="cordova.js"></script>
</body>
</html>

View File

@@ -0,0 +1,32 @@
// import {Dialog, Helper, ThemeManager, Translator, ViewInflater} from "../../../../../js/lib/pwa-lib";
//
// export class ChooseThemeDialog extends Dialog {
//
// constructor() {
// let viewPromise = ViewInflater.inflate("html/application/Dialog/chooseTheme.html").then(view => {
//
// let template = view.querySelector("#choose-theme-template");
// template.remove();
// template.id = null;
//
// let themeTemplateContainer = view.querySelector("#theme-choose-container");
//
// for (let i = 0; i < ThemeManager.themes.length; i++) {
// let themeElem = template.cloneNode(true);
// let theme = ThemeManager.themes[i];
// themeElem.querySelector(".name").appendChild(Translator.makePersistentTranslation(theme._name));
// themeElem["dataset"]["theme"] = theme._name;
//
// themeElem.addEventListener("click", () => {
// this.result = themeElem["dataset"]["theme"];
// this.close()
// });
// themeTemplateContainer.appendChild(themeElem);
// }
//
// return view;
// });
//
// super(viewPromise, "choose-theme-Dialog-title");
// }
// }

View File

@@ -0,0 +1,7 @@
// import {ConfirmDialog, Dialog, Helper, ThemeManager, Translator, ViewInflater} from "../../../../../js/lib/pwa-lib";
//
// export class PersistDialog extends ConfirmDialog{
// constructor() {
// super(Helper.isChrome()?"persist-storage-Dialog-message":"persist-storage-Dialog-message-firefox", "persist-storage-Dialog-title");
// }
// }

View File

@@ -0,0 +1,23 @@
import {Dialog} from "cordova-sites/dist/client/js/Dialog/Dialog";
import {Helper} from "js-helper/dist/shared/Helper";
import {ViewInflater} from "cordova-sites/dist/client/js/ViewInflater";
export class ShareDialog extends Dialog{
constructor() {
let viewPromise = ViewInflater.getInstance().load("html/application/Dialog/share.html").then(view => {
//TODO [MIG] ShareManager
view.appendChild(ShareManager.generateDefaultShareElement(window.location.hostname + Helper.basePath("")));
let closeListener = () => {
this.close();
};
view.querySelectorAll("a").forEach((element) => {
element.addEventListener("click", closeListener);
});
return view;
});
super(viewPromise, "share-Dialog");
}
}

View File

@@ -0,0 +1,91 @@
import {CreditsSite} from "../Sites/CreditsSite";
import {PrivacyPolicySite} from "../Sites/PrivacyPolicySite";
import {ImpressumSite} from "../Sites/ImpressumSite";
import {NativeStoragePromise} from "cordova-sites/dist/client/js/NativeStoragePromise";
import {AbstractFragment} from "cordova-sites/dist/client/js/Context/AbstractFragment";
import view from "../../html/fragment/settings.html";
import {LevelData} from "../../../shared/model/LevelData";
import {LastSyncDates} from "cordova-sites-easy-sync/dist/client/LastSyncDates";
import {SoundManager} from "cordova-sites/dist/client/js/Sound/SoundManager";
import {Toast} from "cordova-sites/dist/client/js/Toast/Toast";
import {Matomo} from "cordova-sites/dist/client/js/Legacy/Matomo";
import {LevelPlayed} from "../model/LevelPlayed";
import {ContactSite} from "../Sites/ContactSite";
export class WordRotatorSettingFragment extends AbstractFragment {
constructor(site) {
super(site, view);
}
async onViewLoaded() {
let res = super.onViewLoaded();
this.findBy("#reset-levels").addEventListener("click", async () => {
await NativeStoragePromise.remove("currentLevel");
await NativeStoragePromise.remove("levelCounter");
await NativeStoragePromise.remove("tutorial-step");
await LevelPlayed.clear();
await LevelData.clear();
await LastSyncDates.clear();
});
if (location.hostname.includes("beta") || location.hostname.includes("127.0.0.1") || location.hostname.includes("localhost")) {
this.findBy("#reset-levels").classList.remove("hidden");
}
let playMusicButton = this.findBy("#play-music");
playMusicButton.checked = (await NativeStoragePromise.getItem("play-music", "1") === "1")
playMusicButton.addEventListener("change", async () => {
await NativeStoragePromise.setItem("play-music", (playMusicButton.checked) ? "1" : "0");
let soundManager = SoundManager.getInstance();
soundManager.set({muted: !playMusicButton.checked}, SoundManager.CHANNELS.MUSIC);
if (playMusicButton.checked) {
await soundManager.play(SoundManager.CHANNELS.MUSIC);
}
//TODO [MIG] Matomo
Matomo.push(["trackEvent", "MainMenu", "PlayMusic", "Play Music", (playMusicButton.checked) ? 1 : 0]);
});
let playSoundButton = this.findBy("#play-sound");
playSoundButton.checked = (await NativeStoragePromise.getItem("play-sound", "1") === "1");
playSoundButton.addEventListener("change", async () => {
await NativeStoragePromise.setItem("play-sound", (playSoundButton.checked) ? "1" : "0");
let soundManager = SoundManager.getInstance();
soundManager.set({muted: !playSoundButton.checked}, SoundManager.CHANNELS.SOUND);
//TODO [MIG] Matomo
Matomo.push(["trackEvent", "MainMenu", "PlaySound", "Play Sound", (playSoundButton.checked) ? 1 : 0]);
});
this.findBy("#track-switch").addEventListener("change", function (e) {
Matomo.setTrack(this.checked === true);
e.stopPropagation();
e.preventDefault();
});
this.findBy("#credits-button").addEventListener("click", () => {
this.getSite().startSite(CreditsSite);
});
this.findBy("#privacy-policy-button").addEventListener("click", () => {
this.getSite().startSite(PrivacyPolicySite);
});
this.findBy("#contact-button").addEventListener("click", () => {
// new Toast("contact site").show();
this.getSite().startSite(ContactSite);
});
this.findBy("#impressum-button").addEventListener("click", () => {
this.getSite().startSite(ImpressumSite);
});
this.findBy("#version-info").innerText = window["version"];
return res;
}
onStart() {
Matomo.update("Settings Sites");
super.onStart();
}
}

View File

@@ -0,0 +1,41 @@
import view from "../../html/sites/contactSite.html"
import {App} from "cordova-sites/dist/client/js/App";
import {Form} from "cordova-sites/dist/client/js/Form";
import {DataManager} from "cordova-sites/dist/client/js/DataManager";
import {Toast} from "cordova-sites/dist/client/js/Toast/Toast";
import {Translator} from "cordova-sites/dist/client/js/Translator";
import {MenuSite} from "cordova-sites/dist/client/js/Context/MenuSite";
export class ContactSite extends MenuSite {
constructor(siteManager) {
super(siteManager, view);
}
onViewLoaded() {
let res = super.onViewLoaded();
this.findBy("#contactText").appendChild(Translator.makePersistentTranslation("contact text", [__CONTACT_EMAIL__]))
new Form(this.findBy("#contact-form"), async values => {
let result = await DataManager.send("contact", values);
if (result.success) {
new Toast("the message was sent").show();
this.finish();
} else {
if (result) {
new Toast(result.message).show();
} else {
new Toast("Es ist ein Fehler aufgetreten...").show();
}
}
});
return res;
}
}
App.addInitialization((app) => {
app.addDeepLink("contact", ContactSite);
});

View File

@@ -0,0 +1,19 @@
import {WordRotatorBaseSite} from "./WordRotatorBaseSite";
import view from "../../html/sites/credits.html"
import {App} from "cordova-sites/dist/client/js/App";
export class CreditsSite extends WordRotatorBaseSite{
constructor(siteManager) {
super(siteManager, view);
}
onStart(args) {
// Matomo.update("Credits Sites");
return super.onStart(args);
}
}
App.addInitialization(app => {
app.addDeepLink("credits", CreditsSite);
});

View File

@@ -0,0 +1,64 @@
import {UserMenuAction, UserSite} from "cordova-sites-user-management/dist/client";
import view from "../../html/sites/deleteLevels.html"
import {WordRotatorBaseSite} from "./WordRotatorBaseSite";
import {App} from "cordova-sites/dist/client/js/App";
import {NavbarFragment} from "cordova-sites/dist/client/js/Context/Menu/NavbarFragment";
import {DataManager} from "cordova-sites/dist/client/js/DataManager";
export class DeleteWordsSite extends WordRotatorBaseSite {
constructor(siteManager) {
super(siteManager, view);
this.addDelegate(new UserSite(this, "admin"))
}
async onConstruct(args) {
let res = super.onConstruct(args);
this.words = (await DataManager.load("getDoubleUsedWordsAction"))["result"];
return res;
}
onViewLoaded() {
super.onViewLoaded();
let levelTemplate = this.findBy("#level-template");
let wordTemplate = this.findBy("#word-template");
let wordContainer = this.findBy("#word-container");
levelTemplate.id = null;
levelTemplate.remove();
wordTemplate.id = null;
wordTemplate.remove();
for (let k in this.words) {
let wordElem = wordTemplate.cloneNode(true);
wordElem.querySelector(".name").appendChild(document.createTextNode(k));
let levelContainer = wordElem.querySelector(".level-container");
for (let j = 0; j < this.words[k].length; j++) {
let level = this.words[k][j];
let levelElem = levelTemplate.cloneNode(true);
levelElem.querySelector(".id").appendChild(document.createTextNode(level["id"]));
levelElem.querySelector(".words").appendChild(document.createTextNode(level["words"]));
levelElem.querySelector(".positions").appendChild(document.createTextNode(level["rotations"]));
levelElem.querySelector(".delete-button").addEventListener("click", async () => {
let res = await DataManager.send("deleteLevel", {"levelId": level["id"]});
if (res["success"]) {
levelElem.remove();
}
});
levelContainer.appendChild(levelElem);
}
wordContainer.appendChild(wordElem);
}
}
}
App.addInitialization(app => {
NavbarFragment.defaultActions.push(new UserMenuAction("delete-levels", "admin", () => {
app.startSite(DeleteWordsSite);
}));
});

View File

@@ -0,0 +1,14 @@
import {WordRotatorBaseSite} from "./WordRotatorBaseSite";
import view from "../../html/sites/end.html"
export class EndSite extends WordRotatorBaseSite{
constructor(siteManager) {
super(siteManager, view);
}
onStart(args) {
// Matomo.update("End Sites");
return super.onStart(args);
}
}

View File

@@ -0,0 +1,14 @@
import {WordRotatorBaseSite} from "./WordRotatorBaseSite";
import view from "../../html/sites/impressum.html"
import {App} from "cordova-sites/dist/client/js/App";
export class ImpressumSite extends WordRotatorBaseSite{
constructor(siteManager) {
super(siteManager, view);
}
}
App.addInitialization(app => {
app.addDeepLink("impressum", ImpressumSite);
});

View File

@@ -0,0 +1,524 @@
import {TemplateContainer} from "../wordrotator/Segment/TemplateContainer";
import {LevelHelper} from "../wordrotator/Level/LevelHelper";
import {EndSite} from "./EndSite";
import {WordRotatorBaseSite} from "./WordRotatorBaseSite";
import helpIcon from "../../img/help.png";
import {
MenuAction,
Toast,
ScaleHelper,
Matomo,
NativeStoragePromise,
} from "cordova-sites/dist/client";
import view from "../../html/sites/level.html"
import {Helper} from "js-helper/dist/shared/Helper";
import {LevelData} from "../../../shared/model/LevelData";
import {LevelPlayed} from "../model/LevelPlayed";
import {ViewHelper} from "js-helper/dist/client/ViewHelper";
import coinSound from "../../sound/single_coin_fall_on_concrete_.mp3";
import {SoundManager} from "cordova-sites/dist/client/js/Sound/SoundManager";
export class LevelSite extends WordRotatorBaseSite {
constructor(siteManager) {
super(siteManager, view);
this._navbarFragment.setBackgroundImage(null);
}
async onCreateMenu(navbar) {
super.onCreateMenu(navbar);
let coinAction = new MenuAction(Helper.nonNull(await NativeStoragePromise.getItem("coins"), "0"), () => {
}, MenuAction.SHOW_ALWAYS, 900);
coinAction._shouldTranslate = false;
coinAction._liClass = "coin-counter";
navbar.addAction(coinAction);
this.coinAction = coinAction;
let levelCounterAction = new MenuAction(Helper.nonNull(this.levelCounter, "1"), () => {
}, MenuAction.SHOW_ALWAYS, 900);
levelCounterAction._shouldTranslate = false;
levelCounterAction.setLiClass("level-counter");
navbar.addAction(levelCounterAction);
this.levelCounterAction = levelCounterAction;
let helpAction = new MenuAction("", () => {
this.help();
}, MenuAction.SHOW_ALWAYS, 900);
helpAction._shouldTranslate = false;
helpAction._icon = helpIcon;
helpAction.setLiClass("help-action show-while-playing");
navbar.addAction(helpAction);
return navbar;
}
async onConstruct(args) {
this.levelCounter = Helper.nonNull(await NativeStoragePromise.getItem("levelCounter"), 1);
// this.levelCounter = 987;
this.levelScaler = () => {
};
this.wonParams = {
aborted: false,
coinCounterTimer: null,
};
this.coinPromise = Promise.resolve();
let soundManager = SoundManager.getInstance();
soundManager.set({
audio: coinSound,
muted: (NativeStoragePromise.getItem("play-sound", "1") !== "1"),
volume: 0.7
}, SoundManager.CHANNELS.SOUND);
soundManager.resume(SoundManager.CHANNELS.MUSIC);
return super.onConstruct(args);
}
async onViewLoaded() {
let res = super.onViewLoaded();
let leafSegmentTemplate = this.findBy("#segment-leaf-template");
let parentSegmentTemplate = this.findBy("#segment-parent-template");
let rowSegmentTemplate = this.findBy("#segment-row-template");
let triangleTemplate = this.findBy("#segment-triangle-template");
let columnTemplate = this.findBy("#segment-column-template");
leafSegmentTemplate.removeAttribute("id");
parentSegmentTemplate.removeAttribute("id");
rowSegmentTemplate.removeAttribute("id");
triangleTemplate.removeAttribute("id");
columnTemplate.removeAttribute("id");
leafSegmentTemplate.remove();
parentSegmentTemplate.remove();
rowSegmentTemplate.remove();
triangleTemplate.remove();
columnTemplate.remove();
let continueButton = this.findBy("#continue-button");
continueButton.addEventListener("click", () => {
this.nextLevel();
});
let wonText = this.findBy("#won-text");
let scaleHelper = new ScaleHelper();
this.continueButtonScaler = await scaleHelper.scaleToFull(continueButton, continueButton.parentElement, false, true, 2);
this.wonTextScaler = await scaleHelper.scaleToFull(wonText, wonText.parentElement, false, false, 2, null, 5);
this.wonText = wonText;
this.wonText.style.fontSize = "0";
this.templateContainer = new TemplateContainer(leafSegmentTemplate, parentSegmentTemplate, rowSegmentTemplate, triangleTemplate, columnTemplate);
this.coinTemplate = this.findBy("#coin-template");
this.coinContainer = this.findBy("#coin-container");
this.coinTemplate.id = null;
ViewHelper.removeAllChildren(this.coinContainer);
// this.findBy("#help-button").addEventListener("click", () => {
// this.help();
// });
await this.loadLastLevel();
return res;
}
async loadLastLevel() {
try {
let currentLevelInfo = await NativeStoragePromise.getItem("currentLevel");
if (Helper.isNotNull(currentLevelInfo)) {
currentLevelInfo = JSON.parse(currentLevelInfo);
let levelData = await LevelData.findById(currentLevelInfo["id"]);
if (Helper.isNull(levelData)) {
return this.nextLevel();
}
let level = LevelHelper.inflateLevel(levelData, this.templateContainer);
level.setStartRotations(currentLevelInfo["rotations"]);
level.getWonPromise().then(() => {
this.levelWon(level);
});
level.createSegments();
level.setLocks(currentLevelInfo["locks"]);
level.getRootSegment()._updateElement();
level.saveAsCurrentLevel();
let levelSegment = this.findBy("#level");
ViewHelper.removeAllChildren(levelSegment).appendChild(level.getRootSegment().getElement());
let scaleHelper = new ScaleHelper();
this.levelScaler = await scaleHelper.scaleToFull(levelSegment, levelSegment.parentElement, false, false, 1, level.words[0].length * 1.5, null, 0);
this.level = level;
// let res = this.tutorial();
Matomo.push(["trackEvent", "LevelSite", "LoadLastLevel"]);
this.level.checkHasWon();
return;
}
} catch (e) {
console.error(e);
}
return this.nextLevel();
}
startEndSite() {
this.startSite(EndSite);
this.finish();
}
updateLevelCounter() {
this.levelCounterAction.setName(this.levelCounter);
if (this.levelCounter >= 10 && this.levelCounter <= 99) {
this.levelCounterAction.setLiClass("num-10 level-counter");
} else if (this.levelCounter >= 100 && this.levelCounter <= 999) {
this.levelCounterAction.setLiClass("num-100 level-counter");
} else if (this.levelCounter >= 1000) {
this.levelCounterAction.setLiClass("num-1000 level-counter");
} else {
this.levelCounterAction.setLiClass("level-counter");
}
}
async nextLevel() {
this.showLoadingSymbol();
try {
let levelData = await LevelPlayed.getNextLevelData(LevelSite.RENDERER_TYPES);
if (Helper.isNull(levelData)) {
this.startEndSite();
return;
}
const level = LevelHelper.inflateLevel(levelData, this.templateContainer);
//Waiting for Level to be done
if (this.level && level.id === this.level.id) {
console.log("Level is the same as before! reload!");
await new Promise((resolve) => setTimeout(resolve, 50));
// return;
debugger;
return this.nextLevel();
}
level.getWonPromise().then(() => {
this.levelWon(level);
});
level.createSegments();
level.getRootSegment()._updateElement();
level.saveAsCurrentLevel();
let levelSegment = this.findBy("#level");
ViewHelper.removeAllChildren(levelSegment).appendChild(level.getRootSegment().getElement());
this._view.classList.remove('won');
this.wonText.style.fontSize = "0";
this.removeLoadingSymbol();
let scaleHelper = new ScaleHelper();
this.levelScaler = await scaleHelper.scaleToFull(levelSegment, levelSegment.parentElement, false, false, 1, level.words[0].length * 1.5, null, 0);
this.level = level;
this.updateLevelCounter();
this.coinAction.setName(Helper.nonNull(await NativeStoragePromise.getItem("coins"), "0"));
// this.coinAction.redraw();
this.wonParams.aborted = true;
clearTimeout(this.wonParams.coinCounterTimer);
Matomo.push(["trackEvent", "LevelSite", "NextLevel", "Level Number Normal", this.levelCounter]);
this.level.checkHasWon();
return this.tutorial();
} catch (e) {
console.log("Fehler!");
console.error(e);
this.startEndSite();
}
}
async onStart(args) {
Matomo.update("Level Sites");
let res = super.onStart(args);
if (this.levelCounterAction) {
this.updateLevelCounter();
}
this.levelScaler();
//TODO Sound
let soundManager = SoundManager.getInstance();
soundManager.set({
audio: coinSound,
muted: (await NativeStoragePromise.getItem("play-sound", "1") !== "1"),
volume: 0.7
}, SoundManager.CHANNELS.SOUND);
await this.tutorial();
return res;
}
async levelWon(level) {
try {
const savePromise = LevelPlayed.setPlayed(level.getLevelData());
savePromise.then((r) => console.log("levelSaved!", r));
this.levelCounter++;
await NativeStoragePromise.setItem("levelCounter", this.levelCounter);
//Todo richtiges Element aufrufen?
this._view.classList.add('won');
await NativeStoragePromise.remove("currentLevel");
let continueButton = this.findBy("#continue-button");
continueButton.style.transition = "none";
continueButton.style.opacity = 0;
ViewHelper.removeAllChildren(this.coinContainer);
let coinsPerLevel = await NativeStoragePromise.getItem("coinsPerLevel", 5);
let coinsBefore = 0;
let soundManager = SoundManager.getInstance();
let audioOptions = soundManager.get(SoundManager.CHANNELS.SOUND);
this.coinPromise = this.coinPromise.then(async () => {
coinsBefore = parseInt(Helper.nonNull(await NativeStoragePromise.getItem("coins"), "0"));
await NativeStoragePromise.setItem("coins", coinsBefore + parseInt(coinsPerLevel));
}).then(async () => {
return Promise.all([new Promise((r) => {
setTimeout(() => {
//TODO animationen einbauen
continueButton.style.opacity = 1;
r();
}, 500)
}),
audioOptions.loadedPromise.catch(e => {
console.error(e)
})
]);
});
this.wonParams.aborted = false;
for (let i = 0; i < coinsPerLevel; i++) {
let coinElem = this.coinTemplate.cloneNode(true);
this.coinContainer.appendChild(coinElem);
this.coinPromise = this.coinPromise.then(() => {
return new Promise(r => {
let timeout = 350;
if (!this.wonParams.aborted) {
//TODO animationen einbauen
coinElem.style.opacity = 1;
// coinElem.fadeIn(timeout / 1000);
soundManager.play(SoundManager.CHANNELS.SOUND);
this.wonParams.coinCounterTimer = setTimeout(() => {
if (!this.wonParams.aborted) {
this.coinAction.setName(++coinsBefore);
// this.coinAction.redraw();
}
}, timeout / 2);
} else {
r();
}
//Always do the next promise for garbage collection
setTimeout(r, timeout);
})
});
}
this.coinPromise = this.coinPromise.catch((e) => {
console.error(e)
});
this.wonTextScaler();
this.continueButtonScaler();
this.levelScaler();
Matomo.push(["trackEvent", "LevelSite", "LevelWon", "Coins", parseInt(Helper.nonNull(await NativeStoragePromise.getItem("coins"), "0"))]);
let leafs = level.getLeafSegments();
leafs.forEach((leaf, i) => {
let elem = leaf.getElement();
elem.style.animationDelay = i*50+"ms";
elem.classList.add("jump-animation");
})
await savePromise;
} catch (e) {
console.error(e);
}
}
async help() {
let cost = await NativeStoragePromise.getItem("costForHelp", 25);
let currentCoins = parseInt(Helper.nonNull(await NativeStoragePromise.getItem("coins"), 0));
if (currentCoins >= cost) {
currentCoins -= cost;
await NativeStoragePromise.setItem("coins", currentCoins);
this.coinAction.setName(currentCoins);
let rotatables = this.level.getRotatableSegments();
rotatables = rotatables.filter((segment) => {
return (!segment.isSolved(false));
});
let index = Math.floor(Math.random() * rotatables.length);
let segmentToHelp = rotatables[index];
while (segmentToHelp.rotation !== 0) {
segmentToHelp.rotate();
}
segmentToHelp.setIsRotatable(false);
this.level.saveAsCurrentLevel();
// Matomo.push(["trackEvent", "LevelSite", "Help", "Coins", parseInt(Helper.nonNull(localStorage.getItem("coins"), "0"))]);
} else {
new Toast("not-enough-coins").show();
// Matomo.push(["trackEvent", "LevelSite", "Help", "Not enough Coins", parseInt(Helper.nonNull(localStorage.getItem("coins"), "0"))]);
}
}
async tutorial() {
if (this.level.id === LevelSite.TUTORIAL.FIRST_LEVEL) {
let currentStep = Helper.nonNull(await NativeStoragePromise.getItem("tutorial-step"), "1");
let scaleHelper = new ScaleHelper();
this._view.classList.add("tutorial");
this._view.classList.add("step-" + currentStep);
switch (currentStep) {
case "1": {
this.level.setSegmentClickedListener(async () => {
this._view.classList.remove("step-1");
await NativeStoragePromise.setItem("tutorial-step", "2");
this.tutorial();
});
let textElem = this.findBy(".tutorial-text .step-1");
await this.levelScaler();
scaleHelper.scaleToFull(textElem, textElem.parentElement, null, true, 1, 2);
break;
}
case "2": {
this.level.setSegmentClickedListener(() => {
});
this.level.getWonPromise().then(async () => {
this._view.classList.remove("tutorial");
this._view.classList.remove("step-2");
await NativeStoragePromise.remove("tutorial-step");
this.coinPromise = this.coinPromise.then(async () => {
new Toast("extra-coins-after-first-level").show();
await NativeStoragePromise.setItem("coins", parseInt(Helper.nonNull(await NativeStoragePromise.getItem("coins"), "0")) + 50);
this.coinAction.setName(Helper.nonNull(await NativeStoragePromise.getItem("coins"), "0"));
// this.coinAction.redraw();
});
// this.levelScaler();
});
let textElem = this.findBy(".tutorial-text .step-2");
await this.levelScaler();
scaleHelper.scaleToFull(textElem, textElem.parentElement, null, true, 1, 2);
break;
}
default: {
this._view.classList.remove("tutorial");
}
}
} else if (this.level.id === LevelSite.TUTORIAL.SECOND_LEVEL) {
let currentStep = Helper.nonNull(await NativeStoragePromise.getItem("tutorial-step"), "3");
switch (currentStep) {
case "3": {
let scaleHelper = new ScaleHelper();
this._view.classList.add("tutorial");
this._view.classList.add("step-" + currentStep);
let eventListener = async () => {
this._view.classList.remove("tutorial");
this._view.classList.remove("step-3");
await NativeStoragePromise.setItem("tutorial-step", "4");
// this.findBy("#help-button").removeEventListener("click", eventListener);
this.levelScaler();
};
this.findBy(".help-action").addEventListener("click", eventListener);
let textElem = this.findBy(".tutorial-text .step-3");
await this.levelScaler();
scaleHelper.scaleToFull(textElem, textElem.parentElement, null, true, 1, 2);
break;
}
default: {
this._view.classList.remove("tutorial");
}
}
} else if (this.level.id === LevelSite.TUTORIAL.BIG_SEGMENT_LEVEL) {
let currentStep = Helper.nonNull(await NativeStoragePromise.getItem("tutorial-step"), "4");
switch (currentStep) {
case "4": {
let scaleHelper = new ScaleHelper();
this._view.classList.add("tutorial");
this._view.classList.add("step-" + currentStep);
let rotatableSegments = this.level.getRotatableSegments();
let firstSegment = rotatableSegments[2];
let pointer = this.findBy("#tutorial-pointer");
pointer.remove();
firstSegment.element.appendChild(pointer);
this.level.setSegmentClickedListener(async (segment) => {
if (firstSegment === segment) {
this._view.classList.remove("tutorial");
this._view.classList.remove("step-4");
await NativeStoragePromise.setItem("tutorial-step", "5");
this.levelScaler();
}
});
let textElem = this.findBy(".tutorial-text .step-4");
await this.levelScaler();
scaleHelper.scaleToFull(textElem, textElem.parentElement, null, true, 1, 2);
break;
}
default: {
this._view.classList.remove("tutorial");
}
}
}
}
}
LevelSite.RENDERER_TYPES = [20, 40, 60, 80, 81, 82, 83, 100, 110, 111, 112, 120, 140, 160];
// LevelSite.RENDERER_TYPES = [120, 140, 160];
LevelSite.TUTORIAL = {
FIRST_LEVEL: 67,
SECOND_LEVEL: 15,
BIG_SEGMENT_LEVEL: 1921
};

View File

@@ -0,0 +1,257 @@
import {WordRotatorBaseSite} from "./WordRotatorBaseSite";
import {App, Toast, DataManager, ScaleHelper} from "cordova-sites/dist/client";
import {Helper} from "js-helper/dist/shared";
import {LevelSite} from "./LevelSite";
import {TemplateContainer} from "../wordrotator/Segment/TemplateContainer";
import {MainMenuLevel} from "../wordrotator/Level/MainMenuLevel";
import view from "../../html/sites/menu.html"
import {NativeStoragePromise} from "cordova-sites/dist/client";
import {ViewHelper} from "js-helper/dist/client/ViewHelper";
import {LevelPlayed} from "../model/LevelPlayed";
import {SyncJob} from "cordova-sites-easy-sync/dist/client/SyncJob";
import {LevelData} from "../../../shared/model/LevelData";
import {ShareManager} from "cordova-sites/dist/client/js/ShareManager/ShareManager";
import {Translator} from "cordova-sites/dist/client/js/Translator";
import {SoundManager} from "cordova-sites/dist/client/js/Sound/SoundManager";
import {Matomo} from "cordova-sites/dist/client/js/Legacy/Matomo";
import {MenuAction} from "cordova-sites/dist/client/js/Context/Menu/MenuAction/MenuAction";
import {SettingsSite} from "./SettingsSite";
import settingsIcon from "../../img/settings.png";
export class MainMenuSite extends WordRotatorBaseSite {
constructor(siteManager) {
super(siteManager, view);
this.loadLevelPromise = new SyncJob().sync([LevelData]).catch(e => console.error(e));
this.listener = null;
this._navbarFragment.setCanGoBack(false);
}
onCreateMenu(navbar) {
super.onCreateMenu(navbar);
let settingsAction = new MenuAction("", () => {
this.startSite(SettingsSite);
}, MenuAction.SHOW_ALWAYS, null, settingsIcon);
navbar.addAction(settingsAction);
return navbar;
}
async onStart(args) {
// Matomo.update("Menu Sites");
let res = super.onStart(args);
let level = new MainMenuLevel(this.templateContainer);
level.setWords(["WORD", "ROTA", "TORW", "ORDR"]);
level.createSegments();
level.getWonPromise().then(() => {
// Matomo.push(["trackEvent", "MainMenu", "levelSolved"]);
this.startLevelSite();
});
let segment = level.getRootSegment();
segment._updateElement();
let levelSegment = this.findBy("#level");
ViewHelper.removeAllChildren(levelSegment).appendChild(segment.getElement());
let rotationsSegments = level.getRotatableSegments();
let randomRotationFunction = () => {
let timeout = Math.random() * 4500 + 1500;
this.randomRotateTimeout = setTimeout(() => {
let indexBlocked = -1;
let indexesNotRight = [];
for (let i = 0; i < rotationsSegments.length; i++) {
if (rotationsSegments[i].rotation !== 0) {
indexesNotRight.push(i);
if (indexesNotRight.length >= 2) {
break;
}
}
}
if (indexesNotRight.length === 1) {
indexBlocked = indexesNotRight[0];
}
let index = Math.floor(Math.random() * rotationsSegments.length);
if (index === indexBlocked) {
index = (index + 1) % rotationsSegments.length;
}
rotationsSegments[index].rotate();
randomRotationFunction();
}, timeout);
};
randomRotationFunction();
this.listener = async () => {
let playButton = this.findBy("#play-button");
let levelNumber = this.findBy("#level-number");
levelNumber.innerText = Helper.nonNull(await NativeStoragePromise.getItem("levelCounter"), 1);
let levelSegment = this.findBy("#level");
let scaleHelper = new ScaleHelper();
await scaleHelper.scaleToFull(levelSegment, levelSegment.parentElement, false, false, 2, 8, null, false);
let levelStyle = getComputedStyle(levelSegment);
playButton.style.width = levelStyle.getPropertyValue("width");
scaleHelper.scaleToFull(playButton.children[0], playButton, null, null, null, 4, null, false);
await scaleHelper.scaleTo(0.2, levelNumber.parentElement, levelNumber.parentElement.parentElement, null, null, null, 10, null, false);
scaleHelper.scaleToFull(levelNumber, levelNumber.parentElement, false, false, 8, null, null, false);
};
// this.listener();
window.addEventListener("resize", this.listener);
setTimeout(this.listener, 50);
//Musikbuttons update, falls in den Einstellungen umgestellt
// let settingsManager = SettingsManager.getInstance();
let playSoundButton = this.findBy("#play-sound");
playSoundButton.checked = (await NativeStoragePromise.getItem("play-sound", "1") === "1");
let playMusicButton = this.findBy("#play-music");
playMusicButton.checked = (await NativeStoragePromise.getItem("play-music", "1") === "1");
return res;
}
async startLevelSite() {
SoundManager.getInstance().resumeContext();
this.startSite(LevelSite, Promise.race([this.loadLevelPromise, new Promise(async resolve => {
let levelData = await LevelPlayed.getNextLevelData(LevelSite.RENDERER_TYPES);
if (levelData !== null) {
resolve();
}
})]));
}
async onFirstStart() {
super.onFirstStart();
let playButton = this.findBy("#play-button");
playButton.addEventListener("click", () => {
// Matomo.push(["trackEvent", "MainMenu", "startButton"]);
this.startLevelSite();
});
let leafSegmentTemplate = this.findBy("#segment-leaf-template");
let parentSegmentTemplate = this.findBy("#segment-parent-template");
let rowSegmentTemplate = this.findBy("#segment-row-template");
let triangleTemplate = this.findBy("#segment-triangle-template");
leafSegmentTemplate.id = null;
parentSegmentTemplate.id = null;
rowSegmentTemplate.id = null;
triangleTemplate.id = null;
leafSegmentTemplate.remove();
parentSegmentTemplate.remove();
rowSegmentTemplate.remove();
triangleTemplate.remove();
this.templateContainer = new TemplateContainer(leafSegmentTemplate, parentSegmentTemplate, rowSegmentTemplate, triangleTemplate);
if (Helper.nonNull(MainMenuSite.app._cookieClosePromise)) {
MainMenuSite.app._cookieClosePromise.then(() => {
if (this.listener) {
this.listener();
}
});
}
let soundManager = SoundManager.getInstance();
let playMusicButton = this.findBy("#play-music");
playMusicButton.checked = (await NativeStoragePromise.getItem("play-music", "1") === "1");
playMusicButton.addEventListener("change", async () => {
await NativeStoragePromise.setItem("play-music", (playMusicButton.checked) ? "1" : "0");
soundManager.set({muted: !playMusicButton.checked}, SoundManager.CHANNELS.MUSIC);
if (playMusicButton.checked) {
soundManager.play(SoundManager.CHANNELS.MUSIC);
}
//TODO [MIG] Matomo
Matomo.push(["trackEvent", "MainMenu", "PlayMusic", "Play Music", (playMusicButton.checked) ? 1 : 0]);
});
let playSoundButton = this.findBy("#play-sound");
playSoundButton.checked = (await NativeStoragePromise.getItem("play-sound", "1") === "1");
playSoundButton.addEventListener("change", async () => {
await NativeStoragePromise.setItem("play-sound", (playSoundButton.checked) ? "1" : "0");
soundManager.set({muted: !playSoundButton.checked}, SoundManager.CHANNELS.SOUND);
//TODO [MIG] Matomo
Matomo.push(["trackEvent", "MainMenu", "PlaySound", "Play Sound", (playSoundButton.checked) ? 1 : 0]);
});
this.findBy("#share-button").addEventListener("click", () => {
new ShareManager().share(Translator.getInstance().translate("share-text", [window.location]));
});
// this.findBy("#share-buttons").appendChild(ShareManager.generateDefaultShareElement("https://wordrotator.silas.link"));
}
onPause(args) {
clearTimeout(this.randomRotateTimeout);
window.removeEventListener("resize", this.listener);
return super.onPause(args);
}
async loadLevels() {
try {
const db = await WordRotatorDb.getInstance();
const dateLastSync = Helper.nonNull(await db.loadDateLastSync(), 0);
// const dateLastSync = Helper.nonNull(localStorage.getItem("date-last-sync"), 0);
// let numberLevels = db.countLevels();
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"]) {
if (await db.loadNextLevel(LevelSite.RENDERER_TYPES) === null) {
new Toast("sync-error", 6000).show();
}
newLastSync = null;
break;
}
res = res["result"];
newLastSync = Helper.nonNull(newLastSync, res["currentSyncDate"]);
maxRuns = res["maxRuns"];
let levels = res["levels"];
for (let i = 0; i < levels.length; 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") {
await NativeStoragePromise.setItem("date-last-sync", newLastSync);
db.saveDateLastSync(newLastSync);
}
}
catch(e){
// if (await db.loadNextLevel(LevelSite.RENDERER_TYPES) === null) {
new Toast("sync-error", 6000);
// }
console.error(e);
}
}
}
MainMenuSite.app = null;
App.addInitialization(app => {
MainMenuSite.app = app;
});

View File

@@ -0,0 +1,34 @@
import {WordRotatorBaseSite} from "./WordRotatorBaseSite";
import view from "../../html/sites/privacyPolicy.html"
import {App} from "cordova-sites/dist/client/js/App";
import {Matomo} from "cordova-sites/dist/client/js/Legacy/Matomo";
export class PrivacyPolicySite extends WordRotatorBaseSite {
constructor(siteManager) {
super(siteManager,view);
}
async onViewLoaded() {
let trackSwitch =this.findBy("#track-switch");
trackSwitch.addEventListener("change", function (e) {
Matomo.setTrack(this.checked === true);
e.stopPropagation();
e.preventDefault();
});
return super.onViewLoaded();
}
async onStart(args) {
let trackSwitch =this.findBy("#track-switch");
trackSwitch.checked = ((await Matomo.getTrackingPromise()) === "1");
// Matomo.update("Privacy Policy Sites");
return super.onStart(args);
}
}
App.addInitialization(app => {
app.addDeepLink("privacyPolicy", PrivacyPolicySite);
});

View File

@@ -0,0 +1,83 @@
import view from "../../html/sites/selectWords.html"
import {WordRotatorBaseSite} from "./WordRotatorBaseSite";
import {UserMenuAction, UserSite} from "cordova-sites-user-management/dist/client";
import {NavbarFragment} from "cordova-sites/dist/client/js/Context/Menu/NavbarFragment";
import {App} from "cordova-sites/dist/client/js/App";
import {DataManager} from "cordova-sites/dist/dist/client/js/DataManager";
import {ViewHelper} from "js-helper/dist/client/ViewHelper";
export class SelectWordsSite extends WordRotatorBaseSite{
constructor(siteManager) {
super(siteManager, view);
this.addDelegate(new UserSite("select-words"))
}
async onConstruct(args) {
let res = await super.onConstruct(args);
this.stats = (await DataManager.load("words"))["result"];
this.words = this.stats["wordsToCheck"];
console.log(this.stats);
return res;
}
async onViewLoaded() {
let res = super.onViewLoaded();
this.findBy("#not-checked").appendChild(document.createTextNode(this.stats["wordsNotChecked"]));
this.findBy("#checked").appendChild(document.createTextNode(this.stats["wordsChecked"]));
this.findBy("#not-sure").appendChild(document.createTextNode(this.stats["wordsUnsure"]));
this.findBy("#deleted").appendChild(document.createTextNode(this.stats["wordsDeleted"]));
this.findBy("#unused").appendChild(document.createTextNode(this.stats["wordsNotUsed"]));
let template = this.findBy("#word-template");
template.id = null;
template.remove();
let container = this.findBy("#word-container");
let numWords = this.words.length;
for (let i = 0; i < numWords; i++) {
let wordElement = template.cloneNode(true);
wordElement.dataset["id"] = -1;
this.setWord(wordElement, this.words[i]);
container.appendChild(wordElement);
wordElement.querySelector(".button-ok").addEventListener("click", async () => {
let newWord = (await DataManager.send("checkWord", {
"wordId":wordElement.dataset["id"],
"action":"1"
}))["result"];
this.setWord(wordElement, newWord[0]);
});
wordElement.querySelector(".button-unsure").addEventListener("click", async () => {
let newWord = (await DataManager.send("checkWord", {
"wordId":wordElement.dataset["id"],
"action":"2"
}))["result"];
this.setWord(wordElement, newWord[0]);
});
wordElement.querySelector(".button-delete").addEventListener("click", async () => {
let newWord = (await DataManager.send("checkWord", {
"wordId":wordElement.dataset["id"],
"action":"3"
}))["result"];
this.setWord(wordElement, newWord[0]);
});
}
return res;
}
setWord(wordElement, word){
ViewHelper.removeAllChildren(wordElement.querySelector(".word")).appendChild(document.createTextNode(word["word"]));
wordElement.dataset["id"] = word["id"];
}
}
App.addInitialization(app => {
NavbarFragment.defaultActions.push(new UserMenuAction("select-words", "select-words", () => {
app.startSite(SelectWordsSite);
}));
});

View File

@@ -0,0 +1,17 @@
import view from "../../html/sites/settingsSite.html"
import {MenuSite} from "cordova-sites/dist/client/js/Context/MenuSite";
import {WordRotatorSettingFragment} from "../Fragment/WordRotatorSettingFragment";
import {App} from "cordova-sites/dist/client/js/App";
export class SettingsSite extends MenuSite {
constructor(siteManager) {
super(siteManager, view);
this.addFragment("#wordRotatorSettings", new WordRotatorSettingFragment(this));
}
}
App.addInitialization((app) => {
app.addDeepLink("settings", SettingsSite);
});

View File

@@ -0,0 +1,12 @@
import {MenuSite} from "cordova-sites/dist/client";
export class WordRotatorBaseSite extends MenuSite {
async onViewLoaded() {
let res = super.onViewLoaded();
await this.onFirstStart();
return res;
}
async onFirstStart(){}
}

View File

@@ -0,0 +1,10 @@
import {SystemSettings, Translator} from "./lib/pwa-lib";
import {Matomo} from "./lib/pwa-assets";
SystemSettings.setBasePath("/");
Translator.supportedLanguages = ["de"];
Translator.markTranslations = false;
Translator.markUntranslatedTranslations = false;
window["version"] = "1-beta";
Matomo.SIDE_ID = 1;

View File

@@ -0,0 +1,78 @@
import {BaseModel} from "cordova-sites-database/dist/BaseModel";
import {BaseDatabase} from "cordova-sites-database/dist/cordova-sites-database";
import {LevelData} from "../../../shared/model/LevelData";
import {Helper} from "js-helper/dist/shared/Helper";
export class LevelPlayed extends BaseModel {
levelData: LevelData;
played: boolean;
static getColumnDefinitions() {
let columns = super.getColumnDefinitions();
columns["played"] = {type: BaseDatabase.TYPES.BOOLEAN, default: true};
return columns;
}
static getRelationDefinitions() {
let relations = super.getRelationDefinitions();
relations["levelData"] = {
target: LevelData.getSchemaName(),
type: "one-to-one",
joinColumn: true,
cascade: true,
};
return relations;
}
static async setPlayed(levelData, played?){
played = Helper.nonNull(played, true);
let levelPlayed = new LevelPlayed();
levelPlayed.levelData = levelData;
levelPlayed.played = played;
return await levelPlayed.save();
}
static async getNextLevelData(renderer){
let qb = await this._database.createQueryBuilder(LevelData);
qb = qb.select("COUNT(*) as count, difficulty")
.leftJoin(LevelPlayed, "levelPlayed", "levelPlayed.levelData = LevelData.id")
.where("(deleted = 0 OR deleted = 'false')")
.andWhere("renderer IN ("+renderer.join(",")+")")
.andWhere("(levelPlayed.id IS NULL OR levelPlayed.played = 0)")
.groupBy("difficulty")
.orderBy("difficulty, LevelData.id");
let countRes = await qb.getRawMany();
let difficulty = null;
let offset = null;
if (!countRes.some(res => {
if (res["count"] > 0){
difficulty = res["difficulty"];
offset = Math.floor(Math.random() * Math.floor(res["count"]));
return true;
}
return false;
})){
return null;
}
qb = await this._database.createQueryBuilder(LevelData);
qb = qb
.leftJoin(LevelPlayed, "levelPlayed", "levelPlayed.levelData = LevelData.id")
.where("(deleted = 0 OR deleted = 'false')")
.andWhere("difficulty = "+difficulty)
.andWhere("renderer IN ("+renderer.join(",")+")")
.andWhere("(levelPlayed.id IS NULL OR levelPlayed.played = 0)")
.orderBy("LevelData.id")
.limit(1)
.offset(offset);
return await qb.getOne();
}
}
BaseDatabase.addModel(LevelPlayed);

View File

@@ -0,0 +1,14 @@
import {MigrationInterface, QueryRunner, Table} from "typeorm";
import {MigrationHelper} from "js-helper/dist/shared";
import {LevelPlayed} from "../LevelPlayed";
export class ClientSetup1000000002001 implements MigrationInterface {
async up(queryRunner: QueryRunner): Promise<any> {
await MigrationHelper.addTableFromModelClass(LevelPlayed, queryRunner);
}
down(queryRunner: QueryRunner): Promise<any> {
return undefined;
}
}

View File

@@ -0,0 +1,10 @@
import {SystemSettings, Translator} from "./lib/pwa-lib";
import {Matomo} from "./lib/pwa-assets";
SystemSettings.setBasePath("/");
Translator.supportedLanguages = ["de"];
Translator.markTranslations = false;
Translator.markUntranslatedTranslations = false;
window["version"] = "1.1";
Matomo.SIDE_ID = 3;

109
src/client/js/script.js Normal file
View File

@@ -0,0 +1,109 @@
import translationGerman from '../translations/de.json';
import translationEn from '../translations/en.json';
import {App, Translator, DataManager, Toast} from "cordova-sites/dist/client";
import "cordova-sites-user-management/dist/client/js/translationInit"
import "cordova-sites/dist/client/js/translationInit"
import {LoginSite, RegistrationSite, UserManager} from "cordova-sites-user-management/dist/client";
import {BaseDatabase} from "cordova-sites-database/dist/cordova-sites-database";
import {DeleteUserManagement1000000000000} from "cordova-sites-user-management/dist/shared//migrations/DeleteUserManagement";
import {SetupUserManagement1000000001000} from "cordova-sites-user-management/dist/shared/migrations/SetupUserManagement";
import {Setup1000000002000} from "../../shared/model/migration/shared/Setup";
import {SetupEasySync1000000000500} from "cordova-sites-easy-sync/dist/client";
import {MainMenuSite} from "./Sites/MainMenuSite";
import {ClientSetup1000000002001} from "./model/migration/ClientSetup";
import {EasySyncClientDb} from "cordova-sites-easy-sync/dist/client/EasySyncClientDb";
import {NavbarFragment} from "cordova-sites/dist/client/js/Context/Menu/NavbarFragment";
import {NativeStoragePromise} from "cordova-sites/dist/client/js/NativeStoragePromise";
import music from "../sound/brightAndBeautifull__.mp3";
import {SoundManager} from "cordova-sites/dist/client/js/Sound/SoundManager";
window["JSObject"] = Object;
//Disable Google Analytics for VideoJS
window["HELP_IMPROVE_VIDEOJS"] = false;
LoginSite.ADD_LOGIN_ACTION = false;
RegistrationSite.ADD_REGISTRATION_ACTION = false;
App.addInitialization(async () => {
Translator.init({
translations: {
"de": translationGerman,
"en": translationEn
},
fallbackLanguage: "de",
// markTranslations: true,
markUntranslatedTranslations: true,
});
//Setting Title
NavbarFragment.title = "WordRotator";
let soundManager = SoundManager.getInstance();
soundManager.play(SoundManager.CHANNELS.MUSIC, {
audio: music,
loop: true,
volume: 0.6,
muted: (await NativeStoragePromise.getItem("play-music", "1") !== "1")
}).catch(e => console.error(e));
await UserManager.getInstance().getMe().catch(e => console.error(e));
UserManager.getInstance().addLoginChangeCallback(async (isLoggedIn) => {
if (isLoggedIn) {
// await new SyncJob().sync([UserManager.syncParamFor(Definition), UserManager.syncParamFor(ExerciseProgress), UserManager.syncParamFor(WrongAnswer)]).catch(e => console.error(e));
}
});
});
DataManager._basePath = __HOST_ADDRESS__;
DataManager.onlineCallback = isOnline => {
if (!isOnline){
new Toast("not online!").show();
}
};
Object.assign(BaseDatabase.CONNECTION_OPTIONS, {
logging: ["error",],
synchronize: false,
migrationsRun: true,
migrations: [
DeleteUserManagement1000000000000,
SetupEasySync1000000000500,
SetupUserManagement1000000001000,
Setup1000000002000,
ClientSetup1000000002001,
]
});
let app = new App();
app.start(MainMenuSite).catch(e => console.error(e)).then(async () => {
window["queryDb"] = async (sql) => {
// SELECT name FROM my_db.sqlite_master WHERE type='table';
// console.log("DB", EasySyncClientDb.getInstance());
let res = await EasySyncClientDb.getInstance().rawQuery(sql);
console.log(res);
return res;
}
});
app.ready(() => {
console.log("initialisation over", new Date());
if (device.platform === "browser"){
// Check that service workers are supported
if ('serviceWorker' in navigator) {
// Use the window load event to keep the page load performant
window.addEventListener('load', () => {
navigator.serviceWorker.register('service-worker.js');
});
}
}
});

5
src/client/js/sw.js Normal file
View File

@@ -0,0 +1,5 @@
import {precacheAndRoute} from "workbox-precaching";
const precacheManifest = self.__WB_MANIFEST;
precacheAndRoute(precacheManifest || []);

View File

@@ -0,0 +1,76 @@
import {Level} from "./Level";
import {RowSegment} from "../Segment/RowSegment";
import {ParentSegment} from "../Segment/ParentSegment";
import {ColumnSegment} from "../Segment/ColumnSegment";
export class BigSegmentsLevels extends Level{
constructor(templateContainer, wordLength, bigSegmentPositions) {
super(templateContainer);
this.wordLength = wordLength;
this.bigSegmentPositions = bigSegmentPositions;
}
createSegments() {
if (this.words.length >= 4 &&
this.words[0].length >= this.wordLength &&
this.words[1].length >= this.wordLength &&
this.words[2].length >= this.wordLength &&
this.words[3].length >= this.wordLength &&
this.wordLength >= 4
) {
let leafsWords = [];
leafsWords[0] = Level._createLeafsForWord(this.words[0], this.templateContainer.copyLeafTemplate());
leafsWords[1] = Level._createLeafsForWord(this.words[1], this.templateContainer.copyLeafTemplate());
leafsWords[2] = Level._createLeafsForWord(this.words[2], this.templateContainer.copyLeafTemplate());
leafsWords[3] = Level._createLeafsForWord(this.words[3], this.templateContainer.copyLeafTemplate());
let rootSegment = new RowSegment(this.templateContainer.copyRowTemplate());
for (let i = 0; i < this.wordLength / 2; i++) {
let parents = [];
parents[0] = new ParentSegment(this.templateContainer.copyParentTemplate());
parents[1] = new ParentSegment(this.templateContainer.copyParentTemplate());
parents[0].addChild(leafsWords[0][2 * i]);
parents[0].addChild(leafsWords[0][2 * i + 1]);
parents[0].addChild(leafsWords[1][2 * i]);
parents[0].addChild(leafsWords[1][2 * i + 1]);
parents[1].addChild(leafsWords[2][2 * i]);
parents[1].addChild(leafsWords[2][2 * i + 1]);
parents[1].addChild(leafsWords[3][2 * i]);
parents[1].addChild(leafsWords[3][2 * i + 1]);
let parentSegment =null;
if (this.bigSegmentPositions.indexOf(i) !== -1){
parents[2] = new ParentSegment(this.templateContainer.copyParentTemplate());
parents[3] = new ParentSegment(this.templateContainer.copyParentTemplate());
parents[2].addChild(leafsWords[0][2 * i + 2]);
parents[2].addChild(leafsWords[0][2 * i + 3]);
parents[2].addChild(leafsWords[1][2 * i + 2]);
parents[2].addChild(leafsWords[1][2 * i + 3]);
parents[3].addChild(leafsWords[2][2 * i + 2]);
parents[3].addChild(leafsWords[2][2 * i + 3]);
parents[3].addChild(leafsWords[3][2 * i + 2]);
parents[3].addChild(leafsWords[3][2 * i + 3]);
parentSegment = new ParentSegment(this.templateContainer.copyParentTemplate());
parentSegment.addChild(parents[0]);
parentSegment.addChild(parents[2]);
parentSegment.addChild(parents[1]);
parentSegment.addChild(parents[3]);
i++;
}
else{
parentSegment = new ColumnSegment(this.templateContainer.copyColumnTemplate());
parentSegment.addChild(parents[0]);
parentSegment.addChild(parents[1]);
}
rootSegment.addChild(parentSegment);
}
this.setRootSegment(rootSegment)
}
}
}

View File

@@ -0,0 +1,65 @@
import {Level} from "./Level";
import {RowSegment} from "../Segment/RowSegment";
import {ParentSegment} from "../Segment/ParentSegment";
export class FourWordsLevel extends Level {
constructor(templateContainer, wordLength) {
super(templateContainer);
this.wordLength = wordLength;
}
createSegments() {
if (this.words.length >= 4 &&
this.words[0].length >= this.wordLength &&
this.words[1].length >= this.wordLength &&
this.words[2].length >= this.wordLength &&
this.words[3].length >= this.wordLength
) {
let leafsWords = [];
leafsWords[0] = Level._createLeafsForWord(this.words[0], this.templateContainer.copyLeafTemplate());
leafsWords[1] = Level._createLeafsForWord(this.words[1], this.templateContainer.copyLeafTemplate());
leafsWords[2] = Level._createLeafsForWord(this.words[2], this.templateContainer.copyLeafTemplate());
leafsWords[3] = Level._createLeafsForWord(this.words[3], this.templateContainer.copyLeafTemplate());
let rootSegment = new RowSegment(this.templateContainer.copyRowTemplate());
for (let i = 0; i < this.wordLength / 4; i++) {
let parents = [];
parents[0] = new ParentSegment(this.templateContainer.copyParentTemplate());
parents[1] = new ParentSegment(this.templateContainer.copyParentTemplate());
parents[2] = new ParentSegment(this.templateContainer.copyParentTemplate());
parents[3] = new ParentSegment(this.templateContainer.copyParentTemplate());
parents[0].addChild(leafsWords[0][4 * i]);
parents[0].addChild(leafsWords[0][4 * i + 1]);
parents[0].addChild(leafsWords[1][4 * i]);
parents[0].addChild(leafsWords[1][4 * i + 1]);
parents[1].addChild(leafsWords[0][4 * i + 2]);
parents[1].addChild(leafsWords[0][4 * i + 3]);
parents[1].addChild(leafsWords[1][4 * i + 2]);
parents[1].addChild(leafsWords[1][4 * i + 3]);
parents[2].addChild(leafsWords[2][4 * i]);
parents[2].addChild(leafsWords[2][4 * i + 1]);
parents[2].addChild(leafsWords[3][4 * i]);
parents[2].addChild(leafsWords[3][4 * i + 1]);
parents[3].addChild(leafsWords[2][4 * i + 2]);
parents[3].addChild(leafsWords[2][4 * i + 3]);
parents[3].addChild(leafsWords[3][4 * i + 2]);
parents[3].addChild(leafsWords[3][4 * i + 3]);
let parent = new ParentSegment(this.templateContainer.copyParentTemplate());
parent.addChild(parents[0]);
parent.addChild(parents[1]);
parent.addChild(parents[2]);
parent.addChild(parents[3]);
rootSegment.addChild(parent);
}
this.setRootSegment(rootSegment)
}
}
}

View File

@@ -0,0 +1,7 @@
import {FourWordsLevel} from "./FourWordsLevel";
export class FourWordsLevel12 extends FourWordsLevel{
constructor(templateContainer) {
super(templateContainer, 12);
}
}

View File

@@ -0,0 +1,7 @@
import {FourWordsLevel} from "./FourWordsLevel";
export class FourWordsLevel8 extends FourWordsLevel{
constructor(templateContainer) {
super(templateContainer, 8);
}
}

View File

@@ -0,0 +1,218 @@
import {LeafSegment} from "../Segment/LeafSegment";
import {ParentSegment} from "../Segment/ParentSegment";
import {Helper} from "js-helper/dist/shared/Helper";
import {NativeStoragePromise} from "cordova-sites/dist/client";
import {Random} from "js-helper";
export class Level {
constructor(templateContainer) {
this.rootSegment = null;
this.words = [];
this.startRotations = [];
this.templateContainer = templateContainer;
this.levelData = null;
this.hasWon = false;
this.id = null;
this.wonResolver = null;
this.giveUpResolver = null;
this._shakeLeafs = true;
this._shakeLeafsTimeout = null;
this._lastRotation = 0;
this.wonPromise = new Promise((resolve, reject) => {
this.wonResolver = resolve;
this.giveUpResolver = reject;
});
this.segmentClickedListener = () => {
console.log("clicked")
};
}
getLevelData() {
return this.levelData;
}
setLevelData(levelData) {
this.levelData = levelData;
}
async saveAsCurrentLevel() {
let rotations = this.getCurrentRotations();
let locked = this.getCurrentLocked();
await NativeStoragePromise.setItem("currentLevel", JSON.stringify({
"id": this.id,
"rotations": rotations,
"locks": locked
}));
}
getCurrentLocked() {
if (this.rootSegment !== null) {
return this.rootSegment.getCurrentLocked([]);
}
return [];
}
getCurrentRotations() {
if (this.rootSegment !== null) {
return this.rootSegment.getCurrentRotations([]);
}
return [];
}
setLocks(locks) {
if (this.rootSegment !== null) {
this.rootSegment.applyLocks(locks);
}
}
setId(id) {
this.id = id;
}
getId() {
return this.id;
}
getLevel() {
return this;
}
setRootSegment(rootSegment) {
this.rootSegment = rootSegment;
this.rootSegment.setParent(this);
if (this.startRotations) {
this.applyRotations();
}
}
setWords(words) {
this.words = [];
for (let i = 0, n = words.length; i < n; i++) {
this.words.push(words[i].replace(/ß/g, "ẞ").toUpperCase());
}
}
setStartRotations(rotations) {
this.startRotations = rotations;
}
applyRotations(rotations) {
if (this.rootSegment) {
rotations = Helper.nonNull(rotations, this.startRotations);
this.rootSegment.applyRotations(rotations);
}
}
getHasWon() {
return this.hasWon;
}
checkHasWon(delayPromise) {
if (this.rootSegment.isSolved()) {
this.hasWon = true;
const self = this;
Promise.resolve(delayPromise).then(() => {
self.wonResolver(true);
});
return true;
}
this.saveAsCurrentLevel();
return false;
}
getWonPromise() {
return this.wonPromise;
}
getRootSegment() {
return this.rootSegment;
}
createSegments() {
};
getRotatableSegments() {
return Level._getRotatableSegmentsFrom(this.rootSegment);
}
segmentClicked(segment) {
if (this.segmentClickedListener) {
this.segmentClickedListener(segment);
}
this._lastRotation = new Date().getTime();
clearTimeout(this._shakeLeafsTimeout);
if (this._shakeLeafs) {
this._shakeLeafsTimeout = setTimeout(() => {
this.shakeLeafs();
}, Random.getIntRandom(5000) + 25000);
}
}
setSegmentClickedListener(listener) {
this.segmentClickedListener = listener;
}
getLeafSegments() {
return Level._getLeafSegmentsFrom(this.rootSegment);
}
static _getRotatableSegmentsFrom(segment) {
let rotatable = [];
if (segment.canRotate()) {
rotatable.push(segment);
}
if (segment instanceof ParentSegment) {
for (let i = 0; i < segment.children.length; i++) {
rotatable.push.apply(rotatable, Level._getRotatableSegmentsFrom(segment.children[i]));
}
}
return rotatable;
}
shakeLeafs() {
clearTimeout(this._shakeLeafsTimeout);
if (this._shakeLeafs && !this.hasWon) {
const leafs = this.getLeafSegments();
if (leafs.length > 0) {
const index = Random.getIntRandom(leafs.length-1);
const leaf = leafs[index];
leaf.getElement().classList.add("shake");
setTimeout(() => {
leaf.getElement().classList.remove("shake");
}, Random.getIntRandom(350)+650);
}
this._shakeLeafsTimeout = setTimeout(() => {
this.shakeLeafs();
}, Random.getIntRandom(2000) + 5000);
}
}
static _createLeafsForWord(word, leafSegmentTemplate) {
let leafSegments = [];
for (let i = 0, n = word.length; i < n; i++) {
leafSegments.push(new LeafSegment(leafSegmentTemplate.cloneNode(true), word.charAt(i)));
}
return leafSegments;
}
static _getLeafSegmentsFrom(segment) {
let leafs = [];
if (segment instanceof LeafSegment) {
leafs.push(segment);
} else if (segment instanceof ParentSegment) {
for (let i = 0; i < segment.children.length; i++) {
leafs.push(...Level._getLeafSegmentsFrom(segment.children[i]));
}
}
return leafs;
}
}

View File

@@ -0,0 +1,58 @@
import {SimpleLevel} from "./SimpleLevel";
import {RowLevel8} from "./RowLevel8";
import {RowLevel10} from "./RowLevel10";
import {SixWordsRowLevel8} from "./SixWordsRowLevel8";
import {SixWordsRowLevel12} from "./SixWordsRowLevel12";
import {FourWordsLevel8} from "./FourWordsLevel8";
import {FourWordsLevel12} from "./FourWordsLevel12";
import {SimpleFourWordsLevel10_0} from "./SimpleFourWordsLevel10_0";
import {SimpleFourWordsLevel10_1} from "./SimpleFourWordsLevel10_1";
import {SimpleFourWordsLevel10_2} from "./SimpleFourWordsLevel10_2";
import {SimpleFourWordsLevel10_3} from "./SimpleFourWordsLevel10_3";
import {TwoSegmentFourWordsLevel10_0_3} from "./TwoSegmentFourWordsLevel10_0_3";
import {TwoSegmentFourWordsLevel10_1_3} from "./TwoSegmentFourWordsLevel10_1_3";
import {TwoSegmentFourWordsLevel10_0_2} from "./TwoSegmentFourWordsLevel10_0_2";
export class LevelHelper {
static setLevelType(typeId, level) {
LevelHelper.types[typeId] = level;
}
static getLevelClass(type) {
return LevelHelper.types[type];
}
static inflateLevel(levelData, templateContainer) {
let level = new (LevelHelper.types[levelData["renderer"]])(templateContainer);
level.setWords(JSON.parse(levelData["words"].replace(/&quot;/g, '"')));
level.setId(levelData["id"]);
level.setLevelData(levelData);
levelData["positions"] = JSON.parse(levelData["positions"]);
for (let i = 0, n = levelData["positions"].length; i < n; i++) {
if (levelData["positions"][i] <= 4) {
levelData["positions"][i] = 90 * levelData["positions"][i];
}
}
level.setStartRotations(levelData["positions"]);
return level;
}
}
LevelHelper.types = {
20: SimpleLevel,
40: RowLevel8,
60: RowLevel10,
80: SimpleFourWordsLevel10_0,
81: SimpleFourWordsLevel10_1,
82: SimpleFourWordsLevel10_2,
83: SimpleFourWordsLevel10_3,
100: SixWordsRowLevel8,
110: TwoSegmentFourWordsLevel10_0_3,
111: TwoSegmentFourWordsLevel10_1_3,
112: TwoSegmentFourWordsLevel10_0_2,
120: FourWordsLevel8,
140: SixWordsRowLevel12,
160: FourWordsLevel12,
};

View File

@@ -0,0 +1,14 @@
import {FourWordsLevel} from "./FourWordsLevel";
export class MainMenuLevel extends FourWordsLevel{
constructor(templateContainer) {
super(templateContainer, 4);
}
saveAsCurrentLevel() {
}
// checkHasWon(delayPromise) {
// }
}

View File

@@ -0,0 +1,29 @@
import {Level} from "./Level";
import {RowSegment} from "../Segment/RowSegment";
import {ParentSegment} from "../Segment/ParentSegment";
export class RowLevel extends Level {
constructor(container, wordLength) {
super(container);
this.wordLength = wordLength;
}
createSegments() {
if (this.words.length >= 2 && this.words[0].length >= this.wordLength && this.words[1].length >= this.wordLength) {
let leafsWordOne = Level._createLeafsForWord(this.words[0], this.templateContainer.copyLeafTemplate());
let leafsWordTwo = Level._createLeafsForWord(this.words[1], this.templateContainer.copyLeafTemplate());
let rootSegment = new RowSegment(this.templateContainer.copyRowTemplate());
for (let i = 0, n = this.wordLength / 2; i < n; i++) {
let parent = new ParentSegment(this.templateContainer.copyParentTemplate());
parent.addChild(leafsWordOne[2 * i]);
parent.addChild(leafsWordOne[2 * i + 1]);
parent.addChild(leafsWordTwo[2 * i]);
parent.addChild(leafsWordTwo[2 * i + 1]);
rootSegment.addChild(parent);
}
// rootSegment.applyRotations(this.startRotations);
this.setRootSegment(rootSegment)
}
}
}

View File

@@ -0,0 +1,7 @@
import {RowLevel} from "./RowLevel";
export class RowLevel10 extends RowLevel{
constructor(container) {
super(container, 10);
}
}

View File

@@ -0,0 +1,7 @@
import {RowLevel} from "./RowLevel";
export class RowLevel8 extends RowLevel{
constructor(container) {
super(container, 8);
}
}

View File

@@ -0,0 +1,7 @@
import {BigSegmentsLevels} from "./BigSegmentsLevels";
export class SimpleFourWordsLevel extends BigSegmentsLevels{
constructor(templateContainer, wordLength, bigSegmentPosition) {
super(templateContainer, wordLength, [bigSegmentPosition]);
}
}

View File

@@ -0,0 +1,7 @@
import {SimpleFourWordsLevel} from "./SimpleFourWordsLevel";
export class SimpleFourWordsLevel10_0 extends SimpleFourWordsLevel{
constructor(templateContainer) {
super(templateContainer, 10, 0);
}
}

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