mirror of
https://framagit.org/JonathanMM/sutom.git
synced 2024-06-10 09:52:13 +02:00
Compare commits
29 commits
a005e971b5
...
6de079bf0b
Author | SHA1 | Date | |
---|---|---|---|
6de079bf0b | |||
0b7d37adcf | |||
58db9c65ad | |||
2fa99d2a2e | |||
999d7ef326 | |||
ee29afd206 | |||
7200280c17 | |||
4ec1bf5975 | |||
aa1bcacc77 | |||
a4aef5903c | |||
d65cd5f45d | |||
b9e4dc30aa | |||
7273a61271 | |||
e6c67a52f0 | |||
b9b83c9b79 | |||
8b7e939490 | |||
cfa080c6ff | |||
8d126b48a3 | |||
92985f56d0 | |||
a168654292 | |||
8bb4d7139d | |||
965404a51c | |||
d2f035b1ef | |||
51e43bf38c | |||
e4a6439acb | |||
5471bd935e | |||
e452c26724 | |||
34e16f9799 | |||
e15bbc53f5 |
|
@ -13,6 +13,6 @@ Ce script va vérifier la liste des mots, ne garder que les mots acceptés dans
|
|||
Liste des règles suivi par les mots :
|
||||
|
||||
- Le mot n'est pas un nom propre (qui commence par une majuscule dans le fichier mots.txt)
|
||||
- Le mot est entre 6 et 9 lettres
|
||||
- Le mot est entre 6 et 10 lettres
|
||||
- Le mot ne commence pas par une lettre rare, à savoir : K, Q, W, X, Y, Z
|
||||
- Le mot ne contient pas d'espace, d'apostrophe ou de trait d'union
|
||||
|
|
1857
package-lock.json
generated
1857
package-lock.json
generated
File diff suppressed because it is too large
Load diff
Binary file not shown.
BIN
public/fonts/Roboto-Regular.ttf
Normal file
BIN
public/fonts/Roboto-Regular.ttf
Normal file
Binary file not shown.
BIN
public/fonts/RobotoMono-Regular.ttf
Normal file
BIN
public/fonts/RobotoMono-Regular.ttf
Normal file
Binary file not shown.
|
@ -43,7 +43,7 @@
|
|||
</a>
|
||||
</div>
|
||||
</header>
|
||||
<div id="notification"> </div>
|
||||
<div id="notification-area"><div id="notification-label"></div></div>
|
||||
<div id="panel-area">
|
||||
<div id="panel-fenetre">
|
||||
<div id="panel-fenetre-header">
|
||||
|
@ -56,7 +56,7 @@
|
|||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="panel-fenetre-notification"> </div>
|
||||
<div id="panel-fenetre-notification-area"><div id="panel-fenetre-notification-label"></div></div>
|
||||
<div id="panel-fenetre-contenu"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -68,99 +68,42 @@
|
|||
<audio preload src="sons/lettre-bien-place.wav" id="son-lettre-bien-place"></audio>
|
||||
|
||||
<svg>
|
||||
<symbol id="icone-son-active" viewBox="0 0 32 32">
|
||||
<symbol id="icone-son-active" height="24" viewBox="0 96 960 960" width="24">
|
||||
<path
|
||||
d="m11.152 6.0314-4.3386 3.19v13.555l1.4368 1.0571c0.78755 0.57894 2.74 2.0158 4.3386 3.1924 1.5962 1.1743 2.9111 2.1353 2.9228 2.1353 0.01172 0 0.0211-5.6043 0.0211-13.161 0-7.6739-0.0094-13.161-0.0211-13.161-0.01172 0-1.9736 1.4368-4.3597 3.1924z"
|
||||
/>
|
||||
<path
|
||||
d="m25.524 4.3485c-0.32112 0.10548-0.50394 0.35862-0.50628 0.69379 0 0.24142 0.05626 0.35159 0.33518 0.64457 0.76411 0.80865 1.268 1.4345 1.7884 2.2267 1.2493 1.9009 2.0181 4.0128 2.2994 6.3051 0.07735 0.62348 0.0961 0.95866 0.0961 1.7814 0 1.5259-0.16642 2.7213-0.57426 4.137-0.66332 2.3017-1.8634 4.3503-3.6166 6.1809-0.27424 0.2883-0.32815 0.38909-0.32815 0.63988 0 0.21564 0.075 0.39612 0.22267 0.52738 0.15236 0.14064 0.28127 0.18751 0.49925 0.18517 0.26955-0.0024 0.3469-0.04688 0.70083-0.40315 2.0415-2.079 3.5229-4.8097 4.1628-7.6763 0.69614-3.1221 0.47112-6.3848-0.64457-9.3334-0.75474-1.99-1.8564-3.7502-3.3471-5.3488-0.34455-0.37034-0.46878-0.4805-0.6141-0.54378-0.10313-0.044534-0.35862-0.05391-0.47347-0.016407z"
|
||||
/>
|
||||
<path
|
||||
d="m21.624 8.237c-0.31408 0.1172-0.49456 0.36565-0.49691 0.68442-0.0047 0.24611 0.06329 0.37034 0.38206 0.70786 1.3759 1.4509 2.2173 3.2416 2.4775 5.2691 0.06563 0.51097 0.0586 1.7626-0.01172 2.2759-0.27892 2.0251-1.0946 3.7409-2.4775 5.2081-0.30705 0.3258-0.37268 0.45237-0.37268 0.69614 0.0047 0.56957 0.63285 0.9024 1.1157 0.59301 0.12891-0.07969 0.60238-0.59066 0.92584-0.99616 1.1626-1.4556 1.9454-3.2416 2.2103-5.0581 0.09376-0.63754 0.10548-0.81568 0.10548-1.6173 0-0.80161-0.01172-0.97975-0.10548-1.6173-0.21798-1.4884-0.77114-2.9393-1.6103-4.2261-0.52504-0.80396-1.3477-1.765-1.6126-1.8822-0.14532-0.063286-0.40784-0.082037-0.52972-0.037502z"
|
||||
/>
|
||||
<path d="m1.0002 16v6.7856l2.0579-0.0047 2.0556-7e-3v-13.548l-2.0556-0.0070317-2.0579-0.0046878z" />
|
||||
<path
|
||||
d="m17.759 12.119c-0.42425 0.13126-0.64457 0.59769-0.46409 0.98912 0.03516 0.07969 0.13595 0.21564 0.25314 0.33987 0.64926 0.70317 0.98913 1.5821 0.98913 2.5525 0 1.0032-0.3469 1.8681-1.0407 2.6064-0.18751 0.19923-0.26252 0.36799-0.26252 0.58598 0.0023 0.38206 0.2883 0.67973 0.67739 0.70551 0.31877 0.01875 0.51566-0.11016 0.92115-0.60941 1.0454-1.2868 1.411-2.9978 0.98913-4.6269-0.21798-0.84615-0.68911-1.6759-1.3009-2.297-0.12657-0.12892-0.19454-0.17814-0.30002-0.21798-0.13829-0.04922-0.34455-0.06329-0.46175-0.02812z"
|
||||
d="M560 925v-82q90-26 145-100t55-168q0-94-55-168T560 307v-82q124 28 202 125.5T840 575q0 127-78 224.5T560 925ZM120 696V456h160l200-200v640L280 696H120Zm440 40V414q47 22 73.5 66t26.5 96q0 51-26.5 94.5T560 736ZM400 450l-86 86H200v80h114l86 86V450ZM300 576Z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="icone-son-desactive" viewBox="0 0 32 32">
|
||||
<symbol id="icone-son-desactive" height="24" viewBox="0 96 960 960" width="24">
|
||||
<path
|
||||
d="m20.077 11.234a1.1719 1.1719 0 0 0-0.829 0.3438 1.1719 1.1719 0 0 0 0 1.6564l7.1895 7.1879a1.1719 1.1719 0 0 0 1.6564 0 1.1719 1.1719 0 0 0 0-1.6564l-7.1879-7.1879a1.1719 1.1719 0 0 0-0.829-0.3438z"
|
||||
stroke-linecap="round"
|
||||
stroke-width=".82258"
|
||||
/>
|
||||
<path
|
||||
d="m27.265 11.234a1.1719 1.1719 0 0 0-0.8274 0.3438l-7.1895 7.1879a1.1719 1.1719 0 0 0 0 1.6564 1.1719 1.1719 0 0 0 1.658 0l7.1879-7.1879a1.1719 1.1719 0 0 0 0-1.6564 1.1719 1.1719 0 0 0-0.829-0.3438z"
|
||||
stroke-linecap="round"
|
||||
stroke-width=".82258"
|
||||
/>
|
||||
<path
|
||||
d="m11.152 6.0312-4.3386 3.1901v13.555l1.4368 1.0571c0.78756 0.57895 2.7401 2.0158 4.3386 3.1924 1.5962 1.1743 2.9112 2.1353 2.9229 2.1353s0.0211-5.6043 0.0211-13.161c0-7.6741-0.0094-13.161-0.0211-13.161-0.01172 0-1.9736 1.4368-4.3597 3.1924z"
|
||||
/>
|
||||
<path d="m1 16v6.7857l2.058-0.0049 2.0556-0.0074v-13.548l-2.0556-0.0074-2.058-0.00494z" />
|
||||
</symbol>
|
||||
<symbol id="icone-croix" viewBox="0 0 8.4666665 8.4666669">
|
||||
<path
|
||||
style="
|
||||
fill: none;
|
||||
stroke-width: 0.529167;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: miter;
|
||||
stroke-miterlimit: 4;
|
||||
stroke-dasharray: none;
|
||||
stroke-opacity: 1;
|
||||
"
|
||||
d="M 1.6140919,1.6140919 6.8525747,6.8525747"
|
||||
id="path1118"
|
||||
/>
|
||||
<path
|
||||
style="
|
||||
fill: none;
|
||||
stroke-width: 0.529167;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: miter;
|
||||
stroke-miterlimit: 4;
|
||||
stroke-dasharray: none;
|
||||
stroke-opacity: 1;
|
||||
"
|
||||
d="M 6.8525747,1.6140919 1.6140919,6.8525747"
|
||||
id="path1432"
|
||||
d="M792 1000 671 879q-25 16-53 27.5T560 925v-82q14-5 27.5-10t25.5-12L480 688v208L280 696H120V456h128L56 264l56-56 736 736-56 56Zm-8-232-58-58q17-31 25.5-65t8.5-70q0-94-55-168T560 307v-82q124 28 202 125.5T840 575q0 53-14.5 102T784 768ZM650 634l-90-90V414q47 22 73.5 66t26.5 96q0 15-2.5 29.5T650 634ZM480 464 376 360l104-104v208Zm-80 238v-94l-72-72H200v80h114l86 86Zm-36-130Z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="icone-stats" viewBox="0 0 32 32">
|
||||
<symbol id="icone-croix" height="40" viewBox="0 96 960 960" width="40">
|
||||
<path
|
||||
d="m3.077 5.3688c-0.14233 0-0.25668 0.12077-0.25668 0.27108v23.379c0 0.14944 0.11435 0.27108 0.25668 0.27108h5.9999c0.14233 0 0.25668-0.12164 0.25668-0.27108v-23.379c0-0.15031-0.11435-0.27108-0.25668-0.27108z"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="1.7439"
|
||||
fill="none"
|
||||
d="m251.333 851.333-46.666-46.666L433.334 576 204.667 347.333l46.666-46.666L480 529.334l228.667-228.667 46.666 46.666L526.666 576l228.667 228.667-46.666 46.666L480 622.666 251.333 851.333Z"
|
||||
/>
|
||||
<path
|
||||
d="m12.807 16.365c-0.14056 0-0.25349 0.12077-0.25349 0.27108v12.643c0 0.15031 0.11293 0.27108 0.25349 0.27108h5.9262c0.14056 0 0.25349-0.12077 0.25349-0.27108v-12.643c0-0.15031-0.11294-0.27108-0.25349-0.27108z"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="1.744"
|
||||
fill="none"
|
||||
/>
|
||||
<path
|
||||
d="m22.515 10.747c-0.14233 0-0.25668 0.12077-0.25668 0.27108v18.094c0 0.15031 0.11435 0.27108 0.25668 0.27108h6.0007c0.14232 0 0.25668-0.12077 0.25668-0.27108v-18.094c0-0.15031-0.11436-0.27108-0.25668-0.27108z"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="1.7439"
|
||||
fill="none"
|
||||
/>
|
||||
<path d="m2.3991 2.3983v27.203h27.202" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2.7903" />
|
||||
</symbol>
|
||||
<symbol id="icone-regles" viewBox="0 0 32 32">
|
||||
<path
|
||||
d="m13.787 23.247h2.9075v3.638h-2.9075zm2.8216-2.1055h-2.7357v-2.2057q0-1.4466 0.40104-2.3776 0.40104-0.93099 1.6901-2.1628l1.2891-1.2747q0.8164-0.75911 1.1745-1.4323 0.3724-0.67318 0.3724-1.375 0-1.2747-0.94531-2.0625-0.93099-0.78776-2.4779-0.78776-1.1315 0-2.4206 0.5013-1.2747 0.5013-2.6641 1.4609v-2.6927q1.3464-0.81641 2.7214-1.2174 1.3893-0.40104 2.8646-0.40104 2.6354 0 4.2253 1.3893 1.6042 1.3893 1.6042 3.6667 0 1.0885-0.51562 2.0768-0.51562 0.97396-1.8047 2.2057l-1.2604 1.2318q-0.67318 0.67318-0.95963 1.0599-0.27214 0.3724-0.38672 0.73047-0.08594 0.30078-0.12891 0.73047-0.04297 0.42969-0.04297 1.1745z"
|
||||
/>
|
||||
<circle cx="16" cy="16" r="14" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" />
|
||||
<symbol id="icone-stats" height="24" viewBox="0 96 960 960" width="24">
|
||||
<path d="M160 896V456h160v440H160Zm240 0V256h160v640H400Zm240 0V616h160v280H640Z" />
|
||||
</symbol>
|
||||
<symbol id="icone-config" viewBox="0 0 32 32">
|
||||
<symbol id="icone-regles" height="24" viewBox="0 96 960 960" width="24">
|
||||
<path
|
||||
d="m25.1 1.0009c-0.24859-4e-3 -0.49949 0.01-0.74873 0.0174-2.0188 0.0622-4.01 1.6525-4.1616 3.7439-0.50981 2.1512-0.87169 4.4107-1.974 6.354-3.7058 3.71-7.6856 7.1393-11.505 10.732-1.5478 1.48-3.1912 2.8734-4.6112 4.4788-1.1941 1.7248 0.0372 4.6853 2.237 4.6724 1.7332-0.0568 2.7416-1.7429 3.8664-2.8178 4.1892-4.5584 8.0333-9.4317 12.34-13.883 1.1377-0.93788 2.716-1.0269 4.0959-1.4049 0.92741-0.23075 1.9087-0.30646 2.8033-0.63139 1.6048-1.0192 2.7463-2.8492 2.9189-4.7437 0.057-0.45104-0.44752-0.30978-0.44752-0.30978l-2.78 1.2811-2.1238-1.7534-0.35649-1.9778s0.64592-0.63983 0.93495-0.69523l2.7286-1.018c-0.10848-1.1283-1.5342-1.6956-2.4817-1.9526-0.24051-0.0653-0.48684-0.0877-0.73543-0.0919zm-2.0729 7.6496 1.2424 2.9363-1.1244 0.45314-0.0242-0.0565 0.3074-0.12799-0.0588-0.1407 0.0644-0.0145 0.1478-0.0331-0.0662-0.2953-0.1475 0.0328-0.11675 0.026-0.14721-0.35234 0.063-0.0142 0.1478-0.0331-0.0659-0.2953-0.14779 0.0328-0.11558 0.0257-0.1472-0.35265 0.0621-0.0139 0.14779-0.0328-0.0662-0.29559-0.1475 0.0331-0.11439 0.0257-0.1472-0.35293 0.0606-0.0136 0.1478-0.0328-0.0659-0.29558-0.1478 0.0331-0.11321 0.0254-0.20514-0.49186c-0.21772 0.0877-0.22976 0.0949-0.3358 0.13893l-0.0254-0.0594c0.37973-0.15303 0.7595-0.30603 1.1392-0.45906zm-1.9817 0.79839 0.029 0.0674c-0.10243 0.0423-0.10517 0.0455-0.29885 0.12356l0.0987 0.23499-0.0511 0.0115-0.14779 0.0331 0.0662 0.29529 0.1475-0.0331 0.10434-0.0233 0.14839 0.35264-0.0517 0.0115-0.14779 0.0331 0.0659 0.2953 0.1478-0.0331 0.10493-0.0234 0.14809 0.35235-0.0523 0.0118-0.1478 0.0331 0.0662 0.2953 0.1475-0.0328 0.10582-0.0236 0.14809 0.35234-0.0529 0.0118-0.14779 0.0331 0.0659 0.2953 0.14779-0.0328 0.10641-0.0237 0.1676 0.39876 0.31894-0.13272 0.0201 0.0467-1.0538 0.42447-1.2418-2.9364c0.34615-0.13948 0.69225-0.27907 1.0384-0.41855zm-16.315 16.667a1.7456 1.7456 0 0 1 1.7454 1.7457 1.7456 1.7456 0 0 1-1.7454 1.7454 1.7456 1.7456 0 0 1-1.7454-1.7454 1.7456 1.7456 0 0 1 1.7454-1.7457z"
|
||||
stroke-width=".15134"
|
||||
d="M478 816q21 0 35.5-14.5T528 766q0-21-14.5-35.5T478 716q-21 0-35.5 14.5T428 766q0 21 14.5 35.5T478 816Zm-36-154h74q0-33 7.5-52t42.5-52q26-26 41-49.5t15-56.5q0-56-41-86t-97-30q-57 0-92.5 30T342 438l66 26q5-18 22.5-39t53.5-21q32 0 48 17.5t16 38.5q0 20-12 37.5T506 530q-44 39-54 59t-10 73Zm38 314q-83 0-156-31.5T197 859q-54-54-85.5-127T80 576q0-83 31.5-156T197 293q54-54 127-85.5T480 176q83 0 156 31.5T763 293q54 54 85.5 127T880 576q0 83-31.5 156T763 859q-54 54-127 85.5T480 976Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="icone-config" height="24" viewBox="0 96 960 960" width="24">
|
||||
<path
|
||||
d="m370 976-16-128q-13-5-24.5-12T307 821l-119 50L78 681l103-78q-1-7-1-13.5v-27q0-6.5 1-13.5L78 471l110-190 119 50q11-8 23-15t24-12l16-128h220l16 128q13 5 24.5 12t22.5 15l119-50 110 190-103 78q1 7 1 13.5v27q0 6.5-2 13.5l103 78-110 190-118-50q-11 8-23 15t-24 12l-16 128H370Zm112-260q58 0 99-41t41-99q0-58-41-99t-99-41q-59 0-99.5 41T342 576q0 58 40.5 99t99.5 41Zm0-80q-25 0-42.5-17.5T422 576q0-25 17.5-42.5T482 516q25 0 42.5 17.5T542 576q0 25-17.5 42.5T482 636Zm-2-60Zm-40 320h79l14-106q31-8 57.5-23.5T639 729l99 41 39-68-86-65q5-14 7-29.5t2-31.5q0-16-2-31.5t-7-29.5l86-65-39-68-99 42q-22-23-48.5-38.5T533 362l-13-106h-79l-14 106q-31 8-57.5 23.5T321 423l-99-41-39 68 86 64q-5 15-7 30t-2 32q0 16 2 31t7 30l-86 65 39 68 99-42q22 23 48.5 38.5T427 790l13 106Z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="icone-copie" height="20" viewBox="0 96 960 960" width="20">
|
||||
<path
|
||||
d="M216 960q-29.7 0-50.85-21.15Q144 917.7 144 888V336h72v552h456v72H216Zm144-144q-29.7 0-50.85-21.15Q288 773.7 288 744V264q0-29.7 21.15-50.85Q330.3 192 360 192h384q29.7 0 50.85 21.15Q816 234.3 816 264v480q0 29.7-21.15 50.85Q773.7 816 744 816H360Zm0-72h384V264H360v480Zm0 0V264v480Z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="icone-restaure" height="20" viewBox="0 96 960 960" width="20">
|
||||
<path
|
||||
d="M479.788 648Q450 648 429 626.788q-21-21.213-21-51Q408 546 429.212 525q21.213-21 51-21Q510 504 531 525.212q21 21.213 21 51Q552 606 530.788 627q-21.213 21-51 21ZM480 912q-140 0-238.5-98T144 576h72q2 110 78.5 187T480 840q110.314 0 187.157-76.778Q744 686.443 744 576.222 744 466 667.157 389 590.314 312 480 312q-59 0-111.5 25.5T277 408h107v72H144V240h72v130q47.909-62.09 116.955-96.045Q402 240 480 240q70 0 131.133 26.6 61.134 26.6 106.4 71.867 45.267 45.266 71.867 106.4Q816 506 816 576t-26.6 131.133q-26.6 61.134-71.867 106.4-45.266 45.267-106.4 71.867Q550 912 480 912Z"
|
||||
/>
|
||||
</symbol>
|
||||
</svg>
|
||||
|
|
282
public/jeu.css
282
public/jeu.css
|
@ -2,30 +2,45 @@
|
|||
--taille-cellule: 48px;
|
||||
--epaisseur-bordure-cellule: 1px;
|
||||
--epaisseur-padding-cellule: 2px;
|
||||
--couleur-bien-place: #e7002a;
|
||||
--couleur-mal-place: #ffbd00;
|
||||
--couleur-fond-grille: #0077c7;
|
||||
--couleur-bar-max: rgb(231, 0, 42);
|
||||
--couleur-bien-place: rgb(231, 0, 42);
|
||||
--couleur-mal-place: rgb(255, 189, 0);
|
||||
--couleur-fond-grille: rgb(0, 119, 199);
|
||||
--couleur-non-trouve: rgb(112, 112, 112);
|
||||
--couleur-icone: rgb(200, 200, 200);
|
||||
--couleur-fond-rgb: 43, 43, 43;
|
||||
--couleur-fond: rgb(var(--couleur-fond-rgb));
|
||||
--couleur-bordure: #ffffff;
|
||||
--couleur-bordure: rgb(200, 200, 200);
|
||||
--couleur-bordure-grille: #ffffff;
|
||||
--couleur-police: #ffffff;
|
||||
--couleur-police-grille: #ffffff;
|
||||
--taille-icone: 32px;
|
||||
--couleur-police-grille: rgb(255, 255, 255);
|
||||
--couleur-police-grille-pas-curseur: rgb(255, 255, 255, 0.65);
|
||||
--couleur-lettre-speciale: rgb(75, 75, 75);
|
||||
--couleur-lettre-survole: rgba(75, 75, 75, 0.65);
|
||||
--couleur-lettre-speciale-survole: rgba(75, 75, 75, 0.65);
|
||||
--couleur-lettre-survole-bien-place: rgba(231, 0, 42, 0.65);
|
||||
--couleur-lettre-survole-mal-place: rgba(255, 189, 0, 0.65);
|
||||
--taille-icone: 24px;
|
||||
--taille-icone-zone: 48px;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Roboto Medium";
|
||||
src: url("/fonts/Roboto-Medium.ttf");
|
||||
font-family: "Roboto Regular";
|
||||
src: url("/fonts/Roboto-Regular.ttf");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "RobotoMono Regular";
|
||||
src: url("/fonts/RobotoMono-Regular.ttf");
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: "Roboto Medium", Ubuntu, Arial, Helvetica, sans-serif;
|
||||
font-family: "Roboto Regular", Ubuntu, Arial, Helvetica, sans-serif;
|
||||
font-size: 32px;
|
||||
background-color: var(--couleur-fond);
|
||||
height: 100vh;
|
||||
max-height: 95vh;
|
||||
height: 95vh;
|
||||
height: -webkit-fill-available; /* Seulement pour safari et sa flotting bar */
|
||||
text-align: center;
|
||||
color: var(--couleur-police);
|
||||
margin: 0;
|
||||
|
@ -61,19 +76,33 @@ h1 {
|
|||
justify-content: space-around;
|
||||
}
|
||||
|
||||
#configuration-regles-bouton,
|
||||
#configuration-config-bouton,
|
||||
#configuration-stats-bouton,
|
||||
#configuration-audio-bouton {
|
||||
height: var(--taille-icone-zone);
|
||||
width: var(--taille-icone-zone);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#configuration-regles-icone,
|
||||
#configuration-config-icone,
|
||||
#configuration-stats-icone,
|
||||
#configuration-audio-icone {
|
||||
height: var(--taille-icone);
|
||||
width: var(--taille-icone);
|
||||
fill: var(--couleur-icone);
|
||||
}
|
||||
|
||||
#grille {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
background-color: var(--couleur-fond-grille);
|
||||
min-height: calc(6 * var(--taille-cellule) + 12 * var(--epaisseur-bordure-cellule));
|
||||
min-height: calc(6 * var(--taille-cellule) + 10 * var(--epaisseur-bordure-cellule));
|
||||
margin-bottom: auto;
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
.grille table {
|
||||
|
@ -88,7 +117,7 @@ h1 {
|
|||
position: relative;
|
||||
padding: var(--epaisseur-padding-cellule);
|
||||
color: var(--couleur-police-grille);
|
||||
border: 1px solid var(--couleur-bordure-grille);
|
||||
border: var(--epaisseur-bordure-cellule) solid var(--couleur-bordure-grille);
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
|
@ -122,14 +151,15 @@ h1 {
|
|||
#panel-area {
|
||||
display: none;
|
||||
|
||||
font-size: 24px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
#input-area {
|
||||
margin: 0.5em auto 2em;
|
||||
max-width: 100%;
|
||||
width: calc(100% - 20px);
|
||||
width: calc(100% - 5px);
|
||||
max-width: 500px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.input-ligne {
|
||||
|
@ -155,7 +185,7 @@ h1 {
|
|||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: monospace;
|
||||
font-family: "RobotoMono Regular", monospace;
|
||||
}
|
||||
|
||||
.input-lettre.input-lettre-vide,
|
||||
|
@ -184,18 +214,55 @@ h1 {
|
|||
.input-lettre:hover,
|
||||
.input-lettre:active {
|
||||
cursor: pointer;
|
||||
background-color: var(--couleur-lettre-survole);
|
||||
}
|
||||
|
||||
.input-lettre.lettre-bien-place:hover,
|
||||
.input-lettre.lettre-bien-place:active {
|
||||
background-color: var(--couleur-lettre-survole-bien-place);
|
||||
}
|
||||
|
||||
.input-lettre.lettre-mal-place:hover,
|
||||
.input-lettre.lettre-mal-place:active {
|
||||
background-color: var(--couleur-lettre-survole-mal-place);
|
||||
}
|
||||
|
||||
.input-lettre.input-lettre-vide:hover,
|
||||
.input-lettre.input-lettre-vide:active {
|
||||
cursor: initial;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.input-lettre.input-lettre-effacer {
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.input-lettre.input-lettre-effacer,
|
||||
.input-lettre.input-lettre-entree,
|
||||
.input-lettre[data-lettre="."] {
|
||||
background-color: var(--couleur-lettre-speciale);
|
||||
border-color: var(--couleur-lettre-speciale);
|
||||
}
|
||||
|
||||
.input-lettre.input-lettre-effacer:active,
|
||||
.input-lettre.input-lettre-effacer:hover,
|
||||
.input-lettre.input-lettre-entree:active,
|
||||
.input-lettre.input-lettre-entree:hover,
|
||||
.input-lettre[data-lettre="."]:active,
|
||||
.input-lettre[data-lettre="."]:hover {
|
||||
background-color: var(--couleur-lettre-speciale-survole);
|
||||
}
|
||||
|
||||
.grille td.cellule-lettre-pas-curseur {
|
||||
color: var(--couleur-police-grille-pas-curseur);
|
||||
}
|
||||
|
||||
.regles-panel table {
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
.regles-panel #panel-fenetre {
|
||||
.regles-panel #panel-fenetre,
|
||||
.notes-panel #panel-fenetre {
|
||||
font-size: 14px;
|
||||
text-align: left;
|
||||
}
|
||||
|
@ -210,10 +277,28 @@ h1 {
|
|||
color: var(--couleur-police);
|
||||
}
|
||||
|
||||
#notification,
|
||||
#panel-fenetre-notification {
|
||||
#notification-area,
|
||||
#panel-fenetre-notification-area {
|
||||
opacity: 0;
|
||||
transition: opacity linear 1s;
|
||||
min-height: 50px;
|
||||
}
|
||||
|
||||
#panel-fenetre-notification-area {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#notification-label,
|
||||
#panel-fenetre-notification-label {
|
||||
font-size: 22px;
|
||||
background-color: #bdbdbd;
|
||||
width: calc(100% - 5px);
|
||||
max-width: 500px;
|
||||
margin: 0px auto;
|
||||
border-radius: 0.5em;
|
||||
padding: 5px 0px;
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#panel-area {
|
||||
|
@ -247,7 +332,7 @@ h1 {
|
|||
align-content: center;
|
||||
justify-content: space-between;
|
||||
width: calc(100% - 1em);
|
||||
height: calc(36px + 0.75em);
|
||||
min-height: calc(36px + 0.75em);
|
||||
margin-left: 0.5em;
|
||||
margin-right: 0.5em;
|
||||
margin-top: 0.25em;
|
||||
|
@ -260,18 +345,31 @@ h1 {
|
|||
}
|
||||
|
||||
#panel-fenetre-bouton-fermeture {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
text-decoration: none;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#panel-fenetre-bouton-fermeture-icone {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
fill: var(--couleur-icone);
|
||||
}
|
||||
|
||||
.config-panel #panel-fenetre-contenu {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5em;
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
#config-liste {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5em;
|
||||
}
|
||||
|
||||
.config-item {
|
||||
|
@ -279,26 +377,104 @@ h1 {
|
|||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.stats-area {
|
||||
display: table;
|
||||
padding-left: 0.5em;
|
||||
.config-item label {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.config-item select {
|
||||
min-width: 20%;
|
||||
text-align: end;
|
||||
height: min-content;
|
||||
}
|
||||
|
||||
.stats-parties {
|
||||
display: flex;
|
||||
padding: 0 0.5em;
|
||||
width: calc(100% - 1em);
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.stats-ligne {
|
||||
display: table-row;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.stats-cellule {
|
||||
display: table-cell;
|
||||
.stats-label {
|
||||
width: 25px;
|
||||
margin-right: 5px;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.stats-cellule:first-child {
|
||||
.stats-bar-area {
|
||||
flex-grow: 48;
|
||||
}
|
||||
|
||||
.stats-bar {
|
||||
border-radius: 3px;
|
||||
height: 18px;
|
||||
min-width: 10px;
|
||||
background-color: var(--couleur-fond-grille);
|
||||
}
|
||||
|
||||
.stats-bar.bar-max {
|
||||
background-color: var(--couleur-bar-max);
|
||||
}
|
||||
|
||||
.stats-valeur {
|
||||
padding-left: 0.5em;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.stats-numeriques-area {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
margin-top: 1em;
|
||||
grid-template-columns: repeat(auto-fit, minmax(85px, 1fr));
|
||||
justify-items: center;
|
||||
}
|
||||
|
||||
.stats-numerique-case {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 75px;
|
||||
height: 75px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid var(--couleur-bordure);
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.stats-numerique-case-valeur {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.stats-numerique-case-secondaire {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.stats-numerique-case-secondaire::before {
|
||||
content: "/";
|
||||
}
|
||||
|
||||
.stats-numerique-case-secondaire {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.stats-cellule:not(:first-child) {
|
||||
padding-left: 0.5em;
|
||||
text-align: left;
|
||||
.stats-numerique-case-label {
|
||||
margin-top: auto;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.bouton-partage {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.bouton-partage svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.bouton-partage-texte {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.fin-de-partie-panel-phrase {
|
||||
|
@ -306,6 +482,40 @@ h1 {
|
|||
padding-left: 0.5em;
|
||||
}
|
||||
|
||||
.fin-de-partie-panel h3 {
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
#fin-de-partie-panel-partie-veille-area {
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
#fin-de-partie-panel-resume-bouton,
|
||||
#fin-de-partie-panel-stats-bouton,
|
||||
#fin-de-partie-panel-reset-bouton {
|
||||
font-size: 1rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#fin-de-partie-panel-resume-bouton,
|
||||
#fin-de-partie-panel-stats-bouton {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.bouton-partage-texte {
|
||||
bottom: 4px;
|
||||
position: absolute;
|
||||
width: max-content;
|
||||
}
|
||||
|
||||
#config-sauvegarde-area {
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
#config-sauvegarde-area p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
#contenu {
|
||||
margin-left: 2px;
|
||||
|
@ -319,23 +529,25 @@ h1 {
|
|||
|
||||
@media (max-width: 500px) {
|
||||
:root {
|
||||
--taille-cellule: 42px;
|
||||
--taille-cellule: 38px;
|
||||
--taille-icone: 28px;
|
||||
}
|
||||
|
||||
body,
|
||||
.regles-panel table {
|
||||
.regles-panel table,
|
||||
#grille {
|
||||
font-size: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-height: 640px), (max-width: 400px) {
|
||||
:root {
|
||||
--taille-cellule: 36px;
|
||||
--taille-cellule: 34px;
|
||||
}
|
||||
|
||||
body,
|
||||
.regles-panel table {
|
||||
.regles-panel table,
|
||||
#grille {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import { ClavierDisposition } from "./entites/clavierDisposition";
|
|||
import Input from "./input";
|
||||
import ThemeManager from "./themeManager";
|
||||
import { Theme } from "./entites/theme";
|
||||
import CopieHelper from "./copieHelper";
|
||||
|
||||
export default class ConfigurationPanel {
|
||||
private readonly _panelManager: PanelManager;
|
||||
|
@ -35,6 +36,7 @@ export default class ConfigurationPanel {
|
|||
public afficher(): void {
|
||||
let titre = "Configuration";
|
||||
let contenu = document.createElement("div");
|
||||
contenu.id = "config-liste";
|
||||
let config = Sauvegardeur.chargerConfig() ?? Configuration.Default;
|
||||
contenu.appendChild(
|
||||
this.genererConfigItem(
|
||||
|
@ -127,6 +129,31 @@ export default class ConfigurationPanel {
|
|||
)
|
||||
);
|
||||
|
||||
contenu.appendChild(
|
||||
this.genererConfigItem(
|
||||
"Retour haptique (si votre navigateur est compatible)",
|
||||
[
|
||||
{ value: false.toString(), label: "Non" },
|
||||
{ value: true.toString(), label: "Oui" },
|
||||
],
|
||||
(config.haptique ?? Configuration.Default.haptique).toString(),
|
||||
(event: Event) => {
|
||||
event.stopPropagation();
|
||||
let haptique = (event.target as HTMLSelectElement).value === true.toString();
|
||||
|
||||
Sauvegardeur.sauvegarderConfig({
|
||||
...(Sauvegardeur.chargerConfig() ?? Configuration.Default),
|
||||
haptique,
|
||||
});
|
||||
|
||||
// On redessine le clavier pour la prise en compte de l'option
|
||||
if (this._input) this._input.dessinerClavier(config.disposition ?? Configuration.Default.disposition);
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
if (Sauvegardeur.chargerSauvegardeStats()) contenu.appendChild(this.genererZoneExportSauvegarde());
|
||||
|
||||
this._panelManager.setContenuHtmlElement(titre, contenu);
|
||||
this._panelManager.setClasses(["config-panel"]);
|
||||
this._panelManager.afficherPanel();
|
||||
|
@ -159,6 +186,52 @@ export default class ConfigurationPanel {
|
|||
return div;
|
||||
}
|
||||
|
||||
private genererZoneExportSauvegarde(): HTMLElement {
|
||||
let div = document.createElement("div");
|
||||
div.id = "config-sauvegarde-area";
|
||||
|
||||
const titreSection = document.createElement("h3");
|
||||
titreSection.innerText = "Exporter vos statistiques";
|
||||
div.appendChild(titreSection);
|
||||
|
||||
const explication = document.createElement("p");
|
||||
explication.innerText = "Pour transférer vos statistiques sur un autre navigateur, il est possible de suivre les étapes suivantes :";
|
||||
div.appendChild(explication);
|
||||
|
||||
const listeEtape = document.createElement("ol");
|
||||
|
||||
const etape1 = document.createElement("li");
|
||||
|
||||
const etape1Texte = document.createElement("p");
|
||||
etape1Texte.innerText = "Copiez ce lien à usage unique.";
|
||||
etape1.appendChild(etape1Texte);
|
||||
|
||||
const etape1Input = document.createElement("input");
|
||||
const contenuLien = Sauvegardeur.genererLien();
|
||||
const lien = window.location.origin + window.location.pathname + "#" + btoa("s=" + contenuLien);
|
||||
etape1Input.value = lien;
|
||||
etape1Input.readOnly = true;
|
||||
etape1.appendChild(etape1Input);
|
||||
|
||||
const etape1Bouton = CopieHelper.creerBoutonPartage("config-sauvegarde-bouton");
|
||||
CopieHelper.attacheBoutonCopieLien(etape1Bouton, lien, "Lien copié dans le presse papier.");
|
||||
etape1.appendChild(etape1Bouton);
|
||||
|
||||
listeEtape.appendChild(etape1);
|
||||
|
||||
const etape2 = document.createElement("li");
|
||||
etape2.innerText = "Envoyez le lien vers votre autre appareil.";
|
||||
listeEtape.appendChild(etape2);
|
||||
|
||||
const etape3 = document.createElement("li");
|
||||
etape3.innerText = "Ouvrez ce lien dans votre autre navigateur.";
|
||||
listeEtape.appendChild(etape3);
|
||||
|
||||
div.appendChild(listeEtape);
|
||||
|
||||
return div;
|
||||
}
|
||||
|
||||
public setInput(input: Input): void {
|
||||
this._input = input;
|
||||
}
|
||||
|
|
58
ts/copieHelper.ts
Normal file
58
ts/copieHelper.ts
Normal file
|
@ -0,0 +1,58 @@
|
|||
import NotificationMessage from "./notificationMessage";
|
||||
|
||||
export default class CopieHelper {
|
||||
public static attacheBoutonCopieLien(bouton: HTMLElement, lien: string, messageSucces: string): void {
|
||||
bouton.addEventListener("click", (event) => {
|
||||
event.stopPropagation();
|
||||
new Promise((resolve, reject) => {
|
||||
if (window.navigator.clipboard !== undefined) {
|
||||
return resolve(window.navigator.clipboard.writeText(lien));
|
||||
}
|
||||
|
||||
return reject();
|
||||
})
|
||||
.catch(
|
||||
() =>
|
||||
new Promise((resolve, reject) => {
|
||||
if (window.navigator.share !== undefined) return resolve(navigator.share({ text: lien }));
|
||||
|
||||
return reject();
|
||||
})
|
||||
)
|
||||
.then(() => {
|
||||
NotificationMessage.ajouterNotificationPanel(messageSucces, bouton);
|
||||
})
|
||||
.catch((raison) => {
|
||||
NotificationMessage.ajouterNotificationPanel("Votre navigateur n'est pas compatible.", bouton);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public static creerBoutonPartage(idBouton: string, label?: string): HTMLElement {
|
||||
return this.creerBoutonAvecIcone(idBouton, "#icone-copie", label);
|
||||
}
|
||||
|
||||
public static creerBoutonAvecIcone(idBouton: string, icone: string, label?: string): HTMLElement {
|
||||
const lien = document.createElement("a");
|
||||
lien.id = idBouton;
|
||||
lien.className = "bouton-partage";
|
||||
lien.href = "#";
|
||||
|
||||
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
||||
const useSvg = document.createElementNS("http://www.w3.org/2000/svg", "use") as SVGUseElement;
|
||||
useSvg.setAttribute("href", icone);
|
||||
useSvg.setAttribute("stroke", "var(--couleur-icone)");
|
||||
useSvg.setAttribute("fill", "var(--couleur-icone)");
|
||||
svg.appendChild(useSvg);
|
||||
lien.appendChild(svg);
|
||||
|
||||
if (label) {
|
||||
const texteBouton = document.createElement("span");
|
||||
texteBouton.className = "bouton-partage-texte";
|
||||
texteBouton.innerText = label;
|
||||
lien.appendChild(texteBouton);
|
||||
}
|
||||
|
||||
return lien;
|
||||
}
|
||||
}
|
|
@ -35,7 +35,7 @@ export default class Dictionnaire {
|
|||
public static async estMotValide(mot: string, premiereLettre: string, longueur: number): Promise<boolean> {
|
||||
mot = this.nettoyerMot(mot);
|
||||
let ListeMotsProposables = await import("./mots/listeMotsProposables." + longueur + "." + premiereLettre);
|
||||
return mot.length >= 6 && mot.length <= 9 && ListeMotsProposables.default.Dictionnaire.includes(mot);
|
||||
return mot.length >= 6 && mot.length <= 10 && ListeMotsProposables.default.Dictionnaire.includes(mot);
|
||||
}
|
||||
|
||||
public static nettoyerMot(mot: string): string {
|
||||
|
|
|
@ -10,6 +10,8 @@ export default class Configuration {
|
|||
volumeSon: VolumeSon.Normal,
|
||||
disposition: ClavierDisposition.Azerty,
|
||||
theme: Theme.Sombre,
|
||||
haptique: false,
|
||||
changelog: 0,
|
||||
};
|
||||
|
||||
hasAudio: boolean = false;
|
||||
|
@ -18,4 +20,6 @@ export default class Configuration {
|
|||
volumeSon: VolumeSon = VolumeSon.Normal;
|
||||
disposition: ClavierDisposition = ClavierDisposition.Azerty;
|
||||
theme: Theme = Theme.Sombre;
|
||||
haptique: boolean = false;
|
||||
changelog: number = 0;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ export default class SauvegardeStats {
|
|||
public static Default: SauvegardeStats = {
|
||||
partiesJouees: 0,
|
||||
partiesGagnees: 0,
|
||||
dernierePartie: new Date(),
|
||||
dernierePartie: null,
|
||||
repartition: {
|
||||
1: 0,
|
||||
2: 0,
|
||||
|
@ -19,7 +19,7 @@ export default class SauvegardeStats {
|
|||
},
|
||||
};
|
||||
|
||||
dernierePartie: Date = new Date();
|
||||
dernierePartie: Date | null = null;
|
||||
partiesJouees: number = 0;
|
||||
partiesGagnees: number = 0;
|
||||
repartition: {
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
import CopieHelper from "./copieHelper";
|
||||
import Configuration from "./entites/configuration";
|
||||
import LettreResultat from "./entites/lettreResultat";
|
||||
import { LettreStatut } from "./entites/lettreStatut";
|
||||
import SauvegardeStats from "./entites/sauvegardeStats";
|
||||
import Gestionnaire from "./gestionnaire";
|
||||
import InstanceConfiguration from "./instanceConfiguration";
|
||||
import NotificationMessage from "./notificationMessage";
|
||||
import PanelManager from "./panelManager";
|
||||
import Sauvegardeur from "./sauvegardeur";
|
||||
import StatistiquesDisplayer from "./statistiquesDisplayer";
|
||||
|
||||
export default class FinDePartiePanel {
|
||||
private readonly _datePartie: Date;
|
||||
private readonly _panelManager: PanelManager;
|
||||
private readonly _statsButton: HTMLElement;
|
||||
private readonly _gestionnaire: Gestionnaire;
|
||||
|
||||
private _resumeTexte: string = "";
|
||||
private _resumeTexteLegacy: string = "";
|
||||
|
@ -17,11 +21,12 @@ export default class FinDePartiePanel {
|
|||
private _estVictoire: boolean = false;
|
||||
private _partieEstFinie: boolean = false;
|
||||
|
||||
public constructor(datePartie: Date, panelManager: PanelManager) {
|
||||
public constructor(datePartie: Date, panelManager: PanelManager, gestionnaire: Gestionnaire) {
|
||||
this._datePartie = new Date(datePartie);
|
||||
this._datePartie.setHours(0, 0, 0);
|
||||
this._panelManager = panelManager;
|
||||
this._statsButton = document.getElementById("configuration-stats-bouton") as HTMLElement;
|
||||
this._gestionnaire = gestionnaire;
|
||||
|
||||
this._statsButton.addEventListener(
|
||||
"click",
|
||||
|
@ -104,31 +109,8 @@ export default class FinDePartiePanel {
|
|||
}
|
||||
|
||||
private attacherPartage(): void {
|
||||
let resumeBouton = document.getElementById("fin-de-partie-panel-resume-bouton") as HTMLElement;
|
||||
resumeBouton.addEventListener("click", (event) => {
|
||||
event.stopPropagation();
|
||||
new Promise((resolve, reject) => {
|
||||
if (window.navigator.clipboard !== undefined) {
|
||||
return resolve(window.navigator.clipboard.writeText(this._resumeTexte + "\n\nhttps://sutom.nocle.fr"));
|
||||
}
|
||||
|
||||
return reject();
|
||||
})
|
||||
.catch(
|
||||
() =>
|
||||
new Promise((resolve, reject) => {
|
||||
if (window.navigator.share !== undefined) return resolve(navigator.share({ text: this._resumeTexte + "\n\nhttps://sutom.nocle.fr" }));
|
||||
|
||||
return reject();
|
||||
})
|
||||
)
|
||||
.then(() => {
|
||||
NotificationMessage.ajouterNotificationPanel("Résumé copié dans le presse-papier.");
|
||||
})
|
||||
.catch((raison) => {
|
||||
NotificationMessage.ajouterNotificationPanel("Votre navigateur n'est pas compatible.");
|
||||
});
|
||||
});
|
||||
const resumeBouton = document.getElementById("fin-de-partie-panel-resume-bouton") as HTMLElement;
|
||||
CopieHelper.attacheBoutonCopieLien(resumeBouton, this._resumeTexte + "\n\nhttps://sutom.nocle.fr", "Résumé copié dans le presse papier.");
|
||||
}
|
||||
|
||||
public afficher(): void {
|
||||
|
@ -152,47 +134,52 @@ export default class FinDePartiePanel {
|
|||
Peut-être feras-tu mieux demain ? \
|
||||
</p>";
|
||||
}
|
||||
contenu +=
|
||||
'<p>Résumé de ta partie − <a href="#" id="fin-de-partie-panel-resume-bouton">Partager</a></p> \
|
||||
<pre id="fin-de-partie-panel-resume">' +
|
||||
this._resumeTexteLegacy +
|
||||
"</pre>";
|
||||
contenu += StatistiquesDisplayer.genererResumeTexte(this._resumeTexteLegacy).outerHTML;
|
||||
|
||||
if (Sauvegardeur.hasPartieVeilleNonTerminee()) {
|
||||
const partieVeilleArea = document.createElement("div");
|
||||
partieVeilleArea.id = "fin-de-partie-panel-partie-veille-area";
|
||||
|
||||
const partieVeilleLabel = document.createElement("div");
|
||||
partieVeilleLabel.innerText = "Il semblerait que vous n'avez pas terminé votre partie d'hier…";
|
||||
partieVeilleArea.appendChild(partieVeilleLabel);
|
||||
|
||||
partieVeilleArea.appendChild(CopieHelper.creerBoutonAvecIcone("fin-de-partie-panel-reset-bouton", "#icone-restaure", "Terminer la partie"));
|
||||
|
||||
contenu += partieVeilleArea.outerHTML;
|
||||
}
|
||||
}
|
||||
|
||||
let stats = Sauvegardeur.chargerSauvegardeStats();
|
||||
if (stats) {
|
||||
contenu +=
|
||||
'<p>Statistiques</p><div class="stats-area"><div class="stats-ligne"><div class="stats-cellule">Parties :</div>' +
|
||||
`<div class="stats-cellule">${stats.partiesGagnees}/${stats.partiesJouees}</div>` +
|
||||
"</div>" +
|
||||
`<div class="stats-ligne"><div class="stats-cellule">1/6 :</div><div class="stats-cellule">${stats.repartition[1]}</div></div>` +
|
||||
`<div class="stats-ligne"><div class="stats-cellule">2/6 :</div><div class="stats-cellule">${stats.repartition[2]}</div></div>` +
|
||||
`<div class="stats-ligne"><div class="stats-cellule">3/6 :</div><div class="stats-cellule">${stats.repartition[3]}</div></div>` +
|
||||
`<div class="stats-ligne"><div class="stats-cellule">4/6 :</div><div class="stats-cellule">${stats.repartition[4]}</div></div>` +
|
||||
`<div class="stats-ligne"><div class="stats-cellule">5/6 :</div><div class="stats-cellule">${stats.repartition[5]}</div></div>` +
|
||||
`<div class="stats-ligne"><div class="stats-cellule">6/6 :</div><div class="stats-cellule">${stats.repartition[6]}</div></div>` +
|
||||
`<div class="stats-ligne"><div class="stats-cellule">-/6 :</div><div class="stats-cellule">${stats.repartition["-"]}</div></div>` +
|
||||
`<div class="stats-ligne"><div class="stats-cellule">Moyenne :</div><div class="stats-cellule">${this.getMoyenne(stats.repartition)}</div></div>` +
|
||||
'<div class="stats-ligne"><div class="stats-cellule">Lettres :</div>' +
|
||||
'<div class="stats-cellule">' +
|
||||
`${stats.lettresRepartitions.bienPlace} 🟥 ` +
|
||||
`${stats.lettresRepartitions.malPlace} 🟡 ` +
|
||||
`${stats.lettresRepartitions.nonTrouve} 🟦` +
|
||||
"</div>" +
|
||||
"</div>" +
|
||||
"</div>";
|
||||
contenu += StatistiquesDisplayer.genererHtmlStats(stats).outerHTML;
|
||||
}
|
||||
|
||||
this._panelManager.setContenu(titre, contenu);
|
||||
this._panelManager.setClasses(["fin-de-partie-panel"]);
|
||||
if (this._partieEstFinie) this.attacherPartage();
|
||||
if (stats) this.attacherPartageStats(stats);
|
||||
|
||||
const resetButton = document.getElementById("fin-de-partie-panel-reset-bouton") as HTMLElement;
|
||||
if (resetButton) {
|
||||
const veille = new Date();
|
||||
veille.setDate(veille.getDate() - 1);
|
||||
resetButton.addEventListener(
|
||||
"click",
|
||||
(() => {
|
||||
this._gestionnaire.chargerPartieAncienne(veille, Sauvegardeur.chargerPartieVeille());
|
||||
this._panelManager.cacherPanel();
|
||||
}).bind(this)
|
||||
);
|
||||
}
|
||||
this._panelManager.afficherPanel();
|
||||
}
|
||||
|
||||
private getMoyenne(repartition: { 1: number; 2: number; 3: number; 4: number; 5: number; 6: number; "-": number }): string {
|
||||
return (
|
||||
(repartition[1] * 1 + repartition[2] * 2 + repartition[3] * 3 + repartition[4] * 4 + repartition[5] * 5 + repartition[6] * 6 + repartition["-"] * 6) /
|
||||
(repartition[1] + repartition[2] + repartition[3] + repartition[4] + repartition[5] + repartition[6] + repartition["-"])
|
||||
).toLocaleString("fr-FR", { maximumFractionDigits: 2 });
|
||||
private attacherPartageStats(stats: SauvegardeStats): void {
|
||||
const resumeBouton = document.getElementById("fin-de-partie-panel-stats-bouton") as HTMLElement;
|
||||
|
||||
let resumeTexte = StatistiquesDisplayer.genererResumeTexteStatistiques(stats);
|
||||
|
||||
CopieHelper.attacheBoutonCopieLien(resumeBouton, resumeTexte + "\n\nhttps://sutom.nocle.fr", "Résumé copié dans le presse papier.");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,18 +15,21 @@ import ConfigurationPanel from "./configurationPanel";
|
|||
import AudioPanel from "./audioPanel";
|
||||
import ThemeManager from "./themeManager";
|
||||
import InstanceConfiguration from "./instanceConfiguration";
|
||||
import LienHelper from "./lienHelper";
|
||||
import NotesMaJPanel from "./notesMaJPanel";
|
||||
|
||||
export default class Gestionnaire {
|
||||
private _grille: Grille | null = null;
|
||||
private _input: Input | null = null;
|
||||
private readonly _reglesPanel: ReglesPanel;
|
||||
private readonly _finDePartiePanel: FinDePartiePanel;
|
||||
private _finDePartiePanel: FinDePartiePanel;
|
||||
private readonly _configurationPanel: ConfigurationPanel;
|
||||
private readonly _propositions: Array<string>;
|
||||
private readonly _resultats: Array<Array<LettreResultat>>;
|
||||
private readonly _panelManager: PanelManager;
|
||||
private readonly _themeManager: ThemeManager;
|
||||
private readonly _audioPanel: AudioPanel;
|
||||
private readonly _notesMaJPanel: NotesMaJPanel;
|
||||
|
||||
private _motATrouver: string = "";
|
||||
private _compositionMotATrouver: { [lettre: string]: number } = {};
|
||||
|
@ -64,8 +67,9 @@ export default class Gestionnaire {
|
|||
this._panelManager = new PanelManager();
|
||||
this._themeManager = new ThemeManager(this._config);
|
||||
this._reglesPanel = new ReglesPanel(this._panelManager);
|
||||
this._finDePartiePanel = new FinDePartiePanel(this._datePartieEnCours, this._panelManager);
|
||||
this._finDePartiePanel = new FinDePartiePanel(this._datePartieEnCours, this._panelManager, this);
|
||||
this._configurationPanel = new ConfigurationPanel(this._panelManager, this._audioPanel, this._themeManager);
|
||||
this._notesMaJPanel = new NotesMaJPanel(this._panelManager);
|
||||
|
||||
this.choisirMot(this._idPartieEnCours, this._datePartieEnCours)
|
||||
.then(async (mot) => {
|
||||
|
@ -83,19 +87,9 @@ export default class Gestionnaire {
|
|||
}
|
||||
|
||||
private getIdPartie(partieEnCours: PartieEnCours) {
|
||||
if (window.location.hash !== "" && window.location.hash !== "#") {
|
||||
let hashPart = atob(window.location.hash.substring(1)).split("/");
|
||||
for (let infoPos in hashPart) {
|
||||
let info = hashPart[infoPos];
|
||||
if (!info.includes("=")) continue;
|
||||
let infoPart = info.split("=");
|
||||
let infoKey = infoPart[0];
|
||||
const infoDansLocation = LienHelper.extraireInformation("p");
|
||||
|
||||
if (infoKey !== "p") continue;
|
||||
|
||||
return infoPart[1];
|
||||
}
|
||||
}
|
||||
if (infoDansLocation !== null) return infoDansLocation;
|
||||
|
||||
if (partieEnCours.idPartie !== undefined) return partieEnCours.idPartie;
|
||||
|
||||
|
@ -120,6 +114,16 @@ export default class Gestionnaire {
|
|||
}
|
||||
|
||||
private enregistrerPartieDansStats(): void {
|
||||
// On regarde si c'est le même jour que la dernière partie dans les stats.
|
||||
// Si c'est identique, on ne sauvegarde pas
|
||||
if (
|
||||
this._stats.dernierePartie &&
|
||||
this._stats.dernierePartie.getFullYear() === this._datePartieEnCours.getFullYear() &&
|
||||
this._stats.dernierePartie.getMonth() === this._datePartieEnCours.getMonth() &&
|
||||
this._stats.dernierePartie.getDate() === this._datePartieEnCours.getDate()
|
||||
)
|
||||
return;
|
||||
|
||||
this._stats.partiesJouees++;
|
||||
let estVictoire = this._resultats.some((resultat) => resultat.every((item) => item.statut === LettreStatut.BienPlace));
|
||||
if (estVictoire) {
|
||||
|
@ -264,8 +268,59 @@ export default class Gestionnaire {
|
|||
}
|
||||
|
||||
private afficherReglesSiNecessaire(): void {
|
||||
if (this._config.afficherRegles !== undefined && !this._config.afficherRegles) return;
|
||||
if (this._config.afficherRegles !== undefined && !this._config.afficherRegles) {
|
||||
if (this._config.changelog === undefined || this._config.changelog < InstanceConfiguration.derniereMiseAJour) {
|
||||
this._notesMaJPanel.afficher(this._config.changelog ?? 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this._reglesPanel.afficher();
|
||||
}
|
||||
|
||||
public chargerPartieAncienne(datePartie: Date, etatPartie: PartieEnCours): void {
|
||||
let partieEnCours = etatPartie;
|
||||
|
||||
this._idPartieEnCours = this.getIdPartie(partieEnCours);
|
||||
const veille = new Date();
|
||||
veille.setDate(veille.getDate() - 1);
|
||||
|
||||
if (this._idPartieEnCours !== partieEnCours.idPartie && partieEnCours.idPartie !== undefined) {
|
||||
partieEnCours = new PartieEnCours();
|
||||
}
|
||||
|
||||
if (
|
||||
partieEnCours.datePartie &&
|
||||
!(
|
||||
veille.getDate() === partieEnCours.datePartie.getDate() &&
|
||||
veille.getMonth() === partieEnCours.datePartie.getMonth() &&
|
||||
veille.getFullYear() === partieEnCours.datePartie.getFullYear()
|
||||
)
|
||||
) {
|
||||
partieEnCours = new PartieEnCours();
|
||||
}
|
||||
|
||||
if (partieEnCours.datePartie) {
|
||||
this._datePartieEnCours = partieEnCours.datePartie;
|
||||
} else {
|
||||
this._datePartieEnCours = datePartie;
|
||||
}
|
||||
this._dateFinPartie = undefined;
|
||||
|
||||
this._propositions.splice(0);
|
||||
this._resultats.splice(0);
|
||||
this._finDePartiePanel = new FinDePartiePanel(this._datePartieEnCours, this._panelManager, this);
|
||||
|
||||
this.choisirMot(this._idPartieEnCours, this._datePartieEnCours)
|
||||
.then(async (mot) => {
|
||||
this._motATrouver = mot;
|
||||
this._input = new Input(this, this._config, this._motATrouver.length, this._motATrouver[0]);
|
||||
this._panelManager.setInput(this._input);
|
||||
this._grille = new Grille(this._motATrouver.length, this._maxNbPropositions, this._motATrouver[0], this._audioPanel);
|
||||
this._configurationPanel.setInput(this._input);
|
||||
this._compositionMotATrouver = this.decompose(this._motATrouver);
|
||||
await this.chargerPropositions(partieEnCours.propositions);
|
||||
})
|
||||
.catch((raison) => NotificationMessage.ajouterNotification("Aucun mot n'a été trouvé pour aujourd'hui"));
|
||||
}
|
||||
}
|
||||
|
|
11
ts/grille.ts
11
ts/grille.ts
|
@ -39,13 +39,20 @@ export default class Grille {
|
|||
if (nbMot < this._motActuel || (nbMot === this._motActuel && mot.length !== 0)) {
|
||||
if (mot.length <= nbLettre) {
|
||||
contenuCellule = ".";
|
||||
cellule.classList.add("cellule-lettre-pas-curseur");
|
||||
} else {
|
||||
contenuCellule = mot[nbLettre].toUpperCase();
|
||||
cellule.classList.remove("cellule-lettre-pas-curseur");
|
||||
}
|
||||
} else if (nbMot === this._motActuel) {
|
||||
let lettreIndice = this._indice[nbLettre];
|
||||
if (lettreIndice !== undefined) contenuCellule = lettreIndice;
|
||||
else contenuCellule = ".";
|
||||
if (lettreIndice !== undefined) {
|
||||
contenuCellule = lettreIndice;
|
||||
cellule.classList.remove("cellule-lettre-pas-curseur");
|
||||
} else {
|
||||
contenuCellule = ".";
|
||||
cellule.classList.add("cellule-lettre-pas-curseur");
|
||||
}
|
||||
}
|
||||
if (this._resultats.length > nbMot && this._resultats[nbMot][nbLettre]) {
|
||||
let resultat = this._resultats[nbMot][nbLettre];
|
||||
|
|
|
@ -4,6 +4,7 @@ import { LettreStatut } from "./entites/lettreStatut";
|
|||
import { ClavierDisposition } from "./entites/clavierDisposition";
|
||||
import Configuration from "./entites/configuration";
|
||||
import Dictionnaire from "./dictionnaire";
|
||||
import Sauvegardeur from "./sauvegardeur";
|
||||
|
||||
export enum ContexteBloquage {
|
||||
ValidationMot,
|
||||
|
@ -18,8 +19,9 @@ export default class Input {
|
|||
|
||||
private _longueurMot: number;
|
||||
private _motSaisi: string;
|
||||
private _estBloque: Array<ContexteBloquage>; // TODO : Faire un dictionnaire pour savoir qui bloque, pour que si c'est bloqué par finDePartie, et que la fermeture de panel essaye de débloquer, ça ne fasse rien
|
||||
private _estBloque: Array<ContexteBloquage>;
|
||||
private _resultats: Array<Array<LettreResultat>>;
|
||||
private _haptiqueActive: boolean;
|
||||
|
||||
public constructor(gestionnaire: Gestionnaire, configuration: Configuration, longueurMot: number, premiereLettre: string) {
|
||||
this._grille = document.getElementById("grille") as HTMLElement;
|
||||
|
@ -30,6 +32,7 @@ export default class Input {
|
|||
this._motSaisi = "";
|
||||
this._estBloque = new Array<ContexteBloquage>();
|
||||
this._resultats = new Array<Array<LettreResultat>>();
|
||||
this._haptiqueActive = configuration.haptique ?? Configuration.Default.haptique;
|
||||
|
||||
this.ajouterEvenementClavierPhysique();
|
||||
|
||||
|
@ -51,6 +54,7 @@ export default class Input {
|
|||
case "_effacer":
|
||||
lettreDiv.dataset["lettre"] = lettre;
|
||||
lettreDiv.innerText = "⌫";
|
||||
lettreDiv.classList.add("input-lettre-effacer");
|
||||
break;
|
||||
case "_entree":
|
||||
lettreDiv.innerText = "↲";
|
||||
|
@ -72,6 +76,7 @@ export default class Input {
|
|||
|
||||
this._inputArea.appendChild(ligneDiv);
|
||||
}
|
||||
this._haptiqueActive = Sauvegardeur.chargerConfig()?.haptique ?? Configuration.Default.haptique;
|
||||
this.ajouterEvenementClavierVirtuel();
|
||||
this.remettrePropositions();
|
||||
}
|
||||
|
@ -111,6 +116,7 @@ export default class Input {
|
|||
event.stopPropagation();
|
||||
let div = event.currentTarget;
|
||||
if (!div) return;
|
||||
if (this._haptiqueActive && window.navigator.vibrate) window.navigator.vibrate(75);
|
||||
let lettre = (div as HTMLElement).dataset["lettre"];
|
||||
if (lettre === undefined) {
|
||||
return;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
export default class InstanceConfiguration {
|
||||
public static readonly dateOrigine = new Date(2022, 0, 8); // Attention, c'est du js/ts, donc pour le mois, il faut faire -1, Janvier = 0 !
|
||||
public static readonly idPartieParDefaut = "34ccc522-c264-4e51-b293-fd5bd60ef7aa";
|
||||
public static readonly derniereMiseAJour = 512;
|
||||
}
|
||||
|
|
19
ts/lienHelper.ts
Normal file
19
ts/lienHelper.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
export default class LienHelper {
|
||||
public static extraireInformation(cle: string): string | null {
|
||||
if (window.location.hash === "" || window.location.hash === "#") return null;
|
||||
|
||||
let hashPart = atob(window.location.hash.substring(1)).split("/");
|
||||
for (let infoPos in hashPart) {
|
||||
let info = hashPart[infoPos];
|
||||
if (!info.includes("=")) continue;
|
||||
let infoPart = info.split("=");
|
||||
let infoKey = infoPart[0];
|
||||
|
||||
if (infoKey !== cle) continue;
|
||||
|
||||
return infoPart[1];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
85
ts/notesMaJPanel.ts
Normal file
85
ts/notesMaJPanel.ts
Normal file
|
@ -0,0 +1,85 @@
|
|||
import Configuration from "./entites/configuration";
|
||||
import InstanceConfiguration from "./instanceConfiguration";
|
||||
import PanelManager from "./panelManager";
|
||||
import Sauvegardeur from "./sauvegardeur";
|
||||
|
||||
export default class NotesMaJPanel {
|
||||
private readonly _panelManager: PanelManager;
|
||||
|
||||
private readonly _notes = [
|
||||
{
|
||||
version: 512,
|
||||
notes: [
|
||||
"Correction du non affichage du bouton Partie de la veille",
|
||||
"Ajustement de la hauteur du jeu sur certains téléphones",
|
||||
"Correction de la couleur de la longue barre des statistiques",
|
||||
"Ajout des couleurs dans les stats pour les terminaux sans emoji",
|
||||
"Correction d'une coquille dans les options",
|
||||
"Résolution d'un problème de selection de texte sur le clavier",
|
||||
],
|
||||
},
|
||||
{
|
||||
version: 500,
|
||||
notes: [
|
||||
"Revue du design général de l'application",
|
||||
"Refonte du mode clair",
|
||||
"Refonte de l'affichage des statistiques",
|
||||
"Ajout d'un bouton pour partager ses statistiques",
|
||||
"Ajout d'un bouton pour terminer la partie de la veille",
|
||||
"Ajout d'une option pour avoir le clavier haptique",
|
||||
"Ajout d'une option pour transférer ses statistiques sur un autre navigateur",
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
public constructor(panelManager: PanelManager) {
|
||||
this._panelManager = panelManager;
|
||||
}
|
||||
|
||||
public afficher(versionOrigine: number): void {
|
||||
let titre = "Notes de mises à jour";
|
||||
|
||||
// On affiche du plus récent au plus ancien
|
||||
const notesAAfficher = this._notes
|
||||
.filter((note) => note.version > versionOrigine)
|
||||
.sort((a, b) => {
|
||||
if (b.version > a.version) return 1;
|
||||
if (b.version < a.version) return -1;
|
||||
return 0;
|
||||
});
|
||||
|
||||
if (notesAAfficher.length === 0) return;
|
||||
|
||||
const notesArea = document.createElement("div");
|
||||
|
||||
for (let note of notesAAfficher) {
|
||||
const divNote = document.createElement("div");
|
||||
|
||||
const titre = document.createElement("h3");
|
||||
titre.innerText = `Version ${note.version}`;
|
||||
divNote.appendChild(titre);
|
||||
|
||||
const listeNotes = document.createElement("ul");
|
||||
|
||||
for (let item of note.notes) {
|
||||
const itemLi = document.createElement("li");
|
||||
itemLi.innerText = item;
|
||||
listeNotes.appendChild(itemLi);
|
||||
}
|
||||
|
||||
divNote.appendChild(listeNotes);
|
||||
|
||||
notesArea.appendChild(divNote);
|
||||
}
|
||||
|
||||
this._panelManager.setContenuHtmlElement(titre, notesArea);
|
||||
this._panelManager.setClasses(["notes-panel"]);
|
||||
this._panelManager.setCallbackFermeture(() => {
|
||||
Sauvegardeur.sauvegarderConfig({
|
||||
...(Sauvegardeur.chargerConfig() ?? Configuration.Default),
|
||||
changelog: InstanceConfiguration.derniereMiseAJour,
|
||||
});
|
||||
});
|
||||
this._panelManager.afficherPanel();
|
||||
}
|
||||
}
|
|
@ -1,28 +1,34 @@
|
|||
export default class NotificationMessage {
|
||||
private static _notificationArea: HTMLElement = document.getElementById("notification") as HTMLElement;
|
||||
private static _notificationPanelArea: HTMLElement = document.getElementById("panel-fenetre-notification") as HTMLElement;
|
||||
private static _notificationArea: HTMLElement = document.getElementById("notification-area") as HTMLElement;
|
||||
private static _notificationLabel: HTMLElement = document.getElementById("notification-label") as HTMLElement;
|
||||
private static _notificationPanelArea: HTMLElement = document.getElementById("panel-fenetre-notification-area") as HTMLElement;
|
||||
private static _notificationPanelLabel: HTMLElement = document.getElementById("panel-fenetre-notification-label") as HTMLElement;
|
||||
private static _currentTimeout: NodeJS.Timeout | undefined;
|
||||
|
||||
public static ajouterNotification(message: string): void {
|
||||
this.ajouterNotificationDiv(this._notificationArea, message);
|
||||
this.ajouterNotificationDiv(this._notificationArea, this._notificationLabel, message);
|
||||
}
|
||||
|
||||
public static ajouterNotificationPanel(message: string): void {
|
||||
this.ajouterNotificationDiv(this._notificationPanelArea, message);
|
||||
public static ajouterNotificationPanel(message: string, origine: HTMLElement): void {
|
||||
this.ajouterNotificationDiv(this._notificationPanelArea, this._notificationPanelLabel, message);
|
||||
const { top: topParent, left: leftParent } = origine.getBoundingClientRect();
|
||||
this._notificationPanelArea.style.top = `${topParent + 30}px`;
|
||||
this._notificationPanelArea.style.left = `${leftParent - this._notificationPanelArea.getBoundingClientRect().width / 2}px`;
|
||||
}
|
||||
|
||||
private static ajouterNotificationDiv(div: HTMLElement, message: string): void {
|
||||
private static ajouterNotificationDiv(divArea: HTMLElement, divLabel: HTMLElement, message: string): void {
|
||||
if (this._currentTimeout) {
|
||||
clearTimeout(this._currentTimeout);
|
||||
this._currentTimeout = undefined;
|
||||
}
|
||||
div.innerHTML = message;
|
||||
div.style.opacity = "1";
|
||||
divLabel.innerHTML = message;
|
||||
divArea.style.opacity = "1";
|
||||
this._currentTimeout = setTimeout(
|
||||
(() => {
|
||||
div.style.opacity = "0";
|
||||
divArea.style.opacity = "0";
|
||||
this._currentTimeout = setTimeout(
|
||||
(() => {
|
||||
div.innerHTML = " ";
|
||||
divLabel.innerHTML = "";
|
||||
this._currentTimeout = undefined;
|
||||
}).bind(this),
|
||||
1000
|
||||
|
|
|
@ -46,7 +46,8 @@ export default class ReglesPanel {
|
|||
' ou <a target="_blank" href="https://mastodon.social/@JonathanMM">@JonathanMM@mastodon.social</a> sur mastodon. − ' +
|
||||
'<a target="_blank" href="https://framagit.org/JonathanMM/sutom">Page du projet</a><br />' +
|
||||
'Basé sur l\'excellent <a target="_blank" href="https://www.nytimes.com/games/wordle/index.html">Wordle</a> et le regretté Motus.<br />' +
|
||||
"Merci à Emmanuel pour l'aide sur les mots à trouver, et à GaranceAmarante pour l'aide sur le dictionnaire." +
|
||||
"Merci à Emmanuel pour l'aide sur les mots à trouver, et à GaranceAmarante pour l'aide sur le dictionnaire.<br />" +
|
||||
'Les icônes proviennent de <a target="_blank" href="https://m3.material.io/styles/icons/overview">Material Design</a>' +
|
||||
"</p>";
|
||||
|
||||
this._panelManager.setContenu(titre, contenu);
|
||||
|
|
|
@ -2,10 +2,13 @@ import Configuration from "./entites/configuration";
|
|||
import PartieEnCours from "./entites/partieEnCours";
|
||||
import SauvegardePartie from "./entites/sauvegardePartie";
|
||||
import SauvegardeStats from "./entites/sauvegardeStats";
|
||||
import LienHelper from "./lienHelper";
|
||||
import NotificationMessage from "./notificationMessage";
|
||||
|
||||
export default class Sauvegardeur {
|
||||
private static readonly _cleStats = "statistiques";
|
||||
private static readonly _clePartieEnCours = "partieEnCours";
|
||||
private static readonly _clePartieVeille = "partieVeille";
|
||||
private static readonly _cleConfiguration = "configuration";
|
||||
|
||||
public static sauvegarderStats(stats: SauvegardeStats): void {
|
||||
|
@ -13,10 +16,25 @@ export default class Sauvegardeur {
|
|||
}
|
||||
|
||||
public static chargerSauvegardeStats(): SauvegardeStats | undefined {
|
||||
let dataStats = localStorage.getItem(this._cleStats);
|
||||
const contenuLocation = LienHelper.extraireInformation("s");
|
||||
|
||||
if (contenuLocation) {
|
||||
const donneesDepuisLien = Sauvegardeur.chargerInformationDepuisLien(contenuLocation);
|
||||
window.location.hash = "";
|
||||
if (donneesDepuisLien) {
|
||||
NotificationMessage.ajouterNotification("Statistiques chargés avec succès.");
|
||||
Sauvegardeur.sauvegarderStats(donneesDepuisLien);
|
||||
return donneesDepuisLien;
|
||||
}
|
||||
|
||||
NotificationMessage.ajouterNotification("Impossible de charger les statistiques depuis le lien.");
|
||||
}
|
||||
|
||||
const dataStats = localStorage.getItem(this._cleStats);
|
||||
if (!dataStats) return;
|
||||
|
||||
let stats = JSON.parse(dataStats) as SauvegardeStats;
|
||||
if (stats.dernierePartie !== null) stats.dernierePartie = new Date(stats.dernierePartie);
|
||||
return stats;
|
||||
}
|
||||
|
||||
|
@ -31,19 +49,54 @@ export default class Sauvegardeur {
|
|||
}
|
||||
|
||||
public static chargerSauvegardePartieEnCours(): PartieEnCours | undefined {
|
||||
let dataPartieEnCours = localStorage.getItem(this._clePartieEnCours);
|
||||
if (!dataPartieEnCours) return;
|
||||
|
||||
let partieEnCours = JSON.parse(dataPartieEnCours) as SauvegardePartie;
|
||||
let aujourdhui = new Date();
|
||||
let datePartieEnCours = new Date(partieEnCours.datePartie);
|
||||
if (
|
||||
aujourdhui.getDate() !== datePartieEnCours.getDate() ||
|
||||
aujourdhui.getMonth() !== datePartieEnCours.getMonth() ||
|
||||
aujourdhui.getFullYear() !== datePartieEnCours.getFullYear()
|
||||
) {
|
||||
localStorage.removeItem(this._clePartieEnCours);
|
||||
return;
|
||||
let partieEnCours: SauvegardePartie;
|
||||
let datePartieEnCours: Date;
|
||||
|
||||
let dataPartieEnCours = localStorage.getItem(this._clePartieEnCours);
|
||||
if (!dataPartieEnCours) {
|
||||
// On regarde si par hasard, on n'a pas la partie du jour dans les infos de la veille
|
||||
const partieVeille = this.getInfoVeille();
|
||||
|
||||
if (
|
||||
partieVeille &&
|
||||
aujourdhui.getDate() === partieVeille.datePartie.getDate() &&
|
||||
aujourdhui.getMonth() === partieVeille.datePartie.getMonth() &&
|
||||
aujourdhui.getFullYear() === partieVeille.datePartie.getFullYear()
|
||||
) {
|
||||
partieEnCours = partieVeille;
|
||||
datePartieEnCours = partieVeille.datePartie;
|
||||
localStorage.removeItem(this._clePartieVeille);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
partieEnCours = JSON.parse(dataPartieEnCours) as SauvegardePartie;
|
||||
datePartieEnCours = new Date(partieEnCours.datePartie);
|
||||
if (
|
||||
aujourdhui.getDate() !== datePartieEnCours.getDate() ||
|
||||
aujourdhui.getMonth() !== datePartieEnCours.getMonth() ||
|
||||
aujourdhui.getFullYear() !== datePartieEnCours.getFullYear()
|
||||
) {
|
||||
// On regarde si par hasard, on n'a pas la partie du jour dans les infos de la veille
|
||||
const partieVeille = this.getInfoVeille();
|
||||
|
||||
if (
|
||||
partieVeille &&
|
||||
aujourdhui.getDate() === partieVeille.datePartie.getDate() &&
|
||||
aujourdhui.getMonth() === partieVeille.datePartie.getMonth() &&
|
||||
aujourdhui.getFullYear() === partieVeille.datePartie.getFullYear()
|
||||
) {
|
||||
partieEnCours = partieVeille;
|
||||
datePartieEnCours = partieVeille.datePartie;
|
||||
// Et on inverse les données
|
||||
localStorage.setItem(this._clePartieVeille, dataPartieEnCours);
|
||||
} else {
|
||||
localStorage.setItem(this._clePartieVeille, dataPartieEnCours);
|
||||
localStorage.removeItem(this._clePartieEnCours);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
let dateFinPartie = partieEnCours.dateFinPartie === undefined ? undefined : new Date(partieEnCours.dateFinPartie);
|
||||
|
||||
|
@ -55,6 +108,68 @@ export default class Sauvegardeur {
|
|||
};
|
||||
}
|
||||
|
||||
private static getInfoVeille(): SauvegardePartie | undefined {
|
||||
const dataPartieVeille = localStorage.getItem(this._clePartieVeille);
|
||||
if (!dataPartieVeille) return undefined;
|
||||
|
||||
const veille = new Date();
|
||||
veille.setDate(veille.getDate() - 1);
|
||||
|
||||
let partieVeille = JSON.parse(dataPartieVeille) as SauvegardePartie;
|
||||
if (partieVeille.datePartie) partieVeille.datePartie = new Date(partieVeille.datePartie);
|
||||
if (partieVeille.dateFinPartie) partieVeille.dateFinPartie = new Date(partieVeille.dateFinPartie);
|
||||
return partieVeille;
|
||||
}
|
||||
|
||||
public static hasPartieVeilleNonTerminee(): boolean {
|
||||
const partieVeille = this.getInfoVeille();
|
||||
if (!partieVeille) return true;
|
||||
|
||||
const aujourdhui = new Date();
|
||||
|
||||
const veille = new Date();
|
||||
veille.setDate(veille.getDate() - 1);
|
||||
|
||||
return (
|
||||
(aujourdhui.getDate() !== partieVeille.datePartie.getDate() && veille.getDate() !== partieVeille.datePartie.getDate()) ||
|
||||
(aujourdhui.getMonth() !== partieVeille.datePartie.getMonth() && veille.getMonth() !== partieVeille.datePartie.getMonth()) ||
|
||||
(aujourdhui.getFullYear() !== partieVeille.datePartie.getFullYear() && veille.getFullYear() !== partieVeille.datePartie.getFullYear()) ||
|
||||
!partieVeille.dateFinPartie
|
||||
);
|
||||
}
|
||||
|
||||
public static chargerPartieVeille(): PartieEnCours {
|
||||
const veille = new Date();
|
||||
veille.setDate(veille.getDate() - 1);
|
||||
const partieVeille = this.getInfosPartieVeille(veille);
|
||||
let dateFinPartie = partieVeille.dateFinPartie === undefined ? undefined : new Date(partieVeille.dateFinPartie);
|
||||
|
||||
// On va sauvegarder la partie en cours dans la veille pour ne pas la perde
|
||||
const partieEnCours = localStorage.getItem(this._clePartieEnCours);
|
||||
if (partieEnCours) {
|
||||
localStorage.setItem(this._clePartieVeille, partieEnCours);
|
||||
localStorage.removeItem(this._clePartieEnCours);
|
||||
}
|
||||
|
||||
return {
|
||||
datePartie: new Date(partieVeille.datePartie),
|
||||
dateFinPartie: dateFinPartie,
|
||||
propositions: partieVeille.propositions,
|
||||
idPartie: partieVeille.idPartie,
|
||||
};
|
||||
}
|
||||
|
||||
private static getInfosPartieVeille(veille: Date): SauvegardePartie {
|
||||
const dataPartieVeille = localStorage.getItem(this._clePartieVeille);
|
||||
if (!dataPartieVeille) {
|
||||
const dataPartie = new SauvegardePartie();
|
||||
dataPartie.datePartie = veille;
|
||||
return dataPartie;
|
||||
}
|
||||
|
||||
return JSON.parse(dataPartieVeille) as SauvegardePartie;
|
||||
}
|
||||
|
||||
public static sauvegarderConfig(config: Configuration): void {
|
||||
localStorage.setItem(this._cleConfiguration, JSON.stringify(config));
|
||||
}
|
||||
|
@ -66,4 +181,68 @@ export default class Sauvegardeur {
|
|||
let config = JSON.parse(dataConfig) as Configuration;
|
||||
return config;
|
||||
}
|
||||
|
||||
public static genererLien(): string {
|
||||
const stats = Sauvegardeur.chargerSauvegardeStats() ?? SauvegardeStats.Default;
|
||||
return [
|
||||
stats.repartition[1],
|
||||
stats.repartition[2],
|
||||
stats.repartition[3],
|
||||
stats.repartition[4],
|
||||
stats.repartition[5],
|
||||
stats.repartition[6],
|
||||
stats.repartition["-"],
|
||||
stats.lettresRepartitions.bienPlace,
|
||||
stats.lettresRepartitions.malPlace,
|
||||
stats.lettresRepartitions.nonTrouve,
|
||||
stats.dernierePartie ? stats.dernierePartie.toISOString() : "null",
|
||||
].join(",");
|
||||
}
|
||||
|
||||
private static chargerInformationDepuisLien(contenu: string): SauvegardeStats | null {
|
||||
const [
|
||||
UnCoupString,
|
||||
DeuxCoupsString,
|
||||
TroisCoupsString,
|
||||
QuatreCoupsString,
|
||||
CinqCoupsString,
|
||||
SixCoupsString,
|
||||
PerduString,
|
||||
LettresBienPlaceesString,
|
||||
LettresMalPlaceesString,
|
||||
LettresNonTrouveString,
|
||||
dernierePartie,
|
||||
] = contenu.split(",");
|
||||
|
||||
const UnCoup = parseInt(UnCoupString);
|
||||
const DeuxCoups = parseInt(DeuxCoupsString);
|
||||
const TroisCoups = parseInt(TroisCoupsString);
|
||||
const QuatreCoups = parseInt(QuatreCoupsString);
|
||||
const CinqCoups = parseInt(CinqCoupsString);
|
||||
const SixCoups = parseInt(SixCoupsString);
|
||||
const Perdu = parseInt(PerduString);
|
||||
const LettresBienPlacees = parseInt(LettresBienPlaceesString);
|
||||
const LettresMalPlacees = parseInt(LettresMalPlaceesString);
|
||||
const LettresNonTrouve = parseInt(LettresNonTrouveString);
|
||||
|
||||
return {
|
||||
dernierePartie: dernierePartie === "null" ? null : new Date(dernierePartie),
|
||||
partiesJouees: UnCoup + DeuxCoups + TroisCoups + QuatreCoups + CinqCoups + SixCoups + Perdu,
|
||||
partiesGagnees: UnCoup + DeuxCoups + TroisCoups + QuatreCoups + CinqCoups + SixCoups,
|
||||
repartition: {
|
||||
1: UnCoup,
|
||||
2: DeuxCoups,
|
||||
3: TroisCoups,
|
||||
4: QuatreCoups,
|
||||
5: CinqCoups,
|
||||
6: SixCoups,
|
||||
"-": Perdu,
|
||||
},
|
||||
lettresRepartitions: {
|
||||
bienPlace: LettresBienPlacees,
|
||||
malPlace: LettresMalPlacees,
|
||||
nonTrouve: LettresNonTrouve,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
150
ts/statistiquesDisplayer.ts
Normal file
150
ts/statistiquesDisplayer.ts
Normal file
|
@ -0,0 +1,150 @@
|
|||
import CopieHelper from "./copieHelper";
|
||||
import SauvegardeStats from "./entites/sauvegardeStats";
|
||||
|
||||
export default class StatistiquesDisplayer {
|
||||
public static genererResumeTexte(texte: string): HTMLElement {
|
||||
const area = document.createElement("div");
|
||||
|
||||
const titre = document.createElement("h3");
|
||||
titre.innerText = "Résumé de la partie";
|
||||
|
||||
titre.appendChild(CopieHelper.creerBoutonPartage("fin-de-partie-panel-resume-bouton", "Partager"));
|
||||
area.appendChild(titre);
|
||||
|
||||
const resumeArea = document.createElement("pre");
|
||||
resumeArea.id = "fin-de-partie-panel-resume";
|
||||
resumeArea.innerHTML = texte;
|
||||
area.appendChild(resumeArea);
|
||||
|
||||
return area;
|
||||
}
|
||||
|
||||
public static genererHtmlStats(stats: SauvegardeStats): HTMLElement {
|
||||
const statsArea = document.createElement("div");
|
||||
statsArea.className = "stats-area";
|
||||
|
||||
const titre = document.createElement("h3");
|
||||
titre.innerText = "Statistiques";
|
||||
titre.appendChild(CopieHelper.creerBoutonPartage("fin-de-partie-panel-stats-bouton", "Partager"));
|
||||
statsArea.appendChild(titre);
|
||||
|
||||
const statsParties = document.createElement("div");
|
||||
statsParties.className = "stats-parties";
|
||||
|
||||
const max = this.getMax(stats.repartition);
|
||||
|
||||
statsParties.appendChild(this.creerBar("1", stats.repartition[1], max));
|
||||
statsParties.appendChild(this.creerBar("2", stats.repartition[2], max));
|
||||
statsParties.appendChild(this.creerBar("3", stats.repartition[3], max));
|
||||
statsParties.appendChild(this.creerBar("4", stats.repartition[4], max));
|
||||
statsParties.appendChild(this.creerBar("5", stats.repartition[5], max));
|
||||
statsParties.appendChild(this.creerBar("6", stats.repartition[6], max));
|
||||
statsParties.appendChild(this.creerBar("-", stats.repartition["-"], max));
|
||||
|
||||
statsArea.appendChild(statsParties);
|
||||
|
||||
const statsNumeriques = document.createElement("div");
|
||||
statsNumeriques.className = "stats-numeriques-area";
|
||||
|
||||
statsNumeriques.appendChild(this.creerStatNumerique("Victoires", stats.partiesGagnees, stats.partiesJouees));
|
||||
statsNumeriques.appendChild(this.creerStatNumerique("Moyenne", this.getMoyenne(stats.repartition)));
|
||||
statsNumeriques.appendChild(this.creerStatNumerique('Lettres <span class="emoji-carre-rouge">🟥</span>', stats.lettresRepartitions.bienPlace));
|
||||
statsNumeriques.appendChild(this.creerStatNumerique('Lettres <span class="emoji-cercle-jaune">🟡</span>', stats.lettresRepartitions.malPlace));
|
||||
statsNumeriques.appendChild(this.creerStatNumerique('Lettres <span class="emoji-carre-bleu">🟦</span>', stats.lettresRepartitions.nonTrouve));
|
||||
|
||||
statsArea.appendChild(statsNumeriques);
|
||||
|
||||
return statsArea;
|
||||
}
|
||||
|
||||
private static creerBar(label: string, valeur: number, max: number): HTMLElement {
|
||||
const ligne = document.createElement("div");
|
||||
ligne.className = "stats-ligne";
|
||||
|
||||
const labelDiv = document.createElement("div");
|
||||
labelDiv.className = "stats-label";
|
||||
labelDiv.innerText = label;
|
||||
ligne.appendChild(labelDiv);
|
||||
|
||||
const barAreaDiv = document.createElement("div");
|
||||
barAreaDiv.className = "stats-bar-area";
|
||||
|
||||
const barDiv = document.createElement("div");
|
||||
barDiv.className = "stats-bar";
|
||||
|
||||
const longueurEnPourcent = Math.round((valeur / max) * 100);
|
||||
if (valeur === max) barDiv.classList.add("bar-max");
|
||||
|
||||
barDiv.style.width = longueurEnPourcent === 0 ? "0px" : `calc(${longueurEnPourcent}% - 2px)`;
|
||||
barAreaDiv.appendChild(barDiv);
|
||||
ligne.appendChild(barAreaDiv);
|
||||
|
||||
const valeurDiv = document.createElement("div");
|
||||
valeurDiv.className = "stats-valeur";
|
||||
valeurDiv.innerText = valeur.toString();
|
||||
ligne.appendChild(valeurDiv);
|
||||
|
||||
return ligne;
|
||||
}
|
||||
|
||||
private static creerStatNumerique(label: string, valeur: number, valeurSecondaire?: number): HTMLElement {
|
||||
const caseDiv = document.createElement("div");
|
||||
caseDiv.className = "stats-numerique-case";
|
||||
|
||||
const valeurDiv = document.createElement("div");
|
||||
valeurDiv.className = "stats-numerique-case-valeur";
|
||||
valeurDiv.innerText = valeur.toLocaleString("fr-FR", { maximumFractionDigits: 2 });
|
||||
caseDiv.appendChild(valeurDiv);
|
||||
|
||||
if (valeurSecondaire !== undefined) {
|
||||
const secondaireDiv = document.createElement("div");
|
||||
secondaireDiv.className = "stats-numerique-case-secondaire";
|
||||
secondaireDiv.innerText = valeurSecondaire.toLocaleString("fr-FR", { maximumFractionDigits: 2 });
|
||||
caseDiv.appendChild(secondaireDiv);
|
||||
}
|
||||
|
||||
const labelDiv = document.createElement("div");
|
||||
labelDiv.className = "stats-numerique-case-label";
|
||||
labelDiv.innerHTML = label;
|
||||
caseDiv.appendChild(labelDiv);
|
||||
|
||||
return caseDiv;
|
||||
}
|
||||
|
||||
private static getMax(repartition: { 1: number; 2: number; 3: number; 4: number; 5: number; 6: number; "-": number }): number {
|
||||
return Math.max(repartition[1], repartition[2], repartition[3], repartition[4], repartition[5], repartition[6], repartition["-"]);
|
||||
}
|
||||
|
||||
private static getMoyenne(repartition: { 1: number; 2: number; 3: number; 4: number; 5: number; 6: number; "-": number }): number {
|
||||
return (
|
||||
(repartition[1] * 1 + repartition[2] * 2 + repartition[3] * 3 + repartition[4] * 4 + repartition[5] * 5 + repartition[6] * 6 + repartition["-"] * 6) /
|
||||
(repartition[1] + repartition[2] + repartition[3] + repartition[4] + repartition[5] + repartition[6] + repartition["-"])
|
||||
);
|
||||
}
|
||||
|
||||
public static genererResumeTexteStatistiques(stats: SauvegardeStats): string {
|
||||
const max = this.getMax(stats.repartition);
|
||||
|
||||
return `🟡 Statistiques de #SUTOM 🟡
|
||||
|
||||
1/6 - ${this.genererBarTexte(stats.repartition[1], max)} ${stats.repartition[1]}
|
||||
2/6 - ${this.genererBarTexte(stats.repartition[2], max)} ${stats.repartition[2]}
|
||||
3/6 - ${this.genererBarTexte(stats.repartition[3], max)} ${stats.repartition[3]}
|
||||
4/6 - ${this.genererBarTexte(stats.repartition[4], max)} ${stats.repartition[4]}
|
||||
5/6 - ${this.genererBarTexte(stats.repartition[5], max)} ${stats.repartition[5]}
|
||||
6/6 - ${this.genererBarTexte(stats.repartition[6], max)} ${stats.repartition[6]}
|
||||
-/6 - ${this.genererBarTexte(stats.repartition["-"], max)} ${stats.repartition["-"]}
|
||||
|
||||
Moy. : ${this.getMoyenne(stats.repartition).toLocaleString("fr-FR", { maximumFractionDigits: 2 })}
|
||||
${stats.lettresRepartitions.bienPlace}🟥- ${stats.lettresRepartitions.malPlace}🟡- ${stats.lettresRepartitions.nonTrouve}🟦`;
|
||||
}
|
||||
|
||||
private static genererBarTexte(valeur: number, max: number): string {
|
||||
if (valeur === 0) return "";
|
||||
|
||||
const caractere = valeur === max ? "🟥" : "🟦";
|
||||
const longueurEnNbChars = Math.round((valeur / max) * 8);
|
||||
|
||||
return longueurEnNbChars === 0 ? caractere : caractere.repeat(longueurEnNbChars);
|
||||
}
|
||||
}
|
|
@ -10,36 +10,49 @@ export default class ThemeManager {
|
|||
const root = document.documentElement;
|
||||
switch (theme) {
|
||||
case Theme.Clair:
|
||||
root.style.setProperty("--couleur-bien-place", "#e7002a");
|
||||
root.style.setProperty("--couleur-mal-place", "#ffbd00");
|
||||
root.style.setProperty("--couleur-fond-rgb", "255, 254, 246");
|
||||
root.style.setProperty("--couleur-police", "#000000");
|
||||
root.style.setProperty("--couleur-bordure", "#000000");
|
||||
root.style.setProperty("--couleur-icone", "rgb(55, 55, 55)");
|
||||
break;
|
||||
case Theme.ClairAccessible:
|
||||
root.style.setProperty("--couleur-bien-place", "#096800");
|
||||
root.style.setProperty("--couleur-mal-place", "#db7c00");
|
||||
root.style.setProperty("--couleur-fond-rgb", "255, 254, 246");
|
||||
root.style.setProperty("--couleur-fond-rgb", "245, 245, 220");
|
||||
root.style.setProperty("--couleur-police", "#000000");
|
||||
root.style.setProperty("--couleur-bordure", "#000000");
|
||||
root.style.setProperty("--couleur-bordure", "rgb(55, 55, 55)");
|
||||
root.style.setProperty("--couleur-icone", "rgb(55, 55, 55)");
|
||||
break;
|
||||
case Theme.SombreAccessible:
|
||||
root.style.setProperty("--couleur-bien-place", "#096800");
|
||||
root.style.setProperty("--couleur-mal-place", "#db7c00");
|
||||
root.style.setProperty("--couleur-fond-rgb", "43, 43, 43");
|
||||
root.style.setProperty("--couleur-police", "#ffffff");
|
||||
root.style.setProperty("--couleur-bordure", "#ffffff");
|
||||
root.style.setProperty("--couleur-icone", "rgb(200, 200, 200)");
|
||||
root.style.setProperty("--couleur-lettre-speciale", "rgb(210, 210, 210)");
|
||||
root.style.setProperty("--couleur-lettre-survole", "rgb(140, 140, 140)");
|
||||
root.style.setProperty("--couleur-lettre-speciale-survole", "rgb(140, 140, 140)");
|
||||
break;
|
||||
default:
|
||||
root.style.setProperty("--couleur-bien-place", "#e7002a");
|
||||
root.style.setProperty("--couleur-mal-place", "#ffbd00");
|
||||
root.style.setProperty("--couleur-fond-rgb", "43, 43, 43");
|
||||
root.style.setProperty("--couleur-police", "#ffffff");
|
||||
root.style.setProperty("--couleur-bordure", "#ffffff");
|
||||
root.style.setProperty("--couleur-bordure", "rgb(200, 200, 200)");
|
||||
root.style.setProperty("--couleur-icone", "rgb(200, 200, 200)");
|
||||
root.style.setProperty("--couleur-lettre-speciale", "rgb(75, 75, 75)");
|
||||
root.style.setProperty("--couleur-lettre-survole", "rgba(75, 75, 75, 0.65)");
|
||||
root.style.setProperty("--couleur-lettre-speciale-survole", "rgba(75, 75, 75, 0.65)");
|
||||
}
|
||||
switch (theme) {
|
||||
case Theme.ClairAccessible:
|
||||
case Theme.SombreAccessible:
|
||||
root.style.setProperty("--couleur-bien-place", "rgb(9, 104, 0)");
|
||||
root.style.setProperty("--couleur-mal-place", "rgb(219, 124, 0)");
|
||||
break;
|
||||
default:
|
||||
root.style.setProperty("--couleur-bien-place", "rgb(231, 0, 42)");
|
||||
root.style.setProperty("--couleur-mal-place", "rgb(255, 189, 0)");
|
||||
}
|
||||
switch (theme) {
|
||||
case Theme.ClairAccessible:
|
||||
root.style.setProperty("--couleur-lettre-survole-bien-place", "rgb(5, 61, 0)");
|
||||
root.style.setProperty("--couleur-lettre-survole-mal-place", "rgb(128, 72, 0)");
|
||||
break;
|
||||
case Theme.SombreAccessible:
|
||||
root.style.setProperty("--couleur-lettre-survole-bien-place", "rgba(9, 104, 0, 0.65)");
|
||||
root.style.setProperty("--couleur-lettre-survole-mal-place", "rgba(219, 124, 0, 0.65)");
|
||||
break;
|
||||
case Theme.Clair:
|
||||
root.style.setProperty("--couleur-lettre-survole-bien-place", "rgb(153, 0, 28)");
|
||||
root.style.setProperty("--couleur-lettre-survole-mal-place", "rgb(153, 112, 0)");
|
||||
default:
|
||||
root.style.setProperty("--couleur-lettre-survole-bien-place", "rgba(231, 0, 42, 0.65)");
|
||||
root.style.setProperty("--couleur-lettre-survole-mal-place", "rgba(255, 189, 0, 0.65)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ function start() {
|
|||
motTrouve =
|
||||
!(motAnalyse[0] === motAnalyse[0].toUpperCase()) &&
|
||||
motAnalyse.length >= 6 &&
|
||||
motAnalyse.length <= 9 &&
|
||||
motAnalyse.length <= 10 &&
|
||||
!motAnalyse.includes("!") &&
|
||||
!motAnalyse.includes(" ") &&
|
||||
!motAnalyse.includes("-") &&
|
||||
|
|
|
@ -85,7 +85,7 @@ fs.readFile("data/motsATrouve.txt", "UTF8", function (erreur, contenu) {
|
|||
(mot) =>
|
||||
mot &&
|
||||
mot.length >= 6 &&
|
||||
mot.length <= 9 &&
|
||||
mot.length <= 10 &&
|
||||
!mot.includes("!") &&
|
||||
!mot.includes(" ") &&
|
||||
!mot.includes("-") &&
|
||||
|
|
|
@ -45,6 +45,7 @@ function ecrireListeNettoyee(dictionnaire) {
|
|||
}
|
||||
|
||||
fs.readFile("data/mots.txt", "UTF8", function (erreur, contenu) {
|
||||
console.log("Chargement de la liste des mots");
|
||||
//console.log(erreur);
|
||||
var dictionnaire = contenu
|
||||
.split("\n")
|
||||
|
@ -60,7 +61,7 @@ fs.readFile("data/mots.txt", "UTF8", function (erreur, contenu) {
|
|||
(mot) =>
|
||||
!(mot[0] === mot[0].toUpperCase()) &&
|
||||
mot.length >= 6 &&
|
||||
mot.length <= 9 &&
|
||||
mot.length <= 10 &&
|
||||
!mot.includes("!") &&
|
||||
!mot.includes(" ") &&
|
||||
!mot.includes("-") &&
|
||||
|
@ -74,6 +75,7 @@ fs.readFile("data/mots.txt", "UTF8", function (erreur, contenu) {
|
|||
.filter(function (elem, index, self) {
|
||||
return index === self.indexOf(elem);
|
||||
});
|
||||
console.log("Tri du dictionnaire");
|
||||
dictionnaire.sort((a, b) => {
|
||||
if (a.length < b.length) return -1;
|
||||
if (a.length > b.length) return 1;
|
||||
|
@ -87,7 +89,7 @@ fs.readFile("data/mots.txt", "UTF8", function (erreur, contenu) {
|
|||
ecrireListeNettoyee(dictionnaire);
|
||||
ecrireDictionnaire(dictionnaire);
|
||||
|
||||
let longueurs = [6, 7, 8, 9];
|
||||
let longueurs = [6, 7, 8, 9, 10];
|
||||
let initialesPossibles = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "L", "M", "N", "O", "P", "R", "S", "T", "U", "V"];
|
||||
for (let longueur of longueurs) {
|
||||
for (let initiale of initialesPossibles) {
|
||||
|
|
|
@ -54,7 +54,7 @@ fs.readFile("data/motsATrouve.txt", "UTF8", function (erreur, contenu) {
|
|||
(mot) =>
|
||||
mot &&
|
||||
mot.length >= 6 &&
|
||||
mot.length <= 9 &&
|
||||
mot.length <= 10 &&
|
||||
!mot.includes("!") &&
|
||||
!mot.includes(" ") &&
|
||||
!mot.includes("-") &&
|
||||
|
|
|
@ -14,12 +14,12 @@ fs.readFile("data/motsATrouve.txt", "UTF8", function (erreur, contenu) {
|
|||
let motClean = mot.normalize("NFD").replace(/\p{Diacritic}/gu, "");
|
||||
let longueur = motClean.length;
|
||||
|
||||
if (lettres[initiale] === undefined) lettres[initiale] = { 6: 0, 7: 0, 8: 0, 9: 0 };
|
||||
if (lettres[initiale] === undefined) lettres[initiale] = { 6: 0, 7: 0, 8: 0, 9: 0, 10: 0 };
|
||||
|
||||
lettres[initiale][longueur.toString()]++;
|
||||
}
|
||||
|
||||
console.log(" | 6 | 7 | 8 | 9 |");
|
||||
console.log(" | 6 | 7 | 8 | 9 | 10 |");
|
||||
for (let lettre in lettres) {
|
||||
let stats = lettres[lettre];
|
||||
console.log(
|
||||
|
@ -32,6 +32,8 @@ fs.readFile("data/motsATrouve.txt", "UTF8", function (erreur, contenu) {
|
|||
stats["8"].toString().padStart(3) +
|
||||
" | " +
|
||||
stats["9"].toString().padStart(3) +
|
||||
" |" +
|
||||
stats["10"].toString().padStart(3) +
|
||||
" |"
|
||||
);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ fs.readFile("data/motsATrouve.txt", "UTF8", function (erreur, contenu) {
|
|||
(mot) =>
|
||||
mot &&
|
||||
mot.length >= 6 &&
|
||||
mot.length <= 9 &&
|
||||
mot.length <= 10 &&
|
||||
!mot.includes("!") &&
|
||||
!mot.includes(" ") &&
|
||||
!mot.includes("-") &&
|
||||
|
|
Loading…
Reference in a new issue