From e9b3a8d313fe769d28d9ffb0365bc7fd1d9df0a9 Mon Sep 17 00:00:00 2001 From: Nils Otterpohl Date: Tue, 4 Jul 2023 22:26:03 +0200 Subject: [PATCH] Very big commit on the way to version 3 backend --- .gitmodules | 12 + .htaccess | 1 + LICENSE | 119 - README.md | 2 - bin/{errors.php => __errors.php} | 0 bin/{navi.php => __navi.php} | 0 bin/__print.php | 63 + bin/exit.php | 5 +- bin/init.php | 79 +- bin/init_new.php | 22 + bin/print.php | 298 +- client/dropzone.min.js | 1 + client/filter.js | 16 + client/index.html | 81 + client/main.css | 247 ++ client/page.js | 399 ++ client/pages/fahrzeuge.js | 119 + client/pages/personal.js | 160 + client/qr-scanner-worker.min.js | 98 + client/qr-scanner-worker.min.js.map | 1 + client/qr-scanner.umd.min.js | 31 + client/qr-scanner.umd.min.js.map | 1 + client/root.js | 367 ++ client/routes/fahrzeuge.js | 119 + client/routes/personal.js | 144 + client/scanner.js | 92 + client/template.js | 271 ++ client/toastify.css | 79 + client/toastify.js | 394 ++ conf/10_mysql.php.dist | 7 + conf/20_redis.php | 4 + conf/30_login.php | 12 + conf/40_time.php | 6 + conf/50_misc.php | 188 + database.png | Bin 0 -> 301509 bytes database_structure.sql | 858 ----- ext/10_BeforeValidException.php | 6 + ext/11_ExpiredException.php | 6 + ext/12_SignatureInvalidException.php | 6 + ext/13_JWT.php | 512 +++ ext/20_PHPMailer.php | 5 + ext/PHPMailer | 1 + ext/php-jwt | 1 + ext/php-qrcode | 1 + ext/php-settings-container | 1 + index.php | 48 +- index_new.php | 15 + lib/00_main.php | 55 +- lib/10_login.php | 543 +-- lib/20_template.php | 31 +- lib/30_pages.php | 300 +- lib/40_PHPMailer.php | 4623 ----------------------- lib/40_email.php | 271 ++ lib/41_SMTP.php | 1347 ------- lib/42_Exception.php | 39 - lib/43_email.php | 192 - lib/50_content.php | 6 +- lib/60_printer.php | 444 +++ lib/99_manager.php | 332 ++ lib_new/10_response.php | 74 + lib_new/20_request.php | 127 + lib_new/21_filter.php | 111 + lib_new/30_database.php | 41 + lib_new/40_keyvalue.php | 38 + lib_new/50_login.php | 276 ++ lib_new/60_resources.php | 411 ++ lib_new/61_links.php | 92 + lib_new/70_routes.php | 161 + lib_new/71_rights.php | 303 ++ lib_new/80_printer.php | 444 +++ lib_new/99_manager.php | 62 + lib_new_bak/60_resources.php | 337 ++ lib_new_bak/61_links.php | 226 ++ links/Anwesenheiten_Einsaetze.php | 17 + links/Anwesenheiten_Personal.php | 20 + links/Anwesenheiten_Termine.php | 17 + links/Fahrzeuge_Einweisungen.php | 17 + links/Personal_Abteilungen.php | 17 + links/Personal_Gruppen.php | 17 + links/Personal_Lehrgaenge.php | 17 + links/Personal_Verwalter.php | 17 + links/Rechte_Verwalter.php | 17 + links/Spinde_Zuordnung.php | 17 + links/__Termine_Teilnahmen.php | 17 + lnk/anwesenheiten_einstze/link.php | 49 + lnk/anwesenheiten_einstze/module.json | 7 + lnk/anwesenheiten_personal/link.php | 52 + lnk/anwesenheiten_personal/module.json | 7 + lnk/anwesenheiten_termine/link.php | 52 + lnk/anwesenheiten_termine/module.json | 7 + lnk/dateien/link.php | 88 + lnk/dateien/module.json | 6 + lnk/fahrzeuge_einweisungen/link.php | 56 + lnk/fahrzeuge_einweisungen/module.json | 7 + lnk/personal_abteilungen/link.php | 56 + lnk/personal_abteilungen/module.json | 7 + lnk/personal_gruppen/link.php | 56 + lnk/personal_gruppen/module.json | 7 + lnk/personal_lehrgaenge/link.php | 56 + lnk/personal_lehrgaenge/module.json | 7 + lnk/prozesse_fortschritte/link.php | 33 + lnk/prozesse_fortschritte/module.json | 8 + lnk/termine_dienstplaene/link.php | 102 + lnk/termine_dienstplaene/module.json | 7 + lnk/termine_teilnahmen/link.php | 197 + lnk/termine_teilnahmen/module.json | 7 + obj/prozesse/module.json | 4 + obj/prozesse/object.php | 578 +++ pgs/10_termine/module.json | 46 + pgs/10_termine/page.php | 347 ++ pgs/10_termine/template.html | 292 ++ pgs/11_dienstplaene/module.json | 19 + pgs/11_dienstplaene/page.php | 149 + pgs/11_dienstplaene/template.html | 93 + pgs/20_personal/module.json | 34 + pgs/20_personal/page.php | 283 ++ pgs/20_personal/template.html | 266 ++ pgs/21_prozesse/module.json | 23 + pgs/21_prozesse/page.php | 30 + pgs/21_prozesse/template.html | 130 + pgs/22_spinde/module.json | 19 + pgs/22_spinde/page.php | 123 + pgs/22_spinde/template.html | 42 + pgs/30_einsaetze/module.json | 46 + pgs/30_einsaetze/page.php | 270 ++ pgs/30_einsaetze/template.html | 260 ++ pgs/40_anwesenheit/module.json | 24 + pgs/40_anwesenheit/page.php | 172 + pgs/40_anwesenheit/template.html | 117 + pgs/50_fahrzeuge/module.json | 19 + pgs/50_fahrzeuge/page.php | 136 + pgs/50_fahrzeuge/template.html | 90 + pgs/admin/admin.html | 121 + pgs/admin/index.php | 144 + pgs/admin/mail.html | 13 + pgs/blog/blog.css | 38 + pgs/blog/blog.html | 42 + pgs/blog/index.php | 105 + pgs/blog/mail.html | 13 + pgs/board/board.css | 71 + pgs/board/categories.html | 19 + pgs/board/index.php | 169 + pgs/board/main.php | 74 + pgs/board/msg.html | 22 + pgs/board/new.html | 43 + pgs/board/new.php | 77 + pgs/board/notify.txt | 12 + pgs/board/thread.html | 10 + pgs/board/thread.php | 41 + pgs/dienste/index.php | 362 -- pgs/dienste/invite_add.js | 9 - pgs/dienste/invite_list.js | 12 - pgs/dienste/invite_rsvp.js | 12 - pgs/dienste/lib.php | 118 - pgs/dienste/main.css | 79 - pgs/dienste/main.html | 69 - pgs/dienste/module.json | 7 - pgs/dienstplaene/index.php | 116 - pgs/dienstplaene/lib.php | 115 - pgs/dienstplaene/main.css | 50 - pgs/dienstplaene/main.html | 72 - pgs/dienstplaene/module.json | 7 - pgs/info/Anfahrtskizze.png | Bin 0 -> 227574 bytes pgs/info/index.php | 8 + pgs/info/info.css | 32 + pgs/info/info.html | 48 + pgs/pics/index.php | 6 + pic.php | 49 + qr.php | 132 + res/dark/active.png | Bin 0 -> 1104 bytes res/dark/add.png | Bin 0 -> 1645 bytes res/dark/alarm.png | Bin 0 -> 1179 bytes res/dark/barcode.png | Bin 0 -> 204 bytes res/{ => dark}/cancel.png | Bin res/{ => dark}/check.png | Bin res/dark/corona.png | Bin 0 -> 1690 bytes res/dark/date.png | Bin 0 -> 368 bytes res/dark/delete.png | Bin 0 -> 327 bytes res/dark/department.png | Bin 0 -> 210 bytes res/{ => dark}/edit.png | Bin res/{hide.png => dark/filter_neg.png} | Bin res/dark/filter_off.png | Bin 0 -> 933 bytes res/{show.png => dark/filter_on.png} | Bin res/dark/group.png | Bin 0 -> 796 bytes res/dark/hide.png | Bin 0 -> 1157 bytes res/dark/list.png | Bin 0 -> 161 bytes res/dark/location.png | Bin 0 -> 992 bytes res/dark/logout.png | Bin 0 -> 378 bytes res/dark/main.css | 184 + res/dark/mechanism.png | Bin 0 -> 823 bytes res/dark/minus.png | Bin 0 -> 1050 bytes res/dark/note.png | Bin 0 -> 549 bytes res/dark/number.png | Bin 0 -> 581 bytes res/dark/person.png | Bin 0 -> 883 bytes res/dark/preview.png | Bin 0 -> 1116 bytes res/dark/print.png | Bin 0 -> 241 bytes res/dark/progress.png | Bin 0 -> 1421 bytes res/dark/refresh.png | Bin 0 -> 1500 bytes res/dark/save.png | Bin 0 -> 282 bytes res/dark/show.png | Bin 0 -> 1133 bytes res/dark/skill.png | Bin 0 -> 1407 bytes res/dark/sort_asc.png | Bin 0 -> 434 bytes res/dark/sort_desc.png | Bin 0 -> 394 bytes res/dark/star.png | Bin 0 -> 1049 bytes res/dark/teacher.png | Bin 0 -> 1204 bytes res/dark/time.png | Bin 0 -> 1187 bytes res/dark/topic.png | Bin 0 -> 464 bytes res/dark/truck.png | Bin 0 -> 583 bytes res/dark/type.png | Bin 0 -> 914 bytes res/dark/unavailable.png | Bin 0 -> 1522 bytes res/{ => dark}/uncheck.png | Bin res/dark/undo.png | Bin 0 -> 1208 bytes res/{ => dark}/warn.png | Bin res/dropzone.min.js | 1 + res/errors.html | 8 - res/frontpage.jpg | Bin res/light/active.png | Bin 0 -> 1104 bytes res/{ => light}/add.png | Bin res/light/cancel.png | Bin 0 -> 1022 bytes res/light/check.png | Bin 0 -> 1195 bytes res/{ => light}/date.png | Bin res/light/delete.png | Bin 0 -> 311 bytes res/light/department.png | Bin 0 -> 206 bytes res/light/edit.png | Bin 0 -> 890 bytes res/{ => light}/group.png | Bin res/light/hide.png | Bin 0 -> 1157 bytes res/{ => light}/location.png | Bin res/light/logout.png | Bin 0 -> 323 bytes res/{ => light}/main.css | 96 +- res/{ => light}/mechanism.png | Bin res/light/note.png | Bin 0 -> 561 bytes res/light/number.png | Bin 0 -> 555 bytes res/light/person.png | Bin 0 -> 789 bytes res/light/progress.png | Bin 0 -> 1543 bytes res/light/save.png | Bin 0 -> 282 bytes res/light/show.png | Bin 0 -> 1133 bytes res/light/star.png | Bin 0 -> 973 bytes res/{ => light}/teacher.png | Bin res/{ => light}/time.png | Bin res/{ => light}/topic.png | Bin res/{ => light}/type.png | Bin res/light/unavailable.png | Bin 0 -> 1522 bytes res/light/uncheck.png | Bin 0 -> 1034 bytes res/light/undo.png | Bin 0 -> 1208 bytes res/light/warn.png | Bin 0 -> 1122 bytes res/loading.gif | Bin 0 -> 112974 bytes res/main.html | 61 +- res/main.js | 940 ++++- res/nav.html | 6 - res/personal/AGT.svg | 63 + res/personal/CU.svg | 1 + res/personal/FS.svg | 53 + res/personal/FU.svg | 115 + res/personal/Funktion.svg | 1 + res/personal/KF.svg | 63 + res/personal/KS2.svg | 61 + res/personal/KSA.svg | 61 + res/personal/KSB.svg | 61 + res/personal/MA.svg | 64 + res/personal/NS.svg | 53 + res/personal/Nopic.svg | 133 + res/personal/RA.svg | 53 + res/personal/RS.svg | 53 + res/personal/TH.svg | 74 + res/personal/TM1.svg | 1 + res/qr-scanner-worker.min.js | 98 + res/qr-scanner-worker.min.js.map | 1 + res/qr-scanner.umd.min.js | 31 + res/qr-scanner.umd.min.js.map | 1 + res/template.js | 271 ++ res/toastify.css | 79 + res/toastify.js | 394 ++ res/truck.png | Bin 491 -> 0 bytes resources/Anwesenheiten/Anwesenheit.php | 25 + resources/Einsaetze/Art.php | 22 + resources/Einsaetze/Einsatz.php | 28 + resources/Einsaetze/Kategorie.php | 20 + resources/Fahrzeuge/Fahrzeug.php | 23 + resources/Lehrgaenge/Lehrgang.php | 21 + resources/Personal/Funktion.php | 25 + resources/Personal/Kategorie.php | 17 + resources/Personal/Personal.php | 43 + resources/Rechte/Recht.php | 21 + resources/Spinde/Raum.php | 18 + resources/Spinde/Spind.php | 30 + resources/Struktur/Abteilung.php | 21 + resources/Struktur/Gruppe.php | 25 + resources/Struktur/Verwalter.php | 23 + resources/Termine/Dienstplan.php | 22 + resources/Termine/Kategorie.php | 25 + resources/Termine/Platzvergabe.php | 31 + resources/Termine/Termin.php | 32 + roadmap.txt | 70 + routes/Personal.php | 38 + subroutes/Fahrzeuge_Personal.php | 35 + subroutes/Files.php | 28 + subroutes/Personal_Abteilungen.php | 35 + subroutes/Personal_Gruppen.php | 35 + subroutes/Personal_Lehrgaenge.php | 35 + subroutes/Personal_Verwalter.php | 35 + var/00_mysql.php.dist | 2 - var/01_redis.php | 6 + var/10_conf.php | 25 +- var/20_img.php | 21 - var/30_errors.php | 4 +- var/40_lang.php | 9 - var/50_pages.php | 10 - var/60_times.php | 2 - var/{70_mail.php.dist => 70_mail.php} | 10 +- wappen48.png | Bin 0 -> 3453 bytes 310 files changed, 17887 insertions(+), 8843 deletions(-) create mode 100644 .gitmodules create mode 100644 .htaccess delete mode 100644 LICENSE delete mode 100644 README.md rename bin/{errors.php => __errors.php} (100%) mode change 100644 => 100755 rename bin/{navi.php => __navi.php} (100%) mode change 100644 => 100755 create mode 100755 bin/__print.php mode change 100644 => 100755 bin/exit.php mode change 100644 => 100755 bin/init.php create mode 100644 bin/init_new.php create mode 100644 client/dropzone.min.js create mode 100644 client/filter.js create mode 100644 client/index.html create mode 100644 client/main.css create mode 100644 client/page.js create mode 100644 client/pages/fahrzeuge.js create mode 100644 client/pages/personal.js create mode 100644 client/qr-scanner-worker.min.js create mode 100644 client/qr-scanner-worker.min.js.map create mode 100644 client/qr-scanner.umd.min.js create mode 100644 client/qr-scanner.umd.min.js.map create mode 100644 client/root.js create mode 100644 client/routes/fahrzeuge.js create mode 100644 client/routes/personal.js create mode 100644 client/scanner.js create mode 100644 client/template.js create mode 100644 client/toastify.css create mode 100644 client/toastify.js create mode 100644 conf/10_mysql.php.dist create mode 100644 conf/20_redis.php create mode 100644 conf/30_login.php create mode 100644 conf/40_time.php create mode 100644 conf/50_misc.php create mode 100755 database.png delete mode 100644 database_structure.sql create mode 100755 ext/10_BeforeValidException.php create mode 100755 ext/11_ExpiredException.php create mode 100755 ext/12_SignatureInvalidException.php create mode 100755 ext/13_JWT.php create mode 100644 ext/20_PHPMailer.php create mode 160000 ext/PHPMailer create mode 160000 ext/php-jwt create mode 160000 ext/php-qrcode create mode 160000 ext/php-settings-container mode change 100644 => 100755 index.php create mode 100644 index_new.php mode change 100644 => 100755 lib/00_main.php mode change 100644 => 100755 lib/20_template.php mode change 100644 => 100755 lib/30_pages.php delete mode 100644 lib/40_PHPMailer.php create mode 100755 lib/40_email.php delete mode 100644 lib/41_SMTP.php delete mode 100644 lib/42_Exception.php delete mode 100644 lib/43_email.php mode change 100644 => 100755 lib/50_content.php create mode 100644 lib/60_printer.php create mode 100755 lib/99_manager.php create mode 100644 lib_new/10_response.php create mode 100644 lib_new/20_request.php create mode 100644 lib_new/21_filter.php create mode 100644 lib_new/30_database.php create mode 100644 lib_new/40_keyvalue.php create mode 100644 lib_new/50_login.php create mode 100644 lib_new/60_resources.php create mode 100644 lib_new/61_links.php create mode 100644 lib_new/70_routes.php create mode 100644 lib_new/71_rights.php create mode 100644 lib_new/80_printer.php create mode 100644 lib_new/99_manager.php create mode 100644 lib_new_bak/60_resources.php create mode 100644 lib_new_bak/61_links.php create mode 100644 links/Anwesenheiten_Einsaetze.php create mode 100644 links/Anwesenheiten_Personal.php create mode 100644 links/Anwesenheiten_Termine.php create mode 100644 links/Fahrzeuge_Einweisungen.php create mode 100644 links/Personal_Abteilungen.php create mode 100644 links/Personal_Gruppen.php create mode 100644 links/Personal_Lehrgaenge.php create mode 100644 links/Personal_Verwalter.php create mode 100644 links/Rechte_Verwalter.php create mode 100644 links/Spinde_Zuordnung.php create mode 100644 links/__Termine_Teilnahmen.php create mode 100644 lnk/anwesenheiten_einstze/link.php create mode 100644 lnk/anwesenheiten_einstze/module.json create mode 100755 lnk/anwesenheiten_personal/link.php create mode 100755 lnk/anwesenheiten_personal/module.json create mode 100644 lnk/anwesenheiten_termine/link.php create mode 100644 lnk/anwesenheiten_termine/module.json create mode 100755 lnk/dateien/link.php create mode 100755 lnk/dateien/module.json create mode 100644 lnk/fahrzeuge_einweisungen/link.php create mode 100644 lnk/fahrzeuge_einweisungen/module.json create mode 100644 lnk/personal_abteilungen/link.php create mode 100644 lnk/personal_abteilungen/module.json create mode 100755 lnk/personal_gruppen/link.php create mode 100755 lnk/personal_gruppen/module.json create mode 100755 lnk/personal_lehrgaenge/link.php create mode 100755 lnk/personal_lehrgaenge/module.json create mode 100644 lnk/prozesse_fortschritte/link.php create mode 100644 lnk/prozesse_fortschritte/module.json create mode 100644 lnk/termine_dienstplaene/link.php create mode 100644 lnk/termine_dienstplaene/module.json create mode 100755 lnk/termine_teilnahmen/link.php create mode 100755 lnk/termine_teilnahmen/module.json create mode 100644 obj/prozesse/module.json create mode 100644 obj/prozesse/object.php create mode 100755 pgs/10_termine/module.json create mode 100755 pgs/10_termine/page.php create mode 100755 pgs/10_termine/template.html create mode 100644 pgs/11_dienstplaene/module.json create mode 100644 pgs/11_dienstplaene/page.php create mode 100644 pgs/11_dienstplaene/template.html create mode 100755 pgs/20_personal/module.json create mode 100755 pgs/20_personal/page.php create mode 100755 pgs/20_personal/template.html create mode 100755 pgs/21_prozesse/module.json create mode 100755 pgs/21_prozesse/page.php create mode 100755 pgs/21_prozesse/template.html create mode 100644 pgs/22_spinde/module.json create mode 100644 pgs/22_spinde/page.php create mode 100644 pgs/22_spinde/template.html create mode 100644 pgs/30_einsaetze/module.json create mode 100644 pgs/30_einsaetze/page.php create mode 100644 pgs/30_einsaetze/template.html create mode 100644 pgs/40_anwesenheit/module.json create mode 100644 pgs/40_anwesenheit/page.php create mode 100644 pgs/40_anwesenheit/template.html create mode 100644 pgs/50_fahrzeuge/module.json create mode 100644 pgs/50_fahrzeuge/page.php create mode 100644 pgs/50_fahrzeuge/template.html create mode 100755 pgs/admin/admin.html create mode 100755 pgs/admin/index.php create mode 100755 pgs/admin/mail.html create mode 100755 pgs/blog/blog.css create mode 100755 pgs/blog/blog.html create mode 100755 pgs/blog/index.php create mode 100755 pgs/blog/mail.html create mode 100755 pgs/board/board.css create mode 100755 pgs/board/categories.html create mode 100755 pgs/board/index.php create mode 100755 pgs/board/main.php create mode 100755 pgs/board/msg.html create mode 100755 pgs/board/new.html create mode 100755 pgs/board/new.php create mode 100755 pgs/board/notify.txt create mode 100755 pgs/board/thread.html create mode 100755 pgs/board/thread.php delete mode 100644 pgs/dienste/index.php delete mode 100644 pgs/dienste/invite_add.js delete mode 100644 pgs/dienste/invite_list.js delete mode 100644 pgs/dienste/invite_rsvp.js delete mode 100644 pgs/dienste/lib.php delete mode 100644 pgs/dienste/main.css delete mode 100644 pgs/dienste/main.html delete mode 100644 pgs/dienste/module.json delete mode 100644 pgs/dienstplaene/index.php delete mode 100644 pgs/dienstplaene/lib.php delete mode 100644 pgs/dienstplaene/main.css delete mode 100644 pgs/dienstplaene/main.html delete mode 100644 pgs/dienstplaene/module.json create mode 100755 pgs/info/Anfahrtskizze.png create mode 100755 pgs/info/index.php create mode 100755 pgs/info/info.css create mode 100755 pgs/info/info.html create mode 100755 pgs/pics/index.php create mode 100644 pic.php create mode 100644 qr.php create mode 100755 res/dark/active.png create mode 100755 res/dark/add.png create mode 100644 res/dark/alarm.png create mode 100644 res/dark/barcode.png rename res/{ => dark}/cancel.png (100%) mode change 100644 => 100755 rename res/{ => dark}/check.png (100%) mode change 100644 => 100755 create mode 100755 res/dark/corona.png create mode 100755 res/dark/date.png create mode 100755 res/dark/delete.png create mode 100755 res/dark/department.png rename res/{ => dark}/edit.png (100%) mode change 100644 => 100755 rename res/{hide.png => dark/filter_neg.png} (100%) mode change 100644 => 100755 create mode 100755 res/dark/filter_off.png rename res/{show.png => dark/filter_on.png} (100%) mode change 100644 => 100755 create mode 100755 res/dark/group.png create mode 100755 res/dark/hide.png create mode 100644 res/dark/list.png create mode 100755 res/dark/location.png create mode 100644 res/dark/logout.png create mode 100755 res/dark/main.css create mode 100755 res/dark/mechanism.png create mode 100644 res/dark/minus.png create mode 100755 res/dark/note.png create mode 100644 res/dark/number.png create mode 100755 res/dark/person.png create mode 100755 res/dark/preview.png create mode 100755 res/dark/print.png create mode 100755 res/dark/progress.png create mode 100755 res/dark/refresh.png create mode 100755 res/dark/save.png create mode 100755 res/dark/show.png create mode 100755 res/dark/skill.png create mode 100755 res/dark/sort_asc.png create mode 100755 res/dark/sort_desc.png create mode 100755 res/dark/star.png create mode 100755 res/dark/teacher.png create mode 100755 res/dark/time.png create mode 100755 res/dark/topic.png create mode 100755 res/dark/truck.png create mode 100755 res/dark/type.png create mode 100755 res/dark/unavailable.png rename res/{ => dark}/uncheck.png (100%) mode change 100644 => 100755 create mode 100755 res/dark/undo.png rename res/{ => dark}/warn.png (100%) mode change 100644 => 100755 create mode 100755 res/dropzone.min.js delete mode 100644 res/errors.html mode change 100644 => 100755 res/frontpage.jpg create mode 100755 res/light/active.png rename res/{ => light}/add.png (100%) mode change 100644 => 100755 create mode 100755 res/light/cancel.png create mode 100755 res/light/check.png rename res/{ => light}/date.png (100%) mode change 100644 => 100755 create mode 100755 res/light/delete.png create mode 100755 res/light/department.png create mode 100755 res/light/edit.png rename res/{ => light}/group.png (100%) mode change 100644 => 100755 create mode 100755 res/light/hide.png rename res/{ => light}/location.png (100%) mode change 100644 => 100755 create mode 100644 res/light/logout.png rename res/{ => light}/main.css (63%) mode change 100644 => 100755 rename res/{ => light}/mechanism.png (100%) mode change 100644 => 100755 create mode 100755 res/light/note.png create mode 100644 res/light/number.png create mode 100755 res/light/person.png create mode 100755 res/light/progress.png create mode 100755 res/light/save.png create mode 100755 res/light/show.png create mode 100755 res/light/star.png rename res/{ => light}/teacher.png (100%) mode change 100644 => 100755 rename res/{ => light}/time.png (100%) mode change 100644 => 100755 rename res/{ => light}/topic.png (100%) mode change 100644 => 100755 rename res/{ => light}/type.png (100%) mode change 100644 => 100755 create mode 100755 res/light/unavailable.png create mode 100755 res/light/uncheck.png create mode 100755 res/light/undo.png create mode 100755 res/light/warn.png create mode 100644 res/loading.gif mode change 100644 => 100755 res/main.html mode change 100644 => 100755 res/main.js delete mode 100644 res/nav.html create mode 100755 res/personal/AGT.svg create mode 100755 res/personal/CU.svg create mode 100755 res/personal/FS.svg create mode 100755 res/personal/FU.svg create mode 100755 res/personal/Funktion.svg create mode 100755 res/personal/KF.svg create mode 100755 res/personal/KS2.svg create mode 100755 res/personal/KSA.svg create mode 100755 res/personal/KSB.svg create mode 100755 res/personal/MA.svg create mode 100755 res/personal/NS.svg create mode 100755 res/personal/Nopic.svg create mode 100755 res/personal/RA.svg create mode 100755 res/personal/RS.svg create mode 100755 res/personal/TH.svg create mode 100755 res/personal/TM1.svg create mode 100644 res/qr-scanner-worker.min.js create mode 100644 res/qr-scanner-worker.min.js.map create mode 100644 res/qr-scanner.umd.min.js create mode 100644 res/qr-scanner.umd.min.js.map create mode 100755 res/template.js create mode 100755 res/toastify.css create mode 100755 res/toastify.js delete mode 100644 res/truck.png create mode 100644 resources/Anwesenheiten/Anwesenheit.php create mode 100644 resources/Einsaetze/Art.php create mode 100644 resources/Einsaetze/Einsatz.php create mode 100644 resources/Einsaetze/Kategorie.php create mode 100644 resources/Fahrzeuge/Fahrzeug.php create mode 100644 resources/Lehrgaenge/Lehrgang.php create mode 100644 resources/Personal/Funktion.php create mode 100644 resources/Personal/Kategorie.php create mode 100644 resources/Personal/Personal.php create mode 100644 resources/Rechte/Recht.php create mode 100644 resources/Spinde/Raum.php create mode 100644 resources/Spinde/Spind.php create mode 100644 resources/Struktur/Abteilung.php create mode 100644 resources/Struktur/Gruppe.php create mode 100644 resources/Struktur/Verwalter.php create mode 100644 resources/Termine/Dienstplan.php create mode 100644 resources/Termine/Kategorie.php create mode 100644 resources/Termine/Platzvergabe.php create mode 100644 resources/Termine/Termin.php create mode 100755 roadmap.txt create mode 100644 routes/Personal.php create mode 100644 subroutes/Fahrzeuge_Personal.php create mode 100644 subroutes/Files.php create mode 100644 subroutes/Personal_Abteilungen.php create mode 100644 subroutes/Personal_Gruppen.php create mode 100644 subroutes/Personal_Lehrgaenge.php create mode 100644 subroutes/Personal_Verwalter.php mode change 100644 => 100755 var/00_mysql.php.dist create mode 100755 var/01_redis.php mode change 100644 => 100755 var/10_conf.php delete mode 100644 var/20_img.php mode change 100644 => 100755 var/30_errors.php delete mode 100644 var/40_lang.php delete mode 100644 var/50_pages.php mode change 100644 => 100755 var/60_times.php rename var/{70_mail.php.dist => 70_mail.php} (64%) mode change 100644 => 100755 create mode 100755 wappen48.png diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..5b835a2 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,12 @@ +[submodule "ext/PHPMailer"] + path = ext/PHPMailer + url = https://github.com/PHPMailer/PHPMailer.git +[submodule "ext/php-jwt"] + path = ext/php-jwt + url = https://github.com/firebase/php-jwt.git +[submodule "ext/php-qrcode"] + path = ext/php-qrcode + url = https://github.com/chillerlan/php-qrcode +[submodule "ext/php-settings-container"] + path = ext/php-settings-container + url = https://github.com/chillerlan/php-settings-container.git diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..17df4ee --- /dev/null +++ b/.htaccess @@ -0,0 +1 @@ +CGIPassAuth On diff --git a/LICENSE b/LICENSE deleted file mode 100644 index a343ccd..0000000 --- a/LICENSE +++ /dev/null @@ -1,119 +0,0 @@ -Creative Commons Legal Code - -CC0 1.0 Universal CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES -NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE -AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION -ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE -OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS -LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION -OR WORKS PROVIDED HEREUNDER. - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer exclusive -Copyright and Related Rights (defined below) upon the creator and subsequent -owner(s) (each and all, an "owner") of an original work of authorship and/or -a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the -purpose of contributing to a commons of creative, cultural and scientific -works ("Commons") that the public can reliably and without fear of later claims -of infringement build upon, modify, incorporate in other works, reuse and -redistribute as freely as possible in any form whatsoever and for any purposes, -including without limitation commercial purposes. These owners may contribute -to the Commons to promote the ideal of a free culture and the further production -of creative, cultural and scientific works, or to gain reputation or greater -distribution for their Work in part through the use and efforts of others. - -For these and/or other purposes and motivations, and without any expectation -of additional consideration or compensation, the person associating CC0 with -a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright -and Related Rights in the Work, voluntarily elects to apply CC0 to the Work -and publicly distribute the Work under its terms, with knowledge of his or -her Copyright and Related Rights in the Work and the meaning and intended -legal effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be protected -by copyright and related or neighboring rights ("Copyright and Related Rights"). -Copyright and Related Rights include, but are not limited to, the following: - -i. the right to reproduce, adapt, distribute, perform, display, communicate, -and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - -iii. publicity and privacy rights pertaining to a person's image or likeness -depicted in a Work; - -iv. rights protecting against unfair competition in regards to a Work, subject -to the limitations in paragraph 4(a), below; - -v. rights protecting the extraction, dissemination, use and reuse of data -in a Work; - -vi. database rights (such as those arising under Directive 96/9/EC of the -European Parliament and of the Council of 11 March 1996 on the legal protection -of databases, and under any national implementation thereof, including any -amended or successor version of such directive); and - -vii. other similar, equivalent or corresponding rights throughout the world -based on applicable law or treaty, and any national implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention of, -applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and -unconditionally waives, abandons, and surrenders all of Affirmer's Copyright -and Related Rights and associated claims and causes of action, whether now -known or unknown (including existing as well as future claims and causes of -action), in the Work (i) in all territories worldwide, (ii) for the maximum -duration provided by applicable law or treaty (including future time extensions), -(iii) in any current or future medium and for any number of copies, and (iv) -for any purpose whatsoever, including without limitation commercial, advertising -or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the -benefit of each member of the public at large and to the detriment of Affirmer's -heirs and successors, fully intending that such Waiver shall not be subject -to revocation, rescission, cancellation, termination, or any other legal or -equitable action to disrupt the quiet enjoyment of the Work by the public -as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason be -judged legally invalid or ineffective under applicable law, then the Waiver -shall be preserved to the maximum extent permitted taking into account Affirmer's -express Statement of Purpose. In addition, to the extent the Waiver is so -judged Affirmer hereby grants to each affected person a royalty-free, non -transferable, non sublicensable, non exclusive, irrevocable and unconditional -license to exercise Affirmer's Copyright and Related Rights in the Work (i) -in all territories worldwide, (ii) for the maximum duration provided by applicable -law or treaty (including future time extensions), (iii) in any current or -future medium and for any number of copies, and (iv) for any purpose whatsoever, -including without limitation commercial, advertising or promotional purposes -(the "License"). The License shall be deemed effective as of the date CC0 -was applied by Affirmer to the Work. Should any part of the License for any -reason be judged legally invalid or ineffective under applicable law, such -partial invalidity or ineffectiveness shall not invalidate the remainder of -the License, and in such case Affirmer hereby affirms that he or she will -not (i) exercise any of his or her remaining Copyright and Related Rights -in the Work or (ii) assert any associated claims and causes of action with -respect to the Work, in either case contrary to Affirmer's express Statement -of Purpose. - - 4. Limitations and Disclaimers. - -a. No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, -licensed or otherwise affected by this document. - -b. Affirmer offers the Work as-is and makes no representations or warranties -of any kind concerning the Work, express, implied, statutory or otherwise, -including without limitation warranties of title, merchantability, fitness -for a particular purpose, non infringement, or the absence of latent or other -defects, accuracy, or the present or absence of errors, whether or not discoverable, -all to the greatest extent permissible under applicable law. - -c. Affirmer disclaims responsibility for clearing rights of other persons -that may apply to the Work or any use thereof, including without limitation -any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims -responsibility for obtaining any necessary consents, permissions or other -rights required for any use of the Work. - -d. Affirmer understands and acknowledges that Creative Commons is not a party -to this document and has no duty or obligation with respect to this CC0 or -use of the Work. diff --git a/README.md b/README.md deleted file mode 100644 index 5d5681f..0000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# App - diff --git a/bin/errors.php b/bin/__errors.php old mode 100644 new mode 100755 similarity index 100% rename from bin/errors.php rename to bin/__errors.php diff --git a/bin/navi.php b/bin/__navi.php old mode 100644 new mode 100755 similarity index 100% rename from bin/navi.php rename to bin/__navi.php diff --git a/bin/__print.php b/bin/__print.php new file mode 100755 index 0000000..b03e95b --- /dev/null +++ b/bin/__print.php @@ -0,0 +1,63 @@ + $value) { + $gets.= ($gets=="" ? "?" : "&").$key."=".$value; + } + $output["stat"] = tplReplMarker($output["stat"], "###PAGEGET###", $gets); +} elseif ($output["showlogin"]=="off") { + //$tpllgn = tplExtrSection($output["stat"], "###LOGOFF###"); + $output["stat"] = tplReplSection($output["stat"], "###LOGIN###", ""); +} + +foreach ($lang as $key => $value) { + $output["stat"] = tplReplMarker($output["stat"], $key, $value[$user["address.plural"]]); +} + +$output["stat"] = tplReplMarker($output["stat"], "###SECTOKEN###", $_SESSION["secTokenUse"]); + +//Print page +echo $output["stat"]; + + +?> \ No newline at end of file diff --git a/bin/exit.php b/bin/exit.php old mode 100644 new mode 100755 index ea56bed..4b7a14c --- a/bin/exit.php +++ b/bin/exit.php @@ -1,5 +1,4 @@ close(); - -?> \ No newline at end of file +$mysqli->close(); +$redis->close(); diff --git a/bin/init.php b/bin/init.php old mode 100644 new mode 100755 index ee8821f..6f12814 --- a/bin/init.php +++ b/bin/init.php @@ -1,70 +1,25 @@ $value) { - $ret[$key] = is_array($value) ? cleanInput($value) : (is_string($value) ? SS($value) : SI($value)); - } - return $ret; -} -$input = cleanInput($_REQUEST); - -//Check login attempt -if (isset($input["login"],$input["pass"],$input["submit"]) && $input["secToken"]==$_SESSION["secTokenVerify"]) -{ - //Login attempt - if (!lgnLogin($mysqli, $input["login"], $input["pass"])) - { - addError("Login Failed: ", $mysqli->error); - } -} - -//Init main variables -//array $page = (string main, string sub, array css = [strings], array js = [strings]) -//array $output = (string stat, string navi, string main) -//array $temp = (EMPTY) - can be used for temporary variables -$page = array -( - "main" => "", - "sub" => "" -); -$output = array -( - "stat" => tplLoadFile(FRAMETPL), //Load Mainframe - "main" => "", - "navi" => "", - "error" => "", - "css" => array(), - "js" => array(), - "showlogin" => "in" -); -addStyle(FRAMECSS, FRAMECSS!=""); -addJScript(FRAMEJS, FRAMEJS!=""); -$temp = array(); -$user = array( - "address.plural" => 1 -); - -if (isset($input["userMod"]) && $input["userMod"]=="Ausloggen") -{ - lgnLogout(); -} - -?> \ No newline at end of file +// Authenticate user and prepare input/output +$man = new Manager($mysqli, $redis, JWT_KEY); diff --git a/bin/init_new.php b/bin/init_new.php new file mode 100644 index 0000000..89280c9 --- /dev/null +++ b/bin/init_new.php @@ -0,0 +1,22 @@ + $value) { - $gets.= ($gets=="" ? "?" : "&").$key."=".$value; + $ret = ""; + if (array_key_exists($key, $content)) { + if ($getText && isset($options[$key])) { + if (is_array($content[$key])) { + $ret = array(); + foreach ($options[$key] as $option) { + if (in_array($option["value"], $content[$key])) { + $ret[] = $option["display"]; + } + } + } else { + foreach ($options[$key] as $option) { + $ret = " "; + if ($option["value"]==$content[$key]) { + $ret = $option["display"]; + break; + } + } + } + } else { + $ret = $content[$key]; + } + } else if (isset($data[$key])) { + if (isset($data[$key]["default"]) && $data[$key]["default"]!="") { + $ret = $data[$key]["default"]; + } else if ($demoMode) { + $ret = $data[$key]["title"]; + } + } else if (isset($links[$key])) { + $ret = array(); + } else if (isset($refs[$key])) { + $ret = array(); + } else { + $ret = $key; } - $output["stat"] = tplReplMarker($output["stat"], "###PAGEGET###", $gets); -} elseif ($output["showlogin"]=="off") { - //$tpllgn = tplExtrSection($output["stat"], "###LOGOFF###"); - $output["stat"] = tplReplSection($output["stat"], "###LOGIN###", ""); + + if (isset($data[$key]["prefix"]) && !is_array($ret)) { + $ret = $data[$key]["prefix"].$ret; + } + if (isset($data[$key]["postfix"]) && !is_array($ret)) { + $ret.= $data[$key]["postfix"]; + } + + return $ret; } -foreach ($lang as $key => $value) { - $output["stat"] = tplReplMarker($output["stat"], $key, $value[$user["address.plural"]]); +function moveIfOverlap(&$floating, &$left, &$top, $width, $height, $dir = "none", $lastdir = "none") { + $moved = false; + foreach ($floating as $key => $float) { + if ( + $left < $float["right"] && + $left+$width > $float["left"] && + $top < $float["bottom"] && + $top+$height > $float["top"] + ) { + if ($float["dir"]=="left" && $lastdir!="right") { + $left = $float["right"]; + } else if ($float["dir"]=="right" && $lastdir!="left") { + $left = $float["left"] - $width; + } else if ($float["dir"]=="up" && $lastdir!="down") { + $top = $float["bottom"]; + } else if ($float["dir"]=="down" && $lastdir!="up") { + $top = $float["top"] - $height; + } + $lastdir = $float["dir"]; + $moved = true; + } + } + if ($moved) { + moveIfOverlap($floating, $left, $top, $width, $height, $dir, $lastdir); + } else if ($dir!="none") { + $floating[] = array( + "left" => $left, + "right" => $left + $width, + "top" => $top, + "bottom" => $top + $height, + "dir" => $dir + ); + } } -$output["stat"] = tplReplMarker($output["stat"], "###SECTOKEN###", $_SESSION["secTokenUse"]); +if (lgnCheckLogin($mysqli) && isset($_POST["page"], $_POST["layout"]) && $_POST["layout"]!="") { + $page = $_POST["page"]; + $data = $_POST["data"]; + $links = $_POST["links"] ?? array(); + $refs = $_POST["refs"] ?? array(); + $options = $_POST["options"]; -//Print page -echo $output["stat"]; + $content = array(); + $id = null; + if (isset($_POST["ID"]) && $_POST["ID"]!="") { + $id = $_POST["ID"]; + $cntRow = cntGetRow($mysqli, $page, $id, $links, $refs); + $content = $cntRow["erg"]; + if ($cntRow["err"]!="") { + echo "
".$cntRow["err"]."
"; + } + } + $res = $mysqli->query("select * from print_layouts where ID='".$_POST["layout"]."'"); + $layout = $res->fetch_assoc(); + $floating = array(); + echo "
"; + + $res = $mysqli->query("select * from print_elements where key_layout_ID='".$layout["ID"]."' order by ord asc"); + while ($row = $res->fetch_assoc()) { + $do_print = false; + $cond = explode("|", $row["cond"]); + if ($row["params"]=="") { + $row["params"] = "{}"; + } + $params = json_decode($row["params"], true); + switch ($cond[0]) { + case null: + case "": + case "0": //Print always + $do_print = true; + break; + case "1": //Field has to be NOT null and not empty text + if (sizeof($cond)>1 && (getContent($cond[1])!=null && getContent($cond[1], true)!="")) + $do_print = true; + break; + case "2": //Field has to be null or empty text + if (sizeof($cond)>1 && (getContent($cond[1])==null || getContent($cond[1], true)=="")) + $do_print = true; + break; + case "3": //Field has to be value (second parameter) or include value if is link + if (sizeof($cond)>2 && ((array_key_exists($cond[1], $links) && in_array($cond[2], getContent($cond[1]))) || (getContent($cond[1])==$cond[2]))) + $do_print = true; + break; + case "4": //Field has to be NOT value (second parameter) or DONT include value if is link + if (sizeof($cond)>2 && ((array_key_exists($cond[1], $links) && !in_array($cond[2], getContent($cond[1]))) && (getContent($cond[1])!=$cond[2]))) + $do_print = true; + break; + case "5": //Field has to be text (second parameter) or include text if it is link + if (sizeof($cond)>2 && ((array_key_exists($cond[1], $links) && in_array($cond[2], getContent($cond[1], true))) || (getContent($cond[1], true)==$cond[2]))) + $do_print = true; + break; + case "6": //Field has to be NOT text (second parameter) or DONT include text if it is link + if (sizeof($cond)>2 && ((array_key_exists($cond[1], $links) && !in_array($cond[2], getContent($cond[1], true))) && (getContent($cond[1], true)!=$cond[2]))) + $do_print = true; + break; + } + if ($id===null) {//Demo mode + $do_print = true; + } + $print_count = 0; + if ($do_print) { + $print_count = $params["repeat"] ?? 1; + } + + while ($print_count>0) { + $print_count--; + $border = array(); + $border["top"] = isset($params["border-top"]) ? $params["border-top"] : (isset($params["border"]) ? $params["border"] : "0"); + $border["bottom"] = isset($params["border-bottom"]) ? $params["border-bottom"] : (isset($params["border"]) ? $params["border"] : "0"); + $border["left"] = isset($params["border-left"]) ? $params["border-left"] : (isset($params["border"]) ? $params["border"] : "0"); + $border["right"] = isset($params["border-right"]) ? $params["border-right"] : (isset($params["border"]) ? $params["border"] : "0"); + $border["color"] = isset($params["border-color"]) ? $params["border-color"] : "#000000"; + $border["string"] = ""; + if ($border["left"]!="0") { + $border["string"].= "border-left: 1px solid ".$border["color"]."; "; + } + if ($border["right"]!="0") { + $border["string"].= "border-right: 1px solid ".$border["color"]."; "; + } + if ($border["top"]!="0") { + $border["string"].= "border-top: 1px solid ".$border["color"]."; "; + } + if ($border["bottom"]!="0") { + $border["string"].= "border-bottom: 1px solid ".$border["color"]."; "; + } + + $cnt = $row["content"]; + $fields = array(); + if (preg_match_all("/#([^#]+)#/", $cnt, $matches, PREG_SET_ORDER)) { + foreach ($matches as $match) { + $replace = ""; + $fields[] = $match[1]; + if (array_key_exists($match[1], $links)) { + $replace = implode(", ", getContent($match[1], true, $id===null)); + } else if (array_key_exists($match[1], $data)) { + $replace = getContent($match[1], true, $id===null); + } else { + foreach ($data as $key => $val) { + if ($val["group"]==$match[1]) { + $replace.=getContent($key, true, $id===null); + } + } + } + $cnt = str_replace("#".$match[1]."#", $replace, $cnt); + } + } + + $left = $row["posl"]; + $top = $row["post"]; + $width = $row["dimw"]; + if ($width == 0) { + $width = 10; + } + $height = $row["dimh"]; + if ($height == 0) { + $height = 10; + } + moveIfOverlap($floating, $left, $top, $width, $height, isset($params["float"]) ? $params["float"] : "none"); + + switch ($row["type"]) { + case "img": + if (isset($params["aspect"]) && $params["aspect"]=="keep") { + $imgsize = "max-width: ".$width."mm; max-height: ".$height."mm; width: auto; height: auto; "; + } + if (isset($params["aspect"]) && $params["aspect"]=="height") { + $imgsize = "height: ".$height."mm; width: auto; "; + } else { + $imgsize = "width: ".$width."mm; height: ".$height."mm; "; + } + $path = $cnt; + if (count($fields)) { + $path = "uploads/".$page."/".$fields[0]."/".$cnt; + } + if (file_exists("../".$path)) { + echo ""; + } + break; + case "text": + $rotate = ""; + if (isset($params["rotate"]) && $params["rotate"]=="1") { + $rotate = "transform: rotate(-90deg); "; + $left = "calc(".($left + ($height - $width)/2)."mm - ".$border["left"]."px); "; + $top = "calc(".($top + ($width - $height)/2)."mm - ".$border["top"]."px); "; + } else { + $left.= "mm; "; + $top.= "mm; "; + } + $font = "font-family: ".(isset($params["font"]) && $params["font"]=="narrow" ? "Calibri, Carlito, Arial Narrow, Liberation Sans Narrow, Arial, Liberation Sans; " : "Arial, Liberation Sans; "); + $font.= "font-size: ".(isset($params["size"]) ? $params["size"] : $height)."mm; "; + if (isset($params["weight"])) { + $font.= "font-weight: ".$params["weight"]."; "; + } + if (isset($params["align"])) { + $font.= "text-align: ".$params["align"]."; "; + } + echo "".$cnt.""; + break; + } + } + } + echo "
"; +} ?> \ No newline at end of file diff --git a/client/dropzone.min.js b/client/dropzone.min.js new file mode 100644 index 0000000..a4d6480 --- /dev/null +++ b/client/dropzone.min.js @@ -0,0 +1 @@ +"use strict";function _typeof(e){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function _possibleConstructorReturn(e,t){return!t||"object"!==_typeof(t)&&"function"!=typeof t?_assertThisInitialized(e):t}function _getPrototypeOf(e){return(_getPrototypeOf=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function _assertThisInitialized(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&_setPrototypeOf(e,t)}function _setPrototypeOf(e,t){return(_setPrototypeOf=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,t){for(var n=0;n'),this.element.appendChild(e));var l=e.getElementsByTagName("span")[0];return l&&(null!=l.textContent?l.textContent=this.options.dictFallbackMessage:null!=l.innerText&&(l.innerText=this.options.dictFallbackMessage)),this.element.appendChild(this.getFallbackForm())},resize:function(e,t,n,i){var r={srcX:0,srcY:0,srcWidth:e.width,srcHeight:e.height},o=e.width/e.height;null==t&&null==n?(t=r.srcWidth,n=r.srcHeight):null==t?t=n*o:null==n&&(n=t/o);var a=(t=Math.min(t,r.srcWidth))/(n=Math.min(n,r.srcHeight));if(r.srcWidth>t||r.srcHeight>n)if("crop"===i)a\n
\n
\n
\n
\n
\n
\n
\n
\n \n Check\n \n \n \n \n
\n
\n \n Error\n \n \n \n \n \n \n
\n',drop:function(){return this.element.classList.remove("dz-drag-hover")},dragstart:function(){},dragend:function(){return this.element.classList.remove("dz-drag-hover")},dragenter:function(){return this.element.classList.add("dz-drag-hover")},dragover:function(){return this.element.classList.add("dz-drag-hover")},dragleave:function(){return this.element.classList.remove("dz-drag-hover")},paste:function(){},reset:function(){return this.element.classList.remove("dz-started")},addedfile:function(t){var n=this;if(this.element===this.previewsContainer&&this.element.classList.add("dz-started"),this.previewsContainer){t.previewElement=C.createElement(this.options.previewTemplate.trim()),t.previewTemplate=t.previewElement,this.previewsContainer.appendChild(t.previewElement);var e=!0,i=!1,r=void 0;try{for(var o,a=t.previewElement.querySelectorAll("[data-dz-name]")[Symbol.iterator]();!(e=(o=a.next()).done);e=!0){var l=o.value;l.textContent=t.name}}catch(e){i=!0,r=e}finally{try{e||null==a.return||a.return()}finally{if(i)throw r}}var s=!0,u=!1,c=void 0;try{for(var d,p=t.previewElement.querySelectorAll("[data-dz-size]")[Symbol.iterator]();!(s=(d=p.next()).done);s=!0)(l=d.value).innerHTML=this.filesize(t.size)}catch(e){u=!0,c=e}finally{try{s||null==p.return||p.return()}finally{if(u)throw c}}this.options.addRemoveLinks&&(t._removeLink=C.createElement(''.concat(this.options.dictRemoveFile,"")),t.previewElement.appendChild(t._removeLink));var h=function(e){return e.preventDefault(),e.stopPropagation(),t.status===C.UPLOADING?C.confirm(n.options.dictCancelUploadConfirmation,function(){return n.removeFile(t)}):n.options.dictRemoveFileConfirmation?C.confirm(n.options.dictRemoveFileConfirmation,function(){return n.removeFile(t)}):n.removeFile(t)},f=!0,v=!1,m=void 0;try{for(var y,g=t.previewElement.querySelectorAll("[data-dz-remove]")[Symbol.iterator]();!(f=(y=g.next()).done);f=!0){y.value.addEventListener("click",h)}}catch(e){v=!0,m=e}finally{try{f||null==g.return||g.return()}finally{if(v)throw m}}}},removedfile:function(e){return null!=e.previewElement&&null!=e.previewElement.parentNode&&e.previewElement.parentNode.removeChild(e.previewElement),this._updateMaxFilesReachedClass()},thumbnail:function(e,t){if(e.previewElement){e.previewElement.classList.remove("dz-file-preview");var n=!0,i=!1,r=void 0;try{for(var o,a=e.previewElement.querySelectorAll("[data-dz-thumbnail]")[Symbol.iterator]();!(n=(o=a.next()).done);n=!0){var l=o.value;l.alt=e.name,l.src=t}}catch(e){i=!0,r=e}finally{try{n||null==a.return||a.return()}finally{if(i)throw r}}return setTimeout(function(){return e.previewElement.classList.add("dz-image-preview")},1)}},error:function(e,t){if(e.previewElement){e.previewElement.classList.add("dz-error"),"String"!=typeof t&&t.error&&(t=t.error);var n=!0,i=!1,r=void 0;try{for(var o,a=e.previewElement.querySelectorAll("[data-dz-errormessage]")[Symbol.iterator]();!(n=(o=a.next()).done);n=!0){o.value.textContent=t}}catch(e){i=!0,r=e}finally{try{n||null==a.return||a.return()}finally{if(i)throw r}}}},errormultiple:function(){},processing:function(e){if(e.previewElement&&(e.previewElement.classList.add("dz-processing"),e._removeLink))return e._removeLink.innerHTML=this.options.dictCancelUpload},processingmultiple:function(){},uploadprogress:function(e,t){if(e.previewElement){var n=!0,i=!1,r=void 0;try{for(var o,a=e.previewElement.querySelectorAll("[data-dz-uploadprogress]")[Symbol.iterator]();!(n=(o=a.next()).done);n=!0){var l=o.value;"PROGRESS"===l.nodeName?l.value=t:l.style.width="".concat(t,"%")}}catch(e){i=!0,r=e}finally{try{n||null==a.return||a.return()}finally{if(i)throw r}}}},totaluploadprogress:function(){},sending:function(){},sendingmultiple:function(){},success:function(e){if(e.previewElement)return e.previewElement.classList.add("dz-success")},successmultiple:function(){},canceled:function(e){return this.emit("error",e,this.options.dictUploadCanceled)},canceledmultiple:function(){},complete:function(e){if(e._removeLink&&(e._removeLink.innerHTML=this.options.dictRemoveFile),e.previewElement)return e.previewElement.classList.add("dz-complete")},completemultiple:function(){},maxfilesexceeded:function(){},maxfilesreached:function(){},queuecomplete:function(){},addedfiles:function(){}},this.prototype._thumbnailQueue=[],this.prototype._processingThumbnail=!1}},{key:"extend",value:function(e){for(var t=arguments.length,n=new Array(1"))),this.clickableElements.length){!function l(){return s.hiddenFileInput&&s.hiddenFileInput.parentNode.removeChild(s.hiddenFileInput),s.hiddenFileInput=document.createElement("input"),s.hiddenFileInput.setAttribute("type","file"),(null===s.options.maxFiles||1")),n+='');var i=C.createElement(n);return"FORM"!==this.element.tagName?(t=C.createElement('
'))).appendChild(i):(this.element.setAttribute("enctype","multipart/form-data"),this.element.setAttribute("method",this.options.method)),null!=t?t:i}},{key:"getExistingFallback",value:function(){for(var e=function(e){var t=!0,n=!1,i=void 0;try{for(var r,o=e[Symbol.iterator]();!(t=(r=o.next()).done);t=!0){var a=r.value;if(/(^| )fallback($| )/.test(a.className))return a}}catch(e){n=!0,i=e}finally{try{t||null==o.return||o.return()}finally{if(n)throw i}}},t=0,n=["div","form"];t".concat(t," ").concat(this.options.dictFileSizeUnits[n])}},{key:"_updateMaxFilesReachedClass",value:function(){return null!=this.options.maxFiles&&this.getAcceptedFiles().length>=this.options.maxFiles?(this.getAcceptedFiles().length===this.options.maxFiles&&this.emit("maxfilesreached",this.files),this.element.classList.add("dz-max-files-reached")):this.element.classList.remove("dz-max-files-reached")}},{key:"drop",value:function(e){if(e.dataTransfer){this.emit("drop",e);for(var t=[],n=0;n1024*this.options.maxFilesize*1024?t(this.options.dictFileTooBig.replace("{{filesize}}",Math.round(e.size/1024/10.24)/100).replace("{{maxFilesize}}",this.options.maxFilesize)):C.isValidFile(e,this.options.acceptedFiles)?null!=this.options.maxFiles&&this.getAcceptedFiles().length>=this.options.maxFiles?(t(this.options.dictMaxFilesExceeded.replace("{{maxFiles}}",this.options.maxFiles)),this.emit("maxfilesexceeded",e)):this.options.accept.call(this,e,t):t(this.options.dictInvalidFileType)}},{key:"addFile",value:function(t){var n=this;t.upload={uuid:C.uuidv4(),progress:0,total:t.size,bytesSent:0,filename:this._renameFile(t)},this.files.push(t),t.status=C.ADDED,this.emit("addedfile",t),this._enqueueThumbnail(t),this.accept(t,function(e){e?(t.accepted=!1,n._errorProcessing([t],e)):(t.accepted=!0,n.options.autoQueue&&n.enqueueFile(t)),n._updateMaxFilesReachedClass()})}},{key:"enqueueFiles",value:function(e){var t=!0,n=!1,i=void 0;try{for(var r,o=e[Symbol.iterator]();!(t=(r=o.next()).done);t=!0){var a=r.value;this.enqueueFile(a)}}catch(e){n=!0,i=e}finally{try{t||null==o.return||o.return()}finally{if(n)throw i}}return null}},{key:"enqueueFile",value:function(e){var t=this;if(e.status!==C.ADDED||!0!==e.accepted)throw new Error("This file can't be queued because it has already been processed or was rejected.");if(e.status=C.QUEUED,this.options.autoProcessQueue)return setTimeout(function(){return t.processQueue()},0)}},{key:"_enqueueThumbnail",value:function(e){var t=this;if(this.options.createImageThumbnails&&e.type.match(/image.*/)&&e.size<=1024*this.options.maxThumbnailFilesize*1024)return this._thumbnailQueue.push(e),setTimeout(function(){return t._processThumbnailQueue()},0)}},{key:"_processThumbnailQueue",value:function(){var t=this;if(!this._processingThumbnail&&0!==this._thumbnailQueue.length){this._processingThumbnail=!0;var n=this._thumbnailQueue.shift();return this.createThumbnail(n,this.options.thumbnailWidth,this.options.thumbnailHeight,this.options.thumbnailMethod,!0,function(e){return t.emit("thumbnail",n,e),t._processingThumbnail=!1,t._processThumbnailQueue()})}}},{key:"removeFile",value:function(e){if(e.status===C.UPLOADING&&this.cancelUpload(e),this.files=without(this.files,e),this.emit("removedfile",e),0===this.files.length)return this.emit("reset")}},{key:"removeAllFiles",value:function(e){null==e&&(e=!1);var t=!0,n=!1,i=void 0;try{for(var r,o=this.files.slice()[Symbol.iterator]();!(t=(r=o.next()).done);t=!0){var a=r.value;a.status===C.UPLOADING&&!e||this.removeFile(a)}}catch(e){n=!0,i=e}finally{try{t||null==o.return||o.return()}finally{if(n)throw i}}return null}},{key:"resizeImage",value:function(r,e,t,n,o){var a=this;return this.createThumbnail(r,e,t,n,!0,function(e,t){if(null==t)return o(r);var n=a.options.resizeMimeType;null==n&&(n=r.type);var i=t.toDataURL(n,a.options.resizeQuality);return"image/jpeg"!==n&&"image/jpg"!==n||(i=ExifRestore.restore(r.dataURL,i)),o(C.dataURItoBlob(i))})}},{key:"createThumbnail",value:function(e,t,n,i,r,o){var a=this,l=new FileReader;l.onload=function(){e.dataURL=l.result,"image/svg+xml"!==e.type?a.createThumbnailFromUrl(e,t,n,i,r,o):null!=o&&o(l.result)},l.readAsDataURL(e)}},{key:"displayExistingFile",value:function(t,e,n,i,r){var o=this,a=!(4u.options.chunkSize),s[0].upload.totalChunkCount=Math.ceil(t.size/u.options.chunkSize)}if(s[0].upload.chunked){var r=s[0],o=e[0];r.upload.chunks=[];var i=function(){for(var e=0;void 0!==r.upload.chunks[e];)e++;if(!(e>=r.upload.totalChunkCount)){0;var t=e*u.options.chunkSize,n=Math.min(t+u.options.chunkSize,r.size),i={name:u._getParamName(0),data:o.webkitSlice?o.webkitSlice(t,n):o.slice(t,n),filename:r.upload.filename,chunkIndex:e};r.upload.chunks[e]={file:r,index:e,dataBlock:i,status:C.UPLOADING,progress:0,retries:0},u._uploadData(s,[i])}};if(r.upload.finishedChunkUpload=function(e){var t=!0;e.status=C.SUCCESS,e.dataBlock=null,e.xhr=null;for(var n=0;n>1}var s=l/t;return 0==s?1:s},drawImageIOSFix=function(e,t,n,i,r,o,a,l,s,u){var c=detectVerticalSquash(t);return e.drawImage(t,n,i,r,o,a,l,s,u/c)},ExifRestore=function(){function e(){_classCallCheck(this,e)}return _createClass(e,null,[{key:"initClass",value:function(){this.KEY_STR="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}},{key:"encode64",value:function(e){for(var t="",n=void 0,i=void 0,r="",o=void 0,a=void 0,l=void 0,s="",u=0;o=(n=e[u++])>>2,a=(3&n)<<4|(i=e[u++])>>4,l=(15&i)<<2|(r=e[u++])>>6,s=63&r,isNaN(i)?l=s=64:isNaN(r)&&(s=64),t=t+this.KEY_STR.charAt(o)+this.KEY_STR.charAt(a)+this.KEY_STR.charAt(l)+this.KEY_STR.charAt(s),n=i=r="",o=a=l=s="",ue.length)break}return n}},{key:"decode64",value:function(e){var t=void 0,n=void 0,i="",r=void 0,o=void 0,a="",l=0,s=[];for(/[^A-Za-z0-9\+\/\=]/g.exec(e)&&console.warn("There were invalid base64 characters in the input text.\nValid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\nExpect errors in decoding."),e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");t=this.KEY_STR.indexOf(e.charAt(l++))<<2|(r=this.KEY_STR.indexOf(e.charAt(l++)))>>4,n=(15&r)<<4|(o=this.KEY_STR.indexOf(e.charAt(l++)))>>2,i=(3&o)<<6|(a=this.KEY_STR.indexOf(e.charAt(l++))),s.push(t),64!==o&&s.push(n),64!==a&&s.push(i),t=n=i="",r=o=a="",l + + + + + + + OF56-App (Client v3) + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+ + diff --git a/client/main.css b/client/main.css new file mode 100644 index 0000000..787eb36 --- /dev/null +++ b/client/main.css @@ -0,0 +1,247 @@ +/* tpl/main.css */ +body { + font-family: arial; + font-size: 20px; + width: 100%; + height: 100%; + margin: 0; + padding: 0; + background-color: #000; + color: #fff; +} +header { + background: #000 url(/res/frontpage.jpg) center no-repeat; + background-size: cover; + width: 100%; + height: 100vh; +} +#loginbox { + position: absolute; + width: 18em; + left: calc(50% - 9em); + bottom: 5em; +} +#loginbox p { + background-color: #000; + text-align: center; + padding: 0.2em; + border-radius: 0.2em; +} +a {color: #fff; text-decoration: underline;} +ul {list-style: none; padding: 0; margin: 0;} +li { + display: inline-block; + padding: 0.2em; + margin: 0.1em; + border-radius: 0.2em; +} +li img {height: 0.8em;} +li > img {margin: 0 0.4em 0 0.2em;} +.button > img, li > .button {margin: 0 0.2em 0 0.2em;} +li .button { + padding: 0 0.1em; + background-color: #000; + border-radius: 0.2em; + border: 0.05em solid #fff; +} +.button {border: 0.05em solid #fff; background-color: #000; cursor: pointer;} +.button:hover {background-color: #333;} +nav { + vertical-align: middle; + text-align: left; + background-color: #9b0000; + position: sticky; + top: 0; + z-index: 100; +} +nav ul {padding: 0 0.5em;} +nav li { + padding: 0.5em 0.75em; + font-weight: bold; + margin: 0; + background-color: #9b0000; + border: 0; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + cursor: pointer; +} +nav li:hover {background-color: #f00;} +nav li.current {background-color: #000;} +#navigation_select { + display:none; + background-color: #9b0000; + font-weight: bold; + padding: 0.5em 0.75em; + width: 100%; +} +main {padding: 0 1.75em;} +article {margin: 0 0 2em 0; max-width: 60em;} +article:first-of-type {margin: 2em 0 2em 0;} +article img {max-width: 100%;} +h1 img {height: 0.8em;} +input, select { + background-color: #000; + color: #fff; + font-size: 100%; + padding: 0.1em; + border: 1px solid #fff; + box-sizing: border-box; +} +.list_entry select {height: 1.4em;} +input[type="submit"], button {background-color: #9b0000; color: #fff; font-size: 100%;} +.login { + width: 12em; + text-align: center; + border: 0.1em solid #fff; + padding: 0.2em; + margin: 0.1em; + box-sizing: content-box; +} +.disabled, input[type="submit"].disabled { + background-color: #333; +} +a.toggleVisibility {text-decoration: none;} +h1 { + background-color: #333; + display: inline; + padding: 0.3em 0.6em; + border-radius: 0.2em; +} +div.toggleVisibility { + padding: 1em; + border: 0.3em solid #333; + border-radius: 0.2em; +} +.group_title { + border-bottom: none; + border-left: 0.3em solid #333; + border-right: 0.3em solid #333; + padding: 0.5em; + border-top: 0.2em solid #333; + border-top-right-radius: 0.3em; + border-top-left-radius: 0.3em; + background-color: #333; +} +.group_title h1 { + padding-left: 0; +} +.list_entry_row { + border-bottom: 0.05em dashed #333; + border-left: 0.3em solid #333; + border-right: 0.3em solid #333; + border-top: 0; + padding: 0.2em; + min-height: 1.733em; +} +.list_entry_row ul {display: inline;} +.list_entry_row .block {display: block;} +.list_entry {border-bottom: 0.05em dotted #333;} +.list_entry:last-of-type {border-bottom: none;} +.list_entry_title { + border-bottom: none; + border-left: 0.3em solid #333; + border-right: 0.3em solid #333; + padding: 0.2em; + border-top: 0.1em solid #333; + background-color: #333; +} +.list_entry .list_entry_row:last-of-type {border-bottom: none;} +.list_entry:last-of-type .list_entry_row:last-of-type {border-bottom: 0.3em solid #333;} +/*.list_entry:last-of-type .list_entry_title:last-of-type {border-bottom: 0.05em solid #888;}*/ +.list_entry_title li {background-color: #000;} +.list_entry:first-of-type .list_entry_title {border-top-right-radius: 0.2em;} +.list_entry:last-of-type div:last-of-type {border-bottom-right-radius: 0.2em; border-bottom-left-radius: 0.2em;} +.list_selected div {border-color: #9b0000;} +.list_selected .list_entry_title {background-color: #9b0000;} + +.list_entry .bild { + position: relative; + float: right; + display: flex; + align-items: center; + justify-content: center; + height: 4em; + min-width: 4em; + padding: 0; + background-color: #fff; + overflow: hidden; +} +.list_entry .bild img { + position: absolute; + z-index: 1; + max-height: 4em; + max-width: 4em; +} +.list_entry .bild form { + position: absolute; + z-index: 10; + top: 0; + left: 0; + height: 4em; + width: 4em; + opacity: 0.6; + background-color: #fff; +} +.list_entry .bild form button { + height: 4em; + width: 4em; + padding: 0; +} +.list_entry .bild .deleter { + position: absolute; + z-index: 20; + bottom: -0.2em; + right: -0.2em; + background-color: #000; + border: 0.05em solid #fff; + border-radius: 0.2em; +} +.list_entry .bild .deleter img {position: relative;height: 0.8em;} +.list_entry .bild .dz-default {max-height: 100%;} + +#qrscanner { + display: none; + position: fixed; + left: 2em; + right: 2em; + top: 2em; + bottom: 2em; + width: auto; + height: auto; + z-index: 100; + background-color: #555; + padding: 2em; + align-items: center; + flex-direction: row; + justify-content: space-around; +} +#qrscanner_text, #qrscanner_video {/*width:100%;*/} +#qrscanner_close {position: fixed; z-index: 999; right: 2.5em; top: 2.5em;} +#qrscanner_video {max-height: 80%; max-width: 80%;} + +.chocolate {background-color: #840;} +.merlot {background-color: #804;} +.mughal {background-color: #480;} +.philippine {background-color: #084;} +.blue {background-color: #048;} +.indigo {background-color: #408;} +.purple {background-color: #404;} +.olive {background-color: #440;} +.teal {background-color: #044;} +.red {background-color: #400;} +.pacific {background-color: #004;} +.green {background-color: #040;} + +@media only screen and (orientation: portrait) { + body {font-size: 4vw;} + nav {font-size: 6vw;} + #navigation_select {display:inline;font-size: 6vw;} + #navigation {display:none;} + main {padding: 0 1em;} + nav li {padding: 1em 0.35em;} + table {font-size: 4vw;} + input,button,select {font-size: 4vw;} + input[type=radio] {border: 0; height: 1em;} + #qrscanner {flex-direction: column; padding: 0;} + #qrscanner_video {max-height: 40%; max-width: 100%;} +} \ No newline at end of file diff --git a/client/page.js b/client/page.js new file mode 100644 index 0000000..2bfa46c --- /dev/null +++ b/client/page.js @@ -0,0 +1,399 @@ +class Page +{ + constructor(groupName, json, route, array, groups, subs, selects, globalAdmin) { + this.group = groups[groupName]; + this.groupName = groupName; + this.ID = json.ID; + this.route = route; + this.array = array; + this.groups = groups; + this.subs = subs; + this.selects = selects; + this.admin = globalAdmin || false;//json.admin; // Local admin rights + + this.init(json); + this.initSubs(json); + } + + /* Static functions */ + + static Open() { + document.getElementById("nav_" + Root.instance.page.toLowerCase()).classList.remove("current"); + document.getElementById("nav_" + this.route.toLowerCase()).classList.add("current"); + Root.instance.page = this.route; + document.getElementById("navigation_select").value = this.route; + //this.FetchOptions(); + this.Load(); + } + + static SetVisibility(visible) { + this.visible = visible; + document.getElementById("nav_"+this.route.toLowerCase()).style.display = visible ? "inline" : "none"; + document.getElementById("nav_sel_"+this.route.toLowerCase()).style.display = visible ? "inline" : "none"; + } + + static UpdateData(json) { + //this.meta = json.meta; + this.prints = json.prints; + this.admin = json.admin; + for (let sub in this.subs) { + this.subs[sub].entries = json.options[sub.toUpperCase()]; + } + for (let sel in this.selects) { + this.selects[sel] = json.options[sel.toUpperCase()]; + } + this.visible = true; + /*this.selected = []; + if ("undefined"!=typeof(json.selected)) { + this.selected = json.selected; + }*/ + for (var k in this.filter) { + delete this.filter[k]; + } + this.filter = []; + for (var l in json.filter) { + this.filter.push(new APIFilter(json.filter[l], "none"!=json.filter[l].field ? this.mainFields[json.filter[l].field].type : "none")); + } + return true; + } + + static Render() { + let html = ""; + if (this.admin) { + html+= "
" + this.RenderAdd() + "
"; + } + for (const group in this.groups) { + const groupHtml = this.RenderGroup(group); + html+= groupHtml.begin; + + + for (const e in this.groups[group]) { + const entry = this.groups[group][e]; + html+= entry.renderContainer()/*Entry(false, true)*/; + } + html+= ""; + } + document.getElementById("content").innerHTML = html; + for (const ID in this.array) { + this.array[ID].renderEntry(); + this.array[ID].addEntryEvents(); + this.array[ID].renderSubs(); + this.array[ID].addSubEvents(); + } + const _this = this; + Root.AddEventListenerIfButtonExists(this.route + "/Add/Add", function (event) {_this.Add();}); + } + + static Value(id, name) { + const e = document.getElementById(this.route+"/"+id+"/"+name); + return (e!==null ? e.value : null); + } + + static Add(contextId = null) { + let request = new XMLHttpRequest(); + let json = this.Collect("Add", contextId); + json.secToken = Root.instance.secToken; + const _this = this; + + request.open("POST", Root.instance.url + this.route); + request.setRequestHeader("Authorization", "Bearer " + Root.instance.jwt); + request.setRequestHeader("Content-Type", "application/json"); + request.setRequestHeader("Accept", "application/json"); + request.onreadystatechange = function() { + if (request.readyState != 4) return; + const {ok, json} = Root.instance.FinishResponse(request); + if (ok) { + //_this.UpdateData(json); + if (typeof(_this.groups[json.content.GROUP])=="undefined") { + _this.groups[json.content.GROUP] = []; + const groupHtml = _this.RenderGroup(json.content.GROUP); + document.getElementById("content").insertAdjacentHTML("beforeend", groupHtml.begin + groupHtml.end); + } + const group = _this.groups[json.content.GROUP]; + _this.array[json.content.ID] = _this.New(json.content.GROUP, json.content); + group.push(_this.array[json.content.ID]); + // Add html + var elList = document.getElementById("Group/" + json.content.GROUP); + elList.insertAdjacentHTML("beforeend", _this.array[json.content.ID].renderEntry(false, true)); + _this.array[json.content.ID].addEntryEvents(); + } }; + + request.send(JSON.stringify(json)); + } + + static Load(id = null) { + let request = new XMLHttpRequest(); + const _this = this; + let path = Root.instance.url + this.route + (id !== null ? "/"+id : ""); + + if (this.filter.length>0) { + path += "?filter="+encodeURI(JSON.stringify(this.getFilter())); + } + + request.open("GET", path); + request.setRequestHeader("Authorization", "Bearer " + Root.instance.jwt); + request.setRequestHeader("Accept", "application/json"); + request.onreadystatechange = function() { + if (request.readyState != 4) return; + const {ok, json} = Root.instance.FinishResponse(request); + if (ok) { + if (id!==null) { + _this.array[id].init(json.content); + _this.Reset(); + } else { + _this.UpdateData(json); + for (let g in json.content) { + const groupID = json.content[g].ID; + _this.groups[groupID] = []; + let group = _this.groups[groupID]; + for (let i in json.content[g].ENTRIES) { + _this.array[json.content[g].ENTRIES[i].ID] = _this.New(groupID, json.content[g].ENTRIES[i]); + group.push(_this.array[json.content[g].ENTRIES[i].ID]); + } } } } + _this.Render(); + } + request.send(); + } + + /* Public functions */ + + Save() { + const _this = this; + let request = new XMLHttpRequest(); + + const json = this.collect(); + json.secToken = Root.instance.secToken; + request.open("PATCH", Root.instance.url + this.marker()); + request.setRequestHeader("Authorization", "Bearer " + Root.instance.jwt); + request.setRequestHeader("Content-Type", "application/json"); + request.setRequestHeader("Accept", "application/json"); + + request.onreadystatechange = function() { + if (request.readyState != 4) return; + const {ok, json} = Root.instance.FinishResponse(request); + if (ok) { + //_this.UpdateData(json); + if (typeof(_this.groups[json.content.GROUP])=="undefined") { + _this.groups[json.content.GROUP] = []; + const groupHtml = _this.RenderGroup(json.content.GROUP); + document.getElementById("content").insertAdjacentHTML("beforeend", groupHtml.begin + groupHtml.end); + } + if (_this.groupName!=json.content.GROUP) { + _this.removeFromGroup(); + let element = document.getElementById(_this.marker()); + let groupel = document.getElementById("Group/" + json.content.GROUP); + _this.groups[json.content.GROUP].push(_this); + groupel.appendChild(element); + } + _this.init(json.content); + _this.Show(false); + } }; + request.send(JSON.stringify(json)); + } + + Delete() { + const _this = this; + let request = new XMLHttpRequest(); + + request.open("DELETE", Root.instance.url + this.marker()); + request.setRequestHeader("Authorization", "Bearer " + Root.instance.jwt); + request.setRequestHeader("Content-Type", "application/json"); + request.setRequestHeader("Accept", "application/json"); + + request.onreadystatechange = function() { + if (request.readyState != 4) return; + const {ok, json} = Root.instance.FinishResponse(request); + if (ok) { + _this.removeFromGroup(); + delete _this.array[_this.ID]; + let element = document.getElementById(_this.marker()); + element.parentNode.removeChild(element); + } }; + + request.send(JSON.stringify({secToken: Root.instance.secToken})); + } + + Show(edit = false) { + this.renderEntry(edit, false); + this.addEntryEvents(edit); + } + + SubShow(sub, edit) { + document.getElementById(this.marker(sub, "Add")).innerHTML = this.renderSubAdd(sub, edit); + this.addSubEvents(edit); + } + + SubAdd(sub) { + const id = document.getElementById(this.marker(sub, "Add", sub)).value; + let request = new XMLHttpRequest(); + const _this = this; + + request.open("POST", Root.instance.url + this.marker(sub, id)); + request.setRequestHeader("Authorization", "Bearer " + Root.instance.jwt); + request.setRequestHeader("Content-Type", "application/json"); + request.setRequestHeader("Accept", "application/json"); + request.onreadystatechange = function() { + if (request.readyState != 4) return; + const {ok, json} = Root.instance.FinishResponse(request); + if (ok) { + _this.updateSubs(sub, json.content.SUB[sub.toUpperCase()]); + } }; + request.send(JSON.stringify({secToken: Root.instance.secToken})); + } + + SubDelete(sub, id) { + let request = new XMLHttpRequest(); + const _this = this; + + request.open("DELETE", Root.instance.url + this.marker(sub, id)); + request.setRequestHeader("Authorization", "Bearer " + Root.instance.jwt); + request.setRequestHeader("Content-Type", "application/json"); + request.setRequestHeader("Accept", "application/json"); + request.onreadystatechange = function() { + if (request.readyState != 4) return; + const {ok, json} = Root.instance.FinishResponse(request); + if (ok) { + _this.updateSubs(sub, json.content.SUB[sub.toUpperCase()]); + } }; + request.send(JSON.stringify({secToken: Root.instance.secToken})); + } + + /* "Private" functions */ + + initSubs(json) { + for (const s in this.subs) { + this[s] = new Set(); + for (let i in json.SUB[s.toUpperCase()]) { + this[s].add(json.SUB[s.toUpperCase()][i].ID); + } } } + + updateSubs(sub, newSubList) { + this[sub].clear(); + for (let i in newSubList) { + this[sub].add(newSubList[i].ID); + } + this.renderSubs(sub); + this.addSubEvents(sub); + } + + // first = action or subroute, second = subID, third = subAction + marker(firstAppend = null, secondAppend = null, thirdAppend = null) { + let id = this.route + "/" + this.ID; + if (firstAppend!==null) { + id+= "/" + firstAppend; + if (secondAppend!==null) { + id+= "/" + secondAppend; + if (thirdAppend!==null) { + id+= "/" + thirdAppend; + } } } + return id; + } + + renderContainer() { + let html = "
" + + "
"; + if (Object.keys(this.subs).length>0) { + html+= "
"; + for (let s in this.subs) { + html+= "
    "; + } + html+= "
    "; + } + html+= "
    "; + return html; + } + + renderField(icon, value) { + return "
  • " + value + "
  • "; + } + + renderInput(name, value, width = 8, maxLength = null) { + return ""; + } + + renderButton(icon, name, title) { + return "
  • " + } + + renderSelect(name, selected, width = 8) { + let html = ""; + } + + renderSubs(onlyOneSub = null) { + // TODO: SUBS + let subs = {}; + if (onlyOneSub===null) { + subs = this.subs; + } else { + subs[onlyOneSub] = this.subs[onlyOneSub]; + } + for (let s in subs) { + let html = ""; + if (typeof(this.subs[s])!="undefined") { + for (let e in this.subs[s].entries) { + const entry = this.subs[s].entries[e]; + if (this[s].has(entry.ID)) { + html+= "
  • " + + (typeof(entry.KÜRZEL)!="undefined" ? entry.KÜRZEL : entry.NAME) + + (this.admin ? " " : "") + + "
  • "; + } } + if (this.admin) { + html+= "
  • " + this.renderSubAdd(s, false) + "
  • "; + } + document.getElementById(this.marker(s)).innerHTML = html; + } } } + + renderSubAdd(sub, add) { + let html = ""; + if (add) { + html+= ""; + html+= ""; + html+= ""; + } else { + html+= ""; + } + return html; + } + + addSubEvents() { + const _this = this; + for (let sub in this.subs) { + for (const id of this[sub]) { + Root.AddEventListenerIfButtonExists(this.marker(sub, id, "Delete"), function (event) {_this.SubDelete(sub, id);}); + } + Root.AddEventListenerIfButtonExists(this.marker(sub, "Add/Show"), function (event) {_this.SubShow(sub, true);}); + Root.AddEventListenerIfButtonExists(this.marker(sub, "Add/Add"), function (event) {_this.SubAdd(sub);}); + Root.AddEventListenerIfButtonExists(this.marker(sub, "Add/Reset"), function (event) {_this.SubShow(sub, false);}); + } } + + removeFromGroup() { + for (let i in this.groups[this.group]) { + if (this.groups[this.group][i].ID==this.ID) { + delete _this.groups[this.group][i]; + break; + } } } + + addEntryEvents(edit) { + const _this = this; + if (edit) { + Root.AddEventListenerIfButtonExists(this.marker("Save"), function (event) {_this.Save();}); + Root.AddEventListenerIfButtonExists(this.marker("Delete"), function (event) {_this.Delete();}); + Root.AddEventListenerIfButtonExists(this.marker("Reset"), function (event) {_this.Show(false);}); + } else { + Root.AddEventListenerIfButtonExists(this.marker("Edit"), function (event) {_this.Show(true);}); + } } +} diff --git a/client/pages/fahrzeuge.js b/client/pages/fahrzeuge.js new file mode 100644 index 0000000..6f83ab8 --- /dev/null +++ b/client/pages/fahrzeuge.js @@ -0,0 +1,119 @@ +class Fahrzeuge extends Page +{ + static route = "Fahrzeuge"; + static array = {}; + static groups = {}; + static subs = { + "Eingewiesene": {color: "chocolate", icon: "person.png", entries: []} + }; + static selects = {}; + static admin = false; // global page admin rights + static prints = []; + static filter = []; + //static selected = []; + //static dropzones = {}; + static visible = false; + + constructor(groupName, json) { + super( + groupName, + json, + Fahrzeuge.route, + Fahrzeuge.array, + Fahrzeuge.groups, + Fahrzeuge.subs, + Fahrzeuge.selects, + Fahrzeuge.admin/*, + Fahrzeuge.prints, + Fahrzeuge.filter, + Fahrzeuge.selected, + Fahrzeuge.dropzones*/ + ); + } + + init(json) { + this.Kürzel = json.MAIN.KÜRZEL; + this.Name = json.MAIN.NAME; + this.Bild = json.MAIN.BILD; + } + + renderEntry(drawEdit) { + let html = "
    "; + if (this.Bild.EXISTIERT) { + html+= ""; + if (drawEdit) { + html+= "
    "; + } + } else { + html+= ""; + } + if (drawEdit) { + html+= "
    "; + } + html += "
    "; + if (drawEdit) { + html+= "
      " + + "
    • " + + "
    • " + + "
    • " + + "
    • " + + "
    • " + + "
    "; + } else { + html+= "
    • " + this.Name + "
    • " + "
    • " + this.Kürzel + "
    • "; + if (this.admin) { + html += "
    • "; + } + html+= "
    "; + } + document.getElementById(this.marker("Main")).innerHTML = html; + } + + static RenderAdd() { + let html = "

    Fahrzeug hinzufügen

    " + + "
    • Name:
    • " + + "
    • Kürzel:
    • " + + "
    • Hinzufügen
    "; + return html; + } + + renderGroup() { + return Fahrzeuge.RenderGroup(this.groupName); + } + + static RenderGroup(groupName) { + return { + begin: "

    " + groupName + "

    ", + end: "
    " + }; + } + + static New(groupName, json) { + return new Fahrzeuge(groupName, json); + } + + collect() { + return Fahrzeuge.Collect(this.ID); + } + + static Collect(id, contextId = null) { + return { + ID: id, + KÜRZEL: this.Value(id, "Kürzel"), + NAME: this.Value(id, "Name") + }; + } + + static RenderSelect(selectId, fahrzeugId, nullable = true) { + let html = ""; + return html; + } +} diff --git a/client/pages/personal.js b/client/pages/personal.js new file mode 100644 index 0000000..fc31711 --- /dev/null +++ b/client/pages/personal.js @@ -0,0 +1,160 @@ +class PersonalPage extends Page +{ + static routes = { + "Personal": {needRead: true, needWrite: false} + } + + + + + + + + + + + + + + static route = "Personal"; + static array = {}; + static groups = {}; + static subs = { + "Abteilungen": {color: "purple", icon: "department.png", entries: []}, + "Gruppen": {color: "olive", icon: "group.png", entries: []}, + "Lehrgänge": {color: "teal", icon: "skill.png", entries: []}, + "Einweisungen": {color: "chocolate", icon: "person.png", entries: []} + }; + static selects = { + "Kategorie" : [], + "Funktion" : [] + }; + static admin = true; // global page admin rights + static prints = []; + static filter = []; + //static selected = []; + //static dropzones = {}; + static visible = false; + + constructor(groupName, json) { + super( + groupName, + json, + Personal.route, + Personal.array, + Personal.groups, + Personal.subs, + Personal.selects, + Personal.admin/*, + Personal.prints, + Personal.filter, + Personal.selected, + Personal.dropzones*/ + ); + } + + init(json) { + this.OFNr = json.MAIN.OFNR; + this.PNr = json.MAIN.PNR; + this.Nr = json.MAIN.NR; + this.Login = json.MAIN.LOGIN; + this.Email = json.MAIN.EMAIL; + this.Vornamen = json.MAIN.VORNAMEN; + this.Nachnamen = json.MAIN.NACHNAMEN; + this.Name = json.MAIN.NAME; + this.Bild = json.MAIN.BILD; + this.Kategorie = json.MAIN.KATEGORIE; + this.Funktion = json.MAIN.FUNKTION; + } + + renderEntry(drawEdit) { + let html = "
    "; + if (this.Bild.EXISTIERT) { + html+= ""; + if (drawEdit) { + html+= "
    "; + } + } else { + html+= ""; + } + if (drawEdit) { + html+= "
    "; + } + html += "
      "; + + // TODO: Draw selectbox + + if (drawEdit) { + html+= this.renderField("number.png", this.renderInput("OFNr", this.OFNr, 1.5, 2) + "-" + this.renderInput("PNr", this.PNr, 2, 3)) + + this.renderField("person.png", this.renderInput("Nachnamen", this.Nachnamen) + ", " + this.renderInput("Vornamen", this.Vornamen)) + + this.renderField("type.png", this.renderSelect("Kategorie", this.Kategorie.ID)) + + this.renderField("note.png", this.renderInput("Login", this.Login) + "@feuerwehr-bs.net") + + this.renderField("star.png", this.renderSelect("Funktion", this.Funktion.ID, 2.5)) + + this.renderButton("save.png", "Save", "Speichern") + + this.renderButton("delete.png", "Delete", "Löschen") + + this.renderButton("cancel.png", "Reset", "Zurücksetzen"); + } else { + html+= this.renderField("number.png", this.Nr) + + this.renderField("person.png", "" + this.Nachnamen + ", " + this.Vornamen + "") + + (this.Login=="" || this.Login===null ? this.renderField("note.png", "Kein Login!") : "") + + this.renderField("star.png", this.Funktion!==null ? this.Funktion.KÜRZEL : "-"); + if (this.admin) { + html += this.renderButton("edit.png", "Edit", "Bearbeiten"); + } + } + html+= "
    "; + document.getElementById(this.marker("Main")).innerHTML = html; + } + + static RenderAdd() { + let html = "

    Fahrzeug hinzufügen

    " + + "
    • Name:
    • " + + "
    • Kürzel:
    • " + + "
    • Hinzufügen
    "; + return html; + } + + renderGroup() { + return Personal.RenderGroup(this.groupName); + } + + static RenderGroup(groupName) { + return { + begin: "

    " + groupName + "

    ", + end: "
    " + }; + } + + static New(groupName, json) { + return new Personal(groupName, json); + } + + collect() { + return Personal.Collect(this.ID); + } + + static Collect(id, contextId = null) { + return { + ID: id, + OFNR: this.Value(id, "OFNr"), + PNR: this.Value(id, "PNr"), + NACHNAMEN: this.Value(id, "Nachnamen"), + VORNAMEN: this.Value(id, "Vornamen"), + KATEGORIE: this.Value(id, "Kategorie"), + LOGIN: this.Value(id, "Login"), + FUNKTION: this.Value(id, "Funktion") + }; + } + + static RenderSelect(selectId, fahrzeugId, nullable = true) { + let html = ""; + return html; + } +} diff --git a/client/qr-scanner-worker.min.js b/client/qr-scanner-worker.min.js new file mode 100644 index 0000000..8425f8b --- /dev/null +++ b/client/qr-scanner-worker.min.js @@ -0,0 +1,98 @@ +export const createWorker=()=>new Worker(URL.createObjectURL(new Blob([`class x{constructor(a,b){this.width=b;this.height=a.length/b;this.data=a}static createEmpty(a,b){return new x(new Uint8ClampedArray(a*b),a)}get(a,b){return 0>a||a>=this.width||0>b||b>=this.height?!1:!!this.data[b*this.width+a]}set(a,b,c){this.data[b*this.width+a]=c?1:0}setRegion(a,b,c,d,e){for(let f=b;fa||32this.available())throw Error("Cannot read "+a.toString()+" bits");var b=0;if(0>8-c<>b;a-=c;this.bitOffset+=c;8===this.bitOffset&&(this.bitOffset=0,this.byteOffset++)}if(0>c<>c, +this.bitOffset+=a)}return b}available(){return 8*(this.bytes.length-this.byteOffset)-this.bitOffset}}var B,C=B||(B={});C.Numeric="numeric";C.Alphanumeric="alphanumeric";C.Byte="byte";C.Kanji="kanji";C.ECI="eci";C.StructuredAppend="structuredappend";var D,E=D||(D={});E[E.Terminator=0]="Terminator";E[E.Numeric=1]="Numeric";E[E.Alphanumeric=2]="Alphanumeric";E[E.Byte=4]="Byte";E[E.Kanji=8]="Kanji";E[E.ECI=7]="ECI";E[E.StructuredAppend=3]="StructuredAppend";let F="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:".split(""); +function ca(a,b){let c=[],d="";b=a.readBits([8,16,16][b]);for(let e=0;e\`%\${("0"+e.toString(16)).substr(-2)}\`).join(""))}catch(e){}return{bytes:c,text:d}} +function da(a,b){a=new ba(a);let c=9>=b?0:26>=b?1:2;for(b={text:"",bytes:[],chunks:[],version:b};4<=a.available();){var d=a.readBits(4);if(d===D.Terminator)return b;if(d===D.ECI)0===a.readBits(1)?b.chunks.push({type:B.ECI,assignmentNumber:a.readBits(7)}):0===a.readBits(1)?b.chunks.push({type:B.ECI,assignmentNumber:a.readBits(14)}):0===a.readBits(1)?b.chunks.push({type:B.ECI,assignmentNumber:a.readBits(21)}):b.chunks.push({type:B.ECI,assignmentNumber:-1});else if(d===D.Numeric){var e=a,f=[];d="";for(var g= +e.readBits([10,12,14][c]);3<=g;){var h=e.readBits(10);if(1E3<=h)throw Error("Invalid numeric value above 999");var k=Math.floor(h/100),m=Math.floor(h/10)%10;h%=10;f.push(48+k,48+m,48+h);d+=k.toString()+m.toString()+h.toString();g-=3}if(2===g){g=e.readBits(7);if(100<=g)throw Error("Invalid numeric value above 99");e=Math.floor(g/10);g%=10;f.push(48+e,48+g);d+=e.toString()+g.toString()}else if(1===g){e=e.readBits(4);if(10<=e)throw Error("Invalid numeric value above 9");f.push(48+e);d+=e.toString()}b.text+= +d;b.bytes.push(...f);b.chunks.push({type:B.Numeric,text:d})}else if(d===D.Alphanumeric){e=a;f=[];d="";for(g=e.readBits([9,11,13][c]);2<=g;)m=e.readBits(11),k=Math.floor(m/45),m%=45,f.push(F[k].charCodeAt(0),F[m].charCodeAt(0)),d+=F[k]+F[m],g-=2;1===g&&(e=e.readBits(6),f.push(F[e].charCodeAt(0)),d+=F[e]);b.text+=d;b.bytes.push(...f);b.chunks.push({type:B.Alphanumeric,text:d})}else if(d===D.Byte)d=ca(a,c),b.text+=d.text,b.bytes.push(...d.bytes),b.chunks.push({type:B.Byte,bytes:d.bytes,text:d.text}); +else if(d===D.Kanji){f=a;d=[];e=f.readBits([8,10,12][c]);for(g=0;gk?k+33088:k+49472,d.push(k>>8,k&255);f=(new TextDecoder("shift-jis")).decode(Uint8Array.from(d));b.text+=f;b.bytes.push(...d);b.chunks.push({type:B.Kanji,bytes:d,text:f})}else d===D.StructuredAppend&&b.chunks.push({type:B.StructuredAppend,currentSequence:a.readBits(4),totalSequence:a.readBits(4),parity:a.readBits(8)})}if(0===a.available()||0===a.readBits(a.available()))return b} +class G{constructor(a,b){if(0===b.length)throw Error("No coefficients.");this.field=a;let c=b.length;if(1a.length&&([b,a]=[a,b]);let c=new Uint8ClampedArray(a.length),d=a.length-b.length;for(var e=0;ea)throw Error("Invalid degree less than 0");if(0===b)return this.field.zero;let c=this.coefficients.length;a=new Uint8ClampedArray(c+a);for(let d=0;d{b^=d}),b;b=this.coefficients[0];for(let d=1;d=this.size&&(a=(a^this.primitive)&this.size-1);for(a=0;aa)throw Error("Invalid monomial degree less than 0");if(0===b)return this.zero;a=new Uint8ClampedArray(a+1);a[0]=b;return new G(this,a)}log(a){if(0===a)throw Error("Can't take log(0)");return this.logTable[a]}exp(a){return this.expTable[a]}} +function fa(a,b,c,d){b.degree()=d/2;){var g=b;let h=e;b=c;e=f;if(b.isZero())return null;c=g;f=a.zero;g=b.getCoefficient(b.degree());for(g=a.inverse(g);c.degree()>=b.degree()&&!c.isZero();){let k=c.degree()-b.degree(),m=a.multiply(c.getCoefficient(c.degree()),g);f=f.addOrSubtract(a.buildMonomial(k,m));c=c.addOrSubtract(b.multiplyByMonomial(k,m))}f=f.multiplyPoly(e).addOrSubtract(h);if(c.degree()>=b.degree())return null}d=f.getCoefficient(0); +if(0===d)return null;a=a.inverse(d);return[f.multiply(a),c.multiply(a)]} +function ha(a,b){let c=new Uint8ClampedArray(a.length);c.set(a);a=new ea(285,256,0);var d=new G(a,c),e=new Uint8ClampedArray(b),f=!1;for(var g=0;gf)return null;c[f]^=d[e]}return c} +let I=[{infoBits:null,versionNumber:1,alignmentPatternCenters:[],errorCorrectionLevels:[{ecCodewordsPerBlock:7,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:19}]},{ecCodewordsPerBlock:10,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:16}]},{ecCodewordsPerBlock:13,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:13}]},{ecCodewordsPerBlock:17,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:9}]}]},{infoBits:null,versionNumber:2,alignmentPatternCenters:[6,18],errorCorrectionLevels:[{ecCodewordsPerBlock:10,ecBlocks:[{numBlocks:1, +dataCodewordsPerBlock:34}]},{ecCodewordsPerBlock:16,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:28}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:22}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:16}]}]},{infoBits:null,versionNumber:3,alignmentPatternCenters:[6,22],errorCorrectionLevels:[{ecCodewordsPerBlock:15,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:55}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:44}]},{ecCodewordsPerBlock:18, +ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:17}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:13}]}]},{infoBits:null,versionNumber:4,alignmentPatternCenters:[6,26],errorCorrectionLevels:[{ecCodewordsPerBlock:20,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:80}]},{ecCodewordsPerBlock:18,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:32}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:24}]},{ecCodewordsPerBlock:16,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:9}]}]}, +{infoBits:null,versionNumber:5,alignmentPatternCenters:[6,30],errorCorrectionLevels:[{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:108}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:43}]},{ecCodewordsPerBlock:18,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:15},{numBlocks:2,dataCodewordsPerBlock:16}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:11},{numBlocks:2,dataCodewordsPerBlock:12}]}]},{infoBits:null,versionNumber:6,alignmentPatternCenters:[6, +34],errorCorrectionLevels:[{ecCodewordsPerBlock:18,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:68}]},{ecCodewordsPerBlock:16,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:27}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:19}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:15}]}]},{infoBits:31892,versionNumber:7,alignmentPatternCenters:[6,22,38],errorCorrectionLevels:[{ecCodewordsPerBlock:20,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:78}]},{ecCodewordsPerBlock:18, +ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:31}]},{ecCodewordsPerBlock:18,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:14},{numBlocks:4,dataCodewordsPerBlock:15}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:13},{numBlocks:1,dataCodewordsPerBlock:14}]}]},{infoBits:34236,versionNumber:8,alignmentPatternCenters:[6,24,42],errorCorrectionLevels:[{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:97}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:38}, +{numBlocks:2,dataCodewordsPerBlock:39}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:18},{numBlocks:2,dataCodewordsPerBlock:19}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:14},{numBlocks:2,dataCodewordsPerBlock:15}]}]},{infoBits:39577,versionNumber:9,alignmentPatternCenters:[6,26,46],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:116}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:36}, +{numBlocks:2,dataCodewordsPerBlock:37}]},{ecCodewordsPerBlock:20,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:16},{numBlocks:4,dataCodewordsPerBlock:17}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:12},{numBlocks:4,dataCodewordsPerBlock:13}]}]},{infoBits:42195,versionNumber:10,alignmentPatternCenters:[6,28,50],errorCorrectionLevels:[{ecCodewordsPerBlock:18,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:68},{numBlocks:2,dataCodewordsPerBlock:69}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:4, +dataCodewordsPerBlock:43},{numBlocks:1,dataCodewordsPerBlock:44}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:6,dataCodewordsPerBlock:19},{numBlocks:2,dataCodewordsPerBlock:20}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:6,dataCodewordsPerBlock:15},{numBlocks:2,dataCodewordsPerBlock:16}]}]},{infoBits:48118,versionNumber:11,alignmentPatternCenters:[6,30,54],errorCorrectionLevels:[{ecCodewordsPerBlock:20,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:81}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:1, +dataCodewordsPerBlock:50},{numBlocks:4,dataCodewordsPerBlock:51}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:22},{numBlocks:4,dataCodewordsPerBlock:23}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:12},{numBlocks:8,dataCodewordsPerBlock:13}]}]},{infoBits:51042,versionNumber:12,alignmentPatternCenters:[6,32,58],errorCorrectionLevels:[{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:92},{numBlocks:2,dataCodewordsPerBlock:93}]}, +{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:6,dataCodewordsPerBlock:36},{numBlocks:2,dataCodewordsPerBlock:37}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:20},{numBlocks:6,dataCodewordsPerBlock:21}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:7,dataCodewordsPerBlock:14},{numBlocks:4,dataCodewordsPerBlock:15}]}]},{infoBits:55367,versionNumber:13,alignmentPatternCenters:[6,34,62],errorCorrectionLevels:[{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:107}]}, +{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:8,dataCodewordsPerBlock:37},{numBlocks:1,dataCodewordsPerBlock:38}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:8,dataCodewordsPerBlock:20},{numBlocks:4,dataCodewordsPerBlock:21}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:12,dataCodewordsPerBlock:11},{numBlocks:4,dataCodewordsPerBlock:12}]}]},{infoBits:58893,versionNumber:14,alignmentPatternCenters:[6,26,46,66],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:115}, +{numBlocks:1,dataCodewordsPerBlock:116}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:40},{numBlocks:5,dataCodewordsPerBlock:41}]},{ecCodewordsPerBlock:20,ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:16},{numBlocks:5,dataCodewordsPerBlock:17}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:12},{numBlocks:5,dataCodewordsPerBlock:13}]}]},{infoBits:63784,versionNumber:15,alignmentPatternCenters:[6,26,48,70],errorCorrectionLevels:[{ecCodewordsPerBlock:22, +ecBlocks:[{numBlocks:5,dataCodewordsPerBlock:87},{numBlocks:1,dataCodewordsPerBlock:88}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:5,dataCodewordsPerBlock:41},{numBlocks:5,dataCodewordsPerBlock:42}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:5,dataCodewordsPerBlock:24},{numBlocks:7,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:12},{numBlocks:7,dataCodewordsPerBlock:13}]}]},{infoBits:68472,versionNumber:16,alignmentPatternCenters:[6,26,50, +74],errorCorrectionLevels:[{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:5,dataCodewordsPerBlock:98},{numBlocks:1,dataCodewordsPerBlock:99}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:7,dataCodewordsPerBlock:45},{numBlocks:3,dataCodewordsPerBlock:46}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:15,dataCodewordsPerBlock:19},{numBlocks:2,dataCodewordsPerBlock:20}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:15},{numBlocks:13,dataCodewordsPerBlock:16}]}]},{infoBits:70749, +versionNumber:17,alignmentPatternCenters:[6,30,54,78],errorCorrectionLevels:[{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:107},{numBlocks:5,dataCodewordsPerBlock:108}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:10,dataCodewordsPerBlock:46},{numBlocks:1,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:22},{numBlocks:15,dataCodewordsPerBlock:23}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:14},{numBlocks:17, +dataCodewordsPerBlock:15}]}]},{infoBits:76311,versionNumber:18,alignmentPatternCenters:[6,30,56,82],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:5,dataCodewordsPerBlock:120},{numBlocks:1,dataCodewordsPerBlock:121}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:9,dataCodewordsPerBlock:43},{numBlocks:4,dataCodewordsPerBlock:44}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:22},{numBlocks:1,dataCodewordsPerBlock:23}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:2, +dataCodewordsPerBlock:14},{numBlocks:19,dataCodewordsPerBlock:15}]}]},{infoBits:79154,versionNumber:19,alignmentPatternCenters:[6,30,58,86],errorCorrectionLevels:[{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:113},{numBlocks:4,dataCodewordsPerBlock:114}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:44},{numBlocks:11,dataCodewordsPerBlock:45}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:21},{numBlocks:4,dataCodewordsPerBlock:22}]}, +{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:9,dataCodewordsPerBlock:13},{numBlocks:16,dataCodewordsPerBlock:14}]}]},{infoBits:84390,versionNumber:20,alignmentPatternCenters:[6,34,62,90],errorCorrectionLevels:[{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:107},{numBlocks:5,dataCodewordsPerBlock:108}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:41},{numBlocks:13,dataCodewordsPerBlock:42}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:15,dataCodewordsPerBlock:24}, +{numBlocks:5,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:15,dataCodewordsPerBlock:15},{numBlocks:10,dataCodewordsPerBlock:16}]}]},{infoBits:87683,versionNumber:21,alignmentPatternCenters:[6,28,50,72,94],errorCorrectionLevels:[{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:116},{numBlocks:4,dataCodewordsPerBlock:117}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:42}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:22}, +{numBlocks:6,dataCodewordsPerBlock:23}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:19,dataCodewordsPerBlock:16},{numBlocks:6,dataCodewordsPerBlock:17}]}]},{infoBits:92361,versionNumber:22,alignmentPatternCenters:[6,26,50,74,98],errorCorrectionLevels:[{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:111},{numBlocks:7,dataCodewordsPerBlock:112}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:46}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:7,dataCodewordsPerBlock:24}, +{numBlocks:16,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:34,dataCodewordsPerBlock:13}]}]},{infoBits:96236,versionNumber:23,alignmentPatternCenters:[6,30,54,74,102],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:121},{numBlocks:5,dataCodewordsPerBlock:122}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:47},{numBlocks:14,dataCodewordsPerBlock:48}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:24}, +{numBlocks:14,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:16,dataCodewordsPerBlock:15},{numBlocks:14,dataCodewordsPerBlock:16}]}]},{infoBits:102084,versionNumber:24,alignmentPatternCenters:[6,28,54,80,106],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:6,dataCodewordsPerBlock:117},{numBlocks:4,dataCodewordsPerBlock:118}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:6,dataCodewordsPerBlock:45},{numBlocks:14,dataCodewordsPerBlock:46}]},{ecCodewordsPerBlock:30, +ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:24},{numBlocks:16,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:30,dataCodewordsPerBlock:16},{numBlocks:2,dataCodewordsPerBlock:17}]}]},{infoBits:102881,versionNumber:25,alignmentPatternCenters:[6,32,58,84,110],errorCorrectionLevels:[{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:8,dataCodewordsPerBlock:106},{numBlocks:4,dataCodewordsPerBlock:107}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:8,dataCodewordsPerBlock:47},{numBlocks:13, +dataCodewordsPerBlock:48}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:7,dataCodewordsPerBlock:24},{numBlocks:22,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:22,dataCodewordsPerBlock:15},{numBlocks:13,dataCodewordsPerBlock:16}]}]},{infoBits:110507,versionNumber:26,alignmentPatternCenters:[6,30,58,86,114],errorCorrectionLevels:[{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:10,dataCodewordsPerBlock:114},{numBlocks:2,dataCodewordsPerBlock:115}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:19, +dataCodewordsPerBlock:46},{numBlocks:4,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:28,dataCodewordsPerBlock:22},{numBlocks:6,dataCodewordsPerBlock:23}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:33,dataCodewordsPerBlock:16},{numBlocks:4,dataCodewordsPerBlock:17}]}]},{infoBits:110734,versionNumber:27,alignmentPatternCenters:[6,34,62,90,118],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:8,dataCodewordsPerBlock:122},{numBlocks:4,dataCodewordsPerBlock:123}]}, +{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:22,dataCodewordsPerBlock:45},{numBlocks:3,dataCodewordsPerBlock:46}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:8,dataCodewordsPerBlock:23},{numBlocks:26,dataCodewordsPerBlock:24}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:12,dataCodewordsPerBlock:15},{numBlocks:28,dataCodewordsPerBlock:16}]}]},{infoBits:117786,versionNumber:28,alignmentPatternCenters:[6,26,50,74,98,122],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:117}, +{numBlocks:10,dataCodewordsPerBlock:118}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:45},{numBlocks:23,dataCodewordsPerBlock:46}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:24},{numBlocks:31,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:15},{numBlocks:31,dataCodewordsPerBlock:16}]}]},{infoBits:119615,versionNumber:29,alignmentPatternCenters:[6,30,54,78,102,126],errorCorrectionLevels:[{ecCodewordsPerBlock:30, +ecBlocks:[{numBlocks:7,dataCodewordsPerBlock:116},{numBlocks:7,dataCodewordsPerBlock:117}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:21,dataCodewordsPerBlock:45},{numBlocks:7,dataCodewordsPerBlock:46}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:23},{numBlocks:37,dataCodewordsPerBlock:24}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:19,dataCodewordsPerBlock:15},{numBlocks:26,dataCodewordsPerBlock:16}]}]},{infoBits:126325,versionNumber:30,alignmentPatternCenters:[6, +26,52,78,104,130],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:5,dataCodewordsPerBlock:115},{numBlocks:10,dataCodewordsPerBlock:116}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:19,dataCodewordsPerBlock:47},{numBlocks:10,dataCodewordsPerBlock:48}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:15,dataCodewordsPerBlock:24},{numBlocks:25,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:23,dataCodewordsPerBlock:15},{numBlocks:25,dataCodewordsPerBlock:16}]}]}, +{infoBits:127568,versionNumber:31,alignmentPatternCenters:[6,30,56,82,108,134],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:13,dataCodewordsPerBlock:115},{numBlocks:3,dataCodewordsPerBlock:116}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:46},{numBlocks:29,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:42,dataCodewordsPerBlock:24},{numBlocks:1,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:23,dataCodewordsPerBlock:15}, +{numBlocks:28,dataCodewordsPerBlock:16}]}]},{infoBits:133589,versionNumber:32,alignmentPatternCenters:[6,34,60,86,112,138],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:115}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:10,dataCodewordsPerBlock:46},{numBlocks:23,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:10,dataCodewordsPerBlock:24},{numBlocks:35,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:19, +dataCodewordsPerBlock:15},{numBlocks:35,dataCodewordsPerBlock:16}]}]},{infoBits:136944,versionNumber:33,alignmentPatternCenters:[6,30,58,86,114,142],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:115},{numBlocks:1,dataCodewordsPerBlock:116}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:14,dataCodewordsPerBlock:46},{numBlocks:21,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:29,dataCodewordsPerBlock:24},{numBlocks:19,dataCodewordsPerBlock:25}]}, +{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:15},{numBlocks:46,dataCodewordsPerBlock:16}]}]},{infoBits:141498,versionNumber:34,alignmentPatternCenters:[6,34,62,90,118,146],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:13,dataCodewordsPerBlock:115},{numBlocks:6,dataCodewordsPerBlock:116}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:14,dataCodewordsPerBlock:46},{numBlocks:23,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:44, +dataCodewordsPerBlock:24},{numBlocks:7,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:59,dataCodewordsPerBlock:16},{numBlocks:1,dataCodewordsPerBlock:17}]}]},{infoBits:145311,versionNumber:35,alignmentPatternCenters:[6,30,54,78,102,126,150],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:12,dataCodewordsPerBlock:121},{numBlocks:7,dataCodewordsPerBlock:122}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:12,dataCodewordsPerBlock:47},{numBlocks:26,dataCodewordsPerBlock:48}]}, +{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:39,dataCodewordsPerBlock:24},{numBlocks:14,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:22,dataCodewordsPerBlock:15},{numBlocks:41,dataCodewordsPerBlock:16}]}]},{infoBits:150283,versionNumber:36,alignmentPatternCenters:[6,24,50,76,102,128,154],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:6,dataCodewordsPerBlock:121},{numBlocks:14,dataCodewordsPerBlock:122}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:6, +dataCodewordsPerBlock:47},{numBlocks:34,dataCodewordsPerBlock:48}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:46,dataCodewordsPerBlock:24},{numBlocks:10,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:15},{numBlocks:64,dataCodewordsPerBlock:16}]}]},{infoBits:152622,versionNumber:37,alignmentPatternCenters:[6,28,54,80,106,132,158],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:122},{numBlocks:4,dataCodewordsPerBlock:123}]}, +{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:29,dataCodewordsPerBlock:46},{numBlocks:14,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:49,dataCodewordsPerBlock:24},{numBlocks:10,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:24,dataCodewordsPerBlock:15},{numBlocks:46,dataCodewordsPerBlock:16}]}]},{infoBits:158308,versionNumber:38,alignmentPatternCenters:[6,32,58,84,110,136,162],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:4, +dataCodewordsPerBlock:122},{numBlocks:18,dataCodewordsPerBlock:123}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:13,dataCodewordsPerBlock:46},{numBlocks:32,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:48,dataCodewordsPerBlock:24},{numBlocks:14,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:42,dataCodewordsPerBlock:15},{numBlocks:32,dataCodewordsPerBlock:16}]}]},{infoBits:161089,versionNumber:39,alignmentPatternCenters:[6,26,54,82,110,138,166], +errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:20,dataCodewordsPerBlock:117},{numBlocks:4,dataCodewordsPerBlock:118}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:40,dataCodewordsPerBlock:47},{numBlocks:7,dataCodewordsPerBlock:48}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:43,dataCodewordsPerBlock:24},{numBlocks:22,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:10,dataCodewordsPerBlock:15},{numBlocks:67,dataCodewordsPerBlock:16}]}]},{infoBits:167017, +versionNumber:40,alignmentPatternCenters:[6,30,58,86,114,142,170],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:19,dataCodewordsPerBlock:118},{numBlocks:6,dataCodewordsPerBlock:119}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:18,dataCodewordsPerBlock:47},{numBlocks:31,dataCodewordsPerBlock:48}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:34,dataCodewordsPerBlock:24},{numBlocks:34,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:20,dataCodewordsPerBlock:15}, +{numBlocks:61,dataCodewordsPerBlock:16}]}]}];function J(a,b){a^=b;for(b=0;a;)b++,a&=a-1;return b}function K(a,b){return b<<1|a} +let ia=[{bits:21522,formatInfo:{errorCorrectionLevel:1,dataMask:0}},{bits:20773,formatInfo:{errorCorrectionLevel:1,dataMask:1}},{bits:24188,formatInfo:{errorCorrectionLevel:1,dataMask:2}},{bits:23371,formatInfo:{errorCorrectionLevel:1,dataMask:3}},{bits:17913,formatInfo:{errorCorrectionLevel:1,dataMask:4}},{bits:16590,formatInfo:{errorCorrectionLevel:1,dataMask:5}},{bits:20375,formatInfo:{errorCorrectionLevel:1,dataMask:6}},{bits:19104,formatInfo:{errorCorrectionLevel:1,dataMask:7}},{bits:30660,formatInfo:{errorCorrectionLevel:0, +dataMask:0}},{bits:29427,formatInfo:{errorCorrectionLevel:0,dataMask:1}},{bits:32170,formatInfo:{errorCorrectionLevel:0,dataMask:2}},{bits:30877,formatInfo:{errorCorrectionLevel:0,dataMask:3}},{bits:26159,formatInfo:{errorCorrectionLevel:0,dataMask:4}},{bits:25368,formatInfo:{errorCorrectionLevel:0,dataMask:5}},{bits:27713,formatInfo:{errorCorrectionLevel:0,dataMask:6}},{bits:26998,formatInfo:{errorCorrectionLevel:0,dataMask:7}},{bits:5769,formatInfo:{errorCorrectionLevel:3,dataMask:0}},{bits:5054, +formatInfo:{errorCorrectionLevel:3,dataMask:1}},{bits:7399,formatInfo:{errorCorrectionLevel:3,dataMask:2}},{bits:6608,formatInfo:{errorCorrectionLevel:3,dataMask:3}},{bits:1890,formatInfo:{errorCorrectionLevel:3,dataMask:4}},{bits:597,formatInfo:{errorCorrectionLevel:3,dataMask:5}},{bits:3340,formatInfo:{errorCorrectionLevel:3,dataMask:6}},{bits:2107,formatInfo:{errorCorrectionLevel:3,dataMask:7}},{bits:13663,formatInfo:{errorCorrectionLevel:2,dataMask:0}},{bits:12392,formatInfo:{errorCorrectionLevel:2, +dataMask:1}},{bits:16177,formatInfo:{errorCorrectionLevel:2,dataMask:2}},{bits:14854,formatInfo:{errorCorrectionLevel:2,dataMask:3}},{bits:9396,formatInfo:{errorCorrectionLevel:2,dataMask:4}},{bits:8579,formatInfo:{errorCorrectionLevel:2,dataMask:5}},{bits:11994,formatInfo:{errorCorrectionLevel:2,dataMask:6}},{bits:11245,formatInfo:{errorCorrectionLevel:2,dataMask:7}}],ja=[a=>0===(a.y+a.x)%2,a=>0===a.y%2,a=>0===a.x%3,a=>0===(a.y+a.x)%3,a=>0===(Math.floor(a.y/2)+Math.floor(a.x/3))%2,a=>0===a.x*a.y% +2+a.x*a.y%3,a=>0===(a.y*a.x%2+a.y*a.x%3)%2,a=>0===((a.y+a.x)%2+a.y*a.x%3)%2]; +function ka(a,b,c){c=ja[c.dataMask];let d=a.height;var e=17+4*b.versionNumber;let f=x.createEmpty(e,e);f.setRegion(0,0,9,9,!0);f.setRegion(e-8,0,8,9,!0);f.setRegion(0,e-8,9,8,!0);for(var g of b.alignmentPatternCenters)for(var h of b.alignmentPatternCenters)6===g&&6===h||6===g&&h===e-7||g===e-7&&6===h||f.setRegion(g-2,h-2,5,5,!0);f.setRegion(6,9,1,e-17,!0);f.setRegion(9,6,e-17,1,!0);6n;n++){let q=k-n;if(!f.get(q,l)){h++;let r=a.get(q,l);c({y:l,x:q})&&(r=!r);g=g<<1|r;8===h&&(b.push(g),g=h=0)}}}e=!e}return b} +function la(a){var b=a.height,c=Math.floor((b-17)/4);if(6>=c)return I[c-1];c=0;for(var d=5;0<=d;d--)for(var e=b-9;e>=b-11;e--)c=K(a.get(e,d),c);d=0;for(e=5;0<=e;e--)for(let g=b-9;g>=b-11;g--)d=K(a.get(e,g),d);a=Infinity;let f;for(let g of I){if(g.infoBits===c||g.infoBits===d)return g;b=J(c,g.infoBits);b=a)return f} +function ma(a){let b=0;for(var c=0;8>=c;c++)6!==c&&(b=K(a.get(c,8),b));for(c=7;0<=c;c--)6!==c&&(b=K(a.get(8,c),b));var d=a.height;c=0;for(var e=d-1;e>=d-7;e--)c=K(a.get(8,e),c);for(e=d-8;e=a?d:null} +function na(a,b,c){let d=b.errorCorrectionLevels[c],e=[],f=0;d.ecBlocks.forEach(h=>{for(let k=0;ke+f.numDataCodewords,0);c=new Uint8ClampedArray(c);a=0;for(let e of d){d=ha(e.codewords,e.codewords.length-e.numDataCodewords);if(!d)return null;for(let f=0;f{const p=g*r+m*u+q;return{x:(e*r+h*u+l)/p,y:(f*r+k*u+n)/p}};for(let r=0;rMath.sqrt(Math.pow(b.x-a.x,2)+Math.pow(b.y-a.y,2));function O(a){return a.reduce((b,c)=>b+c)} +function qa(a,b,c){let d=N(a,b),e=N(b,c),f=N(a,c),g,h,k;e>=d&&e>=f?[g,h,k]=[b,a,c]:f>=e&&f>=d?[g,h,k]=[a,b,c]:[g,h,k]=[a,c,b];0>(k.x-h.x)*(g.y-h.y)-(k.y-h.y)*(g.x-h.x)&&([g,k]=[k,g]);return{bottomLeft:g,topLeft:h,topRight:k}} +function ra(a,b,c,d){d=(O(P(a,c,d,5))/7+O(P(a,b,d,5))/7+O(P(c,a,d,5))/7+O(P(b,a,d,5))/7)/4;if(1>d)throw Error("Invalid module size");b=Math.round(N(a,b)/d);a=Math.round(N(a,c)/d);a=Math.floor((b+a)/2)+7;switch(a%4){case 0:a++;break;case 2:a--}return{dimension:a,moduleSize:d}} +function Q(a,b,c,d){let e=[{x:Math.floor(a.x),y:Math.floor(a.y)}];var f=Math.abs(b.y-a.y)>Math.abs(b.x-a.x);if(f){var g=Math.floor(a.y);var h=Math.floor(a.x);a=Math.floor(b.y);b=Math.floor(b.x)}else g=Math.floor(a.x),h=Math.floor(a.y),a=Math.floor(b.x),b=Math.floor(b.y);let k=Math.abs(a-g),m=Math.abs(b-h),l=Math.floor(-k/2),n=g{d+=Math.pow(a[f]-e*c,2)});return{averageSize:c,error:d}} +function S(a,b,c){try{let d=P(a,{x:-1,y:a.y},c,b.length),e=P(a,{x:a.x,y:-1},c,b.length),f=P(a,{x:Math.max(0,a.x-a.y)-1,y:Math.max(0,a.y-a.x)-1},c,b.length),g=P(a,{x:Math.min(c.width,a.x+a.y)+1,y:Math.min(c.height,a.y+a.x)+1},c,b.length),h=R(d,b),k=R(e,b),m=R(f,b),l=R(g,b),n=(h.averageSize+k.averageSize+m.averageSize+l.averageSize)/4;return Math.sqrt(h.error*h.error+k.error*k.error+m.error*m.error+l.error*l.error)+(Math.pow(h.averageSize-n,2)+Math.pow(k.averageSize-n,2)+Math.pow(m.averageSize-n,2)+ +Math.pow(l.averageSize-n,2))/n}catch(d){return Infinity}}function T(a,b){for(var c=Math.round(b.x);a.get(c,Math.round(b.y));)c--;for(var d=Math.round(b.x);a.get(d,Math.round(b.y));)d++;c=(c+d)/2;for(d=Math.round(b.y);a.get(Math.round(c),d);)d--;for(b=Math.round(b.y);a.get(Math.round(c),b);)b++;return{x:c,y:(d+b)/2}} +function sa(a){var b=[],c=[];let d=[];var e=[];for(let p=0;p<=a.height;p++){var f=0,g=!1;let t=[0,0,0,0,0];for(let v=-1;v<=a.width;v++){var h=a.get(v,p);if(h===g)f++;else{t=[t[1],t[2],t[3],t[4],f];f=1;g=h;var k=O(t)/7;k=Math.abs(t[0]-k)y>=w.bottom.startX&& +y<=w.bottom.endX||z>=w.bottom.startX&&y<=w.bottom.endX||y<=w.bottom.startX&&z>=w.bottom.endX&&1.5>t[2]/(w.bottom.endX-w.bottom.startX)&&.5y>=w.bottom.startX&&y<=w.bottom.endX||z>=w.bottom.startX&&y<=w.bottom.endX||y<=w.bottom.startX&&z>=w.bottom.endX&&1.5>t[2]/(w.bottom.endX-w.bottom.startX)&&.5v.bottom.y!==p&&2<=v.bottom.y-v.top.y));c=c.filter(v=>v.bottom.y===p);d.push(...e.filter(v=>v.bottom.y!==p));e=e.filter(v=>v.bottom.y===p)}b.push(...c.filter(p=>2<=p.bottom.y-p.top.y));d.push(...e);c=[];for(var l of b)2>l.bottom.y-l.top.y||(b=(l.top.startX+l.top.endX+l.bottom.startX+l.bottom.endX)/4,e=(l.top.y+l.bottom.y+1)/2,a.get(Math.round(b),Math.round(e))&&(f=[l.top.endX-l.top.startX,l.bottom.endX-l.bottom.startX,l.bottom.y-l.top.y+ +1],f=O(f)/f.length,g=S({x:Math.round(b),y:Math.round(e)},[1,1,3,1,1],a),c.push({score:g,x:b,y:e,size:f})));if(3>c.length)return null;c.sort((p,t)=>p.score-t.score);l=[];for(b=0;bp.score-t.score);l.push({points:[e,f[0],f[1]],score:e.score+f[0].score+f[1].score})}l.sort((p,t)=>p.score-t.score);let {topRight:q,topLeft:r,bottomLeft:u}=qa(...l[0].points); +l=U(a,d,q,r,u);n=[];l&&n.push({alignmentPattern:{x:l.alignmentPattern.x,y:l.alignmentPattern.y},bottomLeft:{x:u.x,y:u.y},dimension:l.dimension,topLeft:{x:r.x,y:r.y},topRight:{x:q.x,y:q.y}});l=T(a,q);b=T(a,r);c=T(a,u);(a=U(a,d,l,b,c))&&n.push({alignmentPattern:{x:a.alignmentPattern.x,y:a.alignmentPattern.y},bottomLeft:{x:c.x,y:c.y},topLeft:{x:b.x,y:b.y},topRight:{x:l.x,y:l.y},dimension:a.dimension});return 0===n.length?null:n} +function U(a,b,c,d,e){let f,g;try{({dimension:f,moduleSize:g}=ra(d,c,e,a))}catch(l){return null}var h=c.x-d.x+e.x,k=c.y-d.y+e.y;c=(N(d,e)+N(d,c))/2/g;e=1-3/c;let m={x:d.x+e*(h-d.x),y:d.y+e*(k-d.y)};b=b.map(l=>{const n=(l.top.startX+l.top.endX+l.bottom.startX+l.bottom.endX)/4;l=(l.top.y+l.bottom.y+1)/2;if(a.get(Math.floor(n),Math.floor(l))){var q=S({x:Math.floor(n),y:Math.floor(l)},[1,1,1],a)+N({x:n,y:l},m);return{x:n,y:l,score:q}}}).filter(l=>!!l).sort((l,n)=>l.score-n.score);return{alignmentPattern:15<= +c&&b.length?b[0]:m,dimension:f}} +function V(a){var b=sa(a);if(!b)return null;for(let e of b){b=pa(a,e);var c=b.matrix;if(null==c)c=null;else{var d=L(c);if(d)c=d;else{for(d=0;d{a[c]=b[c]})} +function X(a,b,c,d={}){let e=Object.create(null);W(e,ta);W(e,d);d="onlyInvert"===e.inversionAttempts||"invertFirst"===e.inversionAttempts;var f="attemptBoth"===e.inversionAttempts||d;var g=e.greyScaleWeights,h=e.canOverwriteImage,k=b*c;if(a.length!==4*k)throw Error("Malformed data passed to binarizer.");var m=0;if(h){var l=new Uint8ClampedArray(a.buffer,m,k);m+=k}l=new A(b,c,l);if(g.useIntegerApproximation)for(var n=0;n>8)}else for(n=0;nv;v++)for(let w=0;8>w;w++){let aa=l.get(8*r+w,8*q+v);p=Math.min(p,aa);t=Math.max(t,aa)}v=(p+t)/2;v=Math.min(255,1.11*v);24>=t-p&&(v=p/2,0a?2:a>c?c:a;h=n-3;h=2>b?2:b>h?h:b;k=0;for(m=-2;2>=m;m++)for(p=-2;2>=p;p++)k+=u.get(c+m,h+p);c=k/25;for(h=0;8>h;h++)for(k=0;8>k;k++)m=8*a+h,p=8*b+k,t=l.get(m,p),q.set(m,p,t<=c),f&&r.set(m,p,!(t<=c))}f=f?{binarized:q,inverted:r}:{binarized:q};let {binarized:z,inverted:y}=f;(f=V(d? +y:z))||"attemptBoth"!==e.inversionAttempts&&"invertFirst"!==e.inversionAttempts||(f=V(d?z:y));return f}X.default=X;let Y="dontInvert",Z={red:77,green:150,blue:29,useIntegerApproximation:!0}; +self.onmessage=a=>{let b=a.data.id,c=a.data.data;switch(a.data.type){case "decode":(a=X(c.data,c.width,c.height,{inversionAttempts:Y,greyScaleWeights:Z}))?self.postMessage({id:b,type:"qrResult",data:a.data,cornerPoints:[a.location.topLeftCorner,a.location.topRightCorner,a.location.bottomRightCorner,a.location.bottomLeftCorner]}):self.postMessage({id:b,type:"qrResult",data:null});break;case "grayscaleWeights":Z.red=c.red;Z.green=c.green;Z.blue=c.blue;Z.useIntegerApproximation=c.useIntegerApproximation; +break;case "inversionMode":switch(c){case "original":Y="dontInvert";break;case "invert":Y="onlyInvert";break;case "both":Y="attemptBoth";break;default:throw Error("Invalid inversion mode");}break;case "close":self.close()}} +`]),{type:"application/javascript"}))//# sourceMappingURL=qr-scanner-worker.min.js.map diff --git a/client/qr-scanner-worker.min.js.map b/client/qr-scanner-worker.min.js.map new file mode 100644 index 0000000..618e36e --- /dev/null +++ b/client/qr-scanner-worker.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"qr-scanner-worker.min.js","sources":["node_modules/jsqr-es6/src/BitMatrix.ts","node_modules/jsqr-es6/src/binarizer/index.ts","node_modules/jsqr-es6/src/decoder/decodeData/BitStream.ts","node_modules/jsqr-es6/src/decoder/decodeData/index.ts","node_modules/jsqr-es6/src/decoder/reedsolomon/GenericGFPoly.ts","node_modules/jsqr-es6/src/decoder/reedsolomon/GenericGF.ts","node_modules/jsqr-es6/src/decoder/reedsolomon/index.ts","node_modules/jsqr-es6/src/decoder/version.ts","node_modules/jsqr-es6/src/decoder/decoder.ts","node_modules/jsqr-es6/src/extractor/index.ts","node_modules/jsqr-es6/src/locator/index.ts","node_modules/jsqr-es6/src/index.ts","src/worker.ts"],"sourcesContent":["export class BitMatrix {\n public static createEmpty(width: number, height: number) {\n return new BitMatrix(new Uint8ClampedArray(width * height), width);\n }\n\n public width: number;\n public height: number;\n private data: Uint8ClampedArray;\n\n constructor(data: Uint8ClampedArray, width: number) {\n this.width = width;\n this.height = data.length / width;\n this.data = data;\n }\n\n public get(x: number, y: number): boolean {\n if (x < 0 || x >= this.width || y < 0 || y >= this.height) {\n return false;\n }\n return !!this.data[y * this.width + x];\n }\n\n public set(x: number, y: number, v: boolean) {\n this.data[y * this.width + x] = v ? 1 : 0;\n }\n\n public setRegion(left: number, top: number, width: number, height: number, v: boolean) {\n for (let y = top; y < top + height; y++) {\n for (let x = left; x < left + width; x++) {\n this.set(x, y, !!v);\n }\n }\n }\n}\n","import {BitMatrix} from \"../BitMatrix\";\nimport {GreyscaleWeights} from \"../index\";\n\nconst REGION_SIZE = 8;\nconst MIN_DYNAMIC_RANGE = 24;\n\nfunction numBetween(value: number, min: number, max: number): number {\n return value < min ? min : value > max ? max : value;\n}\n\n// Like BitMatrix but accepts arbitry Uint8 values\nclass Matrix {\n private data: Uint8ClampedArray;\n private width: number;\n constructor(width: number, height: number, buffer?: Uint8ClampedArray) {\n this.width = width;\n const bufferSize = width * height;\n if (buffer && buffer.length !== bufferSize) {\n throw new Error(\"Wrong buffer size\");\n }\n this.data = buffer || new Uint8ClampedArray(bufferSize);\n }\n public get(x: number, y: number) {\n return this.data[y * this.width + x];\n }\n public set(x: number, y: number, value: number) {\n this.data[y * this.width + x] = value;\n }\n}\n\nexport function binarize(data: Uint8ClampedArray, width: number, height: number, returnInverted: boolean,\n greyscaleWeights: GreyscaleWeights, canOverwriteImage: boolean) {\n const pixelCount = width * height;\n if (data.length !== pixelCount * 4) {\n throw new Error(\"Malformed data passed to binarizer.\");\n }\n // assign the greyscale and binary image within the rgba buffer as the rgba image will not be needed after conversion\n let bufferOffset = 0;\n // Convert image to greyscale\n let greyscaleBuffer: Uint8ClampedArray;\n if (canOverwriteImage) {\n greyscaleBuffer = new Uint8ClampedArray(data.buffer, bufferOffset, pixelCount);\n bufferOffset += pixelCount;\n }\n const greyscalePixels = new Matrix(width, height, greyscaleBuffer);\n if (greyscaleWeights.useIntegerApproximation) {\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const pixelPosition = (y * width + x) * 4;\n const r = data[pixelPosition];\n const g = data[pixelPosition + 1];\n const b = data[pixelPosition + 2];\n greyscalePixels.set(x, y,\n // tslint:disable-next-line no-bitwise\n (greyscaleWeights.red * r + greyscaleWeights.green * g + greyscaleWeights.blue * b + 128) >> 8);\n }\n }\n } else {\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const pixelPosition = (y * width + x) * 4;\n const r = data[pixelPosition];\n const g = data[pixelPosition + 1];\n const b = data[pixelPosition + 2];\n greyscalePixels.set(x, y,\n greyscaleWeights.red * r + greyscaleWeights.green * g + greyscaleWeights.blue * b);\n }\n }\n }\n const horizontalRegionCount = Math.ceil(width / REGION_SIZE);\n const verticalRegionCount = Math.ceil(height / REGION_SIZE);\n const blackPointsCount = horizontalRegionCount * verticalRegionCount;\n\n let blackPointsBuffer: Uint8ClampedArray;\n if (canOverwriteImage) {\n blackPointsBuffer = new Uint8ClampedArray(data.buffer, bufferOffset, blackPointsCount);\n bufferOffset += blackPointsCount;\n }\n const blackPoints = new Matrix(horizontalRegionCount, verticalRegionCount, blackPointsBuffer);\n for (let verticalRegion = 0; verticalRegion < verticalRegionCount; verticalRegion++) {\n for (let hortizontalRegion = 0; hortizontalRegion < horizontalRegionCount; hortizontalRegion++) {\n let min = Infinity;\n let max = 0;\n for (let y = 0; y < REGION_SIZE; y++) {\n for (let x = 0; x < REGION_SIZE; x++) {\n const pixelLumosity =\n greyscalePixels.get(hortizontalRegion * REGION_SIZE + x, verticalRegion * REGION_SIZE + y);\n min = Math.min(min, pixelLumosity);\n max = Math.max(max, pixelLumosity);\n }\n }\n // We could also compute the real average of all pixels but following the assumption that the qr code consists\n // of bright and dark pixels and essentially not much in between, by (min + max)/2 we make the cut really between\n // those two classes. If using the average over all pixel in a block of mostly bright pixels and few dark pixels,\n // the avg would tend to the bright side and darker bright pixels could be interpreted as dark.\n let average = (min + max) / 2;\n // Small bias towards black by moving the threshold up. We do this, as in the finder patterns white holes tend\n // to appear which makes them undetectable.\n const blackBias = 1.11;\n average = Math.min(255, average * blackBias);\n if (max - min <= MIN_DYNAMIC_RANGE) {\n // If variation within the block is low, assume this is a block with only light or only\n // dark pixels. In that case we do not want to use the average, as it would divide this\n // low contrast area into black and white pixels, essentially creating data out of noise.\n //\n // Default the blackpoint for these blocks to be half the min - effectively white them out\n average = min / 2;\n\n if (verticalRegion > 0 && hortizontalRegion > 0) {\n // Correct the \"white background\" assumption for blocks that have neighbors by comparing\n // the pixels in this block to the previously calculated black points. This is based on\n // the fact that dark barcode symbology is always surrounded by some amount of light\n // background for which reasonable black point estimates were made. The bp estimated at\n // the boundaries is used for the interior.\n\n // The (min < bp) is arbitrary but works better than other heuristics that were tried.\n const averageNeighborBlackPoint = (\n blackPoints.get(hortizontalRegion, verticalRegion - 1) +\n (2 * blackPoints.get(hortizontalRegion - 1, verticalRegion)) +\n blackPoints.get(hortizontalRegion - 1, verticalRegion - 1)\n ) / 4;\n if (min < averageNeighborBlackPoint) {\n average = averageNeighborBlackPoint; // no need to apply black bias as already applied to neighbors\n }\n }\n }\n blackPoints.set(hortizontalRegion, verticalRegion, average);\n }\n }\n\n let binarized: BitMatrix;\n if (canOverwriteImage) {\n const binarizedBuffer = new Uint8ClampedArray(data.buffer, bufferOffset, pixelCount);\n bufferOffset += pixelCount;\n binarized = new BitMatrix(binarizedBuffer, width);\n } else {\n binarized = BitMatrix.createEmpty(width, height);\n }\n\n let inverted: BitMatrix = null;\n if (returnInverted) {\n if (canOverwriteImage) {\n const invertedBuffer = new Uint8ClampedArray(data.buffer, bufferOffset, pixelCount);\n inverted = new BitMatrix(invertedBuffer, width);\n } else {\n inverted = BitMatrix.createEmpty(width, height);\n }\n }\n\n for (let verticalRegion = 0; verticalRegion < verticalRegionCount; verticalRegion++) {\n for (let hortizontalRegion = 0; hortizontalRegion < horizontalRegionCount; hortizontalRegion++) {\n const left = numBetween(hortizontalRegion, 2, horizontalRegionCount - 3);\n const top = numBetween(verticalRegion, 2, verticalRegionCount - 3);\n let sum = 0;\n for (let xRegion = -2; xRegion <= 2; xRegion++) {\n for (let yRegion = -2; yRegion <= 2; yRegion++) {\n sum += blackPoints.get(left + xRegion, top + yRegion);\n }\n }\n const threshold = sum / 25;\n for (let xRegion = 0; xRegion < REGION_SIZE; xRegion++) {\n for (let yRegion = 0; yRegion < REGION_SIZE; yRegion++) {\n const x = hortizontalRegion * REGION_SIZE + xRegion;\n const y = verticalRegion * REGION_SIZE + yRegion;\n const lum = greyscalePixels.get(x, y);\n binarized.set(x, y, lum <= threshold);\n if (returnInverted) {\n inverted.set(x, y, !(lum <= threshold));\n }\n }\n }\n }\n }\n if (returnInverted) {\n return { binarized, inverted };\n }\n return { binarized };\n}\n","// tslint:disable:no-bitwise\n\nexport class BitStream {\n private bytes: Uint8ClampedArray;\n private byteOffset: number = 0;\n private bitOffset: number = 0;\n\n constructor(bytes: Uint8ClampedArray) {\n this.bytes = bytes;\n }\n\n public readBits(numBits: number): number {\n if (numBits < 1 || numBits > 32 || numBits > this.available()) {\n throw new Error(\"Cannot read \" + numBits.toString() + \" bits\");\n }\n\n let result = 0;\n // First, read remainder from current byte\n if (this.bitOffset > 0) {\n const bitsLeft = 8 - this.bitOffset;\n const toRead = numBits < bitsLeft ? numBits : bitsLeft;\n const bitsToNotRead = bitsLeft - toRead;\n const mask = (0xFF >> (8 - toRead)) << bitsToNotRead;\n result = (this.bytes[this.byteOffset] & mask) >> bitsToNotRead;\n numBits -= toRead;\n this.bitOffset += toRead;\n if (this.bitOffset === 8) {\n this.bitOffset = 0;\n this.byteOffset++;\n }\n }\n\n // Next read whole bytes\n if (numBits > 0) {\n while (numBits >= 8) {\n result = (result << 8) | (this.bytes[this.byteOffset] & 0xFF);\n this.byteOffset++;\n numBits -= 8;\n }\n\n // Finally read a partial byte\n if (numBits > 0) {\n const bitsToNotRead = 8 - numBits;\n const mask = (0xFF >> bitsToNotRead) << bitsToNotRead;\n result = (result << numBits) | ((this.bytes[this.byteOffset] & mask) >> bitsToNotRead);\n this.bitOffset += numBits;\n }\n }\n return result;\n }\n\n public available(): number {\n return 8 * (this.bytes.length - this.byteOffset) - this.bitOffset;\n }\n}\n","// tslint:disable:no-bitwise\nimport { BitStream } from \"./BitStream\";\n\nexport interface Chunk {\n type: Mode;\n text: string;\n}\n\nexport interface ByteChunk {\n type: Mode.Byte | Mode.Kanji;\n bytes: number[];\n}\n\nexport interface ECIChunk {\n type: Mode.ECI;\n assignmentNumber: number;\n}\n\nexport interface StructuredAppend {\n type: Mode.StructuredAppend;\n currentSequence: number;\n totalSequence: number;\n parity: number;\n}\n\nexport type Chunks = Array;\n\nexport interface DecodedQR {\n text: string;\n bytes: number[];\n chunks: Chunks;\n version: number;\n}\n\nexport enum Mode {\n Numeric = \"numeric\",\n Alphanumeric = \"alphanumeric\",\n Byte = \"byte\",\n Kanji = \"kanji\",\n ECI = \"eci\",\n StructuredAppend = \"structuredappend\",\n}\n\nenum ModeByte {\n Terminator = 0x0,\n Numeric = 0x1,\n Alphanumeric = 0x2,\n Byte = 0x4,\n Kanji = 0x8,\n ECI = 0x7,\n StructuredAppend = 0x3,\n // FNC1FirstPosition = 0x5,\n // FNC1SecondPosition = 0x9,\n}\n\nfunction decodeNumeric(stream: BitStream, size: number) {\n const bytes: number[] = [];\n let text = \"\";\n\n const characterCountSize = [10, 12, 14][size];\n let length = stream.readBits(characterCountSize);\n // Read digits in groups of 3\n while (length >= 3) {\n const num = stream.readBits(10);\n if (num >= 1000) {\n throw new Error(\"Invalid numeric value above 999\");\n }\n\n const a = Math.floor(num / 100);\n const b = Math.floor(num / 10) % 10;\n const c = num % 10;\n\n bytes.push(48 + a, 48 + b, 48 + c);\n text += a.toString() + b.toString() + c.toString();\n length -= 3;\n }\n\n // If the number of digits aren't a multiple of 3, the remaining digits are special cased.\n if (length === 2) {\n const num = stream.readBits(7);\n if (num >= 100) {\n throw new Error(\"Invalid numeric value above 99\");\n }\n\n const a = Math.floor(num / 10);\n const b = num % 10;\n\n bytes.push(48 + a, 48 + b);\n text += a.toString() + b.toString();\n } else if (length === 1) {\n const num = stream.readBits(4);\n if (num >= 10) {\n throw new Error(\"Invalid numeric value above 9\");\n }\n\n bytes.push(48 + num);\n text += num.toString();\n }\n\n return { bytes, text };\n}\n\nconst AlphanumericCharacterCodes = [\n \"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\",\n \"9\", \"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\",\n \"I\", \"J\", \"K\", \"L\", \"M\", \"N\", \"O\", \"P\", \"Q\",\n \"R\", \"S\", \"T\", \"U\", \"V\", \"W\", \"X\", \"Y\", \"Z\",\n \" \", \"$\", \"%\", \"*\", \"+\", \"-\", \".\", \"/\", \":\",\n];\n\nfunction decodeAlphanumeric(stream: BitStream, size: number) {\n const bytes: number[] = [];\n let text = \"\";\n\n const characterCountSize = [9, 11, 13][size];\n let length = stream.readBits(characterCountSize);\n while (length >= 2) {\n const v = stream.readBits(11);\n\n const a = Math.floor(v / 45);\n const b = v % 45;\n\n bytes.push(AlphanumericCharacterCodes[a].charCodeAt(0), AlphanumericCharacterCodes[b].charCodeAt(0));\n text += AlphanumericCharacterCodes[a] + AlphanumericCharacterCodes[b];\n length -= 2;\n }\n\n if (length === 1) {\n const a = stream.readBits(6);\n bytes.push(AlphanumericCharacterCodes[a].charCodeAt(0));\n text += AlphanumericCharacterCodes[a];\n }\n\n return { bytes, text };\n}\n\nfunction decodeByte(stream: BitStream, size: number) {\n const bytes: number[] = [];\n let text = \"\";\n\n const characterCountSize = [8, 16, 16][size];\n const length = stream.readBits(characterCountSize);\n for (let i = 0; i < length; i++) {\n const b = stream.readBits(8);\n bytes.push(b);\n }\n try {\n text += decodeURIComponent(bytes.map(b => `%${(\"0\" + b.toString(16)).substr(-2)}`).join(\"\"));\n } catch {\n // failed to decode\n }\n\n return { bytes, text };\n}\n\nfunction decodeKanji(stream: BitStream, size: number) {\n const bytes: number[] = [];\n\n const characterCountSize = [8, 10, 12][size];\n const length = stream.readBits(characterCountSize);\n for (let i = 0; i < length; i++) {\n const k = stream.readBits(13);\n\n let c = (Math.floor(k / 0xC0) << 8) | (k % 0xC0);\n if (c < 0x1F00) {\n c += 0x8140;\n } else {\n c += 0xC140;\n }\n\n bytes.push(c >> 8, c & 0xFF);\n }\n\n const text = new TextDecoder(\"shift-jis\").decode(Uint8Array.from(bytes));\n return { bytes, text };\n}\n\nexport function decode(data: Uint8ClampedArray, version: number): DecodedQR {\n const stream = new BitStream(data);\n\n // There are 3 'sizes' based on the version. 1-9 is small (0), 10-26 is medium (1) and 27-40 is large (2).\n const size = version <= 9 ? 0 : version <= 26 ? 1 : 2;\n\n const result: DecodedQR = {\n text: \"\",\n bytes: [],\n chunks: [],\n version,\n };\n\n while (stream.available() >= 4) {\n const mode = stream.readBits(4);\n if (mode === ModeByte.Terminator) {\n return result;\n } else if (mode === ModeByte.ECI) {\n if (stream.readBits(1) === 0) {\n result.chunks.push({\n type: Mode.ECI,\n assignmentNumber: stream.readBits(7),\n });\n } else if (stream.readBits(1) === 0) {\n result.chunks.push({\n type: Mode.ECI,\n assignmentNumber: stream.readBits(14),\n });\n } else if (stream.readBits(1) === 0) {\n result.chunks.push({\n type: Mode.ECI,\n assignmentNumber: stream.readBits(21),\n });\n } else {\n // ECI data seems corrupted\n result.chunks.push({\n type: Mode.ECI,\n assignmentNumber: -1,\n });\n }\n } else if (mode === ModeByte.Numeric) {\n const numericResult = decodeNumeric(stream, size);\n result.text += numericResult.text;\n result.bytes.push(...numericResult.bytes);\n result.chunks.push({\n type: Mode.Numeric,\n text: numericResult.text,\n });\n } else if (mode === ModeByte.Alphanumeric) {\n const alphanumericResult = decodeAlphanumeric(stream, size);\n result.text += alphanumericResult.text;\n result.bytes.push(...alphanumericResult.bytes);\n result.chunks.push({\n type: Mode.Alphanumeric,\n text: alphanumericResult.text,\n });\n } else if (mode === ModeByte.Byte) {\n const byteResult = decodeByte(stream, size);\n result.text += byteResult.text;\n result.bytes.push(...byteResult.bytes);\n result.chunks.push({\n type: Mode.Byte,\n bytes: byteResult.bytes,\n text: byteResult.text,\n });\n } else if (mode === ModeByte.Kanji) {\n const kanjiResult = decodeKanji(stream, size);\n result.text += kanjiResult.text;\n result.bytes.push(...kanjiResult.bytes);\n result.chunks.push({\n type: Mode.Kanji,\n bytes: kanjiResult.bytes,\n text: kanjiResult.text,\n });\n } else if (mode === ModeByte.StructuredAppend) {\n result.chunks.push({\n type: Mode.StructuredAppend,\n currentSequence: stream.readBits(4),\n totalSequence: stream.readBits(4),\n parity: stream.readBits(8),\n });\n }\n }\n\n // If there is no data left, or the remaining bits are all 0, then that counts as a termination marker\n if (stream.available() === 0 || stream.readBits(stream.available()) === 0) {\n return result;\n }\n}\n","import GenericGF, { addOrSubtractGF } from \"./GenericGF\";\n\nexport default class GenericGFPoly {\n private field: GenericGF;\n private coefficients: Uint8ClampedArray;\n\n constructor(field: GenericGF, coefficients: Uint8ClampedArray) {\n if (coefficients.length === 0) {\n throw new Error(\"No coefficients.\");\n }\n this.field = field;\n const coefficientsLength = coefficients.length;\n if (coefficientsLength > 1 && coefficients[0] === 0) {\n // Leading term must be non-zero for anything except the constant polynomial \"0\"\n let firstNonZero = 1;\n while (firstNonZero < coefficientsLength && coefficients[firstNonZero] === 0) {\n firstNonZero++;\n }\n if (firstNonZero === coefficientsLength) {\n this.coefficients = field.zero.coefficients;\n } else {\n this.coefficients = new Uint8ClampedArray(coefficientsLength - firstNonZero);\n for (let i = 0; i < this.coefficients.length; i++) {\n this.coefficients[i] = coefficients[firstNonZero + i];\n }\n }\n } else {\n this.coefficients = coefficients;\n }\n }\n\n public degree() {\n return this.coefficients.length - 1;\n }\n\n public isZero() {\n return this.coefficients[0] === 0;\n }\n\n public getCoefficient(degree: number) {\n return this.coefficients[this.coefficients.length - 1 - degree];\n }\n\n public addOrSubtract(other: GenericGFPoly) {\n if (this.isZero()) {\n return other;\n }\n if (other.isZero()) {\n return this;\n }\n\n let smallerCoefficients = this.coefficients;\n let largerCoefficients = other.coefficients;\n if (smallerCoefficients.length > largerCoefficients.length) {\n [smallerCoefficients, largerCoefficients] = [largerCoefficients, smallerCoefficients];\n }\n const sumDiff = new Uint8ClampedArray(largerCoefficients.length);\n const lengthDiff = largerCoefficients.length - smallerCoefficients.length;\n for (let i = 0; i < lengthDiff; i++) {\n sumDiff[i] = largerCoefficients[i];\n }\n\n for (let i = lengthDiff; i < largerCoefficients.length; i++) {\n sumDiff[i] = addOrSubtractGF(smallerCoefficients[i - lengthDiff], largerCoefficients[i]);\n }\n\n return new GenericGFPoly(this.field, sumDiff);\n }\n\n public multiply(scalar: number) {\n if (scalar === 0) {\n return this.field.zero;\n }\n if (scalar === 1) {\n return this;\n }\n const size = this.coefficients.length;\n const product = new Uint8ClampedArray(size);\n for (let i = 0; i < size; i++) {\n product[i] = this.field.multiply(this.coefficients[i], scalar);\n }\n\n return new GenericGFPoly(this.field, product);\n }\n\n public multiplyPoly(other: GenericGFPoly): GenericGFPoly {\n if (this.isZero() || other.isZero()) {\n return this.field.zero;\n }\n const aCoefficients = this.coefficients;\n const aLength = aCoefficients.length;\n const bCoefficients = other.coefficients;\n const bLength = bCoefficients.length;\n const product = new Uint8ClampedArray(aLength + bLength - 1);\n for (let i = 0; i < aLength; i++) {\n const aCoeff = aCoefficients[i];\n for (let j = 0; j < bLength; j++) {\n product[i + j] = addOrSubtractGF(product[i + j],\n this.field.multiply(aCoeff, bCoefficients[j]));\n }\n }\n return new GenericGFPoly(this.field, product);\n }\n\n public multiplyByMonomial(degree: number, coefficient: number) {\n if (degree < 0) {\n throw new Error(\"Invalid degree less than 0\");\n }\n if (coefficient === 0) {\n return this.field.zero;\n }\n const size = this.coefficients.length;\n const product = new Uint8ClampedArray(size + degree);\n for (let i = 0; i < size; i++) {\n product[i] = this.field.multiply(this.coefficients[i], coefficient);\n }\n return new GenericGFPoly(this.field, product);\n }\n\n public evaluateAt(a: number) {\n let result = 0;\n if (a === 0) {\n // Just return the x^0 coefficient\n return this.getCoefficient(0);\n }\n const size = this.coefficients.length;\n if (a === 1) {\n // Just the sum of the coefficients\n this.coefficients.forEach((coefficient) => {\n result = addOrSubtractGF(result, coefficient);\n });\n return result;\n }\n result = this.coefficients[0];\n for (let i = 1; i < size; i++) {\n result = addOrSubtractGF(this.field.multiply(a, result), this.coefficients[i]);\n }\n return result;\n }\n}\n","import GenericGFPoly from \"./GenericGFPoly\";\n\nexport function addOrSubtractGF(a: number, b: number) {\n return a ^ b; // tslint:disable-line:no-bitwise\n}\n\nexport default class GenericGF {\n public primitive: number;\n public size: number;\n public generatorBase: number;\n public zero: GenericGFPoly;\n public one: GenericGFPoly;\n\n private expTable: number[];\n private logTable: number[];\n\n constructor(primitive: number, size: number, genBase: number) {\n this.primitive = primitive;\n this.size = size;\n this.generatorBase = genBase;\n this.expTable = new Array(this.size);\n this.logTable = new Array(this.size);\n\n let x = 1;\n for (let i = 0; i < this.size; i++) {\n this.expTable[i] = x;\n x = x * 2;\n if (x >= this.size) {\n x = (x ^ this.primitive) & (this.size - 1); // tslint:disable-line:no-bitwise\n }\n }\n\n for (let i = 0; i < this.size - 1; i++) {\n this.logTable[this.expTable[i]] = i;\n }\n this.zero = new GenericGFPoly(this, Uint8ClampedArray.from([0]));\n this.one = new GenericGFPoly(this, Uint8ClampedArray.from([1]));\n }\n\n public multiply(a: number, b: number) {\n if (a === 0 || b === 0) {\n return 0;\n }\n return this.expTable[(this.logTable[a] + this.logTable[b]) % (this.size - 1)];\n }\n\n public inverse(a: number) {\n if (a === 0) {\n throw new Error(\"Can't invert 0\");\n }\n return this.expTable[this.size - this.logTable[a] - 1];\n }\n\n public buildMonomial(degree: number, coefficient: number): GenericGFPoly {\n if (degree < 0) {\n throw new Error(\"Invalid monomial degree less than 0\");\n }\n if (coefficient === 0) {\n return this.zero;\n }\n const coefficients = new Uint8ClampedArray(degree + 1);\n coefficients[0] = coefficient;\n return new GenericGFPoly(this, coefficients);\n }\n\n public log(a: number) {\n if (a === 0) {\n throw new Error(\"Can't take log(0)\");\n }\n return this.logTable[a];\n }\n\n public exp(a: number) {\n return this.expTable[a];\n }\n}\n","import GenericGF, { addOrSubtractGF } from \"./GenericGF\";\nimport GenericGFPoly from \"./GenericGFPoly\";\n\nfunction runEuclideanAlgorithm(field: GenericGF, a: GenericGFPoly, b: GenericGFPoly, R: number): GenericGFPoly[] {\n // Assume a's degree is >= b's\n if (a.degree() < b.degree()) {\n [a, b] = [b, a];\n }\n\n let rLast = a;\n let r = b;\n let tLast = field.zero;\n let t = field.one;\n\n // Run Euclidean algorithm until r's degree is less than R/2\n while (r.degree() >= R / 2) {\n const rLastLast = rLast;\n const tLastLast = tLast;\n rLast = r;\n tLast = t;\n\n // Divide rLastLast by rLast, with quotient in q and remainder in r\n if (rLast.isZero()) {\n // Euclidean algorithm already terminated?\n return null;\n }\n r = rLastLast;\n let q = field.zero;\n const denominatorLeadingTerm = rLast.getCoefficient(rLast.degree());\n const dltInverse = field.inverse(denominatorLeadingTerm);\n while (r.degree() >= rLast.degree() && !r.isZero()) {\n const degreeDiff = r.degree() - rLast.degree();\n const scale = field.multiply(r.getCoefficient(r.degree()), dltInverse);\n q = q.addOrSubtract(field.buildMonomial(degreeDiff, scale));\n r = r.addOrSubtract(rLast.multiplyByMonomial(degreeDiff, scale));\n }\n\n t = q.multiplyPoly(tLast).addOrSubtract(tLastLast);\n\n if (r.degree() >= rLast.degree()) {\n return null;\n }\n }\n\n const sigmaTildeAtZero = t.getCoefficient(0);\n if (sigmaTildeAtZero === 0) {\n return null;\n }\n\n const inverse = field.inverse(sigmaTildeAtZero);\n return [t.multiply(inverse), r.multiply(inverse)];\n}\n\nfunction findErrorLocations(field: GenericGF, errorLocator: GenericGFPoly): number[] {\n // This is a direct application of Chien's search\n const numErrors = errorLocator.degree();\n if (numErrors === 1) {\n return [errorLocator.getCoefficient(1)];\n }\n const result: number[] = new Array(numErrors);\n let errorCount = 0;\n for (let i = 1; i < field.size && errorCount < numErrors; i++) {\n if (errorLocator.evaluateAt(i) === 0) {\n result[errorCount] = field.inverse(i);\n errorCount++;\n }\n }\n if (errorCount !== numErrors) {\n return null;\n }\n return result;\n}\n\nfunction findErrorMagnitudes(field: GenericGF, errorEvaluator: GenericGFPoly, errorLocations: number[]): number[] {\n // This is directly applying Forney's Formula\n const s = errorLocations.length;\n const result: number[] = new Array(s);\n for (let i = 0; i < s; i++) {\n const xiInverse = field.inverse(errorLocations[i]);\n let denominator = 1;\n for (let j = 0; j < s; j++) {\n if (i !== j) {\n denominator = field.multiply(denominator, addOrSubtractGF(1, field.multiply(errorLocations[j], xiInverse)));\n }\n }\n result[i] = field.multiply(errorEvaluator.evaluateAt(xiInverse), field.inverse(denominator));\n if (field.generatorBase !== 0) {\n result[i] = field.multiply(result[i], xiInverse);\n }\n }\n return result;\n}\n\nexport function decode(bytes: number[], twoS: number) {\n const outputBytes = new Uint8ClampedArray(bytes.length);\n outputBytes.set(bytes);\n\n const field = new GenericGF(0x011D, 256, 0); // x^8 + x^4 + x^3 + x^2 + 1\n const poly = new GenericGFPoly(field, outputBytes);\n\n const syndromeCoefficients = new Uint8ClampedArray(twoS);\n let error = false;\n for (let s = 0; s < twoS; s++) {\n const evaluation = poly.evaluateAt(field.exp(s + field.generatorBase));\n syndromeCoefficients[syndromeCoefficients.length - 1 - s] = evaluation;\n if (evaluation !== 0) {\n error = true;\n }\n }\n if (!error) {\n return outputBytes;\n }\n\n const syndrome = new GenericGFPoly(field, syndromeCoefficients);\n\n const sigmaOmega = runEuclideanAlgorithm(field, field.buildMonomial(twoS, 1), syndrome, twoS);\n if (sigmaOmega === null) {\n return null;\n }\n\n const errorLocations = findErrorLocations(field, sigmaOmega[0]);\n if (errorLocations == null) {\n return null;\n }\n\n const errorMagnitudes = findErrorMagnitudes(field, sigmaOmega[1], errorLocations);\n for (let i = 0; i < errorLocations.length; i++) {\n const position = outputBytes.length - 1 - field.log(errorLocations[i]);\n if (position < 0) {\n return null;\n }\n outputBytes[position] = addOrSubtractGF(outputBytes[position], errorMagnitudes[i]);\n }\n\n return outputBytes;\n}\n","export interface Version {\n infoBits: number;\n versionNumber: number;\n alignmentPatternCenters: number[];\n errorCorrectionLevels: Array<{\n ecCodewordsPerBlock: number;\n ecBlocks: Array<{\n numBlocks: number;\n dataCodewordsPerBlock: number;\n }>\n }>;\n}\n\nexport const VERSIONS: Version[] = [\n {\n infoBits: null,\n versionNumber: 1,\n alignmentPatternCenters: [],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 7,\n ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 19 }],\n },\n {\n ecCodewordsPerBlock: 10,\n ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 16 }],\n },\n {\n ecCodewordsPerBlock: 13,\n ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 13 }],\n },\n {\n ecCodewordsPerBlock: 17,\n ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 9 }],\n },\n ],\n },\n {\n infoBits: null,\n versionNumber: 2,\n alignmentPatternCenters: [6, 18],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 10,\n ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 34 }],\n },\n {\n ecCodewordsPerBlock: 16,\n ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 28 }],\n },\n {\n ecCodewordsPerBlock: 22,\n ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 22 }],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 16 }],\n },\n ],\n },\n {\n infoBits: null,\n versionNumber: 3,\n alignmentPatternCenters: [6, 22],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 15,\n ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 55 }],\n },\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 44 }],\n },\n {\n ecCodewordsPerBlock: 18,\n ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 17 }],\n },\n {\n ecCodewordsPerBlock: 22,\n ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 13 }],\n },\n ],\n },\n {\n infoBits: null,\n versionNumber: 4,\n alignmentPatternCenters: [6, 26],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 20,\n ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 80 }],\n },\n {\n ecCodewordsPerBlock: 18,\n ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 32 }],\n },\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 24 }],\n },\n {\n ecCodewordsPerBlock: 16,\n ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 9 }],\n },\n ],\n },\n {\n infoBits: null,\n versionNumber: 5,\n alignmentPatternCenters: [6, 30],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 108 }],\n },\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 43 }],\n },\n {\n ecCodewordsPerBlock: 18,\n ecBlocks: [\n { numBlocks: 2, dataCodewordsPerBlock: 15 },\n { numBlocks: 2, dataCodewordsPerBlock: 16 },\n ],\n },\n {\n ecCodewordsPerBlock: 22,\n ecBlocks: [\n { numBlocks: 2, dataCodewordsPerBlock: 11 },\n { numBlocks: 2, dataCodewordsPerBlock: 12 },\n ],\n },\n ],\n },\n {\n infoBits: null,\n versionNumber: 6,\n alignmentPatternCenters: [6, 34],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 18,\n ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 68 }],\n },\n {\n ecCodewordsPerBlock: 16,\n ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 27 }],\n },\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 19 }],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 15 }],\n },\n ],\n },\n {\n infoBits: 0x07C94,\n versionNumber: 7,\n alignmentPatternCenters: [6, 22, 38],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 20,\n ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 78 }],\n },\n {\n ecCodewordsPerBlock: 18,\n ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 31 }],\n },\n {\n ecCodewordsPerBlock: 18,\n ecBlocks: [\n { numBlocks: 2, dataCodewordsPerBlock: 14 },\n { numBlocks: 4, dataCodewordsPerBlock: 15 },\n ],\n },\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 13 },\n { numBlocks: 1, dataCodewordsPerBlock: 14 },\n ],\n },\n ],\n },\n {\n infoBits: 0x085BC,\n versionNumber: 8,\n alignmentPatternCenters: [6, 24, 42],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 97 }],\n },\n {\n ecCodewordsPerBlock: 22,\n ecBlocks: [\n { numBlocks: 2, dataCodewordsPerBlock: 38 },\n { numBlocks: 2, dataCodewordsPerBlock: 39 },\n ],\n },\n {\n ecCodewordsPerBlock: 22,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 18 },\n { numBlocks: 2, dataCodewordsPerBlock: 19 },\n ],\n },\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 14 },\n { numBlocks: 2, dataCodewordsPerBlock: 15 },\n ],\n },\n ],\n },\n {\n infoBits: 0x09A99,\n versionNumber: 9,\n alignmentPatternCenters: [6, 26, 46],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 116 }],\n },\n {\n ecCodewordsPerBlock: 22,\n ecBlocks: [\n { numBlocks: 3, dataCodewordsPerBlock: 36 },\n { numBlocks: 2, dataCodewordsPerBlock: 37 },\n ],\n },\n {\n ecCodewordsPerBlock: 20,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 16 },\n { numBlocks: 4, dataCodewordsPerBlock: 17 },\n ],\n },\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 12 },\n { numBlocks: 4, dataCodewordsPerBlock: 13 },\n ],\n },\n ],\n },\n {\n infoBits: 0x0A4D3,\n versionNumber: 10,\n alignmentPatternCenters: [6, 28, 50],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 18,\n ecBlocks: [\n { numBlocks: 2, dataCodewordsPerBlock: 68 },\n { numBlocks: 2, dataCodewordsPerBlock: 69 },\n ],\n },\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 43 },\n { numBlocks: 1, dataCodewordsPerBlock: 44 },\n ],\n },\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [\n { numBlocks: 6, dataCodewordsPerBlock: 19 },\n { numBlocks: 2, dataCodewordsPerBlock: 20 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 6, dataCodewordsPerBlock: 15 },\n { numBlocks: 2, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x0BBF6,\n versionNumber: 11,\n alignmentPatternCenters: [6, 30, 54],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 20,\n ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 81 }],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 1, dataCodewordsPerBlock: 50 },\n { numBlocks: 4, dataCodewordsPerBlock: 51 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 22 },\n { numBlocks: 4, dataCodewordsPerBlock: 23 },\n ],\n },\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [\n { numBlocks: 3, dataCodewordsPerBlock: 12 },\n { numBlocks: 8, dataCodewordsPerBlock: 13 },\n ],\n },\n ],\n },\n {\n infoBits: 0x0C762,\n versionNumber: 12,\n alignmentPatternCenters: [6, 32, 58],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [\n { numBlocks: 2, dataCodewordsPerBlock: 92 },\n { numBlocks: 2, dataCodewordsPerBlock: 93 },\n ],\n },\n {\n ecCodewordsPerBlock: 22,\n ecBlocks: [\n { numBlocks: 6, dataCodewordsPerBlock: 36 },\n { numBlocks: 2, dataCodewordsPerBlock: 37 },\n ],\n },\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 20 },\n { numBlocks: 6, dataCodewordsPerBlock: 21 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 7, dataCodewordsPerBlock: 14 },\n { numBlocks: 4, dataCodewordsPerBlock: 15 },\n ],\n },\n ],\n },\n {\n infoBits: 0x0D847,\n versionNumber: 13,\n alignmentPatternCenters: [6, 34, 62],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 107 }],\n },\n {\n ecCodewordsPerBlock: 22,\n ecBlocks: [\n { numBlocks: 8, dataCodewordsPerBlock: 37 },\n { numBlocks: 1, dataCodewordsPerBlock: 38 },\n ],\n },\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [\n { numBlocks: 8, dataCodewordsPerBlock: 20 },\n { numBlocks: 4, dataCodewordsPerBlock: 21 },\n ],\n },\n {\n ecCodewordsPerBlock: 22,\n ecBlocks: [\n { numBlocks: 12, dataCodewordsPerBlock: 11 },\n { numBlocks: 4, dataCodewordsPerBlock: 12 },\n ],\n },\n ],\n },\n {\n infoBits: 0x0E60D,\n versionNumber: 14,\n alignmentPatternCenters: [6, 26, 46, 66],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 3, dataCodewordsPerBlock: 115 },\n { numBlocks: 1, dataCodewordsPerBlock: 116 },\n ],\n },\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 40 },\n { numBlocks: 5, dataCodewordsPerBlock: 41 },\n ],\n },\n {\n ecCodewordsPerBlock: 20,\n ecBlocks: [\n { numBlocks: 11, dataCodewordsPerBlock: 16 },\n { numBlocks: 5, dataCodewordsPerBlock: 17 },\n ],\n },\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [\n { numBlocks: 11, dataCodewordsPerBlock: 12 },\n { numBlocks: 5, dataCodewordsPerBlock: 13 },\n ],\n },\n ],\n },\n {\n infoBits: 0x0F928,\n versionNumber: 15,\n alignmentPatternCenters: [6, 26, 48, 70],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 22,\n ecBlocks: [\n { numBlocks: 5, dataCodewordsPerBlock: 87 },\n { numBlocks: 1, dataCodewordsPerBlock: 88 },\n ],\n },\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [\n { numBlocks: 5, dataCodewordsPerBlock: 41 },\n { numBlocks: 5, dataCodewordsPerBlock: 42 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 5, dataCodewordsPerBlock: 24 },\n { numBlocks: 7, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [\n { numBlocks: 11, dataCodewordsPerBlock: 12 },\n { numBlocks: 7, dataCodewordsPerBlock: 13 },\n ],\n },\n ],\n },\n {\n infoBits: 0x10B78,\n versionNumber: 16,\n alignmentPatternCenters: [6, 26, 50, 74],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [\n { numBlocks: 5, dataCodewordsPerBlock: 98 },\n { numBlocks: 1, dataCodewordsPerBlock: 99 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 7, dataCodewordsPerBlock: 45 },\n { numBlocks: 3, dataCodewordsPerBlock: 46 },\n ],\n },\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [\n { numBlocks: 15, dataCodewordsPerBlock: 19 },\n { numBlocks: 2, dataCodewordsPerBlock: 20 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 3, dataCodewordsPerBlock: 15 },\n { numBlocks: 13, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x1145D,\n versionNumber: 17,\n alignmentPatternCenters: [6, 30, 54, 78],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 1, dataCodewordsPerBlock: 107 },\n { numBlocks: 5, dataCodewordsPerBlock: 108 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 10, dataCodewordsPerBlock: 46 },\n { numBlocks: 1, dataCodewordsPerBlock: 47 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 1, dataCodewordsPerBlock: 22 },\n { numBlocks: 15, dataCodewordsPerBlock: 23 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 2, dataCodewordsPerBlock: 14 },\n { numBlocks: 17, dataCodewordsPerBlock: 15 },\n ],\n },\n ],\n },\n {\n infoBits: 0x12A17,\n versionNumber: 18,\n alignmentPatternCenters: [6, 30, 56, 82],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 5, dataCodewordsPerBlock: 120 },\n { numBlocks: 1, dataCodewordsPerBlock: 121 },\n ],\n },\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [\n { numBlocks: 9, dataCodewordsPerBlock: 43 },\n { numBlocks: 4, dataCodewordsPerBlock: 44 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 17, dataCodewordsPerBlock: 22 },\n { numBlocks: 1, dataCodewordsPerBlock: 23 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 2, dataCodewordsPerBlock: 14 },\n { numBlocks: 19, dataCodewordsPerBlock: 15 },\n ],\n },\n ],\n },\n {\n infoBits: 0x13532,\n versionNumber: 19,\n alignmentPatternCenters: [6, 30, 58, 86],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 3, dataCodewordsPerBlock: 113 },\n { numBlocks: 4, dataCodewordsPerBlock: 114 },\n ],\n },\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [\n { numBlocks: 3, dataCodewordsPerBlock: 44 },\n { numBlocks: 11, dataCodewordsPerBlock: 45 },\n ],\n },\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [\n { numBlocks: 17, dataCodewordsPerBlock: 21 },\n { numBlocks: 4, dataCodewordsPerBlock: 22 },\n ],\n },\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [\n { numBlocks: 9, dataCodewordsPerBlock: 13 },\n { numBlocks: 16, dataCodewordsPerBlock: 14 },\n ],\n },\n ],\n },\n {\n infoBits: 0x149A6,\n versionNumber: 20,\n alignmentPatternCenters: [6, 34, 62, 90],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 3, dataCodewordsPerBlock: 107 },\n { numBlocks: 5, dataCodewordsPerBlock: 108 },\n ],\n },\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [\n { numBlocks: 3, dataCodewordsPerBlock: 41 },\n { numBlocks: 13, dataCodewordsPerBlock: 42 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 15, dataCodewordsPerBlock: 24 },\n { numBlocks: 5, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 15, dataCodewordsPerBlock: 15 },\n { numBlocks: 10, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x15683,\n versionNumber: 21,\n alignmentPatternCenters: [6, 28, 50, 72, 94],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 116 },\n { numBlocks: 4, dataCodewordsPerBlock: 117 },\n ],\n },\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [{ numBlocks: 17, dataCodewordsPerBlock: 42 }],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 17, dataCodewordsPerBlock: 22 },\n { numBlocks: 6, dataCodewordsPerBlock: 23 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 19, dataCodewordsPerBlock: 16 },\n { numBlocks: 6, dataCodewordsPerBlock: 17 },\n ],\n },\n ],\n },\n {\n infoBits: 0x168C9,\n versionNumber: 22,\n alignmentPatternCenters: [6, 26, 50, 74, 98],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 2, dataCodewordsPerBlock: 111 },\n { numBlocks: 7, dataCodewordsPerBlock: 112 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [{ numBlocks: 17, dataCodewordsPerBlock: 46 }],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 7, dataCodewordsPerBlock: 24 },\n { numBlocks: 16, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [{ numBlocks: 34, dataCodewordsPerBlock: 13 }],\n },\n ],\n },\n {\n infoBits: 0x177EC,\n versionNumber: 23,\n alignmentPatternCenters: [6, 30, 54, 74, 102],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 121 },\n { numBlocks: 5, dataCodewordsPerBlock: 122 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 47 },\n { numBlocks: 14, dataCodewordsPerBlock: 48 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 11, dataCodewordsPerBlock: 24 },\n { numBlocks: 14, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 16, dataCodewordsPerBlock: 15 },\n { numBlocks: 14, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x18EC4,\n versionNumber: 24,\n alignmentPatternCenters: [6, 28, 54, 80, 106],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 6, dataCodewordsPerBlock: 117 },\n { numBlocks: 4, dataCodewordsPerBlock: 118 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 6, dataCodewordsPerBlock: 45 },\n { numBlocks: 14, dataCodewordsPerBlock: 46 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 11, dataCodewordsPerBlock: 24 },\n { numBlocks: 16, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 30, dataCodewordsPerBlock: 16 },\n { numBlocks: 2, dataCodewordsPerBlock: 17 },\n ],\n },\n ],\n },\n {\n infoBits: 0x191E1,\n versionNumber: 25,\n alignmentPatternCenters: [6, 32, 58, 84, 110],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [\n { numBlocks: 8, dataCodewordsPerBlock: 106 },\n { numBlocks: 4, dataCodewordsPerBlock: 107 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 8, dataCodewordsPerBlock: 47 },\n { numBlocks: 13, dataCodewordsPerBlock: 48 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 7, dataCodewordsPerBlock: 24 },\n { numBlocks: 22, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 22, dataCodewordsPerBlock: 15 },\n { numBlocks: 13, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x1AFAB,\n versionNumber: 26,\n alignmentPatternCenters: [6, 30, 58, 86, 114],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 10, dataCodewordsPerBlock: 114 },\n { numBlocks: 2, dataCodewordsPerBlock: 115 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 19, dataCodewordsPerBlock: 46 },\n { numBlocks: 4, dataCodewordsPerBlock: 47 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 28, dataCodewordsPerBlock: 22 },\n { numBlocks: 6, dataCodewordsPerBlock: 23 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 33, dataCodewordsPerBlock: 16 },\n { numBlocks: 4, dataCodewordsPerBlock: 17 },\n ],\n },\n ],\n },\n {\n infoBits: 0x1B08E,\n versionNumber: 27,\n alignmentPatternCenters: [6, 34, 62, 90, 118],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 8, dataCodewordsPerBlock: 122 },\n { numBlocks: 4, dataCodewordsPerBlock: 123 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 22, dataCodewordsPerBlock: 45 },\n { numBlocks: 3, dataCodewordsPerBlock: 46 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 8, dataCodewordsPerBlock: 23 },\n { numBlocks: 26, dataCodewordsPerBlock: 24 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 12, dataCodewordsPerBlock: 15 },\n { numBlocks: 28, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x1CC1A,\n versionNumber: 28,\n alignmentPatternCenters: [6, 26, 50, 74, 98, 122],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 3, dataCodewordsPerBlock: 117 },\n { numBlocks: 10, dataCodewordsPerBlock: 118 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 3, dataCodewordsPerBlock: 45 },\n { numBlocks: 23, dataCodewordsPerBlock: 46 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 24 },\n { numBlocks: 31, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 11, dataCodewordsPerBlock: 15 },\n { numBlocks: 31, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x1D33F,\n versionNumber: 29,\n alignmentPatternCenters: [6, 30, 54, 78, 102, 126],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 7, dataCodewordsPerBlock: 116 },\n { numBlocks: 7, dataCodewordsPerBlock: 117 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 21, dataCodewordsPerBlock: 45 },\n { numBlocks: 7, dataCodewordsPerBlock: 46 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 1, dataCodewordsPerBlock: 23 },\n { numBlocks: 37, dataCodewordsPerBlock: 24 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 19, dataCodewordsPerBlock: 15 },\n { numBlocks: 26, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x1ED75,\n versionNumber: 30,\n alignmentPatternCenters: [6, 26, 52, 78, 104, 130],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 5, dataCodewordsPerBlock: 115 },\n { numBlocks: 10, dataCodewordsPerBlock: 116 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 19, dataCodewordsPerBlock: 47 },\n { numBlocks: 10, dataCodewordsPerBlock: 48 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 15, dataCodewordsPerBlock: 24 },\n { numBlocks: 25, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 23, dataCodewordsPerBlock: 15 },\n { numBlocks: 25, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x1F250,\n versionNumber: 31,\n alignmentPatternCenters: [6, 30, 56, 82, 108, 134],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 13, dataCodewordsPerBlock: 115 },\n { numBlocks: 3, dataCodewordsPerBlock: 116 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 2, dataCodewordsPerBlock: 46 },\n { numBlocks: 29, dataCodewordsPerBlock: 47 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 42, dataCodewordsPerBlock: 24 },\n { numBlocks: 1, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 23, dataCodewordsPerBlock: 15 },\n { numBlocks: 28, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x209D5,\n versionNumber: 32,\n alignmentPatternCenters: [6, 34, 60, 86, 112, 138],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [{ numBlocks: 17, dataCodewordsPerBlock: 115 }],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 10, dataCodewordsPerBlock: 46 },\n { numBlocks: 23, dataCodewordsPerBlock: 47 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 10, dataCodewordsPerBlock: 24 },\n { numBlocks: 35, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 19, dataCodewordsPerBlock: 15 },\n { numBlocks: 35, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x216F0,\n versionNumber: 33,\n alignmentPatternCenters: [6, 30, 58, 86, 114, 142],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 17, dataCodewordsPerBlock: 115 },\n { numBlocks: 1, dataCodewordsPerBlock: 116 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 14, dataCodewordsPerBlock: 46 },\n { numBlocks: 21, dataCodewordsPerBlock: 47 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 29, dataCodewordsPerBlock: 24 },\n { numBlocks: 19, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 11, dataCodewordsPerBlock: 15 },\n { numBlocks: 46, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x228BA,\n versionNumber: 34,\n alignmentPatternCenters: [6, 34, 62, 90, 118, 146],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 13, dataCodewordsPerBlock: 115 },\n { numBlocks: 6, dataCodewordsPerBlock: 116 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 14, dataCodewordsPerBlock: 46 },\n { numBlocks: 23, dataCodewordsPerBlock: 47 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 44, dataCodewordsPerBlock: 24 },\n { numBlocks: 7, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 59, dataCodewordsPerBlock: 16 },\n { numBlocks: 1, dataCodewordsPerBlock: 17 },\n ],\n },\n ],\n },\n {\n infoBits: 0x2379F,\n versionNumber: 35,\n alignmentPatternCenters: [6, 30, 54, 78, 102, 126, 150],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 12, dataCodewordsPerBlock: 121 },\n { numBlocks: 7, dataCodewordsPerBlock: 122 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 12, dataCodewordsPerBlock: 47 },\n { numBlocks: 26, dataCodewordsPerBlock: 48 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 39, dataCodewordsPerBlock: 24 },\n { numBlocks: 14, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 22, dataCodewordsPerBlock: 15 },\n { numBlocks: 41, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x24B0B,\n versionNumber: 36,\n alignmentPatternCenters: [ 6, 24, 50, 76, 102, 128, 154 ],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 6, dataCodewordsPerBlock: 121 },\n { numBlocks: 14, dataCodewordsPerBlock: 122 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 6, dataCodewordsPerBlock: 47 },\n { numBlocks: 34, dataCodewordsPerBlock: 48 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 46, dataCodewordsPerBlock: 24 },\n { numBlocks: 10, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 2, dataCodewordsPerBlock: 15 },\n { numBlocks: 64, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x2542E,\n versionNumber: 37,\n alignmentPatternCenters: [ 6, 28, 54, 80, 106, 132, 158 ],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 17, dataCodewordsPerBlock: 122 },\n { numBlocks: 4, dataCodewordsPerBlock: 123 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 29, dataCodewordsPerBlock: 46 },\n { numBlocks: 14, dataCodewordsPerBlock: 47 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 49, dataCodewordsPerBlock: 24 },\n { numBlocks: 10, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 24, dataCodewordsPerBlock: 15 },\n { numBlocks: 46, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x26A64,\n versionNumber: 38,\n alignmentPatternCenters: [ 6, 32, 58, 84, 110, 136, 162 ],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 122 },\n { numBlocks: 18, dataCodewordsPerBlock: 123 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 13, dataCodewordsPerBlock: 46 },\n { numBlocks: 32, dataCodewordsPerBlock: 47 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 48, dataCodewordsPerBlock: 24 },\n { numBlocks: 14, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 42, dataCodewordsPerBlock: 15 },\n { numBlocks: 32, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x27541,\n versionNumber: 39,\n alignmentPatternCenters: [ 6, 26, 54, 82, 110, 138, 166 ],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 20, dataCodewordsPerBlock: 117 },\n { numBlocks: 4, dataCodewordsPerBlock: 118 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 40, dataCodewordsPerBlock: 47 },\n { numBlocks: 7, dataCodewordsPerBlock: 48 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 43, dataCodewordsPerBlock: 24 },\n { numBlocks: 22, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 10, dataCodewordsPerBlock: 15 },\n { numBlocks: 67, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x28C69,\n versionNumber: 40,\n alignmentPatternCenters: [ 6, 30, 58, 86, 114, 142, 170 ],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 19, dataCodewordsPerBlock: 118 },\n { numBlocks: 6, dataCodewordsPerBlock: 119 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 18, dataCodewordsPerBlock: 47 },\n { numBlocks: 31, dataCodewordsPerBlock: 48 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 34, dataCodewordsPerBlock: 24 },\n { numBlocks: 34, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 20, dataCodewordsPerBlock: 15 },\n { numBlocks: 61, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n];\n","import { BitMatrix } from \"../BitMatrix\";\nimport { Point } from \"../Point\";\nimport { decode as decodeData, DecodedQR } from \"./decodeData\";\nimport { decode as rsDecode } from \"./reedsolomon\";\nimport { Version, VERSIONS } from \"./version\";\n\n// tslint:disable:no-bitwise\nfunction numBitsDiffering(x: number, y: number) {\n let z = x ^ y;\n let bitCount = 0;\n while (z) {\n bitCount++;\n z &= z - 1;\n }\n return bitCount;\n}\n\nfunction pushBit(bit: any, byte: number) {\n return (byte << 1) | bit;\n}\n// tslint:enable:no-bitwise\n\nconst FORMAT_INFO_TABLE = [\n { bits: 0x5412, formatInfo: { errorCorrectionLevel: 1, dataMask: 0 } },\n { bits: 0x5125, formatInfo: { errorCorrectionLevel: 1, dataMask: 1 } },\n { bits: 0x5E7C, formatInfo: { errorCorrectionLevel: 1, dataMask: 2 } },\n { bits: 0x5B4B, formatInfo: { errorCorrectionLevel: 1, dataMask: 3 } },\n { bits: 0x45F9, formatInfo: { errorCorrectionLevel: 1, dataMask: 4 } },\n { bits: 0x40CE, formatInfo: { errorCorrectionLevel: 1, dataMask: 5 } },\n { bits: 0x4F97, formatInfo: { errorCorrectionLevel: 1, dataMask: 6 } },\n { bits: 0x4AA0, formatInfo: { errorCorrectionLevel: 1, dataMask: 7 } },\n { bits: 0x77C4, formatInfo: { errorCorrectionLevel: 0, dataMask: 0 } },\n { bits: 0x72F3, formatInfo: { errorCorrectionLevel: 0, dataMask: 1 } },\n { bits: 0x7DAA, formatInfo: { errorCorrectionLevel: 0, dataMask: 2 } },\n { bits: 0x789D, formatInfo: { errorCorrectionLevel: 0, dataMask: 3 } },\n { bits: 0x662F, formatInfo: { errorCorrectionLevel: 0, dataMask: 4 } },\n { bits: 0x6318, formatInfo: { errorCorrectionLevel: 0, dataMask: 5 } },\n { bits: 0x6C41, formatInfo: { errorCorrectionLevel: 0, dataMask: 6 } },\n { bits: 0x6976, formatInfo: { errorCorrectionLevel: 0, dataMask: 7 } },\n { bits: 0x1689, formatInfo: { errorCorrectionLevel: 3, dataMask: 0 } },\n { bits: 0x13BE, formatInfo: { errorCorrectionLevel: 3, dataMask: 1 } },\n { bits: 0x1CE7, formatInfo: { errorCorrectionLevel: 3, dataMask: 2 } },\n { bits: 0x19D0, formatInfo: { errorCorrectionLevel: 3, dataMask: 3 } },\n { bits: 0x0762, formatInfo: { errorCorrectionLevel: 3, dataMask: 4 } },\n { bits: 0x0255, formatInfo: { errorCorrectionLevel: 3, dataMask: 5 } },\n { bits: 0x0D0C, formatInfo: { errorCorrectionLevel: 3, dataMask: 6 } },\n { bits: 0x083B, formatInfo: { errorCorrectionLevel: 3, dataMask: 7 } },\n { bits: 0x355F, formatInfo: { errorCorrectionLevel: 2, dataMask: 0 } },\n { bits: 0x3068, formatInfo: { errorCorrectionLevel: 2, dataMask: 1 } },\n { bits: 0x3F31, formatInfo: { errorCorrectionLevel: 2, dataMask: 2 } },\n { bits: 0x3A06, formatInfo: { errorCorrectionLevel: 2, dataMask: 3 } },\n { bits: 0x24B4, formatInfo: { errorCorrectionLevel: 2, dataMask: 4 } },\n { bits: 0x2183, formatInfo: { errorCorrectionLevel: 2, dataMask: 5 } },\n { bits: 0x2EDA, formatInfo: { errorCorrectionLevel: 2, dataMask: 6 } },\n { bits: 0x2BED, formatInfo: { errorCorrectionLevel: 2, dataMask: 7 } },\n];\n\nconst DATA_MASKS = [\n (p: Point) => ((p.y + p.x) % 2) === 0,\n (p: Point) => (p.y % 2) === 0,\n (p: Point) => p.x % 3 === 0,\n (p: Point) => (p.y + p.x) % 3 === 0,\n (p: Point) => (Math.floor(p.y / 2) + Math.floor(p.x / 3)) % 2 === 0,\n (p: Point) => ((p.x * p.y) % 2) + ((p.x * p.y) % 3) === 0,\n (p: Point) => ((((p.y * p.x) % 2) + (p.y * p.x) % 3) % 2) === 0,\n (p: Point) => ((((p.y + p.x) % 2) + (p.y * p.x) % 3) % 2) === 0,\n];\n\ninterface FormatInformation {\n errorCorrectionLevel: number;\n dataMask: number;\n}\n\nfunction buildFunctionPatternMask(version: Version): BitMatrix {\n const dimension = 17 + 4 * version.versionNumber;\n const matrix = BitMatrix.createEmpty(dimension, dimension);\n\n matrix.setRegion(0, 0, 9, 9, true); // Top left finder pattern + separator + format\n matrix.setRegion(dimension - 8, 0, 8, 9, true); // Top right finder pattern + separator + format\n matrix.setRegion(0, dimension - 8, 9, 8, true); // Bottom left finder pattern + separator + format\n\n // Alignment patterns\n for (const x of version.alignmentPatternCenters) {\n for (const y of version.alignmentPatternCenters) {\n if (!(x === 6 && y === 6 || x === 6 && y === dimension - 7 || x === dimension - 7 && y === 6)) {\n matrix.setRegion(x - 2, y - 2, 5, 5, true);\n }\n }\n }\n\n matrix.setRegion(6, 9, 1, dimension - 17, true); // Vertical timing pattern\n matrix.setRegion(9, 6, dimension - 17, 1, true); // Horizontal timing pattern\n\n if (version.versionNumber > 6) {\n matrix.setRegion(dimension - 11, 0, 3, 6, true); // Version info, top right\n matrix.setRegion(0, dimension - 11, 6, 3, true); // Version info, bottom left\n }\n\n return matrix;\n}\n\nfunction readCodewords(matrix: BitMatrix, version: Version, formatInfo: FormatInformation) {\n const dataMask = DATA_MASKS[formatInfo.dataMask];\n const dimension = matrix.height;\n\n const functionPatternMask = buildFunctionPatternMask(version);\n\n const codewords: number[] = [];\n let currentByte = 0;\n let bitsRead = 0;\n\n // Read columns in pairs, from right to left\n let readingUp = true;\n for (let columnIndex = dimension - 1; columnIndex > 0; columnIndex -= 2) {\n if (columnIndex === 6) { // Skip whole column with vertical alignment pattern;\n columnIndex--;\n }\n for (let i = 0; i < dimension; i++) {\n const y = readingUp ? dimension - 1 - i : i;\n for (let columnOffset = 0; columnOffset < 2; columnOffset++) {\n const x = columnIndex - columnOffset;\n if (!functionPatternMask.get(x, y)) {\n bitsRead++;\n let bit = matrix.get(x, y);\n if (dataMask({y, x})) {\n bit = !bit;\n }\n currentByte = pushBit(bit, currentByte);\n if (bitsRead === 8) { // Whole bytes\n codewords.push(currentByte);\n bitsRead = 0;\n currentByte = 0;\n }\n }\n }\n }\n readingUp = !readingUp;\n }\n return codewords;\n}\n\nfunction readVersion(matrix: BitMatrix): Version {\n const dimension = matrix.height;\n\n const provisionalVersion = Math.floor((dimension - 17) / 4);\n if (provisionalVersion <= 6) { // 6 and under dont have version info in the QR code\n return VERSIONS[provisionalVersion - 1];\n }\n\n let topRightVersionBits = 0;\n for (let y = 5; y >= 0; y--) {\n for (let x = dimension - 9; x >= dimension - 11; x--) {\n topRightVersionBits = pushBit(matrix.get(x, y), topRightVersionBits);\n }\n }\n\n let bottomLeftVersionBits = 0;\n for (let x = 5; x >= 0; x--) {\n for (let y = dimension - 9; y >= dimension - 11; y--) {\n bottomLeftVersionBits = pushBit(matrix.get(x, y), bottomLeftVersionBits);\n }\n }\n\n let bestDifference = Infinity;\n let bestVersion: Version;\n for (const version of VERSIONS) {\n if (version.infoBits === topRightVersionBits || version.infoBits === bottomLeftVersionBits) {\n return version;\n }\n\n let difference = numBitsDiffering(topRightVersionBits, version.infoBits);\n if (difference < bestDifference) {\n bestVersion = version;\n bestDifference = difference;\n }\n\n difference = numBitsDiffering(bottomLeftVersionBits, version.infoBits);\n if (difference < bestDifference) {\n bestVersion = version;\n bestDifference = difference;\n }\n }\n // We can tolerate up to 3 bits of error since no two version info codewords will\n // differ in less than 8 bits.\n if (bestDifference <= 3) {\n return bestVersion;\n }\n}\n\nfunction readFormatInformation(matrix: BitMatrix) {\n let topLeftFormatInfoBits = 0;\n for (let x = 0; x <= 8; x++) {\n if (x !== 6) { // Skip timing pattern bit\n topLeftFormatInfoBits = pushBit(matrix.get(x, 8), topLeftFormatInfoBits);\n }\n }\n for (let y = 7; y >= 0; y--) {\n if (y !== 6) { // Skip timing pattern bit\n topLeftFormatInfoBits = pushBit(matrix.get(8, y), topLeftFormatInfoBits);\n }\n }\n\n const dimension = matrix.height;\n let topRightBottomRightFormatInfoBits = 0;\n for (let y = dimension - 1; y >= dimension - 7; y--) { // bottom left\n topRightBottomRightFormatInfoBits = pushBit(matrix.get(8, y), topRightBottomRightFormatInfoBits);\n }\n for (let x = dimension - 8; x < dimension; x++) { // top right\n topRightBottomRightFormatInfoBits = pushBit(matrix.get(x, 8), topRightBottomRightFormatInfoBits);\n }\n\n let bestDifference = Infinity;\n let bestFormatInfo = null;\n for (const {bits, formatInfo} of FORMAT_INFO_TABLE) {\n if (bits === topLeftFormatInfoBits || bits === topRightBottomRightFormatInfoBits) {\n return formatInfo;\n }\n let difference = numBitsDiffering(topLeftFormatInfoBits, bits);\n if (difference < bestDifference) {\n bestFormatInfo = formatInfo;\n bestDifference = difference;\n }\n if (topLeftFormatInfoBits !== topRightBottomRightFormatInfoBits) { // also try the other option\n difference = numBitsDiffering(topRightBottomRightFormatInfoBits, bits);\n if (difference < bestDifference) {\n bestFormatInfo = formatInfo;\n bestDifference = difference;\n }\n }\n }\n // Hamming distance of the 32 masked codes is 7, by construction, so <= 3 bits differing means we found a match\n if (bestDifference <= 3) {\n return bestFormatInfo;\n }\n return null;\n}\n\nfunction getDataBlocks(codewords: number[], version: Version, ecLevel: number) {\n const ecInfo = version.errorCorrectionLevels[ecLevel];\n const dataBlocks: Array<{\n numDataCodewords: number;\n codewords: number[];\n }> = [];\n\n let totalCodewords = 0;\n ecInfo.ecBlocks.forEach(block => {\n for (let i = 0; i < block.numBlocks; i++) {\n dataBlocks.push({ numDataCodewords: block.dataCodewordsPerBlock, codewords: [] });\n totalCodewords += block.dataCodewordsPerBlock + ecInfo.ecCodewordsPerBlock;\n }\n });\n\n // In some cases the QR code will be malformed enough that we pull off more or less than we should.\n // If we pull off less there's nothing we can do.\n // If we pull off more we can safely truncate\n if (codewords.length < totalCodewords) {\n return null;\n }\n codewords = codewords.slice(0, totalCodewords);\n\n const shortBlockSize = ecInfo.ecBlocks[0].dataCodewordsPerBlock;\n // Pull codewords to fill the blocks up to the minimum size\n for (let i = 0; i < shortBlockSize; i++) {\n for (const dataBlock of dataBlocks) {\n dataBlock.codewords.push(codewords.shift());\n }\n }\n\n // If there are any large blocks, pull codewords to fill the last element of those\n if (ecInfo.ecBlocks.length > 1) {\n const smallBlockCount = ecInfo.ecBlocks[0].numBlocks;\n const largeBlockCount = ecInfo.ecBlocks[1].numBlocks;\n for (let i = 0; i < largeBlockCount; i++) {\n dataBlocks[smallBlockCount + i].codewords.push(codewords.shift());\n }\n }\n\n // Add the rest of the codewords to the blocks. These are the error correction codewords.\n while (codewords.length > 0) {\n for (const dataBlock of dataBlocks) {\n dataBlock.codewords.push(codewords.shift());\n }\n }\n\n return dataBlocks;\n}\n\nfunction decodeMatrix(matrix: BitMatrix) {\n const version = readVersion(matrix);\n if (!version) {\n return null;\n }\n\n const formatInfo = readFormatInformation(matrix);\n if (!formatInfo) {\n return null;\n }\n\n const codewords = readCodewords(matrix, version, formatInfo);\n const dataBlocks = getDataBlocks(codewords, version, formatInfo.errorCorrectionLevel);\n if (!dataBlocks) {\n return null;\n }\n\n // Count total number of data bytes\n const totalBytes = dataBlocks.reduce((a, b) => a + b.numDataCodewords, 0);\n const resultBytes = new Uint8ClampedArray(totalBytes);\n\n let resultIndex = 0;\n for (const dataBlock of dataBlocks) {\n const correctedBytes = rsDecode(dataBlock.codewords, dataBlock.codewords.length - dataBlock.numDataCodewords);\n if (!correctedBytes) {\n return null;\n }\n for (let i = 0; i < dataBlock.numDataCodewords; i++) {\n resultBytes[resultIndex++] = correctedBytes[i];\n }\n }\n\n try {\n return decodeData(resultBytes, version.versionNumber);\n } catch {\n return null;\n }\n}\n\nexport function decode(matrix: BitMatrix): DecodedQR {\n if (matrix == null) {\n return null;\n }\n const result = decodeMatrix(matrix);\n if (result) {\n return result;\n }\n // Decoding didn't work, try mirroring the QR across the topLeft -> bottomRight line.\n for (let x = 0; x < matrix.width; x++) {\n for (let y = x + 1; y < matrix.height; y++) {\n if (matrix.get(x, y) !== matrix.get(y, x)) {\n matrix.set(x, y, !matrix.get(x, y));\n matrix.set(y, x, !matrix.get(y, x));\n }\n }\n }\n return decodeMatrix(matrix);\n}\n","import {BitMatrix} from \"../BitMatrix\";\nimport {Point, QRLocation} from \"../locator\";\n\ninterface PerspectiveTransform {\n a11: number;\n a21: number;\n a31: number;\n a12: number;\n a22: number;\n a32: number;\n a13: number;\n a23: number;\n a33: number;\n}\n\nfunction squareToQuadrilateral(p1: Point, p2: Point, p3: Point, p4: Point): PerspectiveTransform {\n const dx3 = p1.x - p2.x + p3.x - p4.x;\n const dy3 = p1.y - p2.y + p3.y - p4.y;\n if (dx3 === 0 && dy3 === 0) { // Affine\n return {\n a11: p2.x - p1.x,\n a12: p2.y - p1.y,\n a13: 0,\n a21: p3.x - p2.x,\n a22: p3.y - p2.y,\n a23: 0,\n a31: p1.x,\n a32: p1.y,\n a33: 1,\n };\n } else {\n const dx1 = p2.x - p3.x;\n const dx2 = p4.x - p3.x;\n const dy1 = p2.y - p3.y;\n const dy2 = p4.y - p3.y;\n const denominator = dx1 * dy2 - dx2 * dy1;\n const a13 = (dx3 * dy2 - dx2 * dy3) / denominator;\n const a23 = (dx1 * dy3 - dx3 * dy1) / denominator;\n return {\n a11: p2.x - p1.x + a13 * p2.x,\n a12: p2.y - p1.y + a13 * p2.y,\n a13,\n a21: p4.x - p1.x + a23 * p4.x,\n a22: p4.y - p1.y + a23 * p4.y,\n a23,\n a31: p1.x,\n a32: p1.y,\n a33: 1,\n };\n }\n}\n\nfunction quadrilateralToSquare(p1: Point, p2: Point, p3: Point, p4: Point): PerspectiveTransform {\n // Here, the adjoint serves as the inverse:\n const sToQ = squareToQuadrilateral(p1, p2, p3, p4);\n return {\n a11: sToQ.a22 * sToQ.a33 - sToQ.a23 * sToQ.a32,\n a12: sToQ.a13 * sToQ.a32 - sToQ.a12 * sToQ.a33,\n a13: sToQ.a12 * sToQ.a23 - sToQ.a13 * sToQ.a22,\n a21: sToQ.a23 * sToQ.a31 - sToQ.a21 * sToQ.a33,\n a22: sToQ.a11 * sToQ.a33 - sToQ.a13 * sToQ.a31,\n a23: sToQ.a13 * sToQ.a21 - sToQ.a11 * sToQ.a23,\n a31: sToQ.a21 * sToQ.a32 - sToQ.a22 * sToQ.a31,\n a32: sToQ.a12 * sToQ.a31 - sToQ.a11 * sToQ.a32,\n a33: sToQ.a11 * sToQ.a22 - sToQ.a12 * sToQ.a21,\n };\n}\n\nfunction times(a: PerspectiveTransform, b: PerspectiveTransform): PerspectiveTransform {\n return {\n a11: a.a11 * b.a11 + a.a21 * b.a12 + a.a31 * b.a13,\n a12: a.a12 * b.a11 + a.a22 * b.a12 + a.a32 * b.a13,\n a13: a.a13 * b.a11 + a.a23 * b.a12 + a.a33 * b.a13,\n a21: a.a11 * b.a21 + a.a21 * b.a22 + a.a31 * b.a23,\n a22: a.a12 * b.a21 + a.a22 * b.a22 + a.a32 * b.a23,\n a23: a.a13 * b.a21 + a.a23 * b.a22 + a.a33 * b.a23,\n a31: a.a11 * b.a31 + a.a21 * b.a32 + a.a31 * b.a33,\n a32: a.a12 * b.a31 + a.a22 * b.a32 + a.a32 * b.a33,\n a33: a.a13 * b.a31 + a.a23 * b.a32 + a.a33 * b.a33,\n };\n}\n\nexport function extract(image: BitMatrix, location: QRLocation) {\n const qToS = quadrilateralToSquare(\n {x: 3.5, y: 3.5},\n {x: location.dimension - 3.5, y: 3.5},\n {x: location.dimension - 6.5, y: location.dimension - 6.5},\n {x: 3.5, y: location.dimension - 3.5},\n );\n const sToQ = squareToQuadrilateral(location.topLeft, location.topRight, location.alignmentPattern, location.bottomLeft);\n const transform = times(sToQ, qToS);\n\n const matrix = BitMatrix.createEmpty(location.dimension, location.dimension);\n const mappingFunction = (x: number, y: number) => {\n const denominator = transform.a13 * x + transform.a23 * y + transform.a33;\n return {\n x: (transform.a11 * x + transform.a21 * y + transform.a31) / denominator,\n y: (transform.a12 * x + transform.a22 * y + transform.a32) / denominator,\n };\n };\n\n for (let y = 0; y < location.dimension; y++) {\n for (let x = 0; x < location.dimension; x++) {\n const xValue = x + 0.5;\n const yValue = y + 0.5;\n const sourcePixel = mappingFunction(xValue, yValue);\n matrix.set(x, y, image.get(Math.floor(sourcePixel.x), Math.floor(sourcePixel.y)));\n }\n }\n\n return {\n matrix,\n mappingFunction,\n };\n}\n","import { BitMatrix } from \"../BitMatrix\";\n\nconst MAX_FINDERPATTERNS_TO_SEARCH = 5;\nconst MIN_QUAD_RATIO = 0.5;\nconst MAX_QUAD_RATIO = 1.5;\n\nexport interface Point {\n x: number;\n y: number;\n}\n\nexport interface QRLocation {\n topRight: Point;\n bottomLeft: Point;\n topLeft: Point;\n alignmentPattern: Point;\n dimension: number;\n}\n\nconst distance = (a: Point, b: Point) => Math.sqrt((b.x - a.x) ** 2 + (b.y - a.y) ** 2);\n\nfunction sum(values: number[]) {\n return values.reduce((a, b) => a + b);\n}\n\n// Takes three finder patterns and organizes them into topLeft, topRight, etc\nfunction reorderFinderPatterns(pattern1: Point, pattern2: Point, pattern3: Point) {\n // Find distances between pattern centers\n const oneTwoDistance = distance(pattern1, pattern2);\n const twoThreeDistance = distance(pattern2, pattern3);\n const oneThreeDistance = distance(pattern1, pattern3);\n\n let bottomLeft: Point;\n let topLeft: Point;\n let topRight: Point;\n\n // Assume one closest to other two is B; A and C will just be guesses at first\n if (twoThreeDistance >= oneTwoDistance && twoThreeDistance >= oneThreeDistance) {\n [bottomLeft, topLeft, topRight] = [pattern2, pattern1, pattern3];\n } else if (oneThreeDistance >= twoThreeDistance && oneThreeDistance >= oneTwoDistance) {\n [bottomLeft, topLeft, topRight] = [pattern1, pattern2, pattern3];\n } else {\n [bottomLeft, topLeft, topRight] = [pattern1, pattern3, pattern2];\n }\n\n // Use cross product to figure out whether bottomLeft (A) and topRight (C) are correct or flipped in relation to topLeft (B)\n // This asks whether BC x BA has a positive z component, which is the arrangement we want. If it's negative, then\n // we've got it flipped around and should swap topRight and bottomLeft.\n if (((topRight.x - topLeft.x) * (bottomLeft.y - topLeft.y)) - ((topRight.y - topLeft.y) * (bottomLeft.x - topLeft.x)) < 0) {\n [bottomLeft, topRight] = [topRight, bottomLeft];\n }\n\n return { bottomLeft, topLeft, topRight };\n}\n\n// Computes the dimension (number of modules on a side) of the QR Code based on the position of the finder patterns\nfunction computeDimension(topLeft: Point, topRight: Point, bottomLeft: Point, matrix: BitMatrix) {\n const moduleSize = (\n sum(countBlackWhiteRun(topLeft, bottomLeft, matrix, 5)) / 7 + // Divide by 7 since the ratio is 1:1:3:1:1\n sum(countBlackWhiteRun(topLeft, topRight, matrix, 5)) / 7 +\n sum(countBlackWhiteRun(bottomLeft, topLeft, matrix, 5)) / 7 +\n sum(countBlackWhiteRun(topRight, topLeft, matrix, 5)) / 7\n ) / 4;\n\n if (moduleSize < 1) {\n throw new Error(\"Invalid module size\");\n }\n\n const topDimension = Math.round(distance(topLeft, topRight) / moduleSize);\n const sideDimension = Math.round(distance(topLeft, bottomLeft) / moduleSize);\n let dimension = Math.floor((topDimension + sideDimension) / 2) + 7;\n switch (dimension % 4) {\n case 0:\n dimension++;\n break;\n case 2:\n dimension--;\n break;\n }\n return { dimension, moduleSize };\n}\n\n// Takes an origin point and an end point and counts the sizes of the black white run from the origin towards the end point.\n// Returns an array of elements, representing the pixel size of the black white run.\n// Uses a variant of http://en.wikipedia.org/wiki/Bresenham's_line_algorithm\nfunction countBlackWhiteRunTowardsPoint(origin: Point, end: Point, matrix: BitMatrix, length: number) {\n const switchPoints: Point[] = [{x: Math.floor(origin.x), y: Math.floor(origin.y)}];\n const steep = Math.abs(end.y - origin.y) > Math.abs(end.x - origin.x);\n\n let fromX: number;\n let fromY: number;\n let toX: number;\n let toY: number;\n if (steep) {\n fromX = Math.floor(origin.y);\n fromY = Math.floor(origin.x);\n toX = Math.floor(end.y);\n toY = Math.floor(end.x);\n } else {\n fromX = Math.floor(origin.x);\n fromY = Math.floor(origin.y);\n toX = Math.floor(end.x);\n toY = Math.floor(end.y);\n }\n\n const dx = Math.abs(toX - fromX);\n const dy = Math.abs(toY - fromY);\n let error = Math.floor(-dx / 2);\n const xStep = fromX < toX ? 1 : -1;\n const yStep = fromY < toY ? 1 : -1;\n\n let currentPixel = true;\n // Loop up until x == toX, but not beyond\n for (let x = fromX, y = fromY; x !== toX + xStep; x += xStep) {\n // Does current pixel mean we have moved white to black or vice versa?\n // Scanning black in state 0,2 and white in state 1, so if we find the wrong\n // color, advance to next state or end if we are in state 2 already\n const realX = steep ? y : x;\n const realY = steep ? x : y;\n if (matrix.get(realX, realY) !== currentPixel) {\n currentPixel = !currentPixel;\n switchPoints.push({x: realX, y: realY});\n if (switchPoints.length === length + 1) {\n break;\n }\n }\n error += dy;\n if (error > 0) {\n if (y === toY) {\n break;\n }\n y += yStep;\n error -= dx;\n }\n }\n const distances: number[] = [];\n for (let i = 0; i < length; i++) {\n if (switchPoints[i] && switchPoints[i + 1]) {\n distances.push(distance(switchPoints[i], switchPoints[i + 1]));\n } else {\n distances.push(0);\n }\n }\n return distances;\n}\n\n// Takes an origin point and an end point and counts the sizes of the black white run in the origin point\n// along the line that intersects with the end point. Returns an array of elements, representing the pixel sizes\n// of the black white run. Takes a length which represents the number of switches from black to white to look for.\nfunction countBlackWhiteRun(origin: Point, end: Point, matrix: BitMatrix, length: number) {\n const rise = end.y - origin.y;\n const run = end.x - origin.x;\n\n const towardsEnd = countBlackWhiteRunTowardsPoint(origin, end, matrix, Math.ceil(length / 2));\n const awayFromEnd = countBlackWhiteRunTowardsPoint(origin, {x: origin.x - run, y: origin.y - rise}, matrix, Math.ceil(length / 2));\n\n const middleValue = towardsEnd.shift() + awayFromEnd.shift() - 1; // Substract one so we don't double count a pixel\n return awayFromEnd.concat(middleValue).concat(...towardsEnd);\n}\n\n// Takes in a black white run and an array of expected ratios. Returns the average size of the run as well as the \"error\" -\n// that is the amount the run diverges from the expected ratio\nfunction scoreBlackWhiteRun(sequence: number[], ratios: number[]) {\n const averageSize = sum(sequence) / sum(ratios);\n let error = 0;\n ratios.forEach((ratio, i) => {\n error += (sequence[i] - ratio * averageSize) ** 2;\n });\n\n return { averageSize, error };\n}\n\n// Takes an X,Y point and an array of sizes and scores the point against those ratios.\n// For example for a finder pattern takes the ratio list of 1:1:3:1:1 and checks horizontal, vertical and diagonal ratios\n// against that.\nfunction scorePattern(point: Point, ratios: number[], matrix: BitMatrix) {\n try {\n const horizontalRun = countBlackWhiteRun(point, {x: -1, y: point.y}, matrix, ratios.length);\n const verticalRun = countBlackWhiteRun(point, {x: point.x, y: -1}, matrix, ratios.length);\n\n const topLeftPoint = {\n x: Math.max(0, point.x - point.y) - 1,\n y: Math.max(0, point.y - point.x) - 1,\n };\n const topLeftBottomRightRun = countBlackWhiteRun(point, topLeftPoint, matrix, ratios.length);\n\n const bottomLeftPoint = {\n x: Math.min(matrix.width, point.x + point.y) + 1,\n y: Math.min(matrix.height, point.y + point.x) + 1,\n };\n const bottomLeftTopRightRun = countBlackWhiteRun(point, bottomLeftPoint, matrix, ratios.length);\n\n const horzError = scoreBlackWhiteRun(horizontalRun, ratios);\n const vertError = scoreBlackWhiteRun(verticalRun, ratios);\n const diagDownError = scoreBlackWhiteRun(topLeftBottomRightRun, ratios);\n const diagUpError = scoreBlackWhiteRun(bottomLeftTopRightRun, ratios);\n\n const ratioError = Math.sqrt(horzError.error * horzError.error +\n vertError.error * vertError.error +\n diagDownError.error * diagDownError.error +\n diagUpError.error * diagUpError.error);\n\n const avgSize = (horzError.averageSize + vertError.averageSize + diagDownError.averageSize + diagUpError.averageSize) / 4;\n\n const sizeError = ((horzError.averageSize - avgSize) ** 2 +\n (vertError.averageSize - avgSize) ** 2 +\n (diagDownError.averageSize - avgSize) ** 2 +\n (diagUpError.averageSize - avgSize) ** 2) / avgSize;\n return ratioError + sizeError;\n } catch {\n return Infinity;\n }\n}\n\nfunction recenterLocation(matrix: BitMatrix, p: Point): Point {\n let leftX = Math.round(p.x);\n while (matrix.get(leftX, Math.round(p.y))) {\n leftX--;\n }\n let rightX = Math.round(p.x);\n while (matrix.get(rightX, Math.round(p.y))) {\n rightX++;\n }\n const x = (leftX + rightX) / 2;\n\n let topY = Math.round(p.y);\n while (matrix.get(Math.round(x), topY)) {\n topY--;\n }\n let bottomY = Math.round(p.y);\n while (matrix.get(Math.round(x), bottomY)) {\n bottomY++;\n }\n const y = (topY + bottomY) / 2;\n\n return { x, y };\n}\n\ninterface Quad {\n top: {\n startX: number;\n endX: number;\n y: number;\n };\n bottom: {\n startX: number;\n endX: number;\n y: number;\n };\n}\n\nexport function locate(matrix: BitMatrix): QRLocation[] {\n const finderPatternQuads: Quad[] = [];\n let activeFinderPatternQuads: Quad[] = [];\n const alignmentPatternQuads: Quad[] = [];\n let activeAlignmentPatternQuads: Quad[] = [];\n\n for (let y = 0; y <= matrix.height; y++) {\n let length = 0;\n let lastBit = false;\n let scans = [0, 0, 0, 0, 0];\n\n for (let x = -1; x <= matrix.width; x++) {\n const v = matrix.get(x, y);\n if (v === lastBit) {\n length++;\n } else {\n scans = [scans[1], scans[2], scans[3], scans[4], length];\n length = 1;\n lastBit = v;\n\n // Do the last 5 color changes ~ match the expected ratio for a finder pattern? 1:1:3:1:1 of b:w:b:w:b\n const averageFinderPatternBlocksize = sum(scans) / 7;\n const validFinderPattern =\n Math.abs(scans[0] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize &&\n Math.abs(scans[1] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize &&\n Math.abs(scans[2] - 3 * averageFinderPatternBlocksize) < 3 * averageFinderPatternBlocksize &&\n Math.abs(scans[3] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize &&\n Math.abs(scans[4] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize &&\n !v; // And make sure the current pixel is white since finder patterns are bordered in white\n\n // Do the last 3 color changes ~ match the expected ratio for an alignment pattern? 1:1:1 of w:b:w\n const averageAlignmentPatternBlocksize = sum(scans.slice(-3)) / 3;\n const validAlignmentPattern =\n Math.abs(scans[2] - averageAlignmentPatternBlocksize) < averageAlignmentPatternBlocksize &&\n Math.abs(scans[3] - averageAlignmentPatternBlocksize) < averageAlignmentPatternBlocksize &&\n Math.abs(scans[4] - averageAlignmentPatternBlocksize) < averageAlignmentPatternBlocksize &&\n v; // Is the current pixel black since alignment patterns are bordered in black\n\n if (validFinderPattern) {\n // Compute the start and end x values of the large center black square\n const endX = x - scans[3] - scans[4];\n const startX = endX - scans[2];\n\n const line = { startX, endX, y };\n // Is there a quad directly above the current spot? If so, extend it with the new line. Otherwise, create a new quad with\n // that line as the starting point.\n const matchingQuads = activeFinderPatternQuads.filter(q =>\n (startX >= q.bottom.startX && startX <= q.bottom.endX) ||\n (endX >= q.bottom.startX && startX <= q.bottom.endX) ||\n (startX <= q.bottom.startX && endX >= q.bottom.endX && (\n (scans[2] / (q.bottom.endX - q.bottom.startX)) < MAX_QUAD_RATIO &&\n (scans[2] / (q.bottom.endX - q.bottom.startX)) > MIN_QUAD_RATIO\n )),\n );\n if (matchingQuads.length > 0) {\n matchingQuads[0].bottom = line;\n } else {\n activeFinderPatternQuads.push({ top: line, bottom: line });\n }\n }\n if (validAlignmentPattern) {\n // Compute the start and end x values of the center black square\n const endX = x - scans[4];\n const startX = endX - scans[3];\n\n const line = { startX, y, endX };\n // Is there a quad directly above the current spot? If so, extend it with the new line. Otherwise, create a new quad with\n // that line as the starting point.\n const matchingQuads = activeAlignmentPatternQuads.filter(q =>\n (startX >= q.bottom.startX && startX <= q.bottom.endX) ||\n (endX >= q.bottom.startX && startX <= q.bottom.endX) ||\n (startX <= q.bottom.startX && endX >= q.bottom.endX && (\n (scans[2] / (q.bottom.endX - q.bottom.startX)) < MAX_QUAD_RATIO &&\n (scans[2] / (q.bottom.endX - q.bottom.startX)) > MIN_QUAD_RATIO\n )),\n );\n if (matchingQuads.length > 0) {\n matchingQuads[0].bottom = line;\n } else {\n activeAlignmentPatternQuads.push({ top: line, bottom: line });\n }\n }\n }\n }\n finderPatternQuads.push(...activeFinderPatternQuads.filter(q => q.bottom.y !== y && q.bottom.y - q.top.y >= 2));\n activeFinderPatternQuads = activeFinderPatternQuads.filter(q => q.bottom.y === y);\n\n alignmentPatternQuads.push(...activeAlignmentPatternQuads.filter(q => q.bottom.y !== y));\n activeAlignmentPatternQuads = activeAlignmentPatternQuads.filter(q => q.bottom.y === y);\n\n }\n\n finderPatternQuads.push(...activeFinderPatternQuads.filter(q => q.bottom.y - q.top.y >= 2));\n alignmentPatternQuads.push(...activeAlignmentPatternQuads);\n\n // Refactored from cozmo/jsQR to (hopefully) circumvent an issue in Safari 13+ on both Mac and iOS (also including\n // iOS Chrome and other Safari iOS derivatives). Safari was very occasionally and apparently not deterministically\n // throwing a \"RangeError: Array size is not a small enough positive integer.\" exception seemingly within the second\n // .map of the original code (here the second for-loop). This second .map contained a nested .map call over the same\n // array instance which was the chained result from previous calls to .map, .filter and .sort which potentially caused\n // this bug in Safari?\n // Also see https://github.com/cozmo/jsQR/issues/157 and https://bugs.webkit.org/show_bug.cgi?id=211619#c3\n const scoredFinderPatternPositions: Array = [];\n for (const quad of finderPatternQuads) {\n if (quad.bottom.y - quad.top.y < 2) {\n // All quads must be at least 2px tall since the center square is larger than a block\n continue;\n }\n\n // calculate quad center\n const x = (quad.top.startX + quad.top.endX + quad.bottom.startX + quad.bottom.endX) / 4;\n const y = (quad.top.y + quad.bottom.y + 1) / 2;\n if (!matrix.get(Math.round(x), Math.round(y))) {\n continue;\n }\n\n const lengths = [quad.top.endX - quad.top.startX, quad.bottom.endX - quad.bottom.startX, quad.bottom.y - quad.top.y + 1];\n const size = sum(lengths) / lengths.length;\n // Initial scoring of finder pattern quads by looking at their ratios, not taking into account position\n const score = scorePattern({x: Math.round(x), y: Math.round(y)}, [1, 1, 3, 1, 1], matrix);\n scoredFinderPatternPositions.push({ score, x, y, size });\n }\n if (scoredFinderPatternPositions.length < 3) {\n // A QR code has 3 finder patterns, therefore we need at least 3 candidates.\n return null;\n }\n scoredFinderPatternPositions.sort((a, b) => a.score - b.score);\n\n // Now take the top finder pattern options and try to find 2 other options with a similar size.\n const finderPatternGroups: Array<{ points: [Point, Point, Point], score: number }> = [];\n for (let i = 0; i < Math.min(scoredFinderPatternPositions.length, MAX_FINDERPATTERNS_TO_SEARCH); ++i) {\n const point = scoredFinderPatternPositions[i];\n const otherPoints: typeof scoredFinderPatternPositions = [];\n\n for (const otherPoint of scoredFinderPatternPositions) {\n if (otherPoint === point) {\n continue;\n }\n otherPoints.push({\n ...otherPoint,\n score: otherPoint.score + ((otherPoint.size - point.size) ** 2) / point.size, // score similarity of sizes\n });\n }\n otherPoints.sort((a, b) => a.score - b.score);\n\n finderPatternGroups.push({\n points: [point, otherPoints[0], otherPoints[1]], // note that otherPoints.length >= 2 as scoredFinderPatternPositions.length >= 3\n score: point.score + otherPoints[0].score + otherPoints[1].score, // total combined score of the three points in the group\n });\n }\n finderPatternGroups.sort((a, b) => a.score - b.score);\n const bestFinderPatternGroup = finderPatternGroups[0];\n\n const { topRight, topLeft, bottomLeft } = reorderFinderPatterns(...bestFinderPatternGroup.points);\n const alignment = findAlignmentPattern(matrix, alignmentPatternQuads, topRight, topLeft, bottomLeft);\n const result: QRLocation[] = [];\n if (alignment) {\n result.push({\n alignmentPattern: { x: alignment.alignmentPattern.x, y: alignment.alignmentPattern.y },\n bottomLeft: {x: bottomLeft.x, y: bottomLeft.y },\n dimension: alignment.dimension,\n topLeft: {x: topLeft.x, y: topLeft.y },\n topRight: {x: topRight.x, y: topRight.y },\n });\n }\n\n // We normally use the center of the quads as the location of the tracking points, which is optimal for most cases and will account\n // for a skew in the image. However, In some cases, a slight skew might not be real and instead be caused by image compression\n // errors and/or low resolution. For those cases, we'd be better off centering the point exactly in the middle of the black area. We\n // compute and return the location data for the naively centered points as it is little additional work and allows for multiple\n // attempts at decoding harder images.\n const midTopRight = recenterLocation(matrix, topRight);\n const midTopLeft = recenterLocation(matrix, topLeft);\n const midBottomLeft = recenterLocation(matrix, bottomLeft);\n const centeredAlignment = findAlignmentPattern(matrix, alignmentPatternQuads, midTopRight, midTopLeft, midBottomLeft);\n if (centeredAlignment) {\n result.push({\n alignmentPattern: { x: centeredAlignment.alignmentPattern.x, y: centeredAlignment.alignmentPattern.y },\n bottomLeft: { x: midBottomLeft.x, y: midBottomLeft. y },\n topLeft: { x: midTopLeft.x, y: midTopLeft. y },\n topRight: { x: midTopRight.x, y: midTopRight. y },\n dimension: centeredAlignment.dimension,\n });\n }\n\n if (result.length === 0) {\n return null;\n }\n\n return result;\n}\n\nfunction findAlignmentPattern(matrix: BitMatrix, alignmentPatternQuads: Quad[], topRight: Point, topLeft: Point, bottomLeft: Point) {\n // Now that we've found the three finder patterns we can determine the blockSize and the size of the QR code.\n // We'll use these to help find the alignment pattern but also later when we do the extraction.\n let dimension: number;\n let moduleSize: number;\n try {\n ({ dimension, moduleSize } = computeDimension(topLeft, topRight, bottomLeft, matrix));\n } catch (e) {\n return null;\n }\n\n // Now find the alignment pattern\n const bottomRightFinderPattern = { // Best guess at where a bottomRight finder pattern would be\n x: topRight.x - topLeft.x + bottomLeft.x,\n y: topRight.y - topLeft.y + bottomLeft.y,\n };\n const modulesBetweenFinderPatterns = ((distance(topLeft, bottomLeft) + distance(topLeft, topRight)) / 2 / moduleSize);\n const correctionToTopLeft = 1 - (3 / modulesBetweenFinderPatterns);\n const expectedAlignmentPattern = {\n x: topLeft.x + correctionToTopLeft * (bottomRightFinderPattern.x - topLeft.x),\n y: topLeft.y + correctionToTopLeft * (bottomRightFinderPattern.y - topLeft.y),\n };\n\n const alignmentPatterns = alignmentPatternQuads\n .map(q => {\n const x = (q.top.startX + q.top.endX + q.bottom.startX + q.bottom.endX) / 4;\n const y = (q.top.y + q.bottom.y + 1) / 2;\n if (!matrix.get(Math.floor(x), Math.floor(y))) {\n return;\n }\n\n const sizeScore = scorePattern({x: Math.floor(x), y: Math.floor(y)}, [1, 1, 1], matrix);\n const score = sizeScore + distance({x, y}, expectedAlignmentPattern);\n return { x, y, score };\n })\n .filter(v => !!v)\n .sort((a, b) => a.score - b.score);\n\n // If there are less than 15 modules between finder patterns it's a version 1 QR code and as such has no alignmemnt pattern\n // so we can only use our best guess.\n const alignmentPattern = modulesBetweenFinderPatterns >= 15 && alignmentPatterns.length ? alignmentPatterns[0] : expectedAlignmentPattern;\n\n return { alignmentPattern, dimension };\n}\n","import {binarize} from \"./binarizer\";\nimport {BitMatrix} from \"./BitMatrix\";\nimport {Chunks} from \"./decoder/decodeData\";\nimport {decode} from \"./decoder/decoder\";\nimport { Version } from \"./decoder/version\";\nimport {extract} from \"./extractor\";\nimport {locate, Point} from \"./locator\";\n\nexport interface QRCode {\n binaryData: number[];\n data: string;\n chunks: Chunks;\n version: number;\n location: {\n topRightCorner: Point;\n topLeftCorner: Point;\n bottomRightCorner: Point;\n bottomLeftCorner: Point;\n\n topRightFinderPattern: Point;\n topLeftFinderPattern: Point;\n bottomLeftFinderPattern: Point;\n\n bottomRightAlignmentPattern?: Point;\n };\n matrix: BitMatrix;\n}\n\nfunction scan(matrix: BitMatrix): QRCode | null {\n const locations = locate(matrix);\n if (!locations) {\n return null;\n }\n\n for (const location of locations) {\n const extracted = extract(matrix, location);\n const decoded = decode(extracted.matrix);\n if (decoded) {\n return {\n binaryData: decoded.bytes,\n data: decoded.text,\n chunks: decoded.chunks,\n version: decoded.version,\n location: {\n topRightCorner: extracted.mappingFunction(location.dimension, 0),\n topLeftCorner: extracted.mappingFunction(0, 0),\n bottomRightCorner: extracted.mappingFunction(location.dimension, location.dimension),\n bottomLeftCorner: extracted.mappingFunction(0, location.dimension),\n\n topRightFinderPattern: location.topRight,\n topLeftFinderPattern: location.topLeft,\n bottomLeftFinderPattern: location.bottomLeft,\n\n bottomRightAlignmentPattern: location.alignmentPattern,\n },\n matrix: extracted.matrix,\n };\n }\n }\n return null;\n}\n\nexport interface Options {\n inversionAttempts?: \"dontInvert\" | \"onlyInvert\" | \"attemptBoth\" | \"invertFirst\";\n greyScaleWeights?: GreyscaleWeights;\n canOverwriteImage?: boolean;\n}\n\nexport interface GreyscaleWeights {\n red: number;\n green: number;\n blue: number;\n useIntegerApproximation?: boolean;\n}\n\nconst defaultOptions: Options = {\n inversionAttempts: \"attemptBoth\",\n greyScaleWeights: {\n red: 0.2126,\n green: 0.7152,\n blue: 0.0722,\n useIntegerApproximation: false,\n },\n canOverwriteImage: true,\n};\n\nfunction mergeObject(target: any, src: any) {\n Object.keys(src).forEach(opt => { // Sad implementation of Object.assign since we target es5 not es6\n target[opt] = src[opt];\n });\n}\n\nfunction jsQR(data: Uint8ClampedArray, width: number, height: number, providedOptions: Options = {}): QRCode | null {\n const options = Object.create(null);\n mergeObject(options, defaultOptions);\n mergeObject(options, providedOptions);\n\n const tryInvertedFirst = options.inversionAttempts === \"onlyInvert\" || options.inversionAttempts === \"invertFirst\";\n const shouldInvert = options.inversionAttempts === \"attemptBoth\" || tryInvertedFirst;\n const {binarized, inverted} = binarize(data, width, height, shouldInvert, options.greyScaleWeights,\n options.canOverwriteImage);\n let result = scan(tryInvertedFirst ? inverted : binarized);\n if (!result && (options.inversionAttempts === \"attemptBoth\" || options.inversionAttempts === \"invertFirst\")) {\n result = scan(tryInvertedFirst ? binarized : inverted);\n }\n return result;\n}\n\n(jsQR as any).default = jsQR;\nexport default jsQR;\n","// @ts-ignore jsqr-es6 does not provide types currently\nimport jsQR from '../node_modules/jsqr-es6/dist/jsQR.js';\n\ntype GrayscaleWeights = {\n red: number,\n green: number,\n blue: number,\n useIntegerApproximation: boolean,\n};\n\nlet inversionAttempts: 'dontInvert' | 'onlyInvert' | 'attemptBoth' = 'dontInvert';\nlet grayscaleWeights: GrayscaleWeights = {\n // weights for quick luma integer approximation (https://en.wikipedia.org/wiki/YUV#Full_swing_for_BT.601)\n red: 77,\n green: 150,\n blue: 29,\n useIntegerApproximation: true,\n};\n\nself.onmessage = event => {\n const id = event['data']['id'];\n const type = event['data']['type'];\n const data = event['data']['data'];\n\n switch (type) {\n case 'decode':\n decode(data, id);\n break;\n case 'grayscaleWeights':\n setGrayscaleWeights(data);\n break;\n case 'inversionMode':\n setInversionMode(data);\n break;\n case 'close':\n // close after earlier messages in the event loop finished processing\n self.close();\n break;\n }\n};\n\nfunction decode(data: { data: Uint8ClampedArray, width: number, height: number }, requestId: number): void {\n const rgbaData = data['data'];\n const width = data['width'];\n const height = data['height'];\n const result = jsQR(rgbaData, width, height, {\n inversionAttempts: inversionAttempts,\n greyScaleWeights: grayscaleWeights,\n });\n if (!result) {\n (self as unknown as Worker).postMessage({\n id: requestId,\n type: 'qrResult',\n data: null,\n });\n return;\n }\n\n (self as unknown as Worker).postMessage({\n id: requestId,\n type: 'qrResult',\n data: result.data,\n // equivalent to cornerPoints of native BarcodeDetector\n cornerPoints: [\n result.location.topLeftCorner,\n result.location.topRightCorner,\n result.location.bottomRightCorner,\n result.location.bottomLeftCorner,\n ],\n });\n}\n\nfunction setGrayscaleWeights(data: GrayscaleWeights) {\n // update grayscaleWeights in a closure compiler compatible fashion\n grayscaleWeights.red = data['red'];\n grayscaleWeights.green = data['green'];\n grayscaleWeights.blue = data['blue'];\n grayscaleWeights.useIntegerApproximation = data['useIntegerApproximation'];\n}\n\nfunction setInversionMode(inversionMode: 'original' | 'invert' | 'both') {\n switch (inversionMode) {\n case 'original':\n inversionAttempts = 'dontInvert';\n break;\n case 'invert':\n inversionAttempts = 'onlyInvert';\n break;\n case 'both':\n inversionAttempts = 'attemptBoth';\n break;\n default:\n throw new Error('Invalid inversion mode');\n }\n}\n"],"names":["BitMatrix","constructor","data","width","height","length","createEmpty","Uint8ClampedArray","get","x","y","set","v","setRegion","left","top","Matrix","buffer","bufferSize","Error","value","BitStream","bytes","readBits","numBits","available","toString","result","bitOffset","byteOffset","bitsToNotRead","toRead","Mode","ModeByte","decodeByte","stream","size","text","i","push","b","decodeURIComponent","map","substr","join","decode","version","chunks","mode","Terminator","ECI","type","assignmentNumber","Numeric","num","a","c","Alphanumeric","AlphanumericCharacterCodes","charCodeAt","Byte","byteResult","Kanji","Math","floor","k","StructuredAppend","currentSequence","totalSequence","parity","GenericGFPoly","field","coefficients","coefficientsLength","firstNonZero","zero","degree","isZero","getCoefficient","addOrSubtract","other","smallerCoefficients","largerCoefficients","lengthDiff","sumDiff","multiply","scalar","product","multiplyPoly","aLength","j","bLength","addOrSubtractGF","aCoeff","bCoefficients","multiplyByMonomial","coefficient","evaluateAt","forEach","GenericGF","primitive","genBase","generatorBase","expTable","Array","logTable","from","one","inverse","buildMonomial","log","exp","runEuclideanAlgorithm","R","tLast","t","r","rLast","rLastLast","q","dltInverse","degreeDiff","scale","tLastLast","sigmaTildeAtZero","twoS","outputBytes","error","s","syndromeCoefficients","evaluation","syndrome","sigmaOmega","numErrors","errorLocator","errorCount","errorLocations","denominator","xiInverse","errorEvaluator","position","infoBits","versionNumber","alignmentPatternCenters","errorCorrectionLevels","ecCodewordsPerBlock","ecBlocks","numBlocks","dataCodewordsPerBlock","numBitsDiffering","z","bitCount","pushBit","bit","byte","bits","formatInfo","errorCorrectionLevel","dataMask","p","readCodewords","matrix","dimension","bitsRead","currentByte","readingUp","columnIndex","columnOffset","codewords","readVersion","provisionalVersion","VERSIONS","topRightVersionBits","bottomLeftVersionBits","bestDifference","Infinity","bestVersion","difference","readFormatInformation","topLeftFormatInfoBits","topRightBottomRightFormatInfoBits","bestFormatInfo","getDataBlocks","ecLevel","totalCodewords","ecInfo","block","dataBlocks","numDataCodewords","slice","shortBlockSize","dataBlock","shift","largeBlockCount","smallBlockCount","decodeMatrix","resultIndex","correctedBytes","resultBytes","decodeData","squareToQuadrilateral","p1","p2","p3","p4","dx3","dy3","a11","a12","a13","a21","a22","a23","a31","a32","a33","quadrilateralToSquare","sToQ","extract","image","location","qToS","sourcePixel","mappingFunction","sum","values","reduce","reorderFinderPatterns","pattern1","pattern2","pattern3","bottomLeft","topLeft","topRight","twoThreeDistance","oneTwoDistance","oneThreeDistance","computeDimension","countBlackWhiteRun","moduleSize","topDimension","sideDimension","countBlackWhiteRunTowardsPoint","origin","end","steep","fromX","fromY","toX","toY","dx","currentPixel","xStep","realX","realY","switchPoints","dy","yStep","distances","distance","awayFromEnd","concat","middleValue","towardsEnd","scoreBlackWhiteRun","sequence","ratios","ratio","averageSize","scorePattern","point","max","min","vertError","diagDownError","diagUpError","avgSize","recenterLocation","leftX","round","rightX","topY","bottomY","locate","activeFinderPatternQuads","activeAlignmentPatternQuads","lastBit","scans","abs","averageFinderPatternBlocksize","averageAlignmentPatternBlocksize","validFinderPattern","startX","endX","bottom","matchingQuads","line","validAlignmentPattern","finderPatternQuads","filter","alignmentPatternQuads","quad","scoredFinderPatternPositions","score","sort","otherPoint","otherPoints","finderPatternGroups","points","alignment","alignmentPattern","midTopRight","midTopLeft","midBottomLeft","centeredAlignment","findAlignmentPattern","e","correctionToTopLeft","sizeScore","expectedAlignmentPattern","scan","locations","decoded","binaryData","topRightCorner","extracted","topLeftCorner","bottomRightCorner","bottomLeftCorner","topRightFinderPattern","topLeftFinderPattern","bottomLeftFinderPattern","bottomRightAlignmentPattern","inversionAttempts","greyScaleWeights","red","green","blue","useIntegerApproximation","canOverwriteImage","mergeObject","target","src","Object","keys","opt","jsQR","providedOptions","options","defaultOptions","shouldInvert","pixelCount","bufferOffset","greyscaleBuffer","greyscaleWeights","greyscalePixels","blackPointsBuffer","blackPointsCount","verticalRegionCount","verticalRegion","hortizontalRegion","horizontalRegionCount","pixelLumosity","average","blackPoints","averageNeighborBlackPoint","binarized","binarizedBuffer","inverted","returnInverted","invertedBuffer","xRegion","yRegion","lum","threshold","tryInvertedFirst","default","grayscaleWeights","self","onmessage","event","self.onmessage","postMessage","id","cornerPoints","close"],"mappings":"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"} \ No newline at end of file diff --git a/client/qr-scanner.umd.min.js b/client/qr-scanner.umd.min.js new file mode 100644 index 0000000..667ac2f --- /dev/null +++ b/client/qr-scanner.umd.min.js @@ -0,0 +1,31 @@ +'use strict';(function(e,a){"object"===typeof exports&&"undefined"!==typeof module?module.exports=a():"function"===typeof define&&define.amd?define(a):(e="undefined"!==typeof globalThis?globalThis:e||self,e.QrScanner=a())})(this,function(){class e{constructor(a,b,c,d,f){this._legacyCanvasSize=e.DEFAULT_CANVAS_SIZE;this._preferredCamera="environment";this._maxScansPerSecond=25;this._lastScanTimestamp=-1;this._destroyed=this._flashOn=this._paused=this._active=!1;this.$video=a;this.$canvas=document.createElement("canvas"); +c&&"object"===typeof c?this._onDecode=b:(c||d||f?console.warn("You're using a deprecated version of the QrScanner constructor which will be removed in the future"):console.warn("Note that the type of the scan result passed to onDecode will change in the future. To already switch to the new api today, you can pass returnDetailedScanResult: true."),this._legacyOnDecode=b);b="object"===typeof c?c:{};this._onDecodeError=b.onDecodeError||("function"===typeof c?c:this._onDecodeError);this._calculateScanRegion= +b.calculateScanRegion||("function"===typeof d?d:this._calculateScanRegion);this._preferredCamera=b.preferredCamera||f||this._preferredCamera;this._legacyCanvasSize="number"===typeof c?c:"number"===typeof d?d:this._legacyCanvasSize;this._maxScansPerSecond=b.maxScansPerSecond||this._maxScansPerSecond;this._onPlay=this._onPlay.bind(this);this._onLoadedMetaData=this._onLoadedMetaData.bind(this);this._onVisibilityChange=this._onVisibilityChange.bind(this);this._updateOverlay=this._updateOverlay.bind(this); +a.disablePictureInPicture=!0;a.playsInline=!0;a.muted=!0;let h=!1;a.hidden&&(a.hidden=!1,h=!0);document.body.contains(a)||(document.body.appendChild(a),h=!0);c=a.parentElement;if(b.highlightScanRegion||b.highlightCodeOutline){d=!!b.overlay;this.$overlay=b.overlay||document.createElement("div");f=this.$overlay.style;f.position="absolute";f.display="none";f.pointerEvents="none";this.$overlay.classList.add("scan-region-highlight");if(!d&&b.highlightScanRegion){this.$overlay.innerHTML=''; +try{this.$overlay.firstElementChild.animate({transform:["scale(.98)","scale(1.01)"]},{duration:400,iterations:Infinity,direction:"alternate",easing:"ease-in-out"})}catch(m){}c.insertBefore(this.$overlay,this.$video.nextSibling)}b.highlightCodeOutline&&(this.$overlay.insertAdjacentHTML("beforeend",''), +this.$codeOutlineHighlight=this.$overlay.lastElementChild)}this._scanRegion=this._calculateScanRegion(a);requestAnimationFrame(()=>{let m=window.getComputedStyle(a);"none"===m.display&&(a.style.setProperty("display","block","important"),h=!0);"visible"!==m.visibility&&(a.style.setProperty("visibility","visible","important"),h=!0);h&&(console.warn("QrScanner has overwritten the video hiding style to avoid Safari stopping the playback."),a.style.opacity="0",a.style.width="0",a.style.height="0",this.$overlay&& +this.$overlay.parentElement&&this.$overlay.parentElement.removeChild(this.$overlay),delete this.$overlay,delete this.$codeOutlineHighlight);this.$overlay&&this._updateOverlay()});a.addEventListener("play",this._onPlay);a.addEventListener("loadedmetadata",this._onLoadedMetaData);document.addEventListener("visibilitychange",this._onVisibilityChange);window.addEventListener("resize",this._updateOverlay);this._qrEnginePromise=e.createQrEngine()}static set WORKER_PATH(a){console.warn("Setting QrScanner.WORKER_PATH is not required and not supported anymore. Have a look at the README for new setup instructions.")}static async hasCamera(){try{return!!(await e.listCameras(!1)).length}catch(a){return!1}}static async listCameras(a= +!1){if(!navigator.mediaDevices)return[];let b=async()=>(await navigator.mediaDevices.enumerateDevices()).filter(d=>"videoinput"===d.kind),c;try{a&&(await b()).every(d=>!d.label)&&(c=await navigator.mediaDevices.getUserMedia({audio:!1,video:!0}))}catch(d){}try{return(await b()).map((d,f)=>({id:d.deviceId,label:d.label||(0===f?"Default Camera":`Camera ${f+1}`)}))}finally{c&&(console.warn("Call listCameras after successfully starting a QR scanner to avoid creating a temporary video stream"),e._stopVideoStream(c))}}async hasFlash(){let a; +try{if(this.$video.srcObject){if(!(this.$video.srcObject instanceof MediaStream))return!1;a=this.$video.srcObject}else a=(await this._getCameraStream()).stream;return"torch"in a.getVideoTracks()[0].getSettings()}catch(b){return!1}finally{a&&a!==this.$video.srcObject&&(console.warn("Call hasFlash after successfully starting the scanner to avoid creating a temporary video stream"),e._stopVideoStream(a))}}isFlashOn(){return this._flashOn}async toggleFlash(){this._flashOn?await this.turnFlashOff():await this.turnFlashOn()}async turnFlashOn(){if(!this._flashOn&& +!this._destroyed&&(this._flashOn=!0,this._active&&!this._paused))try{if(!await this.hasFlash())throw"No flash available";await this.$video.srcObject.getVideoTracks()[0].applyConstraints({advanced:[{torch:!0}]})}catch(a){throw this._flashOn=!1,a;}}async turnFlashOff(){this._flashOn&&(this._flashOn=!1,await this._restartVideoStream())}destroy(){this.$video.removeEventListener("loadedmetadata",this._onLoadedMetaData);this.$video.removeEventListener("play",this._onPlay);document.removeEventListener("visibilitychange", +this._onVisibilityChange);window.removeEventListener("resize",this._updateOverlay);this._destroyed=!0;this._flashOn=!1;this.stop();e._postWorkerMessage(this._qrEnginePromise,"close")}async start(){if(this._destroyed)throw Error("The QR scanner can not be started as it had been destroyed.");if(!this._active||this._paused)if("https:"!==window.location.protocol&&console.warn("The camera stream is only accessible if the page is transferred via https."),this._active=!0,!document.hidden)if(this._paused= +!1,this.$video.srcObject)await this.$video.play();else try{let {stream:a,facingMode:b}=await this._getCameraStream();!this._active||this._paused?e._stopVideoStream(a):(this._setVideoMirror(b),this.$video.srcObject=a,await this.$video.play(),this._flashOn&&(this._flashOn=!1,this.turnFlashOn().catch(()=>{})))}catch(a){if(!this._paused)throw this._active=!1,a;}}stop(){this.pause();this._active=!1}async pause(a=!1){this._paused=!0;if(!this._active)return!0;this.$video.pause();this.$overlay&&(this.$overlay.style.display= +"none");let b=()=>{this.$video.srcObject instanceof MediaStream&&(e._stopVideoStream(this.$video.srcObject),this.$video.srcObject=null)};if(a)return b(),!0;await new Promise(c=>setTimeout(c,300));if(!this._paused)return!1;b();return!0}async setCamera(a){a!==this._preferredCamera&&(this._preferredCamera=a,await this._restartVideoStream())}static async scanImage(a,b,c,d,f=!1,h=!1){let m,n=!1;b&&("scanRegion"in b||"qrEngine"in b||"canvas"in b||"disallowCanvasResizing"in b||"alsoTryWithoutScanRegion"in +b||"returnDetailedScanResult"in b)?(m=b.scanRegion,c=b.qrEngine,d=b.canvas,f=b.disallowCanvasResizing||!1,h=b.alsoTryWithoutScanRegion||!1,n=!0):b||c||d||f||h?console.warn("You're using a deprecated api for scanImage which will be removed in the future."):console.warn("Note that the return type of scanImage will change in the future. To already switch to the new api today, you can pass returnDetailedScanResult: true.");b=!!c;try{let p,k;[c,p]=await Promise.all([c||e.createQrEngine(),e._loadImage(a)]); +[d,k]=e._drawToCanvas(p,m,d,f);let q;if(c instanceof Worker){let g=c;b||e._postWorkerMessageSync(g,"inversionMode","both");q=await new Promise((l,v)=>{let w,u,r,y=-1;u=t=>{t.data.id===y&&(g.removeEventListener("message",u),g.removeEventListener("error",r),clearTimeout(w),null!==t.data.data?l({data:t.data.data,cornerPoints:e._convertPoints(t.data.cornerPoints,m)}):v(e.NO_QR_CODE_FOUND))};r=t=>{g.removeEventListener("message",u);g.removeEventListener("error",r);clearTimeout(w);v("Scanner error: "+(t? +t.message||t:"Unknown Error"))};g.addEventListener("message",u);g.addEventListener("error",r);w=setTimeout(()=>r("timeout"),1E4);let x=k.getImageData(0,0,d.width,d.height);y=e._postWorkerMessageSync(g,"decode",x,[x.data.buffer])})}else q=await Promise.race([new Promise((g,l)=>window.setTimeout(()=>l("Scanner error: timeout"),1E4)),(async()=>{try{var [g]=await c.detect(d);if(!g)throw e.NO_QR_CODE_FOUND;return{data:g.rawValue,cornerPoints:e._convertPoints(g.cornerPoints,m)}}catch(l){g=l.message||l; +if(/not implemented|service unavailable/.test(g))return e._disableBarcodeDetector=!0,e.scanImage(a,{scanRegion:m,canvas:d,disallowCanvasResizing:f,alsoTryWithoutScanRegion:h});throw`Scanner error: ${g}`;}})()]);return n?q:q.data}catch(p){if(!m||!h)throw p;let k=await e.scanImage(a,{qrEngine:c,canvas:d,disallowCanvasResizing:f});return n?k:k.data}finally{b||e._postWorkerMessage(c,"close")}}setGrayscaleWeights(a,b,c,d=!0){e._postWorkerMessage(this._qrEnginePromise,"grayscaleWeights",{red:a,green:b, +blue:c,useIntegerApproximation:d})}setInversionMode(a){e._postWorkerMessage(this._qrEnginePromise,"inversionMode",a)}static async createQrEngine(a){a&&console.warn("Specifying a worker path is not required and not supported anymore.");a=()=>import("./qr-scanner-worker.min.js").then(c=>c.createWorker());if(!(!e._disableBarcodeDetector&&"BarcodeDetector"in window&&BarcodeDetector.getSupportedFormats&&(await BarcodeDetector.getSupportedFormats()).includes("qr_code")))return a();let b=navigator.userAgentData; +return b&&b.brands.some(({brand:c})=>/Chromium/i.test(c))&&/mac ?OS/i.test(b.platform)&&await b.getHighEntropyValues(["architecture","platformVersion"]).then(({architecture:c,platformVersion:d})=>/arm/i.test(c||"arm")&&13<=parseInt(d||"13")).catch(()=>!0)?a():new BarcodeDetector({formats:["qr_code"]})}_onPlay(){this._scanRegion=this._calculateScanRegion(this.$video);this._updateOverlay();this.$overlay&&(this.$overlay.style.display="");this._scanFrame()}_onLoadedMetaData(){this._scanRegion=this._calculateScanRegion(this.$video); +this._updateOverlay()}_onVisibilityChange(){document.hidden?this.pause():this._active&&this.start()}_calculateScanRegion(a){let b=Math.round(2/3*Math.min(a.videoWidth,a.videoHeight));return{x:Math.round((a.videoWidth-b)/2),y:Math.round((a.videoHeight-b)/2),width:b,height:b,downScaledWidth:this._legacyCanvasSize,downScaledHeight:this._legacyCanvasSize}}_updateOverlay(){requestAnimationFrame(()=>{if(this.$overlay){var a=this.$video,b=a.videoWidth,c=a.videoHeight,d=a.offsetWidth,f=a.offsetHeight,h=a.offsetLeft, +m=a.offsetTop,n=window.getComputedStyle(a),p=n.objectFit,k=b/c,q=d/f;switch(p){case "none":var g=b;var l=c;break;case "fill":g=d;l=f;break;default:("cover"===p?k>q:k{const x=parseFloat(r);return r.endsWith("%")?(y?f-l:d-g)*x/100:x});n=this._scanRegion.width||b;q=this._scanRegion.height||c;p=this._scanRegion.x||0;var u=this._scanRegion.y||0;k=this.$overlay.style;k.width= +`${n/b*g}px`;k.height=`${q/c*l}px`;k.top=`${m+w+u/c*l}px`;c=/scaleX\(-1\)/.test(a.style.transform);k.left=`${h+(c?d-v-g:v)+(c?b-p-n:p)/b*g}px`;k.transform=a.style.transform}})}static _convertPoints(a,b){if(!b)return a;let c=b.x||0,d=b.y||0,f=b.width&&b.downScaledWidth?b.width/b.downScaledWidth:1;b=b.height&&b.downScaledHeight?b.height/b.downScaledHeight:1;for(let h of a)h.x=h.x*f+c,h.y=h.y*b+d;return a}_scanFrame(){!this._active||this.$video.paused||this.$video.ended||("requestVideoFrameCallback"in +this.$video?this.$video.requestVideoFrameCallback.bind(this.$video):requestAnimationFrame)(async()=>{if(!(1>=this.$video.readyState)){var a=Date.now()-this._lastScanTimestamp,b=1E3/this._maxScansPerSecond;asetTimeout(d,b-a));this._lastScanTimestamp=Date.now();try{var c=await e.scanImage(this.$video,{scanRegion:this._scanRegion,qrEngine:this._qrEnginePromise,canvas:this.$canvas})}catch(d){if(!this._active)return;this._onDecodeError(d)}!e._disableBarcodeDetector||await this._qrEnginePromise instanceof +Worker||(this._qrEnginePromise=e.createQrEngine());c?(this._onDecode?this._onDecode(c):this._legacyOnDecode&&this._legacyOnDecode(c.data),this.$codeOutlineHighlight&&(clearTimeout(this._codeOutlineHighlightRemovalTimeout),this._codeOutlineHighlightRemovalTimeout=void 0,this.$codeOutlineHighlight.setAttribute("viewBox",`${this._scanRegion.x||0} `+`${this._scanRegion.y||0} `+`${this._scanRegion.width||this.$video.videoWidth} `+`${this._scanRegion.height||this.$video.videoHeight}`),this.$codeOutlineHighlight.firstElementChild.setAttribute("points", +c.cornerPoints.map(({x:d,y:f})=>`${d},${f}`).join(" ")),this.$codeOutlineHighlight.style.display="")):this.$codeOutlineHighlight&&!this._codeOutlineHighlightRemovalTimeout&&(this._codeOutlineHighlightRemovalTimeout=setTimeout(()=>this.$codeOutlineHighlight.style.display="none",100))}this._scanFrame()})}_onDecodeError(a){a!==e.NO_QR_CODE_FOUND&&console.log(a)}async _getCameraStream(){if(!navigator.mediaDevices)throw"Camera not found.";let a=/^(environment|user)$/.test(this._preferredCamera)?"facingMode": +"deviceId",b=[{width:{min:1024}},{width:{min:768}},{}],c=b.map(d=>Object.assign({},d,{[a]:{exact:this._preferredCamera}}));for(let d of[...c,...b])try{let f=await navigator.mediaDevices.getUserMedia({video:d,audio:!1}),h=this._getFacingMode(f)||(d.facingMode?this._preferredCamera:"environment"===this._preferredCamera?"user":"environment");return{stream:f,facingMode:h}}catch(f){}throw"Camera not found.";}async _restartVideoStream(){let a=this._paused;await this.pause(!0)&&!a&&this._active&&await this.start()}static _stopVideoStream(a){for(let b of a.getTracks())b.stop(), +a.removeTrack(b)}_setVideoMirror(a){this.$video.style.transform="scaleX("+("user"===a?-1:1)+")"}_getFacingMode(a){return(a=a.getVideoTracks()[0])?/rear|back|environment/i.test(a.label)?"environment":/front|user|face/i.test(a.label)?"user":null:null}static _drawToCanvas(a,b,c,d=!1){c=c||document.createElement("canvas");let f=b&&b.x?b.x:0,h=b&&b.y?b.y:0,m=b&&b.width?b.width:a.videoWidth||a.width,n=b&&b.height?b.height:a.videoHeight||a.height;d||(d=b&&b.downScaledWidth?b.downScaledWidth:m,b=b&&b.downScaledHeight? +b.downScaledHeight:n,c.width!==d&&(c.width=d),c.height!==b&&(c.height=b));b=c.getContext("2d",{alpha:!1});b.imageSmoothingEnabled=!1;b.drawImage(a,f,h,m,n,0,0,c.width,c.height);return[c,b]}static async _loadImage(a){if(a instanceof Image)return await e._awaitImageLoad(a),a;if(a instanceof HTMLVideoElement||a instanceof HTMLCanvasElement||a instanceof SVGImageElement||"OffscreenCanvas"in window&&a instanceof OffscreenCanvas||"ImageBitmap"in window&&a instanceof ImageBitmap)return a;if(a instanceof +File||a instanceof Blob||a instanceof URL||"string"===typeof a){let b=new Image;b.src=a instanceof File||a instanceof Blob?URL.createObjectURL(a):a.toString();try{return await e._awaitImageLoad(b),b}finally{(a instanceof File||a instanceof Blob)&&URL.revokeObjectURL(b.src)}}else throw"Unsupported image type.";}static async _awaitImageLoad(a){a.complete&&0!==a.naturalWidth||await new Promise((b,c)=>{let d=f=>{a.removeEventListener("load",d);a.removeEventListener("error",d);f instanceof ErrorEvent? +c("Image load error"):b()};a.addEventListener("load",d);a.addEventListener("error",d)})}static async _postWorkerMessage(a,b,c,d){return e._postWorkerMessageSync(await a,b,c,d)}static _postWorkerMessageSync(a,b,c,d){if(!(a instanceof Worker))return-1;let f=e._workerMessageId++;a.postMessage({id:f,type:b,data:c},d);return f}}e.DEFAULT_CANVAS_SIZE=400;e.NO_QR_CODE_FOUND="No QR code found";e._disableBarcodeDetector=!1;e._workerMessageId=0;return e}) +//# sourceMappingURL=qr-scanner.umd.min.js.map diff --git a/client/qr-scanner.umd.min.js.map b/client/qr-scanner.umd.min.js.map new file mode 100644 index 0000000..924569c --- /dev/null +++ b/client/qr-scanner.umd.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"qr-scanner.umd.min.js","sources":["src/qr-scanner.ts"],"sourcesContent":["class QrScanner {\n static readonly DEFAULT_CANVAS_SIZE = 400;\n static readonly NO_QR_CODE_FOUND = 'No QR code found';\n private static _disableBarcodeDetector = false;\n private static _workerMessageId = 0;\n\n /** @deprecated */\n static set WORKER_PATH(workerPath: string) {\n console.warn('Setting QrScanner.WORKER_PATH is not required and not supported anymore. '\n + 'Have a look at the README for new setup instructions.');\n }\n\n static async hasCamera(): Promise {\n try {\n return !!(await QrScanner.listCameras(false)).length;\n } catch (e) {\n return false;\n }\n }\n\n static async listCameras(requestLabels = false): Promise> {\n if (!navigator.mediaDevices) return [];\n\n const enumerateCameras = async (): Promise> =>\n (await navigator.mediaDevices.enumerateDevices()).filter((device) => device.kind === 'videoinput');\n\n // Note that enumerateDevices can always be called and does not prompt the user for permission.\n // However, enumerateDevices only includes device labels if served via https and an active media stream exists\n // or permission to access the camera was given. Therefore, if we're not getting labels but labels are requested\n // ask for camera permission by opening a stream.\n let openedStream: MediaStream | undefined;\n try {\n if (requestLabels && (await enumerateCameras()).every((camera) => !camera.label)) {\n openedStream = await navigator.mediaDevices.getUserMedia({ audio: false, video: true });\n }\n } catch (e) {\n // Fail gracefully, especially if the device has no camera or on mobile when the camera is already in use\n // and some browsers disallow a second stream.\n }\n\n try {\n return (await enumerateCameras()).map((camera, i) => ({\n id: camera.deviceId,\n label: camera.label || (i === 0 ? 'Default Camera' : `Camera ${i + 1}`),\n }));\n } finally {\n // close the stream we just opened for getting camera access for listing the device labels\n if (openedStream) {\n console.warn('Call listCameras after successfully starting a QR scanner to avoid creating '\n + 'a temporary video stream');\n QrScanner._stopVideoStream(openedStream);\n }\n }\n }\n\n readonly $video: HTMLVideoElement;\n readonly $canvas: HTMLCanvasElement;\n readonly $overlay?: HTMLDivElement;\n private readonly $codeOutlineHighlight?: SVGSVGElement;\n private readonly _onDecode?: (result: QrScanner.ScanResult) => void;\n private readonly _legacyOnDecode?: (result: string) => void;\n private readonly _legacyCanvasSize: number = QrScanner.DEFAULT_CANVAS_SIZE;\n private _preferredCamera: QrScanner.FacingMode | QrScanner.DeviceId = 'environment';\n private readonly _maxScansPerSecond: number = 25;\n private _lastScanTimestamp: number = -1;\n private _scanRegion: QrScanner.ScanRegion;\n private _codeOutlineHighlightRemovalTimeout?: number;\n private _qrEnginePromise: Promise\n private _active: boolean = false;\n private _paused: boolean = false;\n private _flashOn: boolean = false;\n private _destroyed: boolean = false;\n\n constructor(\n video: HTMLVideoElement,\n onDecode: (result: QrScanner.ScanResult) => void,\n options: {\n onDecodeError?: (error: Error | string) => void,\n calculateScanRegion?: (video: HTMLVideoElement) => QrScanner.ScanRegion,\n preferredCamera?: QrScanner.FacingMode | QrScanner.DeviceId,\n maxScansPerSecond?: number;\n highlightScanRegion?: boolean,\n highlightCodeOutline?: boolean,\n overlay?: HTMLDivElement,\n /** just a temporary flag until we switch entirely to the new api */\n returnDetailedScanResult?: true,\n },\n );\n /** @deprecated */\n constructor(\n video: HTMLVideoElement,\n onDecode: (result: string) => void,\n onDecodeError?: (error: Error | string) => void,\n calculateScanRegion?: (video: HTMLVideoElement) => QrScanner.ScanRegion,\n preferredCamera?: QrScanner.FacingMode | QrScanner.DeviceId,\n );\n /** @deprecated */\n constructor(\n video: HTMLVideoElement,\n onDecode: (result: string) => void,\n onDecodeError?: (error: Error | string) => void,\n canvasSize?: number,\n preferredCamera?: QrScanner.FacingMode | QrScanner.DeviceId,\n );\n /** @deprecated */\n constructor(video: HTMLVideoElement, onDecode: (result: string) => void, canvasSize?: number);\n constructor(\n video: HTMLVideoElement,\n onDecode: ((result: QrScanner.ScanResult) => void) | ((result: string) => void),\n canvasSizeOrOnDecodeErrorOrOptions?: number | ((error: Error | string) => void) | {\n onDecodeError?: (error: Error | string) => void,\n calculateScanRegion?: (video: HTMLVideoElement) => QrScanner.ScanRegion,\n preferredCamera?: QrScanner.FacingMode | QrScanner.DeviceId,\n maxScansPerSecond?: number;\n highlightScanRegion?: boolean,\n highlightCodeOutline?: boolean,\n overlay?: HTMLDivElement,\n /** just a temporary flag until we switch entirely to the new api */\n returnDetailedScanResult?: true,\n },\n canvasSizeOrCalculateScanRegion?: number | ((video: HTMLVideoElement) => QrScanner.ScanRegion),\n preferredCamera?: QrScanner.FacingMode | QrScanner.DeviceId,\n ) {\n this.$video = video;\n this.$canvas = document.createElement('canvas');\n\n if (canvasSizeOrOnDecodeErrorOrOptions && typeof canvasSizeOrOnDecodeErrorOrOptions === 'object') {\n // we got an options object using the new api\n this._onDecode = onDecode as QrScanner['_onDecode'];\n } else {\n if (canvasSizeOrOnDecodeErrorOrOptions || canvasSizeOrCalculateScanRegion || preferredCamera) {\n console.warn('You\\'re using a deprecated version of the QrScanner constructor which will be removed in '\n + 'the future');\n } else {\n // Only video and onDecode were specified and we can't distinguish between new or old api usage. For\n // backwards compatibility we have to assume the old api for now. The options object is marked as non-\n // optional in the parameter list above to make clear that ScanResult instead of string is only passed\n // if an options object was provided. However, in the future once legacy support is removed, the options\n // object should become optional.\n console.warn('Note that the type of the scan result passed to onDecode will change in the future. '\n + 'To already switch to the new api today, you can pass returnDetailedScanResult: true.');\n }\n this._legacyOnDecode = onDecode as QrScanner['_legacyOnDecode'];\n }\n\n const options = typeof canvasSizeOrOnDecodeErrorOrOptions === 'object'\n ? canvasSizeOrOnDecodeErrorOrOptions\n : {};\n this._onDecodeError = options.onDecodeError || (typeof canvasSizeOrOnDecodeErrorOrOptions === 'function'\n ? canvasSizeOrOnDecodeErrorOrOptions\n : this._onDecodeError);\n this._calculateScanRegion = options.calculateScanRegion || (typeof canvasSizeOrCalculateScanRegion==='function'\n ? canvasSizeOrCalculateScanRegion\n : this._calculateScanRegion);\n this._preferredCamera = options.preferredCamera || preferredCamera || this._preferredCamera;\n this._legacyCanvasSize = typeof canvasSizeOrOnDecodeErrorOrOptions === 'number'\n ? canvasSizeOrOnDecodeErrorOrOptions\n : typeof canvasSizeOrCalculateScanRegion === 'number'\n ? canvasSizeOrCalculateScanRegion\n : this._legacyCanvasSize;\n this._maxScansPerSecond = options.maxScansPerSecond || this._maxScansPerSecond;\n\n this._onPlay = this._onPlay.bind(this);\n this._onLoadedMetaData = this._onLoadedMetaData.bind(this);\n this._onVisibilityChange = this._onVisibilityChange.bind(this);\n this._updateOverlay = this._updateOverlay.bind(this);\n\n // @ts-ignore\n video.disablePictureInPicture = true;\n // Allow inline playback on iPhone instead of requiring full screen playback,\n // see https://webkit.org/blog/6784/new-video-policies-for-ios/\n // @ts-ignore\n video.playsInline = true;\n // Allow play() on iPhone without requiring a user gesture. Should not really be needed as camera stream\n // includes no audio, but just to be safe.\n video.muted = true;\n\n // Avoid Safari stopping the video stream on a hidden video.\n // See https://github.com/cozmo/jsQR/issues/185\n let shouldHideVideo = false;\n if (video.hidden) {\n video.hidden = false;\n shouldHideVideo = true;\n }\n if (!document.body.contains(video)) {\n document.body.appendChild(video);\n shouldHideVideo = true;\n }\n const videoContainer = video.parentElement!;\n\n if (options.highlightScanRegion || options.highlightCodeOutline) {\n const gotExternalOverlay = !!options.overlay;\n this.$overlay = options.overlay || document.createElement('div');\n const overlayStyle = this.$overlay.style;\n overlayStyle.position = 'absolute';\n overlayStyle.display = 'none';\n overlayStyle.pointerEvents = 'none';\n this.$overlay.classList.add('scan-region-highlight');\n if (!gotExternalOverlay && options.highlightScanRegion) {\n // default style; can be overwritten via css, e.g. by changing the svg's stroke color, hiding the\n // .scan-region-highlight-svg, setting a border, outline, background, etc.\n this.$overlay.innerHTML = ''\n + '';\n try {\n this.$overlay.firstElementChild!.animate({ transform: ['scale(.98)', 'scale(1.01)'] }, {\n duration: 400,\n iterations: Infinity,\n direction: 'alternate',\n easing: 'ease-in-out',\n });\n } catch (e) {}\n videoContainer.insertBefore(this.$overlay, this.$video.nextSibling);\n }\n if (options.highlightCodeOutline) {\n // default style; can be overwritten via css\n this.$overlay.insertAdjacentHTML(\n 'beforeend',\n '',\n );\n this.$codeOutlineHighlight = this.$overlay.lastElementChild as SVGSVGElement;\n }\n }\n this._scanRegion = this._calculateScanRegion(video);\n\n requestAnimationFrame(() => {\n // Checking in requestAnimationFrame which should avoid a potential additional re-flow for getComputedStyle.\n const videoStyle = window.getComputedStyle(video);\n if (videoStyle.display === 'none') {\n video.style.setProperty('display', 'block', 'important');\n shouldHideVideo = true;\n }\n if (videoStyle.visibility !== 'visible') {\n video.style.setProperty('visibility', 'visible', 'important');\n shouldHideVideo = true;\n }\n if (shouldHideVideo) {\n // Hide the video in a way that doesn't cause Safari to stop the playback.\n console.warn('QrScanner has overwritten the video hiding style to avoid Safari stopping the playback.');\n video.style.opacity = '0';\n video.style.width = '0';\n video.style.height = '0';\n if (this.$overlay && this.$overlay.parentElement) {\n this.$overlay.parentElement.removeChild(this.$overlay);\n }\n // @ts-ignore\n delete this.$overlay!;\n // @ts-ignore\n delete this.$codeOutlineHighlight!;\n }\n\n if (this.$overlay) {\n this._updateOverlay();\n }\n });\n\n video.addEventListener('play', this._onPlay);\n video.addEventListener('loadedmetadata', this._onLoadedMetaData);\n document.addEventListener('visibilitychange', this._onVisibilityChange);\n window.addEventListener('resize', this._updateOverlay);\n\n this._qrEnginePromise = QrScanner.createQrEngine();\n }\n\n async hasFlash(): Promise {\n let stream: MediaStream | undefined;\n try {\n if (this.$video.srcObject) {\n if (!(this.$video.srcObject instanceof MediaStream)) return false; // srcObject is not a camera stream\n stream = this.$video.srcObject;\n } else {\n stream = (await this._getCameraStream()).stream;\n }\n return 'torch' in stream.getVideoTracks()[0].getSettings();\n } catch (e) {\n return false;\n } finally {\n // close the stream we just opened for detecting whether it supports flash\n if (stream && stream !== this.$video.srcObject) {\n console.warn('Call hasFlash after successfully starting the scanner to avoid creating '\n + 'a temporary video stream');\n QrScanner._stopVideoStream(stream);\n }\n }\n }\n\n isFlashOn(): boolean {\n return this._flashOn;\n }\n\n async toggleFlash(): Promise {\n if (this._flashOn) {\n await this.turnFlashOff();\n } else {\n await this.turnFlashOn();\n }\n }\n\n async turnFlashOn(): Promise {\n if (this._flashOn || this._destroyed) return;\n this._flashOn = true;\n if (!this._active || this._paused) return; // flash will be turned on later on .start()\n try {\n if (!await this.hasFlash()) throw 'No flash available';\n // Note that the video track is guaranteed to exist and to be a MediaStream due to the check in hasFlash\n await (this.$video.srcObject as MediaStream).getVideoTracks()[0].applyConstraints({\n // @ts-ignore: constraint 'torch' is unknown to ts\n advanced: [{ torch: true }],\n });\n } catch (e) {\n this._flashOn = false;\n throw e;\n }\n }\n\n async turnFlashOff(): Promise {\n if (!this._flashOn) return;\n // applyConstraints with torch: false does not work to turn the flashlight off, as a stream's torch stays\n // continuously on, see https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints#torch. Therefore,\n // we have to stop the stream to turn the flashlight off.\n this._flashOn = false;\n await this._restartVideoStream();\n }\n\n destroy(): void {\n this.$video.removeEventListener('loadedmetadata', this._onLoadedMetaData);\n this.$video.removeEventListener('play', this._onPlay);\n document.removeEventListener('visibilitychange', this._onVisibilityChange);\n window.removeEventListener('resize', this._updateOverlay);\n\n this._destroyed = true;\n this._flashOn = false;\n this.stop(); // sets this._paused = true and this._active = false\n QrScanner._postWorkerMessage(this._qrEnginePromise, 'close');\n }\n\n async start(): Promise {\n if (this._destroyed) throw new Error('The QR scanner can not be started as it had been destroyed.');\n if (this._active && !this._paused) return;\n\n if (window.location.protocol !== 'https:') {\n // warn but try starting the camera anyways\n console.warn('The camera stream is only accessible if the page is transferred via https.');\n }\n\n this._active = true;\n if (document.hidden) return; // camera will be started as soon as tab is in foreground\n this._paused = false;\n if (this.$video.srcObject) {\n // camera stream already/still set\n await this.$video.play();\n return;\n }\n\n try {\n const { stream, facingMode } = await this._getCameraStream();\n if (!this._active || this._paused) {\n // was stopped in the meantime\n QrScanner._stopVideoStream(stream);\n return;\n }\n this._setVideoMirror(facingMode);\n this.$video.srcObject = stream;\n await this.$video.play();\n\n // Restart the flash if it was previously on\n if (this._flashOn) {\n this._flashOn = false; // force turnFlashOn to restart the flash\n this.turnFlashOn().catch(() => {});\n }\n } catch (e) {\n if (this._paused) return;\n this._active = false;\n throw e;\n }\n }\n\n stop(): void {\n this.pause();\n this._active = false;\n }\n\n async pause(stopStreamImmediately = false): Promise {\n this._paused = true;\n if (!this._active) return true;\n this.$video.pause();\n\n if (this.$overlay) {\n this.$overlay.style.display = 'none';\n }\n\n const stopStream = () => {\n if (this.$video.srcObject instanceof MediaStream) {\n // revoke srcObject only if it's a stream which was likely set by us\n QrScanner._stopVideoStream(this.$video.srcObject);\n this.$video.srcObject = null;\n }\n };\n\n if (stopStreamImmediately) {\n stopStream();\n return true;\n }\n\n await new Promise((resolve) => setTimeout(resolve, 300));\n if (!this._paused) return false;\n stopStream();\n return true;\n }\n\n async setCamera(facingModeOrDeviceId: QrScanner.FacingMode | QrScanner.DeviceId): Promise {\n if (facingModeOrDeviceId === this._preferredCamera) return;\n this._preferredCamera = facingModeOrDeviceId;\n // Restart the scanner with the new camera which will also update the video mirror and the scan region.\n await this._restartVideoStream();\n }\n\n static async scanImage(\n imageOrFileOrBlobOrUrl: HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | ImageBitmap\n | SVGImageElement | File | Blob | URL | String,\n options: {\n scanRegion?: QrScanner.ScanRegion | null,\n qrEngine?: Worker | BarcodeDetector | Promise | null,\n canvas?: HTMLCanvasElement | null,\n disallowCanvasResizing?: boolean,\n alsoTryWithoutScanRegion?: boolean,\n /** just a temporary flag until we switch entirely to the new api */\n returnDetailedScanResult?: true,\n },\n ): Promise;\n /** @deprecated */\n static async scanImage(\n imageOrFileOrBlobOrUrl: HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | ImageBitmap\n | SVGImageElement | File | Blob | URL | String,\n scanRegion?: QrScanner.ScanRegion | null,\n qrEngine?: Worker | BarcodeDetector | Promise | null,\n canvas?: HTMLCanvasElement | null,\n disallowCanvasResizing?: boolean,\n alsoTryWithoutScanRegion?: boolean,\n ): Promise;\n static async scanImage(\n imageOrFileOrBlobOrUrl: HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | ImageBitmap\n | SVGImageElement | File | Blob | URL | String,\n scanRegionOrOptions?: QrScanner.ScanRegion | {\n scanRegion?: QrScanner.ScanRegion | null,\n qrEngine?: Worker | BarcodeDetector | Promise | null,\n canvas?: HTMLCanvasElement | null,\n disallowCanvasResizing?: boolean,\n alsoTryWithoutScanRegion?: boolean,\n /** just a temporary flag until we switch entirely to the new api */\n returnDetailedScanResult?: true,\n } | null,\n qrEngine?: Worker | BarcodeDetector | Promise | null,\n canvas?: HTMLCanvasElement | null,\n disallowCanvasResizing: boolean = false,\n alsoTryWithoutScanRegion: boolean = false,\n ): Promise {\n let scanRegion: QrScanner.ScanRegion | null | undefined;\n let returnDetailedScanResult = false;\n if (scanRegionOrOptions && (\n 'scanRegion' in scanRegionOrOptions\n || 'qrEngine' in scanRegionOrOptions\n || 'canvas' in scanRegionOrOptions\n || 'disallowCanvasResizing' in scanRegionOrOptions\n || 'alsoTryWithoutScanRegion' in scanRegionOrOptions\n || 'returnDetailedScanResult' in scanRegionOrOptions\n )) {\n // we got an options object using the new api\n scanRegion = scanRegionOrOptions.scanRegion;\n qrEngine = scanRegionOrOptions.qrEngine;\n canvas = scanRegionOrOptions.canvas;\n disallowCanvasResizing = scanRegionOrOptions.disallowCanvasResizing || false;\n alsoTryWithoutScanRegion = scanRegionOrOptions.alsoTryWithoutScanRegion || false;\n returnDetailedScanResult = true;\n } else if (scanRegionOrOptions || qrEngine || canvas || disallowCanvasResizing || alsoTryWithoutScanRegion) {\n console.warn('You\\'re using a deprecated api for scanImage which will be removed in the future.');\n } else {\n // Only imageOrFileOrBlobOrUrl was specified and we can't distinguish between new or old api usage. For\n // backwards compatibility we have to assume the old api for now. The options object is marked as non-\n // optional in the parameter list above to make clear that ScanResult instead of string is only returned if\n // an options object was provided. However, in the future once legacy support is removed, the options object\n // should become optional.\n console.warn('Note that the return type of scanImage will change in the future. To already switch to the '\n + 'new api today, you can pass returnDetailedScanResult: true.');\n }\n\n const gotExternalEngine = !!qrEngine;\n\n try {\n let image: HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | ImageBitmap\n | SVGImageElement;\n let canvasContext: CanvasRenderingContext2D;\n [qrEngine, image] = await Promise.all([\n qrEngine || QrScanner.createQrEngine(),\n QrScanner._loadImage(imageOrFileOrBlobOrUrl),\n ]);\n [canvas, canvasContext] = QrScanner._drawToCanvas(image, scanRegion, canvas, disallowCanvasResizing);\n let detailedScanResult: QrScanner.ScanResult;\n\n if (qrEngine instanceof Worker) {\n const qrEngineWorker = qrEngine; // for ts to know that it's still a worker later in the event listeners\n if (!gotExternalEngine) {\n // Enable scanning of inverted color qr codes.\n QrScanner._postWorkerMessageSync(qrEngineWorker, 'inversionMode', 'both');\n }\n detailedScanResult = await new Promise((resolve, reject) => {\n let timeout: number;\n let onMessage: (event: MessageEvent) => void;\n let onError: (error: ErrorEvent | string) => void;\n let expectedResponseId = -1;\n onMessage = (event: MessageEvent) => {\n if (event.data.id !== expectedResponseId) {\n return;\n }\n qrEngineWorker.removeEventListener('message', onMessage);\n qrEngineWorker.removeEventListener('error', onError);\n clearTimeout(timeout);\n if (event.data.data !== null) {\n resolve({\n data: event.data.data,\n cornerPoints: QrScanner._convertPoints(event.data.cornerPoints, scanRegion),\n });\n } else {\n reject(QrScanner.NO_QR_CODE_FOUND);\n }\n };\n onError = (error: ErrorEvent | string) => {\n qrEngineWorker.removeEventListener('message', onMessage);\n qrEngineWorker.removeEventListener('error', onError);\n clearTimeout(timeout);\n const errorMessage = !error ? 'Unknown Error' : ((error as ErrorEvent).message || error);\n reject('Scanner error: ' + errorMessage);\n };\n qrEngineWorker.addEventListener('message', onMessage);\n qrEngineWorker.addEventListener('error', onError);\n timeout = setTimeout(() => onError('timeout'), 10000);\n const imageData = canvasContext.getImageData(0, 0, canvas!.width, canvas!.height);\n expectedResponseId = QrScanner._postWorkerMessageSync(\n qrEngineWorker,\n 'decode',\n imageData,\n [imageData.data.buffer],\n );\n });\n } else {\n detailedScanResult = await Promise.race([\n new Promise((resolve, reject) => window.setTimeout(\n () => reject('Scanner error: timeout'),\n 10000,\n )),\n (async (): Promise => {\n try {\n const [scanResult] = await qrEngine.detect(canvas!);\n if (!scanResult) throw QrScanner.NO_QR_CODE_FOUND;\n return {\n data: scanResult.rawValue,\n cornerPoints: QrScanner._convertPoints(scanResult.cornerPoints, scanRegion),\n };\n } catch (e) {\n const errorMessage = (e as Error).message || e as string;\n if (/not implemented|service unavailable/.test(errorMessage)) {\n // Not implemented can apparently for some reason happen even though getSupportedFormats\n // in createQrScanner reported that it's supported, see issue #98.\n // Service unavailable can happen after some time when the BarcodeDetector crashed and\n // can theoretically be recovered from by creating a new BarcodeDetector. However, in\n // newer browsers this issue does not seem to be present anymore and therefore we do not\n // apply this optimization anymore but just set _disableBarcodeDetector in both cases.\n // Also note that if we got an external qrEngine that crashed, we should possibly notify\n // the caller about it, but we also don't do this here, as it's such an unlikely case.\n QrScanner._disableBarcodeDetector = true;\n // retry without passing the broken BarcodeScanner instance\n return QrScanner.scanImage(imageOrFileOrBlobOrUrl, {\n scanRegion,\n canvas,\n disallowCanvasResizing,\n alsoTryWithoutScanRegion,\n });\n }\n throw `Scanner error: ${errorMessage}`;\n }\n })(),\n ]);\n }\n return returnDetailedScanResult ? detailedScanResult : detailedScanResult.data;\n } catch (e) {\n if (!scanRegion || !alsoTryWithoutScanRegion) throw e;\n const detailedScanResult = await QrScanner.scanImage(\n imageOrFileOrBlobOrUrl,\n { qrEngine, canvas, disallowCanvasResizing },\n );\n return returnDetailedScanResult ? detailedScanResult : detailedScanResult.data;\n } finally {\n if (!gotExternalEngine) {\n QrScanner._postWorkerMessage(qrEngine!, 'close');\n }\n }\n }\n\n setGrayscaleWeights(red: number, green: number, blue: number, useIntegerApproximation: boolean = true): void {\n // Note that for the native BarcodeDecoder or if the worker was destroyed, this is a no-op. However, the native\n // implementations work also well with colored qr codes.\n QrScanner._postWorkerMessage(\n this._qrEnginePromise,\n 'grayscaleWeights',\n { red, green, blue, useIntegerApproximation }\n );\n }\n\n setInversionMode(inversionMode: QrScanner.InversionMode): void {\n // Note that for the native BarcodeDecoder or if the worker was destroyed, this is a no-op. However, the native\n // implementations scan normal and inverted qr codes by default\n QrScanner._postWorkerMessage(this._qrEnginePromise, 'inversionMode', inversionMode);\n }\n\n static async createQrEngine(): Promise;\n /** @deprecated */\n static async createQrEngine(workerPath: string): Promise;\n static async createQrEngine(workerPath?: string): Promise {\n if (workerPath) {\n console.warn('Specifying a worker path is not required and not supported anymore.');\n }\n\n // @ts-ignore no types defined for import\n const createWorker = () => (import('./qr-scanner-worker.min.js') as Promise<{ createWorker: () => Worker }>)\n .then((module) => module.createWorker());\n\n const useBarcodeDetector = !QrScanner._disableBarcodeDetector\n && 'BarcodeDetector' in window\n && BarcodeDetector.getSupportedFormats\n && (await BarcodeDetector.getSupportedFormats()).includes('qr_code');\n\n if (!useBarcodeDetector) return createWorker();\n\n // On Macs with an M1/M2 processor and macOS Ventura (macOS version 13), the BarcodeDetector is broken in\n // Chromium based browsers, regardless of the version. For that constellation, the BarcodeDetector does not\n // error but does not detect QR codes. Macs without an M1/M2 or before Ventura are fine.\n // See issue #209 and https://bugs.chromium.org/p/chromium/issues/detail?id=1382442\n // TODO update this once the issue in macOS is fixed\n const userAgentData = navigator.userAgentData;\n const isChromiumOnMacWithArmVentura = userAgentData // all Chromium browsers support userAgentData\n && userAgentData.brands.some(({ brand }) => /Chromium/i.test(brand))\n && /mac ?OS/i.test(userAgentData.platform)\n // Does it have an ARM chip (e.g. M1/M2) and Ventura? Check this last as getHighEntropyValues can\n // theoretically trigger a browser prompt, although no browser currently does seem to show one.\n // If browser or user refused to return the requested values, assume broken ARM Ventura, to be safe.\n && await userAgentData.getHighEntropyValues(['architecture', 'platformVersion'])\n .then(({ architecture, platformVersion }) =>\n /arm/i.test(architecture || 'arm') && parseInt(platformVersion || '13') >= /* Ventura */ 13)\n .catch(() => true);\n if (isChromiumOnMacWithArmVentura) return createWorker();\n\n return new BarcodeDetector({ formats: ['qr_code'] });\n }\n\n private _onPlay(): void {\n this._scanRegion = this._calculateScanRegion(this.$video);\n this._updateOverlay();\n if (this.$overlay) {\n this.$overlay.style.display = '';\n }\n this._scanFrame();\n }\n\n private _onLoadedMetaData(): void {\n this._scanRegion = this._calculateScanRegion(this.$video);\n this._updateOverlay();\n }\n\n private _onVisibilityChange(): void {\n if (document.hidden) {\n this.pause();\n } else if (this._active) {\n this.start();\n }\n }\n\n private _calculateScanRegion(video: HTMLVideoElement): QrScanner.ScanRegion {\n // Default scan region calculation. Note that this can be overwritten in the constructor.\n const smallestDimension = Math.min(video.videoWidth, video.videoHeight);\n const scanRegionSize = Math.round(2 / 3 * smallestDimension);\n return {\n x: Math.round((video.videoWidth - scanRegionSize) / 2),\n y: Math.round((video.videoHeight - scanRegionSize) / 2),\n width: scanRegionSize,\n height: scanRegionSize,\n downScaledWidth: this._legacyCanvasSize,\n downScaledHeight: this._legacyCanvasSize,\n };\n }\n\n private _updateOverlay(): void {\n requestAnimationFrame(() => {\n // Running in requestAnimationFrame which should avoid a potential additional re-flow for getComputedStyle\n // and offsetWidth, offsetHeight, offsetLeft, offsetTop.\n if (!this.$overlay) return;\n const video = this.$video;\n const videoWidth = video.videoWidth;\n const videoHeight = video.videoHeight;\n const elementWidth = video.offsetWidth;\n const elementHeight = video.offsetHeight;\n const elementX = video.offsetLeft;\n const elementY = video.offsetTop;\n\n const videoStyle = window.getComputedStyle(video);\n const videoObjectFit = videoStyle.objectFit;\n const videoAspectRatio = videoWidth / videoHeight;\n const elementAspectRatio = elementWidth / elementHeight;\n let videoScaledWidth: number;\n let videoScaledHeight: number;\n switch (videoObjectFit) {\n case 'none':\n videoScaledWidth = videoWidth;\n videoScaledHeight = videoHeight;\n break;\n case 'fill':\n videoScaledWidth = elementWidth;\n videoScaledHeight = elementHeight;\n break;\n default: // 'cover', 'contains', 'scale-down'\n if (videoObjectFit === 'cover'\n ? videoAspectRatio > elementAspectRatio\n : videoAspectRatio < elementAspectRatio) {\n // The scaled height is the element height\n // - for 'cover' if the video aspect ratio is wider than the element aspect ratio\n // (scaled height matches element height and scaled width overflows element width)\n // - for 'contains'/'scale-down' if element aspect ratio is wider than the video aspect ratio\n // (scaled height matched element height and element width overflows scaled width)\n videoScaledHeight = elementHeight;\n videoScaledWidth = videoScaledHeight * videoAspectRatio;\n } else {\n videoScaledWidth = elementWidth;\n videoScaledHeight = videoScaledWidth / videoAspectRatio;\n }\n if (videoObjectFit === 'scale-down') {\n // for 'scale-down' the dimensions are the minimum of 'contains' and 'none'\n videoScaledWidth = Math.min(videoScaledWidth, videoWidth);\n videoScaledHeight = Math.min(videoScaledHeight, videoHeight);\n }\n }\n\n // getComputedStyle is so nice to convert keywords (left, center, right, top, bottom) to percent and makes\n // sure to set the default of 50% if only one or no component was provided, therefore we can be sure that\n // both components are set. Additionally, it converts units other than px (e.g. rem) to px.\n const [videoX, videoY] = videoStyle.objectPosition.split(' ').map((length, i) => {\n const lengthValue = parseFloat(length);\n return length.endsWith('%')\n ? (!i ? elementWidth - videoScaledWidth : elementHeight - videoScaledHeight) * lengthValue / 100\n : lengthValue;\n });\n\n const regionWidth = this._scanRegion.width || videoWidth;\n const regionHeight = this._scanRegion.height || videoHeight;\n const regionX = this._scanRegion.x || 0;\n const regionY = this._scanRegion.y || 0;\n\n const overlayStyle = this.$overlay.style;\n overlayStyle.width = `${regionWidth / videoWidth * videoScaledWidth}px`;\n overlayStyle.height = `${regionHeight / videoHeight * videoScaledHeight}px`;\n overlayStyle.top = `${elementY + videoY + regionY / videoHeight * videoScaledHeight}px`;\n const isVideoMirrored = /scaleX\\(-1\\)/.test(video.style.transform!);\n overlayStyle.left = `${elementX\n + (isVideoMirrored ? elementWidth - videoX - videoScaledWidth : videoX)\n + (isVideoMirrored ? videoWidth - regionX - regionWidth : regionX) / videoWidth * videoScaledWidth}px`;\n // apply same mirror as on video\n overlayStyle.transform = video.style.transform;\n });\n }\n\n private static _convertPoints(\n points: QrScanner.Point[],\n scanRegion?: QrScanner.ScanRegion | null,\n ): QrScanner.Point[] {\n if (!scanRegion) return points;\n const offsetX = scanRegion.x || 0;\n const offsetY = scanRegion.y || 0;\n const scaleFactorX = scanRegion.width && scanRegion.downScaledWidth\n ? scanRegion.width / scanRegion.downScaledWidth\n : 1;\n const scaleFactorY = scanRegion.height && scanRegion.downScaledHeight\n ? scanRegion.height / scanRegion.downScaledHeight\n : 1;\n for (const point of points) {\n point.x = point.x * scaleFactorX + offsetX;\n point.y = point.y * scaleFactorY + offsetY;\n }\n return points;\n }\n\n private _scanFrame(): void {\n if (!this._active || this.$video.paused || this.$video.ended) return;\n // If requestVideoFrameCallback is available use that to avoid unnecessary scans on the same frame as the\n // camera's framerate can be lower than the screen refresh rate and this._maxScansPerSecond, especially in dark\n // settings where the exposure time is longer. Both, requestVideoFrameCallback and requestAnimationFrame are not\n // being fired if the tab is in the background, which is what we want.\n const requestFrame = 'requestVideoFrameCallback' in this.$video\n // @ts-ignore\n ? this.$video.requestVideoFrameCallback.bind(this.$video)\n : requestAnimationFrame;\n requestFrame(async () => {\n if (this.$video.readyState <= 1) {\n // Skip scans until the video is ready as drawImage() only works correctly on a video with readyState\n // > 1, see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage#Notes.\n // This also avoids false positives for videos paused after a successful scan which remains visible on\n // the canvas until the video is started again and ready.\n this._scanFrame();\n return;\n }\n\n const timeSinceLastScan = Date.now() - this._lastScanTimestamp;\n const minimumTimeBetweenScans = 1000 / this._maxScansPerSecond;\n if (timeSinceLastScan < minimumTimeBetweenScans) {\n await new Promise((resolve) => setTimeout(resolve, minimumTimeBetweenScans - timeSinceLastScan));\n }\n // console.log('Scan rate:', Math.round(1000 / (Date.now() - this._lastScanTimestamp)));\n this._lastScanTimestamp = Date.now();\n\n let result: QrScanner.ScanResult | undefined;\n try {\n result = await QrScanner.scanImage(this.$video, {\n scanRegion: this._scanRegion,\n qrEngine: this._qrEnginePromise,\n canvas: this.$canvas,\n });\n } catch (error) {\n if (!this._active) return;\n this._onDecodeError(error as Error | string);\n }\n\n if (QrScanner._disableBarcodeDetector && !(await this._qrEnginePromise instanceof Worker)) {\n // replace the disabled BarcodeDetector\n this._qrEnginePromise = QrScanner.createQrEngine();\n }\n\n if (result) {\n if (this._onDecode) {\n this._onDecode(result);\n } else if (this._legacyOnDecode) {\n this._legacyOnDecode(result.data);\n }\n\n if (this.$codeOutlineHighlight) {\n clearTimeout(this._codeOutlineHighlightRemovalTimeout);\n this._codeOutlineHighlightRemovalTimeout = undefined;\n this.$codeOutlineHighlight.setAttribute(\n 'viewBox',\n `${this._scanRegion.x || 0} `\n + `${this._scanRegion.y || 0} `\n + `${this._scanRegion.width || this.$video.videoWidth} `\n + `${this._scanRegion.height || this.$video.videoHeight}`,\n );\n const polygon = this.$codeOutlineHighlight.firstElementChild!;\n polygon.setAttribute('points', result.cornerPoints.map(({x, y}) => `${x},${y}`).join(' '));\n this.$codeOutlineHighlight.style.display = '';\n }\n } else if (this.$codeOutlineHighlight && !this._codeOutlineHighlightRemovalTimeout) {\n // hide after timeout to make it flash less when on some frames the QR code is detected and on some not\n this._codeOutlineHighlightRemovalTimeout = setTimeout(\n () => this.$codeOutlineHighlight!.style.display = 'none',\n 100,\n );\n }\n\n this._scanFrame();\n });\n }\n\n private _onDecodeError(error: Error | string): void {\n // default error handler; can be overwritten in the constructor\n if (error === QrScanner.NO_QR_CODE_FOUND) return;\n console.log(error);\n }\n\n private async _getCameraStream(): Promise<{ stream: MediaStream, facingMode: QrScanner.FacingMode }> {\n if (!navigator.mediaDevices) throw 'Camera not found.';\n\n const preferenceType = /^(environment|user)$/.test(this._preferredCamera)\n ? 'facingMode'\n : 'deviceId';\n const constraintsWithoutCamera: Array = [{\n width: { min: 1024 }\n }, {\n width: { min: 768 }\n }, {}];\n const constraintsWithCamera = constraintsWithoutCamera.map((constraint) => Object.assign({}, constraint, {\n [preferenceType]: { exact: this._preferredCamera },\n }));\n\n for (const constraints of [...constraintsWithCamera, ...constraintsWithoutCamera]) {\n try {\n const stream = await navigator.mediaDevices.getUserMedia({ video: constraints, audio: false });\n // Try to determine the facing mode from the stream, otherwise use a guess or 'environment' as\n // default. Note that the guess is not always accurate as Safari returns cameras of different facing\n // mode, even for exact facingMode constraints.\n const facingMode = this._getFacingMode(stream)\n || (constraints.facingMode\n ? this._preferredCamera as QrScanner.FacingMode // a facing mode we were able to fulfill\n : (this._preferredCamera === 'environment'\n ? 'user' // switch as _preferredCamera was environment but we are not able to fulfill it\n : 'environment' // switch from unfulfilled user facingMode or default to environment\n )\n );\n return { stream, facingMode };\n } catch (e) {}\n }\n\n throw 'Camera not found.';\n }\n\n private async _restartVideoStream(): Promise {\n // Note that we always pause the stream and not only if !this._paused as even if this._paused === true, the\n // stream might still be running, as it's by default only stopped after a delay of 300ms.\n const wasPaused = this._paused;\n const paused = await this.pause(true);\n if (!paused || wasPaused || !this._active) return;\n await this.start();\n }\n\n private static _stopVideoStream(stream : MediaStream): void {\n for (const track of stream.getTracks()) {\n track.stop(); // note that this will also automatically turn the flashlight off\n stream.removeTrack(track);\n }\n }\n\n private _setVideoMirror(facingMode: QrScanner.FacingMode): void {\n // in user facing mode mirror the video to make it easier for the user to position the QR code\n const scaleFactor = facingMode === 'user'? -1 : 1;\n this.$video.style.transform = 'scaleX(' + scaleFactor + ')';\n }\n\n private _getFacingMode(videoStream: MediaStream): QrScanner.FacingMode | null {\n const videoTrack = videoStream.getVideoTracks()[0];\n if (!videoTrack) return null; // unknown\n // inspired by https://github.com/JodusNodus/react-qr-reader/blob/master/src/getDeviceId.js#L13\n return /rear|back|environment/i.test(videoTrack.label)\n ? 'environment'\n : /front|user|face/i.test(videoTrack.label)\n ? 'user'\n : null; // unknown\n }\n\n private static _drawToCanvas(\n image: HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | ImageBitmap\n | SVGImageElement,\n scanRegion?: QrScanner.ScanRegion | null,\n canvas?: HTMLCanvasElement | null,\n disallowCanvasResizing= false,\n ): [HTMLCanvasElement, CanvasRenderingContext2D] {\n canvas = canvas || document.createElement('canvas');\n const scanRegionX = scanRegion && scanRegion.x ? scanRegion.x : 0;\n const scanRegionY = scanRegion && scanRegion.y ? scanRegion.y : 0;\n const scanRegionWidth = scanRegion && scanRegion.width\n ? scanRegion.width\n : (image as HTMLVideoElement).videoWidth || image.width as number;\n const scanRegionHeight = scanRegion && scanRegion.height\n ? scanRegion.height\n : (image as HTMLVideoElement).videoHeight || image.height as number;\n\n if (!disallowCanvasResizing) {\n const canvasWidth = scanRegion && scanRegion.downScaledWidth\n ? scanRegion.downScaledWidth\n : scanRegionWidth;\n const canvasHeight = scanRegion && scanRegion.downScaledHeight\n ? scanRegion.downScaledHeight\n : scanRegionHeight;\n // Setting the canvas width or height clears the canvas, even if the values didn't change, therefore only\n // set them if they actually changed.\n if (canvas.width !== canvasWidth) {\n canvas.width = canvasWidth;\n }\n if (canvas.height !== canvasHeight) {\n canvas.height = canvasHeight;\n }\n }\n\n const context = canvas.getContext('2d', { alpha: false })!;\n context.imageSmoothingEnabled = false; // gives less blurry images\n context.drawImage(\n image,\n scanRegionX, scanRegionY, scanRegionWidth, scanRegionHeight,\n 0, 0, canvas.width, canvas.height,\n );\n return [canvas, context];\n }\n\n private static async _loadImage(\n imageOrFileOrBlobOrUrl: HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | ImageBitmap\n | SVGImageElement | File | Blob | URL | String,\n ): Promise {\n if (imageOrFileOrBlobOrUrl instanceof Image) {\n await QrScanner._awaitImageLoad(imageOrFileOrBlobOrUrl);\n return imageOrFileOrBlobOrUrl;\n } else if (imageOrFileOrBlobOrUrl instanceof HTMLVideoElement\n || imageOrFileOrBlobOrUrl instanceof HTMLCanvasElement\n || imageOrFileOrBlobOrUrl instanceof SVGImageElement\n || 'OffscreenCanvas' in window && imageOrFileOrBlobOrUrl instanceof OffscreenCanvas\n || 'ImageBitmap' in window && imageOrFileOrBlobOrUrl instanceof ImageBitmap) {\n return imageOrFileOrBlobOrUrl;\n } else if (imageOrFileOrBlobOrUrl instanceof File || imageOrFileOrBlobOrUrl instanceof Blob\n || imageOrFileOrBlobOrUrl instanceof URL || typeof imageOrFileOrBlobOrUrl === 'string') {\n const image = new Image();\n if (imageOrFileOrBlobOrUrl instanceof File || imageOrFileOrBlobOrUrl instanceof Blob) {\n image.src = URL.createObjectURL(imageOrFileOrBlobOrUrl);\n } else {\n image.src = imageOrFileOrBlobOrUrl.toString();\n }\n try {\n await QrScanner._awaitImageLoad(image);\n return image;\n } finally {\n if (imageOrFileOrBlobOrUrl instanceof File || imageOrFileOrBlobOrUrl instanceof Blob) {\n URL.revokeObjectURL(image.src);\n }\n }\n } else {\n throw 'Unsupported image type.';\n }\n }\n\n private static async _awaitImageLoad(image: HTMLImageElement): Promise {\n if (image.complete && image.naturalWidth !== 0) return; // already loaded\n await new Promise((resolve, reject) => {\n const listener = (event: ErrorEvent | Event) => {\n image.removeEventListener('load', listener);\n image.removeEventListener('error', listener);\n if (event instanceof ErrorEvent) {\n reject('Image load error');\n } else {\n resolve();\n }\n };\n image.addEventListener('load', listener);\n image.addEventListener('error', listener);\n });\n }\n\n private static async _postWorkerMessage(\n qrEngineOrQrEnginePromise: Worker | BarcodeDetector | Promise,\n type: string,\n data?: any,\n transfer?: Transferable[],\n ): Promise {\n return QrScanner._postWorkerMessageSync(await qrEngineOrQrEnginePromise, type, data, transfer);\n }\n\n // sync version of _postWorkerMessage without performance overhead of async functions\n private static _postWorkerMessageSync(\n qrEngine: Worker | BarcodeDetector,\n type: string,\n data?: any,\n transfer?: Transferable[],\n ): number {\n if (!(qrEngine instanceof Worker)) return -1;\n const id = QrScanner._workerMessageId++;\n qrEngine.postMessage({\n id,\n type,\n data,\n }, transfer);\n return id;\n }\n}\n\ndeclare namespace QrScanner {\n export interface ScanRegion {\n x?: number;\n y?: number;\n width?: number;\n height?: number;\n downScaledWidth?: number;\n downScaledHeight?: number;\n }\n\n export type FacingMode = 'environment' | 'user';\n export type DeviceId = string;\n\n export interface Camera {\n id: DeviceId;\n label: string;\n }\n\n export type InversionMode = 'original' | 'invert' | 'both';\n\n export interface Point {\n x: number;\n y: number;\n }\n\n export interface ScanResult {\n data: string;\n // In clockwise order, starting at top left, but this might not be guaranteed in the future.\n cornerPoints: QrScanner.Point[];\n }\n}\n\n// simplified from https://wicg.github.io/shape-detection-api/#barcode-detection-api\ndeclare class BarcodeDetector {\n constructor(options?: { formats: string[] });\n static getSupportedFormats(): Promise;\n detect(image: ImageBitmapSource): Promise>;\n}\n\n// simplified from https://github.com/lukewarlow/user-agent-data-types/blob/master/index.d.ts\ndeclare global {\n interface Navigator {\n readonly userAgentData?: {\n readonly platform: string;\n readonly brands: Array<{\n readonly brand: string;\n readonly version: string;\n }>;\n getHighEntropyValues(hints: string[]): Promise<{\n readonly architecture?: string;\n readonly platformVersion?: string;\n }>;\n };\n }\n}\n\nexport default QrScanner;\n"],"names":["QrScanner","constructor","video","onDecode","canvasSizeOrOnDecodeErrorOrOptions","canvasSizeOrCalculateScanRegion","preferredCamera","DEFAULT_CANVAS_SIZE","$video","$canvas","document","createElement","_onDecode","console","warn","_legacyOnDecode","_onDecodeError","options","onDecodeError","_calculateScanRegion","calculateScanRegion","_preferredCamera","_legacyCanvasSize","_maxScansPerSecond","maxScansPerSecond","_onPlay","bind","_onLoadedMetaData","_onVisibilityChange","_updateOverlay","disablePictureInPicture","playsInline","muted","shouldHideVideo","hidden","body","contains","appendChild","highlightScanRegion","highlightCodeOutline","$overlay","overlay","overlayStyle","position","display","pointerEvents","classList","add","gotExternalOverlay","innerHTML","firstElementChild","animate","transform","duration","iterations","Infinity","direction","easing","e","videoContainer","insertBefore","nextSibling","insertAdjacentHTML","$codeOutlineHighlight","lastElementChild","_scanRegion","requestAnimationFrame","videoStyle","style","setProperty","visibility","opacity","width","height","parentElement","removeChild","addEventListener","window","_qrEnginePromise","createQrEngine","workerPath","hasCamera","length","listCameras","requestLabels","navigator","mediaDevices","filter","device","openedStream","every","enumerateCameras","camera","label","getUserMedia","audio","map","i","id","deviceId","_stopVideoStream","hasFlash","stream","srcObject","MediaStream","_getCameraStream","getVideoTracks","getSettings","isFlashOn","_flashOn","toggleFlash","turnFlashOff","turnFlashOn","_destroyed","_active","_paused","applyConstraints","advanced","torch","_restartVideoStream","destroy","removeEventListener","stop","_postWorkerMessage","start","Error","location","protocol","play","facingMode","_setVideoMirror","catch","pause","stopStreamImmediately","stopStream","Promise","resolve","setTimeout","setCamera","facingModeOrDeviceId","scanImage","imageOrFileOrBlobOrUrl","scanRegionOrOptions","qrEngine","canvas","disallowCanvasResizing","alsoTryWithoutScanRegion","scanRegion","returnDetailedScanResult","image","canvasContext","all","_loadImage","_drawToCanvas","detailedScanResult","Worker","gotExternalEngine","_postWorkerMessageSync","qrEngineWorker","reject","timeout","onMessage","onError","expectedResponseId","event","data","clearTimeout","cornerPoints","_convertPoints","NO_QR_CODE_FOUND","error","imageData","buffer","race","scanResult","rawValue","message","test","errorMessage","_disableBarcodeDetector","setGrayscaleWeights","red","green","blue","useIntegerApproximation","setInversionMode","inversionMode","then","module","createWorker","BarcodeDetector","getSupportedFormats","includes","userAgentData","brands","some","brand","platform","getHighEntropyValues","architecture","platformVersion","parseInt","formats","_scanFrame","x","Math","round","videoWidth","scanRegionSize","y","videoHeight","downScaledWidth","downScaledHeight","videoObjectFit","videoScaledWidth","videoScaledHeight","elementWidth","elementHeight","videoAspectRatio","elementAspectRatio","min","videoY","lengthValue","parseFloat","endsWith","regionWidth","regionHeight","top","elementY","regionY","left","elementX","isVideoMirrored","videoX","regionX","points","point","scaleFactorX","offsetX","scaleFactorY","offsetY","paused","ended","requestVideoFrameCallback","readyState","timeSinceLastScan","minimumTimeBetweenScans","_lastScanTimestamp","Date","now","result","_codeOutlineHighlightRemovalTimeout","undefined","setAttribute","join","log","constraint","preferenceType","exact","constraints","wasPaused","track","removeTrack","_getFacingMode","videoStream","videoTrack","scanRegionWidth","scanRegionHeight","canvasWidth","canvasHeight","alpha","context","imageSmoothingEnabled","drawImage","scanRegionX","scanRegionY","Image","_awaitImageLoad","HTMLVideoElement","HTMLCanvasElement","SVGImageElement","OffscreenCanvas","ImageBitmap","File","Blob","URL","src","createObjectURL","toString","revokeObjectURL","complete","naturalWidth","listener","ErrorEvent","qrEngineOrQrEnginePromise","type","transfer","postMessage"],"mappings":"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"} \ No newline at end of file diff --git a/client/root.js b/client/root.js new file mode 100644 index 0000000..4751c26 --- /dev/null +++ b/client/root.js @@ -0,0 +1,367 @@ +class Root +{ + static instance = null; + + constructor() { + // Init values / parse cookies + if (Root.instance!==null) { + return; + } + Root.instance = this; + this.jwt = this.getCookie("jwt"); + this.secToken = this.getCookie("secToken"); + this.loggedIn = false; + this.url = "https://app.fw-innenstadt.de/index_new.php/"; + this.scanner = new Scanner(this); + this.page = "Start"; + this.routesChecksum = ""; + const _this = this; + Root.AddEventListenerIfButtonExists("loginButton", function (event) {_this.Login();}); + Root.AddEventListenerIfButtonExists("nav_start", function (event) {_this.Open("Start");}); + Root.AddEventListenerIfButtonExists("nav_termine", function (event) {_this.Open("Termine");}); + Root.AddEventListenerIfButtonExists("nav_dienstpläne", function (event) {_this.Open("Dienstpläne");}); + Root.AddEventListenerIfButtonExists("nav_personal", function (event) {_this.Open("Personal");}); + Root.AddEventListenerIfButtonExists("nav_prozesse", function (event) {_this.Open("Prozesse");}); + Root.AddEventListenerIfButtonExists("nav_spinde", function (event) {_this.Open("Spinde");}); + Root.AddEventListenerIfButtonExists("nav_einsätze", function (event) {_this.Open("Einsätze");}); + Root.AddEventListenerIfButtonExists("nav_anwesenheiten", function (event) {_this.Open("Anwesenheiten");}); + Root.AddEventListenerIfButtonExists("nav_fahrzeuge", function (event) {_this.Open("Fahrzeuge");}); + Root.AddEventListenerIfButtonExists("nav_logout", function (event) {_this.Logout();}); + document.getElementById("navigation_select").addEventListener("change", function (event) {_this.Open(document.getElementById("navigation_select").value);}); + this.FetchRoutes(true); + } + + Open(page) { + if ("_LOGOUT_"==page) { + this.Logout(); + return; + } + this.setCookie("page", page); + switch (page) { + case "Termine": + //TerminePage.Open(); + break; + case "Dienstpläne": + //DienstplänePage.Open(); + break; + case "Personal": + PersonalPage.Open(); + break; + case "Prozesse": + //ProzessePage.Open(); + break; + case "Spinde": + //SpindePage.Open(); + break; + case "Einsätze": + //EinsätzePage.Open(); + break; + case "Anwesenheiten": + //AnwesenheitenPage.Open(); + break; + case "Fahrzeuge": + FahrzeugePage.Open(); + break; + default: + //StartPage.Open(); + this.setCookie("page", "Start"); + } + } + + Login() { + var button = document.getElementById("loginButton"); + button.disabled = true; + button.className = "login disabled"; + const json = { + "login": document.getElementById("loginUser").value, + "password": document.getElementById("loginPassword").value/*, + "secToken": typeof(this.secToken)!="undefined" ? this.secToken : ""*/ + }; + + const _this = this; + Root.SetLoadAnimation(true); + let request = new XMLHttpRequest(); + request.open("POST", this.url, true); + request.setRequestHeader("Content-Type", "application/json"); + request.setRequestHeader("Accept", "application/json"); + request.onreadystatechange = function() { + if (request.readyState != 4) return; + Root.SetLoadAnimation(false); + const {ok, json, etag} = _this.FinishResponse(request); + _this.changeLoginScreen(ok); + if (ok) { + _this.updatePages(etag, json); + _this.Open(_this.getCookie("page")); + setTimeout(Root.instance.FetchPages, 10000, false); + } + }; + request.send(JSON.stringify(json)); + } + + Logout() { + const _this = this; + let request = new XMLHttpRequest(); + Root.SetLoadAnimation(true); + request.open("DELETE", this.url, true); + request.setRequestHeader("Content-Type", "application/json"); + request.setRequestHeader("Accept", "application/json"); + request.onreadystatechange = function() { + if (request.readyState != 4) return; + Root.SetLoadAnimation(false); + _this.FinishResponse(request); + _this.changeLoginScreen(false); + }; + request.send({secToken: this.secToken}); + } + + FetchRoutes(callOpenAfterOk = false) { + if (this.jwt!="") { + Root.SetLoadAnimation(true); + const _this = this; + let request = new XMLHttpRequest(); + request.open("OPTIONS", this.url); + request.setRequestHeader("Authorization", "Bearer " + this.jwt); + request.setRequestHeader("Accept", "application/json"); + request.onreadystatechange = function() { + if (request.readyState != 4) return; + Root.SetLoadAnimation(false); + const {ok, json, etag} = _this.FinishResponse(request); + if (ok) { + _this.updatePages(etag, json); + if (callOpenAfterOk) { + _this.Open(_this.getCookie("page")); + } + setTimeout(Root.instance.FetchPages, 10000, false); + } } + request.send(); + } else { + this.changeLoginScreen(false); + } + } + + FinishResponse(request, isHead = false) { + const {ok, json} = isHead ? {ok: true, json: {}} : Root.ParseJson(request.responseText); + if (!ok) { + return {ok: false, json: {}, etag: null}; + } + if (typeof(json.messages)!="undefined") { + Root.ShowMessages(json.messages); + } + if (typeof(json.secToken)!="undefined") { + this.secToken = json.secToken; + this.setCookie("secToken", json.secToken); + } + if (typeof(json.jwt)!="undefined") { + this.jwt = json.jwt; + this.setCookie("jwt", json.jwt); + } + if (request.status>=300) { + let statusString = ""; + switch (request.status) { + //case 200: statusString = "OK"; break; + //case 201: statusString = "Erstellt"; break; + case 400: statusString = "Fehlerhafte Anfrage"; break; + case 401: statusString = "Anmeldung erforderlich"; this.changeLoginScreen(false); break; + case 403: statusString = "Keine Berechtigung"; break; + case 404: statusString = "Nicht gefunden"; break; + case 500: statusString = "Fehler auf Server"; break; + default: statusString = "" + request.status + " = Unbekannt"; + } + Root.ShowMessages(["Anfrage wurde mit Code " + request.status + " abgelehnt.
    (" + statusString + ")"]); + } else { + const etag = typeof(request.getResponseHeader) === 'function' ? request.getResponseHeader("ETag") : null; + return {ok: true, json: json, etag: etag}; + } + return {ok: false, json: {}, etag: null}; + } + + /* "Private" functions */ + + updatePages(etag, json) { + if (etag!=this.routesChecksum) { + //StartPage.SetVisibility(true); + //TerminePage.SetVisibility(json.pages.includes("Termine")); + //DienstplänePage.SetVisibility(json.pages.includes("Dienstpläne")); + PersonalPage.SetVisibility(json); + //ProzessePage.SetVisibility(json.pages.includes("Prozesse")); + //SpindePage.SetVisibility(json.pages.includes("Spinde")); + //EinsätzePage.SetVisibility(json.pages.includes("Einsätze")); + //AnwesenheitenPage.SetVisibility(json.pages.includes("Anwesenheiten")); + FahrzeugePage.SetVisibility(json); + this.pagesChecksum = etag; + } } + + changeLoginScreen(newStatus) { + var s = document.getElementById('header').style; + if (this.loggedIn==null) { + if (!newStatus) { + s.display = "block"; + s.opacity = 1; + } + } else if (newStatus) { + (function fadeOut() {(s.opacity-=0.1)<0 ? s.display="none" : setTimeout(fadeOut, 40)})(); + } else { + var button = document.getElementById("loginButton"); + button.disabled = false; + button.className = "login"; + + s.display = "block"; + (function fadeIn(){(s.opacity-=-0.1)>1 ? s.opacity=1 : setTimeout(fadeIn, 40)})(); + } + this.loggedIn = newStatus; + } + + /*updateLoginStatus(loggedIn) { + if (loggedIn) { + if (loggedIn!=this.loggedIn) { + this.changeLoginScreen(true); + } + return true; + } else { + this.changeLoginScreen(false); + } + return false; + }*/ + + setCookie(cname, cvalue, exdays) { + var d = new Date(); + d.setTime(d.getTime() + (exdays*24*60*60*1000)); + var expires = "expires="+ d.toUTCString(); + document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/;SameSite=Strict;Secure"; + } + + getCookie(cname){ + var name = cname + "="; + var decodedCookie = decodeURIComponent(document.cookie); + var ca = decodedCookie.split(';'); + for(var i = 0; i 0 ? "" : "") + (this.viewTo>" : "") + ""; + for (var v=this.viewFrom; v<=this.viewTo; v++) { + html+= "" + + (v==this.viewFrom && this.viewFrom>0 ? "" : "") + + (v==this.viewTo && this.viewTo>this.viewFrom ? "" : "") + + this.view[v].title + + (v==this.viewFrom && this.viewFrom>" : "") + + (v==this.viewTo && this.viewTo>" : "") + + ""; + } + html+= ""; + + for (let a in Account.byOrdering) { + html+= Account.byOrdering[a].Render(); + } + + this.contentContainer.innerHTML = html+""; + + const _this = this; + addEventListenerIfButtonExists('view_from_left', function (event) {if (_this.viewFrom>0) {--_this.viewFrom; _this.RenderMain();}}); + addEventListenerIfButtonExists('view_from_right', function (event) {if (_this.viewFrom<_this.viewTo) {++_this.viewFrom; _this.RenderMain();}}); + addEventListenerIfButtonExists('view_to_left', function (event) {if (_this.viewTo>_this.viewFrom) {--_this.viewTo; _this.RenderMain();}}); + addEventListenerIfButtonExists('view_to_right', function (event) {if (_this.viewTo<_this.view.length-1) {++_this.viewTo; _this.RenderMain();}}); + addEventListenerIfButtonExists('view_both_left', function (event) {if (_this.viewFrom>0) {--_this.viewFrom; --_this.viewTo; _this.RenderMain();}}); + addEventListenerIfButtonExists('view_both_right', function (event) {if (_this.viewTo<_this.view.length-1) {++_this.viewFrom; ++_this.viewTo; _this.RenderMain();}}); + for (let a in Account.array) { + let accountId = Account.array[a].id; + addEventListenerIfButtonExists('balances_add_' + accountId, function (event) {Balance.Add(_this, _this.RenderMain, accountId);}); + } + }*/ +} + +/*function ToggleEntryView(id) {api.activeRoute.ToggleEntryView(id);} +function Open(path) {api.Open(path);} +function OpenSelected() { + let s = document.getElementById("navigation_select").value; + if (s=="_LOGOUT_") {Logout();} else {api.Open(s);} +} +function Logout() {api.Open("/index.php/Logout");} +function FilterAdd() {api.activeRoute.FilterAdd();} +function FilterDelete(id) {api.activeRoute.FilterDelete(id);} +function FilterChange(id) {api.activeRoute.FilterChange(id);} +function Add() {api.activeRoute.Add();} +function Delete(id, data = {}) {api.Request("DELETE", data, id);} +function Edit(id) {api.activeRoute.Edit(id);} +function Cancel(id) {api.activeRoute.Cancel(id);} +function Save(id) {api.activeRoute.Save(id);} +function SubShowAdd(id, markers) {api.activeRoute.SubShowAdd(id, markers);} +function SubShowScan(id, subroute, parsers) {api.activeRoute.SubShowScan(id, subroute, parsers);} +function HideScanner() {api.scanner.Stop(); document.getElementById("qrscanner").style.display = "none";} +function SwitchCamera() {api.scanner.SwitchCamera();} +function SubAdd(id, markers, subroute) {api.activeRoute.SubAdd(id, markers, subroute);} +function SubDelete(id, subroute, subid = null) {api.Request("DELETE", {}, id, subroute, subid);} +function Request(method, data, id = null, subroute = null, subid = null) {api.Request(method, data, id, subroute, subid);} +function Print(printID, printName) {api.Request("GET", {Print: printID, PrintName: printName});} +function SelectChange(id, state) {api.activeRoute.SelectChange(id, state);}*/ + +document.addEventListener ("DOMContentLoaded", () => { + var root = new Root(); +}); diff --git a/client/routes/fahrzeuge.js b/client/routes/fahrzeuge.js new file mode 100644 index 0000000..b221875 --- /dev/null +++ b/client/routes/fahrzeuge.js @@ -0,0 +1,119 @@ +class Fahrzeuge extends Route +{ + static route = "Fahrzeuge"; + static array = {}; + static groups = {}; + static subs = { + "Eingewiesene": {color: "chocolate", icon: "person.png", entries: []} + }; + static selects = {}; + static admin = false; // global page admin rights + static prints = []; + static filter = []; + //static selected = []; + //static dropzones = {}; + static visible = false; + + constructor(groupName, json) { + super( + groupName, + json, + Fahrzeuge.route, + Fahrzeuge.array, + Fahrzeuge.groups, + Fahrzeuge.subs, + Fahrzeuge.selects, + Fahrzeuge.admin/*, + Fahrzeuge.prints, + Fahrzeuge.filter, + Fahrzeuge.selected, + Fahrzeuge.dropzones*/ + ); + } + + init(json) { + this.Kürzel = json.MAIN.KÜRZEL; + this.Name = json.MAIN.NAME; + this.Bild = json.MAIN.BILD; + } + + renderEntry(drawEdit) { + let html = "
    "; + if (this.Bild.EXISTIERT) { + html+= ""; + if (drawEdit) { + html+= "
    "; + } + } else { + html+= ""; + } + if (drawEdit) { + html+= "
    "; + } + html += "
    "; + if (drawEdit) { + html+= "
      " + + "
    • " + + "
    • " + + "
    • " + + "
    • " + + "
    • " + + "
    "; + } else { + html+= "
    • " + this.Name + "
    • " + "
    • " + this.Kürzel + "
    • "; + if (this.admin) { + html += "
    • "; + } + html+= "
    "; + } + document.getElementById(this.marker("Main")).innerHTML = html; + } + + static RenderAdd() { + let html = "

    Fahrzeug hinzufügen

    " + + "
    • Name:
    • " + + "
    • Kürzel:
    • " + + "
    • Hinzufügen
    "; + return html; + } + + renderGroup() { + return Fahrzeuge.RenderGroup(this.groupName); + } + + static RenderGroup(groupName) { + return { + begin: "

    " + groupName + "

    ", + end: "
    " + }; + } + + static New(groupName, json) { + return new Fahrzeuge(groupName, json); + } + + collect() { + return Fahrzeuge.Collect(this.ID); + } + + static Collect(id, contextId = null) { + return { + ID: id, + KÜRZEL: this.Value(id, "Kürzel"), + NAME: this.Value(id, "Name") + }; + } + + static RenderSelect(selectId, fahrzeugId, nullable = true) { + let html = ""; + return html; + } +} diff --git a/client/routes/personal.js b/client/routes/personal.js new file mode 100644 index 0000000..a6604f5 --- /dev/null +++ b/client/routes/personal.js @@ -0,0 +1,144 @@ +class Personal extends Route +{ + static route = "Personal"; + static array = {}; + static groups = {}; + static subs = { + "Abteilungen": {color: "purple", icon: "department.png", entries: []}, + "Gruppen": {color: "olive", icon: "group.png", entries: []}, + "Lehrgänge": {color: "teal", icon: "skill.png", entries: []}, + "Einweisungen": {color: "chocolate", icon: "person.png", entries: []} + }; + static selects = { + "Kategorie" : [], + "Funktion" : [] + }; + static admin = true; // global page admin rights + static prints = []; + static filter = []; + //static selected = []; + //static dropzones = {}; + static visible = false; + + constructor(groupName, json) { + super( + groupName, + json, + Personal.route, + Personal.array, + Personal.groups, + Personal.subs, + Personal.selects, + Personal.admin/*, + Personal.prints, + Personal.filter, + Personal.selected, + Personal.dropzones*/ + ); + } + + init(json) { + this.OFNr = json.MAIN.OFNR; + this.PNr = json.MAIN.PNR; + this.Nr = json.MAIN.NR; + this.Login = json.MAIN.LOGIN; + this.Email = json.MAIN.EMAIL; + this.Vornamen = json.MAIN.VORNAMEN; + this.Nachnamen = json.MAIN.NACHNAMEN; + this.Name = json.MAIN.NAME; + this.Bild = json.MAIN.BILD; + this.Kategorie = json.MAIN.KATEGORIE; + this.Funktion = json.MAIN.FUNKTION; + } + + renderEntry(drawEdit) { + let html = "
    "; + if (this.Bild.EXISTIERT) { + html+= ""; + if (drawEdit) { + html+= "
    "; + } + } else { + html+= ""; + } + if (drawEdit) { + html+= "
    "; + } + html += "
      "; + + // TODO: Draw selectbox + + if (drawEdit) { + html+= this.renderField("number.png", this.renderInput("OFNr", this.OFNr, 1.5, 2) + "-" + this.renderInput("PNr", this.PNr, 2, 3)) + + this.renderField("person.png", this.renderInput("Nachnamen", this.Nachnamen) + ", " + this.renderInput("Vornamen", this.Vornamen)) + + this.renderField("type.png", this.renderSelect("Kategorie", this.Kategorie.ID)) + + this.renderField("note.png", this.renderInput("Login", this.Login) + "@feuerwehr-bs.net") + + this.renderField("star.png", this.renderSelect("Funktion", this.Funktion.ID, 2.5)) + + this.renderButton("save.png", "Save", "Speichern") + + this.renderButton("delete.png", "Delete", "Löschen") + + this.renderButton("cancel.png", "Reset", "Zurücksetzen"); + } else { + html+= this.renderField("number.png", this.Nr) + + this.renderField("person.png", "" + this.Nachnamen + ", " + this.Vornamen + "") + + (this.Login=="" || this.Login===null ? this.renderField("note.png", "Kein Login!") : "") + + this.renderField("star.png", this.Funktion!==null ? this.Funktion.KÜRZEL : "-"); + if (this.admin) { + html += this.renderButton("edit.png", "Edit", "Bearbeiten"); + } + } + html+= "
    "; + document.getElementById(this.marker("Main")).innerHTML = html; + } + + static RenderAdd() { + let html = "

    Fahrzeug hinzufügen

    " + + "
    • Name:
    • " + + "
    • Kürzel:
    • " + + "
    • Hinzufügen
    "; + return html; + } + + renderGroup() { + return Personal.RenderGroup(this.groupName); + } + + static RenderGroup(groupName) { + return { + begin: "

    " + groupName + "

    ", + end: "
    " + }; + } + + static New(groupName, json) { + return new Personal(groupName, json); + } + + collect() { + return Personal.Collect(this.ID); + } + + static Collect(id, contextId = null) { + return { + ID: id, + OFNR: this.Value(id, "OFNr"), + PNR: this.Value(id, "PNr"), + NACHNAMEN: this.Value(id, "Nachnamen"), + VORNAMEN: this.Value(id, "Vornamen"), + KATEGORIE: this.Value(id, "Kategorie"), + LOGIN: this.Value(id, "Login"), + FUNKTION: this.Value(id, "Funktion") + }; + } + + static RenderSelect(selectId, fahrzeugId, nullable = true) { + let html = ""; + return html; + } +} diff --git a/client/scanner.js b/client/scanner.js new file mode 100644 index 0000000..7fbc235 --- /dev/null +++ b/client/scanner.js @@ -0,0 +1,92 @@ +class Scanner +{ + static api; + static settings; + static scanned; + + constructor(parent) { + Scanner.api = parent; + this.qr = null; + this.cameras = []; + } + + Start(id, subroute, parser) { + Scanner.settings = { + subroute: subroute, + parser: parser, + id: id + }; + Scanner.scanned = {primary: {}, secondary: {}}; + for (let i in parser) { + if (i!=subroute) { + Scanner.scanned.secondary[parser[i]] = null; + } } + + // Find already parsed IDs + const subData = Scanner.api.activeRoute.resourcesIndex[id].data.SUB[parser[subroute]]; + for (let i in subData) { + Scanner.scanned.primary[subData[i].ID] = true; + } + + this.qr = new QrScanner( + document.getElementById("qrscanner_video"), + Scanner.parse, + {returnDetailedScanResult: true, highlightScanRegion: true, highlightCodeOutline: true} + ); + if (QrScanner.hasCamera()) { + let _this = this; + QrScanner.listCameras(true) + .then(result => _this.cameras = result) + .catch(error => alert(error || 'Camera detection failed.')); + } + this.cameraIndex = 0; + document.getElementById("qrscanner_text").innerHTML = ""; + + this.qr.start(); + } + Stop() { + this.qr.stop(); + this.qr.destroy(); + this.qr = null; + } + SwitchCamera() { + if (this.qr!==null && QrScanner.hasCamera()) { + ++this.cameraIndex; + if (this.cameraIndex>=this.cameras.length) { + this.cameraIndex = 0; + } + this.qr.setCamera(this.cameras[this.cameraIndex].id); + } + } + static parse(result) { + let scan = result.data.split("/"); + if (scan.length==3) { + let route = scan[1]; + let subid = scan[2]; + + // Is it a route we should parse? + if (typeof(Scanner.settings.parser[route])!="undefined") { + const marker = Scanner.settings.parser[route]; + + // Is it the primary route and if yes, has this ID been parsed before? + if (route==Scanner.settings.subroute && typeof(Scanner.scanned.primary[subid])=="undefined") { + Scanner.scanned.primary[subid] = true; + + let index = -1; + + const options = Scanner.api.activeRoute.options[marker]; + for (let i in options) { + if (options[i].ID==subid) { + index = i; + break; + } } + // Has the ID been found? + if (index>=0) { + document.getElementById("qrscanner_text").innerHTML += options[index].NAME + "
    "; + Scanner.api.Request("POST", Scanner.scanned.secondary, Scanner.settings.id, Scanner.settings.subroute, subid); + } + } else if(route!=Scanner.settings.subroute) { // Is it a secondary field? + Scanner.scanned.secondary[marker] = subid; + } } } } +} + diff --git a/client/template.js b/client/template.js new file mode 100644 index 0000000..f17a2d1 --- /dev/null +++ b/client/template.js @@ -0,0 +1,271 @@ +class TemplateEngine +{ + constructor(tpl, adminData) { + this.tpl = tpl; + this.adminData = adminData; + this.modeFallback = { + ":EDIT": ":ADMIN", + ":ADMIN": "", + "": null + }; + } + + Render(content, marker, mode = "") { + return this.render(marker, content, this.extractSection(this.tpl, marker, mode), mode); + } + + render(sections, content, tpl, mode = "") { + // content has to be an object of `marker` => `data` + // data can be a primitive, an array, or an object + // Boolean corresponds to a conditional section, call replaceCondition + // String and number correspond to a simple marker, call replaceMarker for it + // Array and object always correspond to a section + // Object can be handed recursively to a new instance of render. Be sure to extract the correct section of tpl though + // If data is an array, iterate over it and hand every entry to a new instance like with object. Concatenate the results + if (typeof(content)!="object" || tpl=="") + return ""; + var ret = tpl; + for (var marker in content) { + var sectionMarker = (sections!="" ? sections+"."+marker : marker); + var type = typeof(content[marker]); + + if (mode==":EDIT" && sections.indexOf("MAIN")!=-1 && typeof(this.adminData[marker])!="undefined") { + var data = this.adminData[marker]; + var admin_tpl = this.extractSection(ret, sectionMarker, mode); + var admin_ret = ""; + for (var i in data) { + if (content[marker]==null) { + data[i].SELECTED = data[i].ID=="__NULL__"; + } else if (Array.isArray(content[marker])) { + var selected = false; + for (var j in content[marker]) { + if (data[i].ID==content[marker][j].ID) { + selected = true; + } + } + data[i].SELECTED = selected; + } else { + data[i].SELECTED = data[i].ID==content[marker].ID; + } + + admin_ret+= this.render(sectionMarker, data[i], admin_tpl, ""); + } + ret = this.replaceSection(ret, sectionMarker, admin_ret, ""); + } else { + if (content[marker]==null) { + ret = this.replaceSection(ret, sectionMarker, "", mode); + ret = this.replaceMarker(ret, sectionMarker, "__NULL__", mode); + } if (type=="boolean") { + ret = this.replaceCondition(ret, sectionMarker, content[marker], mode); + } else if (type=="string" && "__CASE__:"==content[marker].substr(0, 9)) { + ret = this.replaceSwitch(ret, sectionMarker, content[marker].split(":"), mode); + } else if (type=="string" || type=="number") { + ret = this.replaceMarker(ret, sectionMarker, content[marker], mode); + } else if (type=="object" && Array.isArray(content[marker])) { + var arr_tpl = this.extractSection(ret, sectionMarker, mode); + var arr_ret = ""; + for (var ind in content[marker]) { + arr_ret+= this.render(sectionMarker, content[marker][ind], arr_tpl, mode); + } + ret = this.replaceSection(ret, sectionMarker, arr_ret, mode); + } else if (type=="object") { // Hopefully a JSON + ret = this.replaceSection(ret, sectionMarker, this.render(sectionMarker, content[marker], this.extractSection(ret, sectionMarker, mode), mode), mode); + } + } + } + return ret; + } + + makeMarker(marker) { + return "###" + marker + "###"; + } + + makeSectionMarker(marker, pos) { //creates START or END marker of section + return ""; + } + + findMarkerModes(tpl, section) { + var ret = []; + var sectionMarker = this.makeMarker(section+":"); + var markerLength = 5 + sectionMarker.length - 3; // 5 = " + // True text + // + // False text + // + var modeTpl = this.findAndDeleteUnneededModes(tpl, section, mode); + + var sectionMarker = this.makeMarker(section + modeTpl.mode); + var ifMarker = this.makeSectionMarker(sectionMarker, "IF"); + var elseMarker = this.makeSectionMarker(sectionMarker, "ELSE"); + var endMarker = this.makeSectionMarker(sectionMarker, "END"); + + var startPos = modeTpl.tpl.indexOf(ifMarker); + var else_startPos = modeTpl.tpl.indexOf(elseMarker); + var else_endPos = else_startPos + elseMarker.length; + var endPos = modeTpl.tpl.lastIndexOf(endMarker) + endMarker.length; + + if ((startPos==-1) || (else_startPos==-1) || (endPos==-1) || (endPos<=startPos)) { + if (bool) { + return modeTpl.tpl; + } else { + return this.replaceSection(modeTpl.tpl, section, "", modeTpl.mode); + } + } + + var value = ""; + if (bool) { + // Show if-part + value = modeTpl.tpl.substr(startPos, else_startPos - startPos); + } else { + // Show else-part + value = modeTpl.tpl.substr(else_endPos, endPos - else_endPos - endMarker.length); + } + + var ret = (startPos>0 ? modeTpl.tpl.substr(0, startPos) : ""); + ret+= value; + if (endPos + // Default text + // + // Text A + // + // Text B + // + var modeTpl = this.findAndDeleteUnneededModes(tpl, section, mode); + var sectionMarker = this.makeMarker(section + modeTpl.mode); + + var switchMarker = this.makeSectionMarker(sectionMarker, "SWITCH"); + var endMarker = this.makeSectionMarker(sectionMarker, "END"); + var anyMarker = this.makeSectionMarker(sectionMarker, "").substr(0, 5 + sectionMarker.length); // 5 = " + + +

    Anleitung

    + + + + +
    +
      +
    • + + + + + + Sperrfrist + +
    • +
    • ###LIST.MAIN.DATUM###
    • +
    • ###LIST.MAIN.ZEIT###
    • + +
    • ###LIST.MAIN.KATEGORIE.NAME###
    • + +
    • ###LIST.MAIN.THEMA###
    • +
    • ###LIST.MAIN.VERANTWORTLICHE###
    • + + + +
    • + +
    +
    + + +
    +
      +
    • + + + + + + + +
    • +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    • + + + + + + +
    • +
    • + +
    • +
    • +
    • +
    • +
    • +
    +
    + + + +
    +
      +
    • ↳ ###LIST.SUB.ANMELDUNG.RESTRICTIONS###
    • + + +
    • Du darfst kommen
    • + +
    • Auf Warteliste
    • + +
    • Zur Auslosung angemeldet
    • + +
    • Bei Interesse bitte anmelden
    • + +
    • Du leitest diesen Dienst
    • + + +
    • Noch ###LIST.SUB.ANMELDUNG.FREE.NUM### Plätze frei
    • + + +
    • ###LIST.SUB.ANMELDUNG.ACTION.NAME###
    • + +
    +
    + + + + +
    +
      +
    • ↳ ###LIST.SUB.ANMELDUNG.RESTRICTIONS###
    • + + +
    • Du darfst kommen
    • + +
    • Auf Warteliste
    • + +
    • Zur Auslosung angemeldet
    • + +
    • Bei Interesse bitte anmelden
    • + +
    • Du leitest diesen Dienst
    • + + +
    • Noch ###LIST.SUB.ANMELDUNG.FREE.NUM### Plätze frei
    • + + +
    • ###LIST.SUB.ANMELDUNG.ACTION.NAME###
    • + +
    +
    + +
    +
      +
    • ↳ Teilnehmerliste:
    • + + + +
    • + ###LIST.SUB.TEILNAHME.NAME### +
    • + +
    • + ###LIST.SUB.TEILNAHME.NAME### +
    • + +
    • + ###LIST.SUB.TEILNAHME.NAME### +
    • + + +
    • + +
    • +
    +
    + + + + +

    Termin hinzufügen

    + + + + + + + + + diff --git a/pgs/11_dienstplaene/module.json b/pgs/11_dienstplaene/module.json new file mode 100644 index 0000000..31aca9f --- /dev/null +++ b/pgs/11_dienstplaene/module.json @@ -0,0 +1,19 @@ +{ + "route" : "Dienstpläne", + "title" : "Dienstpläne", + "table" : "Dienstpläne", + "marker": "DIENSTPLÄNE", + "dependencies": [], + "show" : 1, + "useRight": "DARF_DIENSTE_VERWALTEN", + "adminRight": "DARF_DIENSTE_VERWALTEN", + "template": "template.html", + "isPage": true, + "links": { + "Termine": {"route":"Termine_Dienstpläne", "mainName":"Dienstplan", "subName":"Termine"} + }, + "mainFields": { + "ABTEILUNG": {"label": "Abteilung", "type": "Select", "filter": true, "add": true, "edit": true}, + "JAHR": {"label": "Jahr", "type": "Integer", "filter": true, "add": true, "edit": true}, + "NAME": {"label": "Name", "type": "String", "filter": true, "add": true, "edit": true} +} } \ No newline at end of file diff --git a/pgs/11_dienstplaene/page.php b/pgs/11_dienstplaene/page.php new file mode 100644 index 0000000..1b6aec0 --- /dev/null +++ b/pgs/11_dienstplaene/page.php @@ -0,0 +1,149 @@ +get($id); + $qry = "UPDATE Termine_Dienstpläne SET Name = ?, Jahr = ?, Abteilung = ? WHERE ID = ?"; + if ($stmt = $this->db->prepare($qry)) { + $Name = $this->man->input["NAME"] ?? $this->output["MAIN"]["NAME"]; + $Jahr = $this->man->input["JAHR"] ?? $this->output["MAIN"]["JAHR"]; + $Abteilung = $this->man->input["ABTEILUNG"] ?? $this->output["MAIN"]["ABTEILUNG"]["ID"]; + $stmt->bind_param( + "siii", + $Name, + $Jahr, + $Abteilung, + $id + ); + if ($stmt->execute()) { + $this->man->AddMessage("Dienstplan wurde aktualisiert!"); + $this->get($id); + return 200; + } else { + $this->man->AddMessage("Mysql error: ".$this->db->error); + } + } else { + $this->man->AddMessage("Mysql error: ".$this->db->error); + } + return 500; + } + + protected function insert() { + $qry = "INSERT INTO Termine_Dienstpläne (Abteilung, Jahr, Name) VALUES (?,?,?)"; + if ($stmt = $this->db->prepare($qry)) { + $Abteilung = $this->man->input["ABTEILUNG"] ?? null; + $Jahr = $this->man->input["JAHR"] ?? 0; + $Name = $this->man->input["NAME"] ?? ""; + $stmt->bind_param( + "iis", + $Abteilung, + $Jahr, + $Name + ); + $stmt->execute(); + if ($stmt->affected_rows==1) { + $this->man->AddMessage("Dienstplan wurde hinzugefügt!"); + $this->get($this->db->insert_id); + return 201; + } else { + $this->man->AddMessage("Dienstplan konnte nicht hinzugefügt werden! (".$Abteilung." / ".$Jahr." / ".$Name.")"); + return 400; + } + } else { + $this->man->AddMessage("Mysql error: ".$this->db->error); + } + return 500; + } + + protected function get($id = null) { + $this->output = []; + $filterID = false; + if ($id!=null) { + $filterID = true; + } + $qry = "SELECT td.ID, td.Abteilung, td.Jahr, td.Name, sa.Kürzel saKürzel, sa.Name saName " + ."FROM Termine_Dienstpläne td LEFT JOIN Struktur_Abteilungen sa ON sa.ID=td.Abteilung " + .($filterID ? "WHERE td.ID = ? " : "") + ."ORDER BY td.Jahr DESC, td.Name DESC, sa.ID ASC"; + if ($stmt = $this->db->prepare($qry)) { + if ($filterID) { + $stmt->bind_param("i", $id); + } + $stmt->execute(); + $res = $stmt->get_result(); + while ($row = $res->fetch_assoc()) { + $termine = $this->termineGetAll($row["ID"]); + + $entry = [ + "ID" => $row["ID"], + "MAIN" => [ + "FULLNAME" => $row["Jahr"]."-".$row["Name"], + "ABTEILUNG" => ["ID" => $row["Abteilung"], "KÜRZEL" => $row["saKürzel"], "NAME" => $row["saName"]], + "JAHR" => $row["Jahr"], + "NAME" => $row["Name"], + ], + "SUB" => [ + "TERMINE" => $termine, + ], + ]; + $this->addEntryToOutput("DEFAULT", $entry, $filterID); + } + } else { + $this->man->AddMessage("Mysql error: ".$this->db->error); + } + + return 200; + } + + protected function fillOptions($admin = false) { + $ret = array(); + //$ret["ABTEILUNG"][] = ["ID" => "__NULL__", "NAME" => "Ohne"]; + $res = $this->db->query("SELECT ID, Name FROM Struktur_Abteilungen"); + while ($row = $res->fetch_assoc()) { + $ret["ABTEILUNG"][] = ["ID" => $row["ID"], "NAME" => $row["Name"]]; + } + $ret["TERMINE"] = $this->termineGetAll(null); + return $ret; + } + + private function termineGetAll($dienstplanID) { + $ret = []; + $qry = "SELECT t.ID, t.Beginn, t.Ende, t.Thema, t.Ort, t.Verantwortliche, t.Kategorie, tk.Name KategorieName, tk.Farbe KategorieFarbe " + ."FROM Termine t LEFT JOIN Termine_Kategorien tk ON tk.ID=t.Kategorie WHERE t.Dienstplan ".($dienstplanID===null ? "IS NULL " : "= ".$dienstplanID." ") + ."ORDER BY t.Beginn ASC "; + if ($res = $this->db->query($qry)) { + while ($row = $res->fetch_assoc()) { + $beginn_time = date("H:i", strtotime($row["Beginn"])); + $ende_time = date("H:i", strtotime($row["Ende"])); + $beginn_date = date("D, d.m.Y", strtotime($row["Beginn"])); + $ende_date = "00:00"==$ende_time ? date("D, d.m.Y", strtotime($row["Ende"]) - 1) : date("D, d.m.Y", strtotime($row["Ende"])); + + $entry = [ + "ID" => $row["ID"], + "BEGINN" => $row["Beginn"], + "BEGINN.DATUM" => date("D, d.m.Y", strtotime($row["Beginn"])), + "BEGINN.ZEIT" => date("H:i", strtotime($row["Beginn"])), + "ENDE" => $row["Ende"], + "ENDE.DATUM" => date("d.m.Y", strtotime($row["Ende"])), + "ENDE.ZEIT" => date("H:i", strtotime($row["Ende"])), + "DATUM" => $beginn_date.($beginn_date!=$ende_date ? " - ".$ende_date : ""), + "ZEIT" => ("00:00"==$ende_time && "00:00"==$beginn_time ? "Ganztägig" : $beginn_time." - ".$ende_time), + "ENDE" => $row["Ende"], + "THEMA" => $row["Thema"], + "ORT" => $row["Ort"], + "KATEGORIE" => $row["Kategorie"], + "KATNAME" => $row["KategorieName"], + "KATFARBE" => $row["KategorieFarbe"], + "VERANTWORTLICHE" => $row["Verantwortliche"] ?? "Keine Verantwortliche", + ]; + $ret[] = $entry; + } + } else { + $this->man->AddMessage("Mysql error: ".$this->db->error); + } + return $ret; + } +} diff --git a/pgs/11_dienstplaene/template.html b/pgs/11_dienstplaene/template.html new file mode 100644 index 0000000..75dd664 --- /dev/null +++ b/pgs/11_dienstplaene/template.html @@ -0,0 +1,93 @@ + + + + + + +
    +
      + +
    • ###LIST.MAIN.ABTEILUNG.NAME###
    • + +
    • ###LIST.MAIN.FULLNAME###
    • +
    • VersteckenAnzeigen
    • +
    • +
    +
    + + +
    +
      +
    • +
    • +
    • +
    • +
    • +
    • +
    +
    + + +
    + +
      +
    • ###LIST.SUB.TERMINE.DATUM###
    • +
    • ###LIST.SUB.TERMINE.ZEIT###
    • +
    • ###LIST.SUB.TERMINE.KATNAME###
    • +
    • ###LIST.SUB.TERMINE.THEMA###
    • +
    • ###LIST.SUB.TERMINE.ORT###
    • +
    • ###LIST.SUB.TERMINE.VERANTWORTLICHE###
    • +
    • +
    + +
    +
    + + + + +

    Dienstplan hinzufügen

    + + + + + + + + + diff --git a/pgs/20_personal/module.json b/pgs/20_personal/module.json new file mode 100755 index 0000000..79a4792 --- /dev/null +++ b/pgs/20_personal/module.json @@ -0,0 +1,34 @@ +{ + "route" : "Personal", + "title" : "Personal", + "table" : "Personal", + "marker": "PERSONAL", + "dependencies": [], + "show" : true, + "useRight": "DARF_PERSONAL_VERWALTEN", + "adminRight": "DARF_PERSONAL_VERWALTEN", + "template": "template.html", + "isPage": true, + "links": { + "Lehrgänge": {"route":"Personal_Lehrgänge", "mainName":"Personal", "subName":"Lehrgänge"}, + "Einweisungen": {"route":"Fahrzeuge_Einweisungen", "mainName":"Personal", "subName":"Fahrzeuge"}, + "Abteilungen": {"route":"Personal_Abteilungen", "mainName":"Personal", "subName":"Abteilungen"}, + "Gruppen": {"route":"Personal_Gruppen", "mainName":"Personal", "subName":"Gruppen"}, + "Bilder": {"route":"Dateien", "mainName":"Personal", "subName":"Bildadresse"} + }, + "mainFields": { + "OFNR": {"label": "OFNr", "type": "Integer", "filter": true, "add": true, "edit": true}, + "PNR": {"label": "PNr", "type": "Integer", "filter": true, "add": true, "edit": true}, + "AUTOPNR": {"label": "Auto-Pnr", "type": "Checkbox", "filter": false, "add": true, "edit": false}, + "NACHNAMEN": {"label": "Nachnamen", "type": "String", "filter": true, "add": true, "edit": true}, + "VORNAMEN": {"label": "Vornamen", "type": "String", "filter": true, "add": true, "edit": true}, + "KATEGORIE": {"label": "Kategorie", "type": "Select", "filter": true, "add": true, "edit": true}, + "LOGIN": {"label": "Login", "type": "String", "filter": true, "add": true, "edit": true}, + "FUNKTION": {"label": "Funktion", "type": "Select", "filter": true, "add": true, "edit": true}, + "AUTOPROZESS": {"label": "Prozess starten", "type": "Select", "filter": false, "add": true, "edit": false}, + "ABTEILUNGEN": {"label": "Abteilungen", "type": "Multiple", "filter": true, "add": false, "edit": false}, + "GRUPPEN": {"label": "Gruppen", "type": "Multiple", "filter": true, "add": false, "edit": false}, + "LEHRGÄNGE": {"label": "Lehrgänge", "type": "Multiple", "filter": true, "add": false, "edit": false}, + "EINWEISUNGEN": {"label": "Einweisungen", "type": "Multiple", "filter": true, "add": false, "edit": false} + } +} diff --git a/pgs/20_personal/page.php b/pgs/20_personal/page.php new file mode 100755 index 0000000..5c95ec7 --- /dev/null +++ b/pgs/20_personal/page.php @@ -0,0 +1,283 @@ +get($id); + + $qry = "UPDATE Personal SET OFnr = ?, Pnr = ?, Login = ?, Nachnamen = ?, Vornamen = ?, Kategorie = ?, Funktion = ? WHERE ID = ?"; + if ($stmt = $this->db->prepare($qry)) { + $OFnr = $this->man->input["OFNR"] ?? $this->output["MAIN"]["OFNR"]; + $Pnr = $this->man->input["PNR"] ?? $this->output["MAIN"]["PNR"]; + $Login = $this->man->input["LOGIN"] ?? $this->output["MAIN"]["LOGIN"]; + $Nachnamen = $this->man->input["NACHNAMEN"] ?? $this->output["MAIN"]["NACHNAMEN"]; + $Vornamen = $this->man->input["VORNAMEN"] ?? $this->output["MAIN"]["VORNAMEN"]; + $Kategorie = $this->man->input["KATEGORIE"] ?? $this->output["MAIN"]["KATEGORIE"]["ID"]; + $Funktion = array_key_exists("FUNKTION", $this->man->input) + ? $this->man->input["FUNKTION"] + : (is_null($this->output["MAIN"]["FUNKTION"]) ? null : $this->output["MAIN"]["FUNKTION"]["ID"]); + $stmt->bind_param( + "iisssiii", + $OFnr, + $Pnr, + $Login, + $Nachnamen, + $Vornamen, + $Kategorie, + $Funktion, + $id + ); + if ($stmt->execute()) { + $this->man->AddMessage("Personal wurde aktualisiert!"); + $this->get($id); + return 200; + } else { + $this->man->AddMessage("Mysql error: ".$this->db->error); + } + } else { + $this->man->AddMessage("Mysql error: ".$this->db->error); + } + return 500; + } + + protected function insert() { + $Pnr = $this->man->input["PNR"] ?? null; + if ($this->man->input["AUTOPNR"] ?? false) { + $res = $this->db->query("SELECT Pnr FROM Personal WHERE Pnr BETWEEN 500 AND 899 ORDER BY Pnr ASC"); + $Pnr = 500; + while ($row = $res->fetch_assoc()) { + if ($row["Pnr"]==$Pnr) { + $Pnr++; + } else { + break; + } } } + $qry = "INSERT INTO Personal (OFnr, Pnr, Login, Nachnamen, Vornamen, Bildadresse, Kategorie, Funktion) VALUES (?,?,?,?,?,NULL,?,?)"; + if ($stmt = $this->db->prepare($qry)) { + $OFnr = $this->man->input["OFNR"] ?? "56"; + $Login = $this->man->input["LOGIN"] ?? ""; + $Nachnamen = $this->man->input["NACHNAMEN"] ?? ""; + $Vornamen = $this->man->input["VORNAMEN"] ?? ""; + $Kategorie = $this->man->input["KATEGORIE"] ?? 0; // Insert will fail if not existing + $Funktion = array_key_exists("FUNKTION", $this->man->input) + ? $this->man->input["FUNKTION"] + : null; + $stmt->bind_param( + "iisssii", + $OFnr, + $Pnr, + $Login, + $Nachnamen, + $Vornamen, + $Kategorie, + $Funktion + ); + $stmt->execute(); + if ($stmt->affected_rows==1) { + $this->man->AddMessage("Personal wurde hinzugefügt!"); + $pid = $this->db->insert_id; + + $autoprozess = $this->man->input["AUTOPROZESS"] ?? ""; + if ($autoprozess!="") { + $stmt2 = $this->db->prepare("SELECT Ziel FROM Prozesse WHERE Name = ?"); + $stmt2->bind_param("s", $autoprozess); + $stmt2->execute(); + $res = $stmt2->get_result(); + while ($row = $res->fetch_assoc()) { + $conditions = json_decode($row["Ziel"], true); + foreach ($conditions as $cond) { + switch ($cond["condition"]) { + case "group_member": + $this->db->query("INSERT INTO Personal_Gruppen (Personal, Gruppen) VALUES (".$pid.", ".$cond["group"].")"); + break; + } } } } + + $this->get($pid); + return 201; + } else { + $this->man->AddMessage("Personal konnte nicht hinzugefügt werden!"); + return 400; + } + } else { + $this->man->AddMessage("Mysql error: ".$this->db->error); + return 500; + } + } + + protected function get($id = null) { + $this->output = []; + if ($id===null && $this->man->Main()!=null) { + $id = $this->man->Main(); + } + + $where = ""; + $having = ""; + if ($id) { + $where = "AND p.ID = ? "; + } else if (sizeof($this->man->Filter())>0) { + /*$where = "WHERE 1 ";*/ + foreach ($this->man->Filter() as $filter) { + $and = "or"==$filter["and"] ? "OR " : "AND "; + if ("none"==$filter["field"]) { + $where.= $and."1 "; + } else { + switch ($filter["field"]) { + case "OFNR": + $where.= $and.$this->getFilterString($filter["op"], ["=", "<>", "<", ">"], "p", "OFnr", $filter["value"]); + break; + case "PNR": + $where.= $and.$this->getFilterString($filter["op"], ["=", "<>", "<", ">"], "p", "Pnr", $filter["value"]); + break; + case "NACHNAMEN": + $where.= $and.$this->getFilterString($filter["op"], ["like", "not like"], "p", "Nachnamen", $filter["value"]); + break; + case "VORNAMEN": + $where.= $and.$this->getFilterString($filter["op"], ["like", "not like"], "p", "Vornamen", $filter["value"]); + break; + case "KATEGORIE": + $where.= $and.$this->getFilterString($filter["op"], ["=", "<>"], "p", "Kategorie", $filter["value"]); + break; + case "FUNKTION": + $where.= $and.$this->getFilterString($filter["op"], ["=", "<>"], "p", "Funktion", $filter["value"]); + break; + case "ABTEILUNGEN": + $having.= $and."(1 "; + foreach ($filter["value"] as $value) { + $having.= "and ".$this->getFilterString($filter["op"], ["like", "not like"], "", "Abteilungen", ",".$value.","); + } + $having.= ") "; + break; + case "GRUPPEN": + $having.= $and."(1 "; + foreach ($filter["value"] as $value) { + $having.= $and.$this->getFilterString($filter["op"], ["like", "not like"], "", "Gruppen", ",".$value.","); + } + $having.= ") "; + break; + case "LEHRGÄNGE": + $having.= $and."(1 "; + foreach ($filter["value"] as $value) { + $having.= $and.$this->getFilterString($filter["op"], ["like", "not like"], "", "Lehrgänge", ",".$value.","); + } + $having.= ") "; + break; + case "EINWEISUNGEN": + $having.= $and."(1 "; + foreach ($filter["value"] as $value) { + $having.= $and.$this->getFilterString($filter["op"], ["like", "not like"], "", "Einweisungen", ",".$value.","); + } + $having.= ") "; + break; + default: + $where.= $and."1 "; + } } } } + + + $qry = "SELECT p.ID, p.OFnr, p.Pnr, p.Login, p.Vornamen, p.Nachnamen, p.Bildadresse, p.Kategorie, pk.Name KategorieName, " + ."p.Funktion, pf.Name FunktionName, pf.Kürzel FunktionKürzel, " + ."CONCAT(',', GROUP_CONCAT(DISTINCT pa.Abteilungen SEPARATOR ','), ',') Abteilungen, " + ."CONCAT(',', GROUP_CONCAT(DISTINCT pg.Gruppen SEPARATOR ','), ',') Gruppen, " + ."CONCAT(',', GROUP_CONCAT(DISTINCT pl.Lehrgänge SEPARATOR ','), ',') Lehrgänge, " + ."CONCAT(',', GROUP_CONCAT(DISTINCT fe.Fahrzeuge SEPARATOR ','), ',') Einweisungen " + ."FROM Personal p " + ."LEFT JOIN Personal_Kategorien pk ON pk.ID=p.Kategorie " + ."LEFT JOIN Personal_Funktionen pf ON pf.ID=p.Funktion " + ."LEFT JOIN Personal_Abteilungen pa ON pa.Personal=p.ID " + ."LEFT JOIN Struktur_Abteilungen sa ON sa.ID=pa.Abteilungen " + ."LEFT JOIN Personal_Gruppen pg ON pg.Personal=p.ID " + ."LEFT JOIN Struktur_Gruppen sg ON sg.ID=pg.Gruppen " + ."LEFT JOIN Personal_Lehrgänge pl ON pl.Personal=p.ID " + ."LEFT JOIN Lehrgänge l ON l.ID = pl.Lehrgänge " + ."LEFT JOIN Fahrzeuge_Einweisungen fe ON fe.Personal=p.ID " + ."LEFT JOIN Fahrzeuge f ON f.ID=fe.Fahrzeuge " + ."WHERE 1 ".$where + ."GROUP BY p.ID " + ."HAVING 1 ".$having + ."ORDER BY p.Nachnamen ASC, p.Vornamen ASC "; + if ($stmt = $this->db->prepare($qry)) { + if ($id) { + $stmt->bind_param("i", $id); + } else { + $this->registerGroup("Führung"); + $this->registerGroup("Kraftfahrer"); + $this->registerGroup("Mannschaft"); + } + $stmt->execute(); + $res = $stmt->get_result(); + while ($row = $res->fetch_assoc()) { + $entry = [ + "ID" => $row["ID"], + "MAIN" => [ + "OFNR" => $row["OFnr"], + "PNR" => $row["Pnr"], + "NR" => $row["OFnr"]."-".$row["Pnr"], + "LOGIN" => $row["Login"], + "EMAIL" => $row["Login"]."@feuerwehr-bs.net", + "VORNAMEN" => $row["Vornamen"], + "NACHNAMEN" => $row["Nachnamen"], + "NAME" => substr($row["Vornamen"], 0, 1).". ".$row["Nachnamen"], + "BILD" => [ + "EXISTIERT" => file_exists($this->prefixImage.$row["Bildadresse"]) && null!==$row["Bildadresse"], + "ADRESSE" => $row["Bildadresse"], + "PFAD" => "/".$this->prefixImage, + ], + "KATEGORIE" => ["ID" => $row["Kategorie"], "NAME" => $row["KategorieName"]], + "FUNKTION" => isset($row["Funktion"]) ? ["ID" => $row["Funktion"], "NAME" => $row["FunktionName"], "KÜRZEL" => $row["FunktionKürzel"]] : null, + "ADMIN" => $this->man->user->HasRight($this->adminRight), + ], + "SUB" => [ + "ABTEILUNGEN" => $this->getSub("ABTEILUNGEN", $row["Abteilungen"]), + "GRUPPEN" => $this->getSub("GRUPPEN", $row["Gruppen"]), + "LEHRGÄNGE" => $this->getSub("LEHRGÄNGE", $row["Lehrgänge"]), + "EINWEISUNGEN" => $this->getSub("EINWEISUNGEN", $row["Einweisungen"]), + ], + ]; + $this->addEntryToOutput($row["KategorieName"], $entry, $id); + } + if ($id && $res->num_rows==0) { + $this->man->AddMessage("Couldn't find requested resource!"); + return 404; + } + } else { + $this->man->AddMessage("Mysql error: ".$this->db->error." / Qry: ".$qry); + return 500; + } + return 200; + } + + protected function fillOptions($admin = false) { + $ret = array(); + $ret["FUNKTION"][] = ["ID" => "__NULL__", "KÜRZEL" => "-", "NAME" => "Ohne"]; + $res = $this->db->query("SELECT ID, Kürzel, Name FROM Personal_Funktionen"); + while ($row = $res->fetch_assoc()) { + $ret["FUNKTION"][] = ["ID" => $row["ID"], "KÜRZEL" => $row["Kürzel"], "NAME" => $row["Name"]]; + } + $res = $this->db->query("SELECT ID, Kürzel, Name FROM Lehrgänge"); + while ($row = $res->fetch_assoc()) { + $ret["LEHRGÄNGE"][] = ["ID" => $row["ID"], "KÜRZEL" => $row["Kürzel"], "NAME" => $row["Name"]]; + } + $res = $this->db->query("SELECT ID, Kürzel, Name FROM Fahrzeuge"); + while ($row = $res->fetch_assoc()) { + $ret["EINWEISUNGEN"][] = ["ID" => $row["ID"], "KÜRZEL" => $row["Kürzel"], "NAME" => $row["Name"]]; + } + $res = $this->db->query("SELECT ID, Kürzel, Name FROM Struktur_Abteilungen"); + while ($row = $res->fetch_assoc()) { + $ret["ABTEILUNGEN"][] = ["ID" => $row["ID"], "KÜRZEL" => $row["Kürzel"], "NAME" => $row["Name"]]; + } + $res = $this->db->query("SELECT ID, Kürzel, Name FROM Struktur_Gruppen"); + while ($row = $res->fetch_assoc()) { + $ret["GRUPPEN"][] = ["ID" => $row["ID"], "KÜRZEL" => $row["Kürzel"], "NAME" => $row["Name"]]; + } + $res = $this->db->query("SELECT ID, Name FROM Personal_Kategorien"); + while ($row = $res->fetch_assoc()) { + $ret["KATEGORIE"][] = ["ID" => $row["ID"], "NAME" => $row["Name"]]; + } + return $ret; + } +} diff --git a/pgs/20_personal/template.html b/pgs/20_personal/template.html new file mode 100755 index 0000000..3874b81 --- /dev/null +++ b/pgs/20_personal/template.html @@ -0,0 +1,266 @@ + + + + + +

    ###GROUP_BEGIN.GROUP###

    + + + + +
    + +
    + + + + + + + +
    +
      +
    • ###LIST.SELECTBOX###
    • +
    • ###LIST.MAIN.NR###
    • +
    • ###LIST.MAIN.NACHNAMEN###, ###LIST.MAIN.VORNAMEN###
    • + + + +
    • ###LIST.MAIN.LOGIN###@feuerwehr-bs.net
    • + +
    • ###LIST.MAIN.FUNKTION.KÜRZEL###
    • + + + + +
    • + +
    + + +
    + + + +
    + + + + +
    +
    +
      +
    • -
    • +
    • ,
    • +
    • +
    • @feuerwehr-bs.net
    • +
    • +
    • +
    • +
    • +
    • +
    + +
    +
    +
      + + +
    • ###LIST.SUB.ABTEILUNGEN.KÜRZEL###
    • + + +
    • ###LIST.SUB.GRUPPEN.KÜRZEL###
    • + + +
    • + ###LIST.SUB.LEHRGÄNGE.KÜRZEL### +
    • + + +
    • + ###LIST.SUB.EINWEISUNGEN.KÜRZEL### +
    • + + + + +
    • ###LIST.SUB.ABTEILUNGEN.KÜRZEL### +
    • + +
    • +
    • + +
    • ###LIST.SUB.GRUPPEN.KÜRZEL### +
    • + +
    • +
    • + +
    • ###LIST.SUB.LEHRGÄNGE.KÜRZEL### +
    • + +
    • +
    • + +
    • ###LIST.SUB.EINWEISUNGEN.KÜRZEL### +
    • + +
    • +
    • + +
    +
    + + + +

    Personal hinzufügen

    + + + + + + + + + + + + + + + + + diff --git a/pgs/21_prozesse/module.json b/pgs/21_prozesse/module.json new file mode 100755 index 0000000..9ba5852 --- /dev/null +++ b/pgs/21_prozesse/module.json @@ -0,0 +1,23 @@ +{ + "route" : "Prozesse", + "title" : "Prozesse", + "table" : "Prozesse", + "marker" : "PROZESSE", + "dependencies": ["Prozesse"], + "show" : true, + "useRight": "DARF_PERSONAL_VERWALTEN", + "adminRight": "DARF_PERSONAL_VERWALTEN", + "template": "template.html", + "isPage": true, + "links": { + "Fortschritte": {"route":"Prozesse_Fortschritte", "mainName":"Prozess_Personal", "subName":"Schritt"} + }, + "mainFields": { + "OFNR": {"label": "OFNr", "type": "Integer", "filter": false, "add": false, "edit": true}, + "PNR": {"label": "PNr", "type": "Integer", "filter": false, "add": false, "edit": true}, + "NACHNAMEN": {"label": "Nachnamen", "type": "String", "filter": false, "add": false, "edit": true}, + "VORNAMEN": {"label": "Vornamen", "type": "String", "filter": false, "add": false, "edit": true}, + "KATEGORIE": {"label": "Kategorie", "type": "Select", "filter": false, "add": false, "edit": true}, + "LOGIN": {"label": "Login", "type": "String", "filter": false, "add": false, "edit": true}, + "FUNKTION": {"label": "Funktion", "type": "String", "filter": false, "add": false, "edit": true} +} } diff --git a/pgs/21_prozesse/page.php b/pgs/21_prozesse/page.php new file mode 100755 index 0000000..4afff1a --- /dev/null +++ b/pgs/21_prozesse/page.php @@ -0,0 +1,30 @@ +prozessListe = $this->man->objects["Prozesse"]; + } + + protected function remove($id) { + if (isset($this->man->input["Finish"])) { + return $this->prozessListe->Finish($id, $this->man->input["Finish"]); + } + return 400; + } + + protected function get($id = null) { + $this->output = $this->prozessListe->Get(); + if (null!==$id && $this->output==[]) { + return 404; + } + return 200; + } +} + +?> \ No newline at end of file diff --git a/pgs/21_prozesse/template.html b/pgs/21_prozesse/template.html new file mode 100755 index 0000000..8626cf6 --- /dev/null +++ b/pgs/21_prozesse/template.html @@ -0,0 +1,130 @@ + + + + + + +

    ###GROUP_BEGIN.GROUP###

    + + + + + +
    +
      +
    • ###LIST.MAIN.NACHNAMEN###, ###LIST.MAIN.VORNAMEN###
    • +
    • ###LIST.MAIN.FORTSCHRITT###
    • + +
    • Unerledigte Aufgaben!
    • + +
    • VersteckenAnzeigen
    • +
    +
    + + +
    + +
    • ###LIST.SUB.SEKTION.NAME###
    + + + +
      +
    • +
    • ###LIST.SUB.SEKTION.SCHRITT.NAME###
    • +
    • ###LIST.SUB.SEKTION.SCHRITT.VON###
    • +
    • ###LIST.SUB.SEKTION.SCHRITT.WANN###
    • +
    • ###LIST.SUB.SEKTION.SCHRITT.NOTIZ###
    • + +
    • Zurücksetzen
    • + +
    + +
      +
    • +
    • ###LIST.SUB.SEKTION.SCHRITT.NAME###
    • +
    • ###LIST.SUB.SEKTION.SCHRITT.VON###
    • +
    • ###LIST.SUB.SEKTION.SCHRITT.WANN###
    • +
    • Nicht zutreffend
    • + +
    • Zurücksetzen
    • + +
    + + + +
      +
    • + +
    • +
    • ###LIST.SUB.SEKTION.SCHRITT.NAME###
    • +
    + + + +
      +
    • Prozess beenden:
    • + +
    • Erfolg
    • + +
    • Erfolg
    • + + +
    • Fehlschlag
    • + +
    • Fehlschlag
    • + + +
    +
    + + diff --git a/pgs/22_spinde/module.json b/pgs/22_spinde/module.json new file mode 100644 index 0000000..03fecc7 --- /dev/null +++ b/pgs/22_spinde/module.json @@ -0,0 +1,19 @@ +{ + "route" : "Spinde", + "title" : "Spinde", + "table" : "Spinde", + "marker" : "SPINDE", + "dependencies": [], + "show" : true, + "useRight": "DARF_PERSONAL_VERWALTEN", + "adminRight": "DARF_PERSONAL_VERWALTEN", + "template": "template.html", + "isPage": true, + "mainFields": { + "RAUM": {"label": "Raum", "type": "Select", "filter": true, "add": false, "edit": false}, + "BESITZER": {"label": "PNr", "type": "Select", "filter": true, "add": false, "edit": true}, + "LINKS": {"label": "Links", "type": "Integer", "filter": false, "add": false, "edit": false}, + "Oben": {"label": "Oben", "type": "Integer", "filter": false, "add": false, "edit": false}, + "HÖHE": {"label": "Höhe", "type": "Integer", "filter": false, "add": false, "edit": false}, + "BREITE": {"label": "Breite", "type": "Integer", "filter": false, "add": false, "edit": false} +} } diff --git a/pgs/22_spinde/page.php b/pgs/22_spinde/page.php new file mode 100644 index 0000000..d119725 --- /dev/null +++ b/pgs/22_spinde/page.php @@ -0,0 +1,123 @@ +get($id); + + $qry = "UPDATE Spinde SET Besitzer = ? WHERE ID = ?"; + if ($stmt = $this->db->prepare($qry)) { + $Besitzer = array_key_exists("BESITZER", $this->man->input) + ? $this->man->input["BESITZER"] + : (is_null($this->output["MAIN"]["BESITZER"]) ? null : $this->output["MAIN"]["BESITZER"]["ID"]); + $stmt->bind_param( + "ii", + $Besitzer, + $id + ); + if ($stmt->execute()) { + $this->man->AddMessage("Spindbesitzer wurde aktualisiert!"); + $this->get($id); + return 200; + } else { + $this->man->AddMessage("Mysql error: ".$this->db->error); + } + } else { + $this->man->AddMessage("Mysql error: ".$this->db->error); + } + return 500; + } + + protected function get($id = null) { + $this->output = []; + if ($id===null && $this->man->Main()!=null) { + $id = $this->man->Main(); + } + + $where = ""; + $having = ""; + if ($id) { + $where = "AND s.ID = ? "; + } else if (sizeof($this->man->Filter())>0) { + /*$where = "WHERE 1 ";*/ + foreach ($this->man->Filter() as $filter) { + $and = "or"==$filter["and"] ? "OR " : "AND "; + if ("none"==$filter["field"]) { + $where.= $and."1 "; + } else { + switch ($filter["field"]) { + case "RAUM": + $where.= $and.$this->getFilterString($filter["op"], ["=", "<>"], "s", "Raum", $filter["value"]); + break; + case "BESITZER": + $where.= $and.$this->getFilterString($filter["op"], ["=", "<>"], "s", "Besitzer", $filter["value"]); + break; + default: + $where.= $and."1 "; + } } } } + + $qry = "SELECT s.ID, s.Raum, s.Besitzer, s.Bezeichnung, s.Links, s.Oben, s.Höhe, s.Breite, s.Orientation, p.Pnr, p.Nachnamen, p.Vornamen, sr.Name srName " + ."FROM Spinde s " + ."LEFT JOIN Spinde_Räume sr ON sr.ID=s.Raum " + ."LEFT JOIN Personal p ON p.ID=s.Besitzer " + ."WHERE 1 ".$where + ."ORDER BY s.Raum ASC "; + if ($stmt = $this->db->prepare($qry)) { + if ($id) { + $stmt->bind_param("i", $id); + } + $stmt->execute(); + $res = $stmt->get_result(); + while ($row = $res->fetch_assoc()) { + $entry = [ + "ID" => strval($row["ID"]), + "GROUP" => $row["srName"], + /*"POS" => [ + "LEFT" => $row["Links"], + "TOP"=> $row["Oben"], + "WIDTH" => $row["Breite"], + "HEIGHT" => $row["Höhe"], + "ROT" => $row["Orientation"], + ],*/ + "MAIN" => [ + "FREI" => is_null($row["Besitzer"]), + "RAUM" => $row["srName"], + "BEZEICHNUNG" => $row["Bezeichnung"], + "BESITZER" => [ + "ID" => $row["Besitzer"], + "PNR" => $row["Pnr"], + "VORNAMEN" => $row["Vornamen"], + "NACHNAMEN" => $row["Nachnamen"], + "NAME" => (is_null($row["Vornamen"]) ? "" : preg_replace("/(? [], + ]; + $this->addEntryToOutput($row["srName"], $entry, $id); + } + if ($id && $res->num_rows==0) { + $this->man->AddMessage("Couldn't find requested resource!"); + return 404; + } + } else { + $this->man->AddMessage("Mysql error: ".$this->db->error." / Qry: ".$qry); + return 500; + } + return 200; + } + + protected function fillOptions($admin = false) { + $ret = array(); + $ret["BESITZER"][] = ["ID" => "__NULL__", "NAME" => "Frei"]; + $res = $this->db->query("SELECT ID, Pnr, Vornamen, Nachnamen FROM Personal ORDER BY Nachnamen ASC, Vornamen ASC"); + while ($row = $res->fetch_assoc()) { + $ret["BESITZER"][] = ["ID" => $row["ID"], "NAME" => preg_replace("/(? + + + + +

    ###GROUP_BEGIN.GROUP###

    + + + +
      +
    • ###LIST.MAIN.RAUM###
    • +
    • ###LIST.MAIN.BEZEICHNUNG###
    • + +
    • Frei
    • + +
    • ###LIST.MAIN.BESITZER.NAME###
    • + +
    • +
    + + +
      +
    • +
    • +
    • +
    + + + + diff --git a/pgs/30_einsaetze/module.json b/pgs/30_einsaetze/module.json new file mode 100644 index 0000000..a1eb9b4 --- /dev/null +++ b/pgs/30_einsaetze/module.json @@ -0,0 +1,46 @@ +{ + "route" : "Einsätze", + "title" : "(Einsätze)", + "table" : "Einsätze", + "marker": "EINSÄTZE", + "dependencies": [], + "show" : 1, + "rights": { + "admin": ["DARF_DIENSTE_VERWALTEN"], + "see": [], + "edit": { + "DARF_EA_DIENSTE_VERWALTEN": { + "GRUPPE":[1] + }, + "DARF_JF_DIENSTE_VERWALTEN": { + "GRUPPE":[2] + }, + "DARF_AE_DIENSTE_VERWALTEN": { + "GRUPPE":[3] + }, + "DARF_KF_DIENSTE_VERWALTEN": { + "KATEGORIE":[4], + "GRUPPE":[1,6] + }, + "DARF_MB_DIENSTE_VERWALTEN": { + "KATEGORIE":[13], + "GRUPPE":[null] + } } }, + "useRight": ["DARF_DIENSTE_VERWALTEN"], + "adminRight": ["DARF_DIENSTE_VERWALTEN", "DARF_KF_DIENSTE_VERWALTEN", "DARF_MB_DIENSTE_VERWALTEN"], + "template": "template.html", + "isPage": true, + "links": { + "Teilnahme": {"route":"Einsätze_Teilnahmen", "mainName":"Einsätze", "subName":"Personal"} + }, + "mainFields": { + "BEGINN": {"label": "Beginn", "type": "DateTime", "filter": true, "add": true, "edit": true}, + "ENDE": {"label": "Ende", "type": "DateTime", "filter": true, "add": true, "edit": true}, + "THEMA": {"label": "Thema", "type": "String", "filter": true, "add": true, "edit": true}, + "ORT": {"label": "Ort", "type": "String", "filter": false, "add": true, "edit": true}, + "DIENSTPLAN": {"label": "Dienstplan", "type": "Select", "filter": true, "add": true, "edit": true}, + "KATEGORIE": {"label": "Kategorie", "type": "Select", "filter": true, "add": true, "edit": true}, + "PLATZVERGABE": {"label": "Platzvergabe", "type": "Select", "filter": false, "add": true, "edit": true}, + "AUSGELOST": {"label": "Ausgelost", "type": "Checkbox", "filter": false, "add": true, "edit": true}, + "GRUPPE": {"label": "Gruppe", "type": "Select", "filter": true, "add": true, "edit": true} +} } \ No newline at end of file diff --git a/pgs/30_einsaetze/page.php b/pgs/30_einsaetze/page.php new file mode 100644 index 0000000..ec62d15 --- /dev/null +++ b/pgs/30_einsaetze/page.php @@ -0,0 +1,270 @@ +get($id); + $qry = "UPDATE Einsätze SET Beginn = ?, Ende = ?, Thema = ?, Ort = ?, Dienstplan = ?, " + ."Kategorie = ?, Platzvergabe = ?, Ausgelost = ?, Gruppe = ? WHERE ID = ?"; + if ($stmt = $this->db->prepare($qry)) { + $Beginn = $this->man->input["ALARMIERUNGSZEIT"] ?? $this->output["MAIN"]["ALARMIERUNGSZEIT"]; + $Ende = $this->man->input["EINSATZENDE"] ?? $this->output["MAIN"]["EINSATZENDE"]; + $Thema = $this->man->input["THEMA"] ?? $this->output["MAIN"]["THEMA"]; + $Ort = $this->man->input["ORT"] ?? $this->output["MAIN"]["ORT"]; + $Dienstplan = $this->man->input["DIENSTPLAN"] ?? $this->output["MAIN"]["DIENSTPLAN"]["ID"]; + $Kategorie = $this->man->input["KATEGORIE"] ?? $this->output["MAIN"]["KATEGORIE"]["ID"]; + $Platzvergabe = array_key_exists("PLATZVERGABE", $this->man->input) + ? $this->man->input["PLATZVERGABE"] + : (is_null($this->output["MAIN"]["PLATZVERGABE"]) ? null : $this->output["MAIN"]["PLATZVERGABE"]["ID"]); + $Ausgelost = $this->man->input["AUSGELOST"] ?? $this->output["MAIN"]["AUSGELOST"]; + $Gruppe = array_key_exists("GRUPPE", $this->man->input) + ? $this->man->input["GRUPPE"] + : (is_null($this->output["MAIN"]["GRUPPE"]) ? null : $this->output["MAIN"]["GRUPPE"]["ID"]); + $stmt->bind_param( + "ssssiiiiii", + $Beginn, + $Ende, + $Thema, + $Ort, + $Dienstplan, + $Kategorie, + $Platzvergabe, + $Ausgelost, + $Gruppe, + $id + ); + if ($stmt->execute()) { + $this->man->AddMessage("Einsatz wurde aktualisiert!"); + $this->get($id); + return 200; + } else { + $this->man->AddMessage("Mysql error: ".$this->db->error); + } + } else { + $this->man->AddMessage("Mysql error: ".$this->db->error); + } + return 500; + } + + protected function insert() { + $qry = "INSERT INTO Einsätze (Beginn, Ende, Thema, Ort, Dienstplan, Kategorie, Platzvergabe, Gruppe) VALUES (?,?,?,?,?,?,?,?)"; + if ($stmt = $this->db->prepare($qry)) { + $Beginn = $this->man->input["ALARMIERUNGSZEIT"] ?? ""; + $Ende = $this->man->input["EINSATZENDE"] ?? ""; + $Thema = $this->man->input["THEMA"] ?? ""; + $Ort = $this->man->input["ORT"] ??""; + $Dienstplan = $this->man->input["DIENSTPLAN"] ?? null; + $Kategorie = $this->man->input["KATEGORIE"] ?? null; + $Platzvergabe = array_key_exists("PLATZVERGABE", $this->man->input) + ? $this->man->input["PLATZVERGABE"] + : null; + $Gruppe = array_key_exists("GRUPPE", $this->man->input) + ? $this->man->input["GRUPPE"] + : null; + $stmt->bind_param( + "ssssiiii", + $Beginn, + $Ende, + $Thema, + $Ort, + $Dienstplan, + $Kategorie, + $Platzvergabe, + $Gruppe + ); + $stmt->execute(); + if ($stmt->affected_rows==1) { + $this->man->AddMessage("Einsatz wurde hinzugefügt!"); + $this->get($this->db->insert_id); + return 201; + } else { + $this->man->AddMessage("Einsatz konnte nicht hinzugefügt werden! (" + .$Beginn." / ".$Ende." / ".$Thema." / ".$Ort." / " + .$Dienstplan." / ".$Kategorie." / ".$Platzvergabe." / ".$Gruppe.")" + ); + return 400; + } + } else { + $this->man->AddMessage("Mysql error: ".$this->db->error); + return 500; + } + } + + protected function get($id = null) { + $this->output = []; + $where = ""; + if ($id) { + $where = "WHERE e.ID = ? "; + } else if (sizeof($this->man->Filter())>0) { + $where = "WHERE 1 "; + foreach ($this->man->Filter() as $filter) { + $where.= "or"==$filter["and"] ? "OR " : "AND "; + if ("none"==$filter["field"]) { + $where.= "1 "; + } else { + switch ($filter["field"]) { + case "ALARMIERUNGSZEIT": + $where.= $this->getFilterString($filter["op"], ["<=", ">="], "t", "Beginn", $filter["value"]); + break; + case "EINSATZENDE": + $where.= $this->getFilterString($filter["op"], ["<=", ">="], "t", "Ende", $filter["value"]); + break; + case "THEMA": + $where.= $this->getFilterString($filter["op"], ["like", "not like"], "t", "Thema", $filter["value"]); + break; + case "DIENSTPLAN": + $where.= $this->getFilterString($filter["op"], ["=", "<>"], "t", "Dienstplan", $filter["value"]); + break; + case "KATEGORIE": + $where.= $this->getFilterString($filter["op"], ["=", "<>"], "t", "Kategorie", $filter["value"]); + break; + case "GRUPPE": + $where.= $this->getFilterString($filter["op"], ["=", "<>"], "t", "Gruppe", $filter["value"]); + break; + default: + $where.= "1 "; + } } } + } else { + /*$datefrom = date("Y-m-d H:i:s"); + $this->man->filter[] = ["and" => "and", "field" => "EINSATZENDE", "op" => ">=", "value" => $datefrom]; + $where = "WHERE ".$this->getFilterString(">=", [">="], "t", "Ende", $datefrom);*/ + } + + $qry = "SELECT e.ID, e.Alarmierungszeit, e.Einsatzende, e.Adresse, e.Art, e.Zusammenfassung, e.Einsatzleiter, e.Überprüft " + .", ea.Kategorie, ea.Name eaName, ea.Stichworte " + .", ek.Name ekName, ek.Farbe " + ."FROM Einsätze e " + ."LEFT JOIN Einsätze_Arten ea ON ea.ID=e.Art " + ."LEFT JOIN Einsätze_Kategorien ek ON ek.ID=ea.Kategorie " + .$where + ."ORDER BY e.Alarmierungszeit DESC "; + if ($stmt = $this->db->prepare($qry)) { + $userID = $this->man->user->ID(); + if ($id) { + $stmt->bind_param("i", $id); + } else { + //$stmt->bind_param("i", $userID, $userID); + } + $stmt->execute(); + $res = $stmt->get_result(); + while ($row = $res->fetch_assoc()) { + $beginn_time = date("H:i", strtotime($row["Alarmierungszeit"])); + $ende_time = date("H:i", strtotime($row["Einsatzende"])); + $beginn_date = date("D, d.m.Y", strtotime($row["Alarmierungszeit"])); + $ende_date = "0000-00-00 00:00:00"== $row["Einsatzende"] ? + "?" : ( + "00:00"==$ende_time ? date("D, d.m.Y", strtotime($row["Einsatzende"]) - 1) : date("D, d.m.Y", strtotime($row["Einsatzende"])) + ); + + $entry = [ + "ID" => $row["ID"], + "MAIN" => [ + "ALARMIERUNGSZEIT" => $row["Alarmierungszeit"], + "ALARMIERUNGSZEIT.DATUM" => date("D, d.m.Y", strtotime($row["Alarmierungszeit"])), + "ALARMIERUNGSZEIT.DATE" => date("Y-m-d", strtotime($row["Alarmierungszeit"])), + "ALARMIERUNGSZEIT.ZEIT" => date("H:i", strtotime($row["Alarmierungszeit"])), + "ALARMIERUNGSZEIT.TIME" => date("H:i", strtotime($row["Alarmierungszeit"])), + "EINSATZENDE" => $row["Einsatzende"], + "EINSATZENDE.DATUM" => date("d.m.Y", strtotime($row["Einsatzende"])), + "EINSATZENDE.DATE" => date("Y-m-d", strtotime($row["Einsatzende"])), + "EINSATZENDE.ZEIT" => date("H:i", strtotime($row["Einsatzende"])), + "EINSATZENDE.TIME" => date("H:i", strtotime($row["Einsatzende"])), + "DATUM" => $beginn_date.($beginn_date!=$ende_date && "?"!=$ende_date ? " - ".$ende_date : ""), + "ZEIT" => $beginn_time." - ".("?"==$ende_date ? "?" : $ende_time), + "ADRESSE" => $row["Adresse"], + "ART" => [ + "ID" => $row["Art"], + "KATEGORIE" => ["ID" => $row["Kategorie"], "NAME" => $row["ekName"], "FARBE" => $row["Farbe"]], + "NAME" => is_null($row["Art"]) ? "Unbekannt" : $row["eaName"], + "STICHWORTE" => $row["Stichworte"] + ], + "ZUSAMMENFASSUNG" => $row["Zusammenfassung"], + "EINSATZLEITER" => $row["Einsatzleiter"], + "ÜBERPRÜFT" => $row["Überprüft"], + "ADMIN" => true, + ], + "SUB" => [ + /*"ANMELDUNG" => $registration, + "TEILNAHME" => $isPrivileged ? $teilnahme : []*/ + ], + ]; + $group = date("Y", strtotime($row["Alarmierungszeit"])); + $this->addEntryToOutput($group, $entry, $id); + } + } else { + $this->man->AddMessage("Mysql error: ".$this->db->error); + } + + return 200; + } + + protected function fillOptions($admin = false) { + $ret = array(); + $res = $this->db->query("SELECT ID, Jahr, Name FROM Termine_Dienstpläne ORDER BY Jahr DESC, Name DESC"); + while ($row = $res->fetch_assoc()) { + $ret["DIENSTPLAN"][] = ["ID" => $row["ID"], "JAHR" => $row["Jahr"], "NAME" => $row["Name"]]; + } + $res = $this->db->query("SELECT ID, Name FROM Einsätze_Kategorien"); + while ($row = $res->fetch_assoc()) { + $ret["KATEGORIE"][] = ["ID" => $row["ID"], "NAME" => $row["Name"]]; + } + $res = $this->db->query("SELECT ID, Kürzel, Name FROM Struktur_Abteilungen"); + while ($row = $res->fetch_assoc()) { + $ret["ABTEILUNG"][] = ["ID" => $row["ID"], "KÜRZEL" => $row["Kürzel"], "NAME" => $row["Name"]]; + } + $ret["PLATZVERGABE"][] = ["ID" => "__NULL__", "NAME" => "Ohne"]; + $res = $this->db->query("SELECT ID, Name FROM Termine_Platzvergaben ORDER BY Name ASC"); + while ($row = $res->fetch_assoc()) { + $ret["PLATZVERGABE"][] = ["ID" => $row["ID"], "NAME" => $row["Name"]]; + } + $ret["GRUPPE"][] = ["ID" => "__NULL__", "KÜRZEL" => "Ohne", "NAME" => "Ohne"]; + $res = $this->db->query("SELECT ID, Kürzel, Name FROM Struktur_Gruppen ORDER BY Name ASC"); + while ($row = $res->fetch_assoc()) { + $ret["GRUPPE"][] = ["ID" => $row["ID"], "KÜRZEL" => $row["Kürzel"], "NAME" => $row["Name"]]; + } + if ($admin) { + $res = $this->db->query("SELECT p.ID, Nachnamen, Vornamen, pk.Name pkName FROM Personal p LEFT JOIN Personal_Kategorien pk ON pk.ID=p.Kategorie " + ."ORDER BY pk.Reihenfolge ASC, Nachnamen ASC, Vornamen ASC"); + $lastKategorie = ""; + while ($row = $res->fetch_assoc()) { + if ($row["pkName"]!=$lastKategorie) { + $ret["TEILNAHME"][] = ["ID" => 0, "NAME" => " === ".$row["pkName"]." === "]; + $lastKategorie = $row["pkName"]; + } + $ret["TEILNAHME"][] = ["ID" => $row["ID"], "NAME" => preg_replace("/(?db->prepare($qry)) { + $stmt->bind_param("i", $terminID); + $stmt->execute(); + $res = $stmt->get_result(); + while ($row = $res->fetch_assoc()) { + $status = $row["Status"]==2 ? "LEAD" : ($row["Status"]==1 ? "CAN" : "WANT"); + $entry = [ + "ID" => $row["ID"], + "NAME" => preg_replace("/(? $row["Nachnamen"], + "VORNAMEN" => $row["Vornamen"], + "STATUS" => "__CASE__:".$status, + "LEHRGÄNGE" => $row["lehrgänge"] ?? "Keine", + ]; + $ret[] = $entry; + } + } else { + $this->man->AddMessage("Mysql error: ".$this->db->error); + } + return $ret; +} } diff --git a/pgs/30_einsaetze/template.html b/pgs/30_einsaetze/template.html new file mode 100644 index 0000000..ea6465f --- /dev/null +++ b/pgs/30_einsaetze/template.html @@ -0,0 +1,260 @@ + + + + +

    ###GROUP_BEGIN.GROUP###

    + + + +
    +
      +
    • ###LIST.MAIN.DATUM###
    • +
    • ###LIST.MAIN.ZEIT###
    • + +
    • ###LIST.MAIN.ART.NAME###
    • + +
    • ###LIST.MAIN.ADRESSE###
    • +
    • ###LIST.MAIN.EINSATZLEITER###
    • + + + +
    • + +
    +
    + + +
    +
      +
    • + + + + + + + +
    • +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    • + + + + + + +
    • +
    • + +
    • +
    • +
    • +
    • +
    • +
    +
    + + + +
    +
      +
    • ↳ ###LIST.SUB.ANMELDUNG.RESTRICTIONS###
    • + + +
    • Du darfst kommen
    • + +
    • Auf Warteliste
    • + +
    • Zur Auslosung angemeldet
    • + +
    • Bei Interesse bitte anmelden
    • + +
    • Du leitest diesen Dienst
    • + + +
    • Noch ###LIST.SUB.ANMELDUNG.FREE.NUM### Plätze frei
    • + + +
    • ###LIST.SUB.ANMELDUNG.ACTION.NAME###
    • + +
    +
    + + + + +
    +
      +
    • ↳ ###LIST.SUB.ANMELDUNG.RESTRICTIONS###
    • + + +
    • Du darfst kommen
    • + +
    • Auf Warteliste
    • + +
    • Zur Auslosung angemeldet
    • + +
    • Bei Interesse bitte anmelden
    • + +
    • Du leitest diesen Dienst
    • + + +
    • Noch ###LIST.SUB.ANMELDUNG.FREE.NUM### Plätze frei
    • + + +
    • ###LIST.SUB.ANMELDUNG.ACTION.NAME###
    • + +
    +
    + +
    +
      +
    • ↳ Teilnehmerliste:
    • + + + +
    • + ###LIST.SUB.TEILNAHME.NAME### +
    • + +
    • + ###LIST.SUB.TEILNAHME.NAME### +
    • + +
    • + ###LIST.SUB.TEILNAHME.NAME### +
    • + + +
    • + +
    • +
    +
    + + + + + + + +

    Termin hinzufügen

    + + + + + + + + + diff --git a/pgs/40_anwesenheit/module.json b/pgs/40_anwesenheit/module.json new file mode 100644 index 0000000..0cd12db --- /dev/null +++ b/pgs/40_anwesenheit/module.json @@ -0,0 +1,24 @@ +{ + "route" : "Anwesenheiten", + "title" : "(Anwesenheiten)", + "table" : "Anwesenheiten", + "marker": "ANWESENHEITEN", + "dependencies": [], + "show" : 1, + "rights": { + "admin": ["DARF_DIENSTE_VERWALTEN"], + "see": [], + "edit": { + } }, + "useRight": ["DARF_DIENSTE_VERWALTEN", "DARF_EINSÄTZE_VERWALTEN", "DARF_ANWESENHEITEN_VERWALTEN"], + "adminRight": ["DARF_DIENSTE_VERWALTEN", "DARF_EINSÄTZE_VERWALTEN", "DARF_ANWESENHEITEN_VERWALTEN"], + "template": "template.html", + "isPage": true, + "links": { + "Termine": {"route":"Anwesenheiten_Termine", "mainName":"Anwesenheiten", "subName":"Termine"}, + "Einsätze": {"route":"Anwesenheiten_Einsätze", "mainName":"Anwesenheiten", "subName":"Einsätze"}, + "Personal": {"route":"Anwesenheiten_Personal", "mainName":"Anwesenheiten", "subName":"Personal"} + }, + "mainFields": { + "BEZEICHNUNG": {"label": "Bezeichnung", "type": "String", "filter": true, "add": true, "edit": true} +} } \ No newline at end of file diff --git a/pgs/40_anwesenheit/page.php b/pgs/40_anwesenheit/page.php new file mode 100644 index 0000000..995b02f --- /dev/null +++ b/pgs/40_anwesenheit/page.php @@ -0,0 +1,172 @@ +man->AddMessage($id); + $this->get($id); + $qry = "UPDATE Anwesenheiten SET Bezeichnung = ? WHERE ID = ?"; + if ($stmt = $this->db->prepare($qry)) { + $Bezeichnung = $this->man->input["BEZEICHNUNG"] ?? $this->output["MAIN"]["BEZEICHNUNG"]; + $stmt->bind_param( + "si", + $Bezeichnung, + $id + ); + if ($stmt->execute()) { + $this->man->AddMessage("Anwesenheitsliste wurde aktualisiert!"); + $this->get($id); + return 200; + } else { + $this->man->AddMessage("Mysql error: ".$this->db->error); + } + } else { + $this->man->AddMessage("Mysql error: ".$this->db->error); + } + return 500; + } + + protected function insert() { + $qry = "INSERT INTO Anwesenheiten (Bezeichnung) VALUES (?)"; + if ($stmt = $this->db->prepare($qry)) { + $Bezeichnung = $this->man->input["BEZEICHNUNG"] ?? ""; + $stmt->bind_param("s", $Bezeichnung); + $stmt->execute(); + if ($stmt->affected_rows==1) { + $this->man->AddMessage("Anwesenheitsliste wurde hinzugefügt!"); + $this->get($this->db->insert_id); + return 201; + } else { + $this->man->AddMessage("Anwesenheitsliste konnte nicht hinzugefügt werden! (".$Bezeichnung.")" + ); + return 400; + } + } else { + $this->man->AddMessage("Mysql error: ".$this->db->error); + return 500; + } + } + + protected function get($id = null) { + $this->output = []; + $where = ""; + if ($id) { + $where = "WHERE a.ID = ? "; + } else if (sizeof($this->man->Filter())>0) { + $where = "WHERE 1 "; + foreach ($this->man->Filter() as $filter) { + $where.= "or"==$filter["and"] ? "OR " : "AND "; + if ("none"==$filter["field"]) { + $where.= "1 "; + } else { + switch ($filter["field"]) { + /*case "BEGINN": + $where.= $this->getFilterString($filter["op"], ["<=", ">="], "t", "Beginn", $filter["value"]); + break; + case "ENDE": + $where.= $this->getFilterString($filter["op"], ["<=", ">="], "t", "Ende", $filter["value"]); + break; + case "THEMA": + $where.= $this->getFilterString($filter["op"], ["like", "not like"], "t", "Thema", $filter["value"]); + break; + case "DIENSTPLAN": + $where.= $this->getFilterString($filter["op"], ["=", "<>"], "t", "Dienstplan", $filter["value"]); + break; + case "KATEGORIE": + $where.= $this->getFilterString($filter["op"], ["=", "<>"], "t", "Kategorie", $filter["value"]); + break; + case "GRUPPE": + $where.= $this->getFilterString($filter["op"], ["=", "<>"], "t", "Gruppe", $filter["value"]); + break;*/ + default: + $where.= "1 "; + } } } + } else { + $where = "WHERE 1 "; + } + + $qry = "SELECT a.*, " + ."CONCAT(',', GROUP_CONCAT(DISTINCT at.Termine SEPARATOR ','), ',') Termine, " + ."CONCAT(',', GROUP_CONCAT(DISTINCT ae.Einsätze SEPARATOR ','), ',') Einsätze, " + ."CONCAT(',', GROUP_CONCAT(DISTINCT ap.Personal SEPARATOR ','), ',') Personal " + ."FROM Anwesenheiten a " + ."LEFT JOIN Anwesenheiten_Termine at ON a.ID=at.Anwesenheiten " + ."LEFT JOIN Anwesenheiten_Einsätze ae ON a.ID=ae.Anwesenheiten " + ."LEFT JOIN Anwesenheiten_Personal ap ON a.ID=ap.Anwesenheiten " + .$where + ."GROUP BY a.ID "; + if ($stmt = $this->db->prepare($qry)) { + $userID = $this->man->user->ID(); + if ($id) { + $stmt->bind_param("i", $id); + } else { + + } + $stmt->execute(); + $res = $stmt->get_result(); + while ($row = $res->fetch_assoc()) { + $entry = [ + "ID" => strval($row["ID"]), + "MAIN" => [ + "BEZEICHNUNG" => $row["Bezeichnung"] + ], + "SUB" => [ + "TERMINE" => $this->getSub("TERMINE", $row["Termine"]), + "EINSÄTZE" => $this->getSub("EINSÄTZE", $row["Einsätze"]), + "PERSONAL" => $this->getSub("PERSONAL", $row["Personal"]) + ], + ]; + $this->addEntryToOutput("DEFAULT", $entry, $id); + } + } else { + $this->man->AddMessage("Mysql error: ".$this->db->error); + } + + return 200; + } + + protected function fillOptions($admin = false) { + $ret = array(); + $res = $this->db->query("SELECT ID, Beginn, Thema " + ."FROM Termine " + ."ORDER BY Beginn DESC"); + while ($row = $res->fetch_assoc()) { + $ret["TERMINE"][] = ["ID" => $row["ID"], "BEGINN" => $row["Beginn"], "THEMA" => $row["Thema"]]; + } + $res = $this->db->query("SELECT e.ID, e.Alarmierungszeit, e.Adresse, ea.Name aName " + ."FROM Einsätze e " + ."LEFT JOIN Einsätze_Arten ea ON ea.ID=e.Art " + ."ORDER BY Alarmierungszeit DESC"); + while ($row = $res->fetch_assoc()) { + $ret["EINSÄTZE"][] = [ + "ID" => $row["ID"], + "ALARMIERUNGSZEIT" => $row["Alarmierungszeit"], + "ADRESSE" => $row["Adresse"], + "ART" => $row["aName"] + ]; + } + $res = $this->db->query("SELECT p.ID, Nachnamen, Vornamen, pk.Name pkName FROM Personal p LEFT JOIN Personal_Kategorien pk ON pk.ID=p.Kategorie " + ."ORDER BY pk.Reihenfolge ASC, Nachnamen ASC, Vornamen ASC"); + $lastKategorie = ""; + while ($row = $res->fetch_assoc()) { + if ($row["pkName"]!=$lastKategorie) { + $ret["PERSONAL"][] = ["ID" => 0, "NAME" => " === ".$row["pkName"]." === "]; + $lastKategorie = $row["pkName"]; + } + $ret["PERSONAL"][] = ["ID" => $row["ID"], "NAME" => preg_replace("/(?db->query("SELECT ID, Name, Kürzel FROM Fahrzeuge"); + $ret["FAHRZEUGE"][] = ["ID" => null, "NAME" => "Keins", "KÜRZEL" => "-"]; + while ($row = $res->fetch_assoc()) { + $ret["FAHRZEUGE"][] = [ + "ID" => $row["ID"], + "NAME" => $row["Name"], + "KÜRZEL" => $row["Kürzel"] + ]; + } + return $ret; + } + +} diff --git a/pgs/40_anwesenheit/template.html b/pgs/40_anwesenheit/template.html new file mode 100644 index 0000000..93a5c9c --- /dev/null +++ b/pgs/40_anwesenheit/template.html @@ -0,0 +1,117 @@ + + + + + + + + + + +
    +
      + +
    • ###LIST.MAIN.BEZEICHNUNG###
    • + + + +
    • + + + +
    • +
    • +
    • +
    • + +
    +
    + +
    +
      + +
    • ###LIST.SUB.TERMINE.BEGINN### (###LIST.SUB.TERMINE.THEMA###)
    • + +
    • +
    • + +
    • ###LIST.SUB.EINSÄTZE.ALARMIERUNGSZEIT### (###LIST.SUB.EINSÄTZE.ADRESSE###) +
    • + +
    • +
    • +
    +
    +
    +
      + +
    • ###LIST.SUB.PERSONAL.NAME### +
    • + +
    • + + +
    • +
    +
    + + + + +

    Anwesenheitsliste hinzufügen

    + + + + + + + + + + + + + + + + + + + + + diff --git a/pgs/50_fahrzeuge/module.json b/pgs/50_fahrzeuge/module.json new file mode 100644 index 0000000..09ed850 --- /dev/null +++ b/pgs/50_fahrzeuge/module.json @@ -0,0 +1,19 @@ +{ + "route" : "Fahrzeuge", + "title" : "(Fahrzeuge)", + "table" : "Fahrzeuge", + "marker" : "FAHRZEUGE", + "dependencies": [], + "show" : true, + "useRight": "DARF_FAHRZEUGE_VERWALTEN", + "adminRight": "DARF_FAHRZEUGE_VERWALTEN", + "template": "template.html", + "isPage": true, + "links": { + "Bilder": {"route":"Dateien", "mainName":"Fahrzeuge", "subName":"Bild"}, + "Eingewiesene": {"route":"Fahrzeuge_Einweisungen", "mainName":"Fahrzeuge", "subName":"Personal"} + }, + "mainFields": { + "KÜRZEL": {"label": "Kürzel", "type": "Select", "filter": true, "add": false, "edit": false}, + "NAME": {"label": "Name", "type": "Select", "filter": true, "add": false, "edit": false} +} } diff --git a/pgs/50_fahrzeuge/page.php b/pgs/50_fahrzeuge/page.php new file mode 100644 index 0000000..721c545 --- /dev/null +++ b/pgs/50_fahrzeuge/page.php @@ -0,0 +1,136 @@ +get($id); + + $qry = "UPDATE Fahrzeuge SET Kürzel = ?, Name = ? WHERE ID = ?"; + if ($stmt = $this->db->prepare($qry)) { + $name = array_key_exists("NAME", $this->man->input) ? $this->man->input["NAME"] : $this->output["MAIN"]["NAME"]; + $kürzel = array_key_exists("KÜRZEL", $this->man->input) ? $this->man->input["KÜRZEL"] : $this->output["MAIN"]["KÜRZEL"]; + $stmt->bind_param( + "ssi", + $kürzel, + $name, + $id + ); + if ($stmt->execute()) { + $this->man->AddMessage("Fahrzeug wurde aktualisiert!"); + $this->get($id); + return 200; + } else { + $this->man->AddMessage("Mysql error: ".$this->db->error); + } + } else { + $this->man->AddMessage("Mysql error: ".$this->db->error); + } + return 500; + } + + protected function insert() { + $res = $this->db->query("SELECT UUID_SHORT() uuid"); + $uuid = $res->fetch_assoc()["uuid"]; + + $qry = "INSERT INTO Fahrzeuge (ID, Kürzel, Name) VALUES (?,?,?)"; + if ($stmt = $this->db->prepare($qry)) { + $Kürzel = $this->man->input["KÜRZEL"] ?? ""; + $Name = $this->man->input["NAME"] ?? ""; + $stmt->bind_param( + "sss", + $uuid, + $Kürzel, + $Name + ); + $stmt->execute(); + if ($stmt->affected_rows==1) { + $this->man->AddMessage("Fahrzeug wurde hinzugefügt!"); + $this->get($uuid); + return 201; + } else { + $this->man->AddMessage("Fahrzeug konnte nicht hinzugefügt werden! (".$Kürzel." / ".$Name.")"); + return 400; + } + } else { + $this->man->AddMessage("Mysql error: ".$this->db->error); + return 500; + } + } + + protected function get($id = null) { + $this->output = []; + $where = ""; + $having = ""; + if ($id) { + $where = "AND f.ID = ? "; + } else if (sizeof($this->man->Filter())>0) { + /*$where = "WHERE 1 ";*/ + foreach ($this->man->Filter() as $filter) { + $and = "or"==$filter["and"] ? "OR " : "AND "; + if ("none"==$filter["field"]) { + $where.= $and."1 "; + } else { + switch ($filter["field"]) { +/* case "RAUM": + $where.= $and.$this->getFilterString($filter["op"], ["=", "<>"], "s", "Raum", $filter["value"]); + break; + case "BESITZER": + $where.= $and.$this->getFilterString($filter["op"], ["=", "<>"], "s", "Besitzer", $filter["value"]); + break;*/ + default: + $where.= $and."1 "; + } } } } + + $qry = "SELECT f.*, CONCAT(',', GROUP_CONCAT(DISTINCT fe.Personal SEPARATOR ','), ',') Eingewiesene FROM Fahrzeuge f " + ."LEFT JOIN Fahrzeuge_Einweisungen fe ON fe.Fahrzeuge=f.ID " + ."LEFT JOIN Personal p ON p.ID=fe.Personal " + ."WHERE 1 ".$where + ."GROUP BY f.ID "; +// ."ORDER BY s.Raum ASC "; + if ($stmt = $this->db->prepare($qry)) { + if ($id) { + $stmt->bind_param("s", $id); + } + $stmt->execute(); + $res = $stmt->get_result(); + while ($row = $res->fetch_assoc()) { + $entry = [ + "ID" => strval($row["ID"]), + "GROUP" => "Fahrzeuge", + "MAIN" => [ + "KÜRZEL" => $row["Kürzel"], + "NAME" => $row["Name"], + "BILD" => [ + "EXISTIERT" => file_exists($this->prefixImage.$row["Bild"]) && null!==$row["Bild"], + "ADRESSE" => $row["Bild"], + "PFAD" => "/".$this->prefixImage, + ], + ], + "SUB" => [ + "EINGEWIESENE" => $this->getSub("EINGEWIESENE", $row["Eingewiesene"]), + ], + ]; + $this->addEntryToOutput("Fahrzeuge", $entry, $id); + } + if ($id && $res->num_rows==0) { + $this->man->AddMessage("Couldn't find requested resource!"); + return 404; + } + } else { + $this->man->AddMessage("Mysql error: ".$this->db->error." / Qry: ".$qry); + return 500; + } + return 200; + } + + protected function fillOptions($admin = false) { + $ret = array(); + $res = $this->db->query("SELECT ID, OFnr, Pnr, Vornamen, Nachnamen FROM Personal ORDER BY Nachnamen ASC, Vornamen ASC"); + while ($row = $res->fetch_assoc()) { + $ret["EINGEWIESENE"][] = ["ID" => $row["ID"], "NAME" => preg_replace("/(? + + + + + + +
    + +
    + + + + + + + +
    +
      +
    • ###LIST.MAIN.NAME###
    • +
    • ###LIST.MAIN.KÜRZEL###
    • +
    • +
    + + +
    + + + +
    + + + + +
    +
    +
      +
    • +
    • +
    • +
    • +
    + +
    +
    +
      + + +
    • + ###LIST.SUB.EINGEWIESENE.NAME### +
    • + + + + +
    • ###LIST.SUB.EINGEWIESENE.NAME### +
    • + +
    • +
    • + +
    +
    + + + + + +

    Fahrzeug hinzufügen

    + + + + + + + + diff --git a/pgs/admin/admin.html b/pgs/admin/admin.html new file mode 100755 index 0000000..a11baca --- /dev/null +++ b/pgs/admin/admin.html @@ -0,0 +1,121 @@ + + + + + +
    +

    Passwort ändern

    +
    + + + + + + + + +
    Altes PW:
    Neues PW:
    PW wiederholen:
    + + +
    Passwort erfolgreich geändert!
    +
    +
    + + + +
    +

    Autorenschaft

    +
    + + + + + + + + + +
    AccountIm Board angezeigter Autor
    ###ADMIN.GSP.LINE.MAIL### + +
    + + +
    +
    +
    + + + +
    +

    Zu dieser Gästegruppe gehörende Accounts

    +
    + + + + + + + + + +
    AccountsBenachrichtigung zu Diskussionen
    ###ADMIN.ACC.LINE.MAIL### + +
    + + +
    +
    +
    + + + +
    +

    Zusätzlichen Account einrichten

    +
    + + + + + +
    eMail-Adresse:
    Passwort:
    + + +
    + Zusätzliche Accounts ermöglichen unterschiedliche Passwörter
    und zusätzliche eMail-Benachrichtigungen. +
    +
    +
    + + + +
    +

    Account-Liste

    +
    + + + + + + + + + +
    GruppeAccountAktionen
    ###ADMIN.LIST.GROUP.NAME### ###ADMIN.LIST.USER.EMAIL### + + +
    + +
    +
    + + + diff --git a/pgs/admin/index.php b/pgs/admin/index.php new file mode 100755 index 0000000..6835867 --- /dev/null +++ b/pgs/admin/index.php @@ -0,0 +1,144 @@ + tplExtrSection(tplLoadFile("pgs/admin/admin.html"), "###ADMIN###"), + "pwd" => "", + "gsp" => "", + "acc" => "", + "add" => "", + "list" => "" +); + +if ($userID = lgnCheckLogin($mysqli)) { + // Passwort ändern + $password_changed_success = false; + if (isset($input["userMod"], $input["secToken"], $input["passOld"], $input["passNew"], $input["passRepeat"]) + && $input["secToken"]==$_SESSION["secTokenVerify"] && $input["userMod"]=="Passwort ändern") + { + $password_changed_success = lgnChangePass($mysqli, $_SESSION["userID"], $input["passOld"], $input["passNew"], $input["passRepeat"]); + } else if (isset($input["addAccount"]) && $input["secToken"]==$_SESSION["secTokenVerify"]) { + if (strlen($input["admin_addacc_mail"])>4 && strpos($input["admin_addacc_mail"], "@") && strlen($input["admin_addacc_pass"])>11) { + $stmt = $mysqli->prepare("SELECT groupID, roleID FROM users WHERE ID = ?"); + $stmt->bind_param("i", $userID); + $stmt->execute(); + $stmt->bind_result($groupID, $roleID); + $stmt->fetch(); + $stmt->close(); + + $password = lgnTransformPassword($input["admin_addacc_pass"]); + if ($stmt = $mysqli->prepare("INSERT INTO users (groupID, roleID, email, iterations, salt, hash) VALUES (?, ?, ?, ?, ?, ?)")) { + $stmt->bind_param("iisiss", $groupID, $roleID, $input["admin_addacc_mail"], $password["iterations"], $password["salt"], $password["hash"]); + $stmt->execute(); + $stmt->close(); + } else { + addError("Mysql", $mysqli->error); + } + } else { + addError("wrongInput", "eMail-Adresse ordentlich? Passwort lang genug? 12 Zeichen mindestens. Besser länger als kompliziert."); + } + } else if (isset($input["chgAccount"]) && $input["secToken"]==$_SESSION["secTokenVerify"]) { + $res = $mysqli->query("SELECT groupID FROM users WHERE ID=".$userID); + $groupID = $res->fetch_assoc()["groupID"]; + foreach ($input["admin_acc"] as $ID => $val) { + $mysqli->query("UPDATE users SET notifications=".$val["notifications"]." WHERE ID=".$ID." AND groupID=".$groupID); + } + } + + $tpl["pwd"] = tplExtrSection($tpl["main"], "###ADMIN.PASSWORD###"); + $tpl["pwd"] = tplReplSection($tpl["pwd"], "###ADMIN.PASSWORD.SUCCESS###", $password_changed_success ? tplExtrSection($tpl["pwd"], "###ADMIN.PASSWORD.SUCCESS###") : ""); + + // Autorenschaft speichern + /*if (isset($input["chgAuthor"]) && $input["secToken"]==$_SESSION["secTokenVerify"] && $stmt = $mysqli->prepare("SELECT u.ID FROM users u WHERE u.groupID=(SELECT groupID FROM users WHERE ID = ?)")) { + $stmt->bind_param("i", $userID); + $stmt->execute(); + $stmt->bind_result($ID); + $array = array(); + while ($stmt->fetch()) { + $array[] = "UPDATE users SET guestID = ".($input["admin_gsp_authors"][$ID] ?? "NULL")." WHERE ID = ".$ID; + } + $stmt->close(); + foreach ($array as $update) { + $mysqli->query($update); + } + }*/ + + // Veraltet + $tpl["gsp"] = ""; + + // Accounts + $tpl["acc"] = tplExtrSection($tpl["main"], "###ADMIN.ACC###"); + $line_tpl = tplExtrSection($tpl["acc"], "###ADMIN.ACC.LINE###"); + $lines = ""; + + $qry = "SELECT u.ID, u.email, u.login, u.notifications FROM users u WHERE u.groupID=(SELECT groupID FROM users WHERE ID = ?)"; + if ($stmt = $mysqli->prepare($qry)) { + $stmt->bind_param("i", $userID); + $stmt->execute(); + $res = $stmt->get_result(); + while ($row = $res->fetch_assoc()) { + $replace = array( + "###ADMIN.ACC.LINE.ID###" => $row["ID"], + "###ADMIN.ACC.LINE.MAIL###" => $row["email"], + "###ADMIN.ACC.LINE.LOGIN###" => $row["login"], + "###ADMIN.ACC.NOTIFICATIONS.SELECTED.0###" => $row["notifications"]==0 ? "selected" : "", + "###ADMIN.ACC.NOTIFICATIONS.SELECTED.1###" => $row["notifications"]==1 ? "selected" : "", + "###ADMIN.ACC.NOTIFICATIONS.SELECTED.2###" => $row["notifications"]==2 ? "selected" : "" + ); + $lines.= tplReplMarkerArray($line_tpl, $replace); + } + $stmt->close(); + } + $tpl["acc"] = tplReplSection($tpl["acc"], "###ADMIN.ACC.LINE###", $lines); + + // Account hinzufügen + $tpl["add"] = tplExtrSection($tpl["main"], "###ADMIN.ADD###"); + + // Account-Liste + if (lgnCheckRight($mysqli, "INVITE_ADD")) { + $tpl["list"] = tplExtrSection($tpl["main"], "###ADMIN.LIST###"); + if (isset($input["admin_list_resendpw"], $input["admin_list_resendcheck"]) && $input["secToken"]==$_SESSION["secTokenVerify"] && $input["admin_list_resendpw"]==$input["admin_list_resendcheck"]) { + $pass = lgnTransformPassword(); + $pass_tpl = tplExtrSection(tplLoadFile("pgs/admin/mail.html"), "###SENDPASSWORD###"); + $text = tplReplMarker($pass_tpl, "###PASSWORD###", $pass["password"]); + $success = emlSendSingleMail($mysqli, $input["admin_list_resendpw"], "Neues Passwort", $text); + if ($success) { + if ($stmt = $mysqli->prepare("UPDATE users SET iterations = ?, salt = ?, hash = ?, lastaction = null WHERE ID = ?")) { + $stmt->bind_param("issi", $pass["iterations"], $pass["salt"], $pass["hash"], $input["admin_list_resendpw"]); + $stmt->execute(); + $stmt->close(); + } + addError("", "Passwort senden erfolgreich!"); + } else { + addError("", "Passwort senden fehlgeschlagen!"); + } + } + + $qry = "SELECT gr.name, u.groupID, u.ID, u.login, u.email, u.eMailFrom, u.notifications, u.lastaction FROM groups gr RIGHT JOIN users u ON u.groupID=gr.ID ORDER BY gr.name ASC, u.email ASC"; + $res = $mysqli->query($qry); + $line_tpl = tplExtrSection($tpl["list"], "###ADMIN.LIST.ACCOUNT###"); + $lines = ""; + while ($row = $res->fetch_assoc()) { + $replace = array( + "###ADMIN.LIST.GROUP.ID###" => $row["groupID"], + "###ADMIN.LIST.GROUP.NAME###" => $row["name"], + "###ADMIN.LIST.USER.ID###" => $row["ID"], + "###ADMIN.LIST.USER.EMAIL###" => $row["email"], + "###ADMIN.LIST.USER.LOGIN###" => $row["login"], + "###ADMIN.LIST.USER.NOTIFICATIONS###" => $row["notifications"] + ); + $line = tplReplMarkerArray($line_tpl, $replace); + $line = tplReplSection($line, "###ADMIN.LIST.USER.LOGGEDIN###", null!=$row["lastaction"] ? tplExtrSection($line_tpl, "###ADMIN.LIST.USER.LOGGEDIN###") : ""); + $lines.= $line; + } + $tpl["list"] = tplReplSection($tpl["list"], "###ADMIN.LIST.ACCOUNT###", $lines); + } +} + +$tpl["main"] = tplReplSection($tpl["main"], "###ADMIN.PASSWORD###", $tpl["pwd"]); +$tpl["main"] = tplReplSection($tpl["main"], "###ADMIN.GSP###", $tpl["gsp"]); +$tpl["main"] = tplReplSection($tpl["main"], "###ADMIN.ACC###", $tpl["acc"]); +$tpl["main"] = tplReplSection($tpl["main"], "###ADMIN.ADD###", $tpl["add"]); +$tpl["main"] = tplReplSection($tpl["main"], "###ADMIN.LIST###", $tpl["list"]); +$output["main"] = $tpl["main"]; + +?> \ No newline at end of file diff --git a/pgs/admin/mail.html b/pgs/admin/mail.html new file mode 100755 index 0000000..b8c93c6 --- /dev/null +++ b/pgs/admin/mail.html @@ -0,0 +1,13 @@ + + + +

    + ###ADDRESSING### ###NICKNAME###,

    + für diesen Account wurde ein neues Passwort für die Hochzeitswebsite von Sophia und Nils generiert:
    + ###PASSWORD###
    + Der Benutzername ist weiterhin die eMail-Adresse, an die diese Nachricht geht.
    + Das Passwort kann (und sollte) nach dem Einloggen unter "Einstellungen" geändert werden.
    + Viele Grüße,
    + Sophia & Nils +

    + diff --git a/pgs/blog/blog.css b/pgs/blog/blog.css new file mode 100755 index 0000000..d2234cf --- /dev/null +++ b/pgs/blog/blog.css @@ -0,0 +1,38 @@ +/* pgs/blog/blog.css */ + +#blog_new td { + padding: 0.5em; +} +#blog_new textarea { + width: calc(100% - 1em); + height: 20em; + font-size: inherit; + font-family: inherit; + padding: 0.5em; +} +#blog_new label { + width: 8em; + display: inline-block; +} +#blog_new input { + width: 100%; +} +#blog_new input[type="submit"] { + width: 49em; +} +#blog_new input[type="checkbox"] { + width: auto; +} + +.blog_entry { + padding: 0; + margin-bottom: 0.2em; + border: 1px solid #000000; +} +.blog_entry_header { + background-color: #fbc8b1; + padding: 0.2em; +} +.blog_entry_main { + padding: 0.4em; +} diff --git a/pgs/blog/blog.html b/pgs/blog/blog.html new file mode 100755 index 0000000..4b1c5e8 --- /dev/null +++ b/pgs/blog/blog.html @@ -0,0 +1,42 @@ + + + +
    +

    Bisherige Rundmails

    +

    Dies ist ein Archiv aller bisher versendeter Rundmails.

    + +
    +
    ###BLOG.ENTRY.AUTHOR###, ###BLOG.ENTRY.DATETIME###: ###BLOG.ENTRY.TITLE###
    +
    Vorsicht: Das Brautpaar selbst darf von dieser Nachricht nichts wissen!

    ###BLOG.ENTRY.TEXT###
    +
    + +
    + + +
    +

    Neue Rundmail verfassen

    +
    + + + + + + + + + + + +
    + + Brautpaar darf Nachricht erhalten und lesen
    + + +
    +
    +
    + + + \ No newline at end of file diff --git a/pgs/blog/index.php b/pgs/blog/index.php new file mode 100755 index 0000000..b086437 --- /dev/null +++ b/pgs/blog/index.php @@ -0,0 +1,105 @@ + tplExtrSection(tplLoadFile("pgs/blog/blog.html"), "BLOG"), + "entry" => "", + "new" => "" +); +addStyle("pgs/blog/blog.css"); + +if ($userID = lgnCheckLogin($mysqli)) { + // Eingabemaske für Blogeintrag + if (lgnCheckRight($mysqli, "BLOG_ADD", $userID)) { + // Neue Nachricht wurde verfasst? + if (isset($input["blog_new_submit"]) && ""!=$input["blog_new_text"] && ""!=$input["blog_new_title"] && $input["secToken"]==$_SESSION["secTokenVerify"]) { + // Autor überprüfen und gegebenenfalls überschreiben + $guestID = null; + $guestName = ""; + $qry = "SELECT g.ID,g.prenames,g.surnames FROM guests g LEFT JOIN users u ON u.groupID=g.groupID WHERE g.companion=0 AND u.ID = ? ORDER BY g.ID = ? DESC LIMIT 1"; + if ($stmt = $mysqli->prepare($qry)) { + $stmt->bind_param("ii", $userID, $input["boardnew_author"]); + $stmt->execute(); + $res = $stmt->get_result(); + if ($row = $res->fetch_assoc()) { + $guestID = $row["ID"]; + $guestName = $row["prenames"]." ".$row["surnames"]; + } + } + + // Datensatz einfügen + $insert = "INSERT INTO blog (guestID, rightID, dttm, title, text) VALUES (?, (SELECT r.ID FROM rights r WHERE name = ?), NOW(), ?, ?)"; + if ($stmt->prepare($insert)) { + $encTitle = cntCipherTextSym($input["blog_new_title"], SYM_CIPHER_KEY); + $encText = cntCipherTextSym($input["blog_new_text"], SYM_CIPHER_KEY); + $right = isset($input["blog_new_brautpaar"]) && $input["blog_new_brautpaar"]=="1" ? null : "HIDDEN_FROM_BRAUTPAAR"; + $stmt->bind_param("isss", $guestID, $right, $encTitle, $encText); + if ($stmt->execute()) { + $text = tplExtrSection(tplLoadFile("pgs/blog/mail.html"), "###MASSMAIL###"); + if ($right==null) { + $text = tplReplSection($text, "###NO_BRAUTPAAR_WARNING###", ""); + } else { + $text = tplReplSection($text, "###NO_BRAUTPAAR_WARNING###", tplExtrSection($text, "###NO_BRAUTPAAR_WARNING###")); + } + $text = tplReplMarker($text, "###TITLE###", $input["blog_new_title"]); + $text = tplReplMarker($text, "###MESSAGE###", str_replace("\\r\\n", "
    ", $input["blog_new_text"])); + $text = tplReplMarker($text, "###FROM###", $guestName); + emlSendMassmail($mysqli, $userID, $guestName, "Rundmail zur Hochzeit von Sophia und Nils", $text, $right); + } + } + } + + $tpl["new"] = tplExtrSection($tpl["main"], "###BLOG.NEW###"); + $tpl["author"] = tplExtrSection($tpl["new"], "###BLOG.NEW.AUTHOR###"); + $authors = ""; + $qry = "SELECT g.ID, g.prenames, g.surnames FROM guests g WHERE g.companion=0 AND g.groupID = (SELECT groupID FROM users WHERE ID = ".$userID.")"; + if ($res = $mysqli->query($qry)) { + while ($row = $res->fetch_assoc()) { + $author = tplReplMarker($tpl["author"], "###BLOG.NEW.AUTHOR.ID", $row["ID"]); + $author = tplReplMarker($author, "###BLOG.NEW.AUTHOR.NAME", $row["prenames"]." ".$row["surnames"]); + $authors.= $author; + } + } + $tpl["new"] = tplReplSection($tpl["new"], "###BLOG.NEW.AUTHOR###", $authors); + if (lgnCheckRight($mysqli, "HIDDEN_FROM_BRAUTPAAR", $userID)) { + $tpl["new"] = tplReplMarker($tpl["new"], "###BLOG.NEW.BRAUTPAAR.OPTIONS###", ""); + } else { + $tpl["new"] = tplReplMarker($tpl["new"], "###BLOG.NEW.BRAUTPAAR.OPTIONS###", "checked style='visibility: hidden;' "); + } + } + + // Blogeinträge auflisten + $tpl["entry"] = tplExtrSection($tpl["main"], "###BLOG.ENTRY###"); + $entries = ""; + $qry = "SELECT b.*, g.prenames, g.surnames FROM blog b LEFT JOIN guests g ON g.ID=b.guestID " + ."LEFT JOIN rolerights r ON r.rightID=b.rightID LEFT JOIN users u ON u.roleID=r.roleID " + ."WHERE b.rightID IS NULL OR u.ID=".$userID; + if ($res = $mysqli->query($qry)) { + while ($row = $res->fetch_assoc()) { + $replace = array( + "###BLOG.ENTRY.ID###" => $row["ID"], + "###BLOG.ENTRY.DATETIME###" => $row["dttm"], + "###BLOG.ENTRY.AUTHOR###" => $row["prenames"]." ".$row["surnames"], + "###BLOG.ENTRY.TITLE###" => cntCipherTextSym($row["title"], SYM_CIPHER_KEY), + "###BLOG.ENTRY.TEXT###" => str_replace("\\r\\n", "
    ", cntCipherTextSym($row["text"], SYM_CIPHER_KEY)) + ); + $entry = tplReplMarkerArray($tpl["entry"], $replace); + if ($row["rightID"]==null) { + $entry = tplReplSection($entry, "###NO_BRAUTPAAR_WARNING###", ""); + } else { + $entry = tplReplSection($entry, "###NO_BRAUTPAAR_WARNING###", tplExtrSection($entry, "###NO_BRAUTPAAR_WARNING###")); + } + + $entries.= $entry; + } + } else { + addError("Mysql", $mysqli->error." // Query: ".$qry); + } + $tpl["entry"] = $entries; +} + +$tpl["main"] = tplReplSection($tpl["main"], "###BLOG.ENTRY###", $tpl["entry"]); +$tpl["main"] = tplReplSection($tpl["main"], "###BLOG.NEW###", $tpl["new"]); +$output["main"] = $tpl["main"]; + +?> \ No newline at end of file diff --git a/pgs/blog/mail.html b/pgs/blog/mail.html new file mode 100755 index 0000000..4705fdb --- /dev/null +++ b/pgs/blog/mail.html @@ -0,0 +1,13 @@ + +

    + ###ADDRESSING### ###NICKNAME###,

    + folgende Rundmail wurde von ###FROM### über die Hochzeitswebsite von Sophia und Nils geschrieben: +
    Vorsicht: Das Brautpaar selbst darf von dieser Nachricht nichts wissen! +

    +
    +

    ###TITLE###

    +

    + ###MESSAGE### +

    +
    + diff --git a/pgs/board/board.css b/pgs/board/board.css new file mode 100755 index 0000000..6cfef2e --- /dev/null +++ b/pgs/board/board.css @@ -0,0 +1,71 @@ +/* pgs/board/board.css */ + +article { + border-top: 3px solid #000000; +} +article:first-of-type { + border-top: none; +} + +#boardnew td { + padding: 0.5em; +} +#boardnew textarea { + width: calc(100% - 1em); + height: 20em; + font-size: inherit; + font-family: inherit; + padding: 0.5em; +} +#boardnew label { + width: 8em; + display: inline-block; +} +#boardnew input { + width: 100%; +} +#boardnew input[type="submit"] { + width: 49em; +} + +.boardmsg { + padding: 0; + /*margin-bottom: 0.2em;*/ + border: 1px solid #000000; +} +.boardmsg_header { + background-color: #fbc8b1; + padding: 0.2em; +} +.boardmsg_main { + padding: 0.4em; +} +.boardmsg_footer { + padding: 0.2em; + /*text-align: right;*/ +} + +a.blocklink { + text-decoration: none; +} + +.boardmsg_indent { + border-left: 1px solid #fbc8b1; + margin-left: 1em; + padding-left: 1em; +} +.boardmsg_indent_first { + margin-left: 1em; +} +.boardmsg_indent_last { + padding-top: 0.2em; +} +.boardmsg_indent_helper { + height: 0.7em; + width: 1em; + float: left; + margin-left: -1em; +} +.boardmsg_indent_last .boardmsg_indent_helper { + border-bottom: 1px solid #fbc8b1; +} \ No newline at end of file diff --git a/pgs/board/categories.html b/pgs/board/categories.html new file mode 100755 index 0000000..41bbe59 --- /dev/null +++ b/pgs/board/categories.html @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/pgs/board/index.php b/pgs/board/index.php new file mode 100755 index 0000000..004a817 --- /dev/null +++ b/pgs/board/index.php @@ -0,0 +1,169 @@ +query($qry)) { + while ($row = $res->fetch_assoc()) { + $replace = array( + "###BOARDMSG.LEVEL###" => ($lvl < 10 ? $lvl : 9), + "###BOARDMSG.ID###" => $row["ID"], + "###BOARDMSG.DATETIME###" => $row["dttm"], + "###BOARDMSG.TITLE###" => $row["deleted"]==0 ? cntCipherTextSym($row["title"], SYM_CIPHER_KEY) : "", + "###BOARDMSG.TEXT###" => $row["deleted"]==0 ? str_replace("\\r\\n", "
    ", cntCipherTextSym($row["text"], SYM_CIPHER_KEY)) : "Nachricht wurde gelöscht" + ); + preg_match_all("/([\s-]?)([A-Z])/", $row["surnames"], $matches); + $replace["###BOARDMSG.AUTHOR###"] = $row["prenames"]." ".implode(".", $matches[0])."."; + $msg = tplReplMarkerArray($tpl, $replace); + + $indent_in_tpl = tplExtrSection($tpl, "###BOARDMSG.INDENT.IN###"); + $indent_out_tpl = tplExtrSection($tpl, "###BOARDMSG.INDENT.OUT###"); + $indent_in = ""; + $indent_out = ""; + for ($i = 0; $i<$lvl; $i++) { + $class = ""; + if ($i==0) { + $class.= " boardmsg_indent_first"; + } + if ($i==$lvl-1) { + $class.= " boardmsg_indent_last"; + } + $indent_in.= tplReplMarker($indent_in_tpl, "###BOARDMSG.INDENT.CLASS###", $class); + $indent_out.= $indent_out_tpl; + } + $msg = tplReplSection($msg, "###BOARDMSG.INDENT.IN###", $indent_in); + $msg = tplReplSection($msg, "###BOARDMSG.INDENT.OUT###", $indent_out); + + if ($row["deleted"]==1) { + $msg = tplReplSection($msg, "###BOARDMSG.FOOTER###", ""); + } elseif ($row["own"]=="0" && !lgnCheckRight($mysqli, "BOARD_DEL", $userID)) { + $msg = tplReplSection($msg, "###BOARDMSG.DEL###", ""); + } + $ret.= $msg.($recursive ? boardLoadThread($mysqli, $userID, $row["ID"], $tpl, $lvl+1) : ""); + } + } else { + addError("Mysql", $mysqli->error." // Query: ".$qry); + } + return $ret; +} +function boardCleanDeletedParents($mysqli, $ID) { + $res = $mysqli->query("SELECT parentID FROM board_messages m WHERE m.ID=".$ID." AND m.deleted=1 " + ." AND (SELECT COUNT(*) FROM board_messages ms WHERE ms.parentID=".$ID.")=0"); + if ($res->num_rows==1) { + $parentID = $res->fetch_assoc()["parentID"]; + $mysqli->query("DELETE FROM board_messages WHERE ID = ".$ID); + if ($parentID!=null) { + boardCleanDeletedParents($mysqli, $parentID); + } + } +} + +if (isset($input["boardnew_submit"], $input["secToken"]) && $input["secToken"]==$_SESSION["secTokenVerify"] && ($userID = lgnCheckLogin($mysqli))) { + // Einfügen neuer Nachricht + + // Kategorie herausfinden und testen ob erlaubt + $categoryID = null; + $parentID = null; + $rootID = null; + $replyto = isset($input["boardnew_replyto"]); + $qry = "SELECT c.ID " + .($replyto ? ", m.rootID FROM board_messages m LEFT JOIN board_categories c ON c.ID=m.categoryID " : "FROM board_categories c ") + ."LEFT JOIN rolerights r ON r.rightID=c.rightID " + ."LEFT JOIN users u ON u.roleID=r.roleID " + ."WHERE (c.rightID IS NULL OR u.ID = ?) AND ".($replyto ? "m.ID = ? " : "c.ID = ? "); + if ($stmt = $mysqli->prepare($qry)) { + $whereID = $replyto ? $input["boardnew_replyto"] : $input["boardnew_cat"]; + $stmt->bind_param("ii", $userID, $whereID); + $stmt->execute(); + $res = $stmt->get_result(); + if ($res->num_rows==0) { + addError("Access", "Kategorie nicht vorhanden oder Zugriff nicht erlaubt1"); + } else { + $cat = $res->fetch_assoc(); + $categoryID = $cat["ID"]; + if ($replyto) { + $parentID = $input["boardnew_replyto"]; + $rootID = $cat["rootID"] ?? $parentID; + } + } + } + + // Autor überprüfen und gegebenenfalls überschreiben + $guestID = null; + $qry = "SELECT g.ID FROM guests g LEFT JOIN users u ON u.groupID=g.groupID WHERE u.ID = ? AND g.companion=0 ORDER BY g.ID = ? DESC LIMIT 1"; + if ($stmt = $mysqli->prepare($qry)) { + $stmt->bind_param("ii", $userID, $input["boardnew_author"]); + $stmt->execute(); + $res = $stmt->get_result(); + if ($res->num_rows==0) { + addError("Access", "Kategorie nicht vorhanden oder Zugriff nicht erlaubt"); + } else { + $guestID = $res->fetch_assoc()["ID"]; + } + } + + // Datensatz einfügen. Wenn Kategorie verboten war, steht sie auf NULL und wird von der Datenbank abgelehnt + $insert = "INSERT INTO board_messages (guestID, categoryID, rootID, parentID, dttm, title, text) VALUES (?, ?, ?, ?, NOW(), ?, ?)"; + if ($stmt->prepare($insert)) { + $encTitle = cntCipherTextSym($input["boardnew_title"], SYM_CIPHER_KEY); + $encText = cntCipherTextSym($input["boardnew_text"], SYM_CIPHER_KEY); + $stmt->bind_param("iiiiss", $guestID, $categoryID, $rootID, $parentID, $encTitle, $encText); + if ($stmt->execute()) { + if (!$replyto) + $input["thread"] = $mysqli->insert_id; + + $neededRight = null; + $res = $mysqli->query("SELECT r.name FROM board_categories c LEFT JOIN rights r ON r.ID=c.rightID WHERE c.ID=".$categoryID); + if ($res->num_rows>0) + $neededRight = $res->fetch_assoc()["name"]; + + $text = tplExtrSection(tplLoadFile("pgs/board/notify.txt"), "###NOTIFICATION###"); + $text = tplReplMarker($text, "###PAGEMAIN###", $page["main"]); + $url = parse_url("https://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']); + $text = tplReplMarker($text, "###PAGEURL###", "https://".$url["host"].$url["path"]); + $text = tplReplMarker($text, "###THREADID###", $input["thread"]); + emlSendNotification($mysqli, $userID, "Neuer Beitrag unter Diskussion", $text, $replyto ? 2 : 1, $neededRight); + } + } +} elseif (isset($input["del"]) && ($userID = lgnCheckLogin($mysqli))) { + $qry = "SELECT m.ID, m.rootID, m.parentID, g.groupID=u.groupID own, (SELECT COUNT(*) FROM board_messages ms WHERE ms.parentID=m.ID) children " + ."FROM board_messages m LEFT JOIN guests g ON g.ID=m.guestID LEFT JOIN users u ON u.ID = ? WHERE m.ID = ?"; + if ($stmt = $mysqli->prepare($qry)) { + $stmt->bind_param("ii", $userID, $input["del"]); + $stmt->execute(); + $res = $stmt->get_result(); + if ($row = $res->fetch_assoc()) { + $input["thread"] = $row["rootID"] ?? $row["ID"]; + + // Darf löschen? + if ($row["own"]==1 || lgnCheckRight($mysqli, "BOARD_DEL", $userID)) { + // Wenn Antworten auf diese Nachricht existieren, nur als gelöscht markieren + if ($row["children"]>0) { + $mysqli->query("UPDATE board_messages SET deleted=1 WHERE ID = ".$row["ID"]); + } else { + $mysqli->query("DELETE FROM board_messages WHERE ID = ".$row["ID"]); + if ($row["parentID"]!=null) { + boardCleanDeletedParents($mysqli, $row["parentID"]); + } + } + if ($row["rootID"]==null) { + $page["sub"] = "main"; + } + } + } + } +} + +addStyle("pgs/board/board.css"); +$tpl = array( + "main" => "" +); +if ($sub = pgsInclSub($page["sub"])) + include $sub; + +$output["main"] = $tpl["main"]; + +?> \ No newline at end of file diff --git a/pgs/board/main.php b/pgs/board/main.php new file mode 100755 index 0000000..8b7396c --- /dev/null +++ b/pgs/board/main.php @@ -0,0 +1,74 @@ +prepare($qry)) { + $stmt->bind_param("i", $userID); + $stmt->execute(); + $catres = $stmt->get_result(); + while ($catrow = $catres->fetch_assoc()) { + $replace = array( + "###BOARDCATS.CAT.ID###" => $catrow["ID"], + "###BOARDCATS.CAT.NAME###" => $catrow["name"], + "###BOARDCATS.CAT.DESC###" => $catrow["description"] + ); + $cat = tplReplMarkerArray($tpl["cat"], $replace); + $threads = ""; + + $qry = "SELECT m.ID, m.dttm, m.title, m.text, g.prenames, g.surnames, " + ."(SELECT COUNT(*) FROM board_messages ms WHERE ms.rootID=m.ID) replies " + ."FROM board_messages m LEFT JOIN guests g ON g.ID = m.guestID " + ."WHERE m.parentID IS NULL AND m.categoryID = ".$catrow["ID"]." " + ."ORDER BY m.dttm DESC"; + if ($thrres = $mysqli->query($qry)) { + if ($thrres->num_rows==0) { + $threads = $tpl["nothreads"]; + } else { + while ($thrrow = $thrres->fetch_assoc()) { + $thread = tplReplMarker($tpl["thread"], "###BOARDCATS.CAT.THREAD.MSG###", tplExtrSection(tplLoadFile("pgs/board/msg.html"), "###BOARDMSG###")); + $thread = tplReplSection($thread, "###BOARDMSG.FOOTER###", ""); + $thread = tplReplSection($thread, "###BOARDMSG.INDENT.IN###", ""); + $thread = tplReplSection($thread, "###BOARDMSG.INDENT.OUT###", ""); + preg_match_all("/([\s-]?)([A-Z])/", $thrrow["surnames"], $matches); + $replace = array( + "###BOARDMSG.ID###" => $thrrow["ID"], + "###BOARDMSG.TITLE###" => cntCipherTextSym($thrrow["title"], SYM_CIPHER_KEY), + "###BOARDMSG.AUTHOR###" => $thrrow["prenames"]." ".implode(".", $matches[0]).".", + "###BOARDMSG.DATETIME###" => $thrrow["dttm"], + "###BOARDMSG.LEVEL###" => 0 + ); + $decText = cntCipherTextSym($thrrow["text"], SYM_CIPHER_KEY); + if (strlen($decText)>33) { + $replace["###BOARDMSG.TEXT###"] = substr($decText, 0, 30)."...
    ".$thrrow["replies"]." Antwort".($thrrow["replies"]!="1" ? "en" : "").""; + } else { + $replace["###BOARDMSG.TEXT###"] = $decText."
    ".$thrrow["replies"]." Antwort".($thrrow["replies"]!="1" ? "en" : "").""; + } + $threads.= tplReplMarkerArray($thread, $replace); + } + } + } else { + addError("Mysql", $mysqli->error); + } + $cat = tplReplSection($cat, "###BOARDCATS.CAT.NOTHREADS###", ""); + $cats.= tplReplSection($cat, "###BOARDCATS.CAT.THREAD###", $threads); + } + $stmt->close(); + $tpl["cat"] = $cats; + } +} +$tpl["main"] = tplReplSection($tpl["main"], "###BOARDCATS.CAT###", $tpl["cat"]); + +?> diff --git a/pgs/board/msg.html b/pgs/board/msg.html new file mode 100755 index 0000000..5b25549 --- /dev/null +++ b/pgs/board/msg.html @@ -0,0 +1,22 @@ + + + + +
    + +
    + +
    ###BOARDMSG.AUTHOR###, ###BOARDMSG.DATETIME###: ###BOARDMSG.TITLE###
    + + +
    ###BOARDMSG.TEXT###
    + + + + +
    +
    + diff --git a/pgs/board/new.html b/pgs/board/new.html new file mode 100755 index 0000000..52a991e --- /dev/null +++ b/pgs/board/new.html @@ -0,0 +1,43 @@ + + + + + diff --git a/pgs/board/new.php b/pgs/board/new.php new file mode 100755 index 0000000..2f8b1a3 --- /dev/null +++ b/pgs/board/new.php @@ -0,0 +1,77 @@ +prepare($qry)) { + $whereID = $replyto ? $input["replyto"] : $input["cat"]; + $stmt->bind_param("ii", $userID, $whereID); + $stmt->execute(); + $catres = $stmt->get_result(); + if ($catres->num_rows==0) { + addError("Access", "Kategorie nicht vorhanden oder Zugriff nicht erlaubt"); + } else { + $cat = $catres->fetch_assoc(); + $replace = array( + "###BOARDNEW.CAT.ID###" => $cat["ID"], + "###BOARDNEW.CAT.NAME###" => $cat["name"], + "###BOARDNEW.CAT.DESC###" => $cat["description"], + "###BOARDNEW.REPLYTO.ID###" => $cat["mID"] ?? "created", + "###BOARDNEW.REPLYTO.ROOTID###" => $cat["rootID"] ?? ($cat["mID"] ?? "error"), + "###BOARDMSG.DATETIME###" => $cat["dttm"] ?? "", + "###BOARDMSG.TITLE###" => cntCipherTextSym($cat["title"] ?? "", SYM_CIPHER_KEY), + "###BOARDMSG.TEXT###" => str_replace("\\r\\n", "
    ", cntCipherTextSym($cat["text"] ?? "", SYM_CIPHER_KEY)) + ); + if ($replyto) { + $tpl["new"] = tplReplSection($tpl["new"], "###BOARDNEW.START###", ""); + preg_match_all("/([\s-]?)([A-Z])/", $cat["surnames"], $matches); + $replace["###BOARDMSG.AUTHOR###"] = $cat["prenames"]." ".implode(".", $matches[0])."."; + $tpl["msg"] = tplExtrSection(tplLoadFile("pgs/board/msg.html"), "###BOARDMSG###"); + $tpl["msg"] = tplReplSection($tpl["msg"], "###BOARDMSG.FOOTER###", ""); + $tpl["msg"] = tplReplSection($tpl["msg"], "###BOARDMSG.INDENT.IN###", ""); + $tpl["msg"] = tplReplSection($tpl["msg"], "###BOARDMSG.INDENT.OUT###", ""); + $tpl["new"] = tplReplMarker($tpl["new"], "###BOARDNEW.REPLYTO.PRINT###", $tpl["msg"]); + } else { + $tpl["new"] = tplReplSection($tpl["new"], "###BOARDNEW.REPLYTO###", ""); + $tpl["new"] = tplReplSection($tpl["new"], "###BOARDNEW.BACKTOTHREAD###", ""); + } + $tpl["new"] = tplReplMarkerArray($tpl["new"], $replace); + + $tpl["author"] = tplExtrSection($tpl["new"], "###BOARDNEW.AUTHOR###"); + $authors = ""; + $qry = "SELECT g.ID, g.prenames, g.surnames FROM guests g WHERE g.companion=0 AND g.groupID = (SELECT groupID FROM users WHERE ID = ?)"; + if ($stmt = $mysqli->prepare($qry)) { + $stmt->bind_param("i", $userID); + $stmt->execute(); + $res = $stmt->get_result(); + while ($row = $res->fetch_assoc()) { + preg_match_all("/([\s-]?)([A-Z])/", $row["surnames"], $matches); + $author = tplReplMarker($tpl["author"], "###BOARDNEW.AUTHOR.ID", $row["ID"]); + $author = tplReplMarker($author, "###BOARDNEW.AUTHOR.NAME", $row["prenames"]." ".implode(".", $matches[0])."."); + $authors.= $author; + } + } + $stmt->close(); + $tpl["new"] = tplReplSection($tpl["new"], "###BOARDNEW.AUTHOR###", $authors); + } + } else { + addError("Mysql", $mysqli->error); + } +} +$tpl["main"] = $tpl["new"]; + +?> diff --git a/pgs/board/notify.txt b/pgs/board/notify.txt new file mode 100755 index 0000000..92e61ec --- /dev/null +++ b/pgs/board/notify.txt @@ -0,0 +1,12 @@ + +###ADDRESSING### ###NICKNAME###, + +auf der Hochzeitswebsite von Sophia und Nils wurde unter Diskussionen ein neuer Beitrag geschrieben. +Diesen findest du hier: +###PAGEURL###?main=###PAGEMAIN###&sub=thread&thread=###THREADID### + +Benachrichtigungen dieser Art können unter "Einstellungen" eingeschränkt oder deaktiviert werden. +Bitte nicht auf diese Nachricht antworten, dieses Postfach wird nicht gelesen. + +Viele Grüße wünscht der Mailroboter von Sophia und Nils! + diff --git a/pgs/board/thread.html b/pgs/board/thread.html new file mode 100755 index 0000000..a9052d9 --- /dev/null +++ b/pgs/board/thread.html @@ -0,0 +1,10 @@ + + + + + diff --git a/pgs/board/thread.php b/pgs/board/thread.php new file mode 100755 index 0000000..31b4cb2 --- /dev/null +++ b/pgs/board/thread.php @@ -0,0 +1,41 @@ +prepare($qry)) { + $stmt->bind_param("ii", $userID, $input["thread"]); + $stmt->execute(); + $catres = $stmt->get_result(); + if ($catres->num_rows==0) { + addError("Access", "Kategorie nicht vorhanden oder Zugriff nicht erlaubt3"); + } else { + $cat = $catres->fetch_assoc(); + $replace = array( + "###BOARDTHR.CAT.ID###" => $cat["ID"], + "###BOARDTHR.CAT.NAME###" => $cat["name"], + "###BOARDTHR.CAT.DESC###" => $cat["description"] + ); + $tpl["thr"] = tplReplMarkerArray($tpl["thr"], $replace); + $tpl["msg"] = tplExtrSection(tplLoadFile("pgs/board/msg.html"), "###BOARDMSG###"); + + $rootID = $cat["rootID"] ?? $cat["mID"]; + $tpl["thr"] = tplReplMarker($tpl["thr"], "###BOARDTHR.MSGS###", boardLoadThread($mysqli, $userID, $rootID, $tpl["msg"])); + } + } else { + addError("Mysql", $mysqli->error); + } +} +$tpl["main"] = $tpl["thr"]; + +?> diff --git a/pgs/dienste/index.php b/pgs/dienste/index.php deleted file mode 100644 index dcb6fd5..0000000 --- a/pgs/dienste/index.php +++ /dev/null @@ -1,362 +0,0 @@ - tplExtrSection(tplLoadFile("pgs/dienste/main.html"), "DIENSTE"), - "show" => "", - "list" => "" -); - -//die("Wartung"); - -addStyle("pgs/dienste/main.css"); - -// Anleitung zeigen -$tpl["show"] = tplExtrSection($tpl["main"], "###DIENSTE.SHOW###"); - -if ($userID = lgnCheckLogin($mysqli)) { - // Abteilungen und Gruppen abrufen - $res = $mysqli->query("SELECT l.Abteilungen, a.Name FROM link_Abteilungen_Personal l LEFT JOIN Abteilungen a ON a.ID=l.Abteilungen WHERE l.Personal='".$userID."'"); - $abteilungen = array(); - $abteilungenIDs = array(); - while ($row = $res->fetch_assoc()) { - $abteilungen[] = $row["Name"]; - $abteilungenIDs[] = $row["Abteilungen"]; - } - $res = $mysqli->query("SELECT l.Personalgruppen, p.Name FROM link_Personal_Personalgruppen l LEFT JOIN Personalgruppen p ON p.ID=l.Personalgruppen WHERE l.Personal='".$userID."'"); - $gruppenIDs = array(null); - while ($row = $res->fetch_assoc()) { - $gruppen[] = $row["Name"]; - $gruppenIDs[] = $row["Personalgruppen"]; - } - - // Terminaktion abarbeiten - $confirm = ""; - if (isset($input["termin"], $input["action"], $input["secToken"]) && $input["secToken"]==$_SESSION["secTokenVerify"]) { - $qry = "SELECT t.ID tID, t.Beginn, t.Ausgelost, IF(t.Beginn=1) num, " - ."(SELECT Status FROM Terminteilnahmen tln WHERE Termin=t.ID AND Personal = ?) Status " - .", (SELECT COUNT(*) FROM Terminteilnahmen t4 LEFT JOIN Termine t5 ON t5.ID=t4.Termin " - ." WHERE t4.Personal=? AND t5.ID!=t.ID AND t5.Terminart=t.Terminart " - ." AND t5.Beginn BETWEEN t.Beginn - INTERVAL 7 DAY AND t.Beginn + INTERVAL 7 DAY) naheDienste " - ."FROM Termine t " - ."LEFT JOIN Dienstpläne d ON d.ID=t.Dienstplan " - ."LEFT JOIN Terminplatzvergabe tpv ON tpv.ID=t.Platzvergabe " - ."LEFT JOIN Terminarten ta ON ta.ID = t.Terminart " - ."LEFT JOIN Berechtigungen b ON ta.Verwaltungsrecht = b.ID " - ."WHERE t.ID = ?"; - if ($stmt = $mysqli->prepare($qry)) { - $stmt->bind_param("iii", $userID, $userID, $input["termin"]); - $stmt->execute(); - $row = $stmt->get_result()->fetch_assoc(); - $stmt->close(); - - // Mögliche Rechte zum Bearbeiten - $possiblePrivileges = array("DARF_DIENSTE_VERWALTEN"); - if (null!==$row["privName"]) { - $possiblePrivileges[] = $row["privName"]; - } - // Unprivilegierte Aktionen - if ("join"==$input["action"] && "0"==$row["vorbei"] && - ((in_array($row["Abteilung"], $abteilungenIDs) && in_array($row["Personalgruppe"], $gruppenIDs) && intVal($row["naheDienste"])==0) || lgnCheckRight($mysqli, $possiblePrivileges, $userID))) { - // Möchte beitreten - if ($row["Ausgelost"]=="1" && (intVal($row["num"])query("REPLACE INTO Terminteilnahmen (Termin, Personal, Status) VALUES ('".$row["tID"]."', '".$userID."', 1)"); - informParticipantFromID($mysqli, $row["tID"], $userID, true); - markOrSendParticipantsList($mysqli, $row["tID"]); - } else { - $mysqli->query("REPLACE INTO Terminteilnahmen (Termin, Personal, Status) VALUES ('".$row["tID"]."', '".$userID."', 0)"); - } - } else if ("leave"==$input["action"] && "0"==$row["vorbei"]) { - // Möchte verlassen - $mysqli->query("DELETE FROM Terminteilnahmen WHERE Termin = ".$row["tID"]." AND Personal = ".$userID); - if (1==$mysqli->affected_rows && "1"==$row["Ausgelost"]) { - markOrSendParticipantsList($mysqli, $row["tID"]); - } - } else if (lgnCheckRight($mysqli, $possiblePrivileges) || "2"==$row["Status"]) { - // Privilegierte Aktionen - - if ("remove"==$input["action"]) { - // Teilnehmer soll entfernt werden - if (isset($input["target"], $input["confirm"])) { - // Entferne Teilnehmer - $qry = "DELETE FROM Terminteilnahmen WHERE Termin = ? AND Personal = ?"; - if ($stmt = $mysqli->prepare($qry)) { - $stmt->bind_param("ii", $row["tID"], $input["target"]); - $stmt->execute(); - if (1==$stmt->affected_rows && "1"==$row["Ausgelost"]) { - informParticipantFromID($mysqli, $row["tID"], $input["target"], false); - markOrSendParticipantsList($mysqli, $row["tID"]); - } - } - } - } else if ("add"==$input["action"] && isset($input["target"], $input["stage"], $input["confirm"])) { - // Teilnehmer soll hinzugefügt werden - $qry = "REPLACE INTO Terminteilnahmen VALUES (?, ?, ?)"; - if ($stmt = $mysqli->prepare($qry)) { - $stmt->bind_param("iii", $row["tID"], $input["target"], $input["stage"]); - $stmt->execute(); - if (1==$stmt->affected_rows && "1"==$row["Ausgelost"]) { - informParticipantFromID($mysqli, $row["tID"], $input["target"], true); - markOrSendParticipantsList($mysqli, $row["tID"]); - } - } - } - if (("edit"==$input["action"] || "add"==$input["action"]) && (!isset($input["confirm"]) || "addmore"==$input["confirm"])) { - // Bestätigung abfragen - $addqry = "SELECT p.ID,Vornamen,Nachnamen,tln.Status FROM Personal p LEFT JOIN Terminteilnahmen tln ON tln.Personal=p.ID AND tln.Termin = ".$row["tID"]." "; - if (isset($input["target"]) && !isset($input["confirm"])) { - $addqry.= "WHERE p.ID = ? "; - $confirm = "Teilnahmestatus des Kameraden ändern zu?
    "; - } else { - $confirm = "Kameraden zum Termin hinzufügen?
    "; - } - $addqry.= "ORDER BY Nachnamen ASC, Vornamen ASC"; - if ($stmt = $mysqli->prepare($addqry)) { - if (isset($input["target"]) && !isset($input["confirm"])) { - $stmt->bind_param("i", $input["target"]); - } - $stmt->execute(); - $addres = $stmt->get_result(); - //$stmt->close(); - $confirm.= "

    " - .("add"==$input["action"] - ? "" - : " Entfernen
    ") - ."
    " - ."
    " - .("add"==$input["action"] ? "" : "") - ."
    "; - } else { - addError("Mysql", $mysqli->error); - } - } - - } // /Privilegierte Aktionen - } // /Termin existiert - // TODO: Corona-Unterweisung - // INSERT IGNORE INTO link_Ausbildungen_Personal SELECT DISTINCT 9, Personal FROM Terminteilnahmen t WHERE Status=1 - } // /Terminaktion - - // Termine auflisten und Anmeldestatus anzeigen - $tpl["list"] = tplExtrSection($tpl["main"], "###DIENSTE.LIST###"); - - // Bestätigungen anzeigen oder verstecken - if ($confirm!="") { - $confirm_tpl = tplExtrSection($tpl["list"], "###DIENSTE.LIST.CONFIRM###"); - $confirm = tplReplMarker($confirm_tpl, "###DIENSTE.LIST.CONFIRM.TEXT###", $confirm); - } - $tpl["list"] = tplReplSection($tpl["list"], "###DIENSTE.LIST.CONFIRM###", $confirm); - - $monthsback = $input["monthsback"] ?? 0; - $tpl["list"] = tplReplMarker($tpl["list"], "###DIENSTE.LIST.DEPARTMENTS###", implode(", ", $abteilungen)); - $tpl["list"] = tplReplMarker($tpl["list"], "###DIENSTE.LIST.GROUPS###", implode(", ", $gruppen)); - $tpl["list"] = tplReplMarker($tpl["list"], "###DIENSTE.LIST.NEWMONTHSBACK###", $monthsback+2); - - $dnst_list_entry_tpl = tplExtrSection($tpl["list"], "###DIENSTE.LIST.ENTRY###"); - $dnst_list_entry = ""; - $qry = "SELECT t.ID, t.Beginn, t.Ende, t.Ort, t.Thema, t.Verantwortliche, t.Ausgelost, t.Personalgruppe, IF(t.Beginn=1) numDabei " - .", (SELECT COUNT(*) FROM Terminteilnahmen t3 WHERE t3.Termin=t.ID AND t3.Status=0) numWill " - .", (SELECT COUNT(*) FROM Terminteilnahmen t4 LEFT JOIN Termine t5 ON t5.ID=t4.Termin " - ." WHERE t4.Personal=? AND t5.ID!=t.ID AND t5.Terminart=t.Terminart " - ." AND t5.Beginn BETWEEN t.Beginn - INTERVAL 7 DAY AND t.Beginn + INTERVAL 7 DAY) naheDienste " - ."FROM Termine t " - ."LEFT JOIN Terminplatzvergabe pv ON pv.ID=t.Platzvergabe " - ."LEFT JOIN Terminarten ta ON ta.ID=t.Terminart " - ."LEFT JOIN Berechtigungen b ON b.ID=ta.Verwaltungsrecht " - ."LEFT JOIN Dienstpläne d ON d.ID=t.Dienstplan " - ."LEFT JOIN Abteilungen ab ON ab.ID=d.Abteilung " - ."LEFT JOIN Personalgruppen pg ON pg.ID=t.Personalgruppe " - ."LEFT JOIN Terminteilnahmen tln ON t.ID=tln.Termin AND tln.Personal = ? " - ."WHERE t.Ende > NOW() - INTERVAL ? MONTH " - ."ORDER BY t.Beginn ASC "; - if ($stmt = $mysqli->prepare($qry)) { - $stmt->bind_param("iii", $userID, $userID, $monthsback); - $stmt->execute(); - $res = $stmt->get_result(); - while ($row = $res->fetch_assoc()) { - $entry = $dnst_list_entry_tpl; - $restrictions = $row["MaxTeilnehmer"]!==null && $row["MaxTeilnehmer"]>0 ? "Auf ".$row["MaxTeilnehmer"]." Plätze begrenzt!" : "Keine Platzbegrenzung."; - $terminPrivileges = $row["privName"]!==null ? array("DARF_DIENSTE_VERWALTEN", $row["privName"]) : "DARF_DIENSTE_VERWALTEN"; - $replace = array( - "###DIENSTE.LIST.ENTRY.ID###" => $row["ID"], - "###DIENSTE.LIST.ENTRY.BEGIN###" => $row["Beginn"], - "###DIENSTE.LIST.ENTRY.BEGIN.DATE###" => strftime("%a, %d.%m.%Y", strtotime($row["Beginn"])), - "###DIENSTE.LIST.ENTRY.BEGIN.TIME###" => strftime("%H:%M", strtotime($row["Beginn"])), - "###DIENSTE.LIST.ENTRY.END###" => $row["Ende"], - "###DIENSTE.LIST.ENTRY.END.DATE###" => strftime("%d.%m.%Y", strtotime($row["Ende"])), - "###DIENSTE.LIST.ENTRY.END.TIME###" => strftime("%H:%M", strtotime($row["Ende"])), - "###DIENSTE.LIST.ENTRY.TYPE###" => $row["taName"], - "###DIENSTE.LIST.ENTRY.DEPARTMENT###" => $row["abName"], - "###DIENSTE.LIST.ENTRY.TOPIC###" => $row["Thema"], - "###DIENSTE.LIST.ENTRY.RESTRICTIONS###" => $restrictions - ); - - if ((in_array($row["abID"], $abteilungenIDs) && in_array($row["Personalgruppe"], $gruppenIDs)) || lgnCheckRight($mysqli, $terminPrivileges)) { - $linkJoin = "
  • ###NAME###
  • "; - $linkLeave = "
  • ###NAME###
  • "; - if (intVal($row["naheDienste"])>0) { - $replace["###DIENSTE.LIST.ENTRY.ALLOWED###"] = ""; - } else { - $replace["###DIENSTE.LIST.ENTRY.ALLOWED###"] = ""; - } - $replace["###DIENSTE.LIST.ENTRY.ACTION###"] = ""; - $replace["###DIENSTE.LIST.ENTRY.ACTIONNAME###"] = ""; - if ($row["vorbei"]=="0" && $row["Ausgelost"]=="0") { - // Noch nicht ausgelost - if ("1"==$row["Status"] || "2"==$row["Status"]) { - // Abmeldung - $replace["###DIENSTE.LIST.ENTRY.ACTION###"] = tplReplMarker($linkLeave, "###NAME###", "Abmelden"); - } else if (intVal($row["naheDienste"])==0 || lgnCheckRight($mysqli, $terminPrivileges)) { - // Anmeldung - $replace["###DIENSTE.LIST.ENTRY.ACTION###"] = tplReplMarker($linkJoin, "###NAME###", "Anmelden"); - } - } else if ($row["vorbei"]=="0") { - // Auslosung bereits geschehen, Dienst aber noch nicht gestartet - if ("1"==$row["Status"] || "2"==$row["Status"]) { - // Dabei: Abmeldung möglich - $replace["###DIENSTE.LIST.ENTRY.ACTION###"] = tplReplMarker($linkLeave, "###NAME###", "Abmelden"); - } else if (("0"==$row["MaxTeilnehmer"] || $row["numDabei"]<$row["MaxTeilnehmer"]) && (intVal($row["naheDienste"])==0 || lgnCheckRight($mysqli, $terminPrivileges))) { - // Nicht dabei und Plätze frei: Mitmachen möglich - $replace["###DIENSTE.LIST.ENTRY.ACTION###"] = tplReplMarker($linkJoin, "###NAME###", "Mitmachen"); - } else if ($row["Status"]==null && (intVal($row["naheDienste"])==0 || lgnCheckRight($mysqli, $terminPrivileges))) { - // Nicht auf Warteliste und keine Plätze frei: Warteliste möglich - $replace["###DIENSTE.LIST.ENTRY.ACTION###"] = tplReplMarker($linkJoin, "###NAME###", "Warteliste eintragen"); - } - } - } else { - $reason = in_array($row["abID"], $abteilungenIDs) ? "Kein Mitglied der Gruppe: ".$row["pgName"] : "Falsche Abteilung: ".$row["abName"]; - $replace["###DIENSTE.LIST.ENTRY.ALLOWED###"] = ""; - $replace["###DIENSTE.LIST.ENTRY.ACTION###"] = ""; - } - if ("2" == $row["Status"] || lgnCheckRight($mysqli, $terminPrivileges)) { - $replace["###DIENSTE.LIST.ENTRY.ACTION###"].= "" - ."
  • Teilnehmer hinzufügen
  • "; - } - // Kandidatenliste - $cqry = "SELECT p.*,GROUP_CONCAT(a.Kürzel) ausb, tln.Status " - ."FROM Terminteilnahmen tln " - ."LEFT JOIN Personal p ON p.ID=tln.Personal " - ."LEFT JOIN link_Ausbildungen_Personal l ON l.Personal=p.ID LEFT JOIN Ausbildungen a ON a.ID=l.Ausbildungen " - ."WHERE tln.Termin = '".$row["ID"]."' GROUP BY p.ID ORDER BY tln.Status DESC, p.Pool DESC, p.Nachnamen ASC, a.ID ASC"; - $cres = $mysqli->query($cqry); - $chosen = array(); - $want = array(); - $responsibles = array(); - if ($cres) { - while ($cand = $cres->fetch_assoc()) { - $name = substr($cand["Vornamen"],0,1).". ".$cand["Nachnamen"]; - $line = $name; - $ausb = explode(",", $cand["ausb"]); - $feats = ""; - if (in_array("KF", $ausb)) { //Kraftfahrer - //$feats.= "🚒"; // <- There is a unicode fire engine in between the quotes - $feats.= ""; - } - /*if (in_array("CU", $ausb)) { //Corono Unterweisung - $feats.= "☣️"; // <- There is a unicode biohazard symbol in between the quotes - }*/ - if ($feats != "") { - $line.= " "./*"(".*/$feats/*.")"*/; - } - - $line = "
  • ".$line."
  • "; - switch ($cand["Status"]) { - case "2": - $responsibles[] = $name; - $chosen[] = "".$line.""; - break; - case "1": - $chosen[] = $line; - break; - case "0": - $want[] = $line; - break; - } - } - $cres->close(); - } else { - addError("mysql", $mysqli->error); - } - $replace["###DIENSTE.LIST.ENTRY.RESPONSIBLES###"] = implode(" / ", $responsibles); - $candidates = ""; - if (lgnCheckRight($mysqli, $terminPrivileges) || 2 == $row["Status"]) { - $candidates = tplExtrSection($entry, "###DIENSTE.LIST.ENTRY.CANDIDATES###"); - if (count($want)>0) { - $candidates = tplReplMarker($candidates, "###DIENSTE.LIST.ENTRY.CANDIDATES.WANT###", implode("", $want)); - } else { - $candidates = tplReplSection($candidates, "###DIENSTE.LIST.ENTRY.CANDIDATES.HASJOIN###", ""); - } - if (count($chosen)>0) { - $candidates = tplReplMarker($candidates, "###DIENSTE.LIST.ENTRY.CANDIDATES.CHOSEN###", implode("", $chosen)); - } else { - $candidates = tplReplSection($candidates, "###DIENSTE.LIST.ENTRY.CANDIDATES.HASREST###", ""); - } - } - $entry = tplReplSection($entry, "###DIENSTE.LIST.ENTRY.CANDIDATES###", $candidates); - - //Anmeldung - if ((!in_array($row["abID"], $abteilungenIDs) || !in_array($row["Personalgruppe"], $gruppenIDs)) && !lgnCheckRight($mysqli, $terminPrivileges)) { - // Keine Anmeldung zugelassen, da falsche Gruppe - $answer = "FOREIGN"; - $entry = tplReplSection($entry, "###DIENSTE.LIST.ENTRY.REGISTRATION###", ""); - } else if ($row["MaxTeilnehmer"]===null) { - // Es gibt gar keine Anmeldung, der Dienst ist für alle offen - $entry = tplReplSection($entry, "###DIENSTE.LIST.ENTRY.CANDIDATES.HASREST###", ""); - $entry = tplReplSection($entry, "###DIENSTE.LIST.ENTRY.CANDIDATES.HASJOIN###", ""); - $entry = tplReplSection($entry, "###DIENSTE.LIST.ENTRY.REGISTRATION###", ""); - $answer = "NOLOTTERY"; - } else { - // Anmeldung ist möglich bzw. erwünscht - if ($row["MaxTeilnehmer"]=="0") { - // Gibt aber keine Beschränkung, daher Warteliste ausblenden - $entry = tplReplSection($entry, "###DIENSTE.LIST.ENTRY.CANDIDATES.HASJOIN###", ""); - } - $freePlaces = intVal($row["MaxTeilnehmer"]) - intVal($row["numDabei"]); - if ("1"==$row["Ausgelost"] && $freePlaces>0) { - $entry = tplReplMarker($entry, "###DIENSTE.LIST.ENTRY.FREE.NUM###", $freePlaces); - } else { - $entry = tplReplSection($entry, "###DIENSTE.LIST.ENTRY.FREE###", ""); - } - - if (2 == $row["Status"]) { - $answer = "LEAD"; - } else if (1 === $row["Status"] || (0 === $row["Status"] && 0 === $row["MaxTeilnehmer"])) { - // TODO: Teilnehmer bei Diensten ohne Begrenzung auf Dabei setzen, nicht auf Will - $answer = "CAN"; - } else if (0 === $row["Status"] && 1 === $row["Ausgelost"]) { - $answer = "WAIT"; - } else if (0 === $row["Status"] && 0 === $row["Ausgelost"]) { - $answer = "WANTS"; - } else { - $answer = "ADD"; - } - } - $entry = tplReplSection($entry, "###DIENSTE.LIST.ENTRY.COMES", tplExtrSection($entry, "###DIENSTE.LIST.ENTRY.COMES.".$answer."###")); - $dnst_list_entry.= tplReplMarkerArray($entry, $replace); - } - $stmt->close(); - } else { - $dnst_list_entry = $mysqli->error; - } - - $tpl["list"] = tplReplSection($tpl["list"], "###DIENSTE.LIST.ENTRY###", $dnst_list_entry); -} - -$tpl["main"] = tplReplSection($tpl["main"], "###DIENSTE.SHOW###", $tpl["show"]); -$tpl["main"] = tplReplSection($tpl["main"], "###DIENSTE.LIST###", $tpl["list"]); -$tpl["main"] = tplReplSection($tpl["main"], "###DIENSTE.LIST###", $tpl["list"]); -$output["main"] = $tpl["main"]; - -?> \ No newline at end of file diff --git a/pgs/dienste/invite_add.js b/pgs/dienste/invite_add.js deleted file mode 100644 index 5c23cff..0000000 --- a/pgs/dienste/invite_add.js +++ /dev/null @@ -1,9 +0,0 @@ -var count = 1; - -function addInviteAddRow(row) { - var tableRef = document.getElementById('invite_add').getElementsByTagName('tbody')[0]; - - // Insert a row in the table at the last row - tableRef.insertAdjacentHTML('beforeend', row.replace(/###COUNT###/g, count)); - count++; -} \ No newline at end of file diff --git a/pgs/dienste/invite_list.js b/pgs/dienste/invite_list.js deleted file mode 100644 index 176d4af..0000000 --- a/pgs/dienste/invite_list.js +++ /dev/null @@ -1,12 +0,0 @@ -var inviteListShowComers = true; - -function toggleInviteListComers() -{ - var elements = document.getElementsByClassName('invite_list_comes_0'); - var display = inviteListShowComers ? "table-row" : "none"; - for (var i = 0; i"; - $traits = array(); - - if ($val["ZF"]) $traits[] = "ZF"; - if ($val["GF"]) $traits[] = "GF"; - if ($val["KF"]) $traits[] = "KF"; - if ($val["AGT"]) $traits[] = "AGT"; - if ($val["TH"]) $traits[] = "TH"; - if (!$val["TM"]) $traits[] = "Kein Grundlehrgang"; - if (count($traits)) $ret.= implode(", ", $traits); - - $ret.= "Corona-Unterweisung: ".($val["CoronaUnt"] ? "Ja" : "Nein")."" - ."".($val["Teilnehmer"] ? "Dabei" : "Will")."\n"; - return $ret; -} - -function informParticipant($name, $mail, $can, $dienst, $verantwortliche) { - $text = "Hallo ".$name."!

    \nDu hast dich für ".$dienst." angemeldet.

    "; - if ($can) { - $text.= "Du wurdest zu diesem Dienst als Teilnehmer ausgelost und DARFST KOMMEN. Sei bitte pünktlich und bring eine Maske mit!
    " - ."Wenn Du dich am Tag des Dienstes nicht gesund fühlst, bleib zuhause! Wenn Du aus welchem Grund auch immer doch nicht kommen kannst, " - ."teile dieses bitte unverzüglich deinen Diensthabenden mit: ".$verantwortliche."

    \n"; - } else { - $text.= "Leider hattest Du diesmal Pech und DARFST N I C H T KOMMEN. Dafür wirst Du bei den nächsten Verlosungen bevorzugt.

    \n"; - } - $text.= "Viele Grüße vom Webserver der OF Innenstadt!"; - emlSendEmail($mail, "Ergebnis der Platzvergabe für ".$dienst, $text); -} -function informParticipantFromID($mysqli, $terminID, $personalID, $can) { - $qry = "SELECT Beginn,Thema,Verantwortliche,a.Name FROM Termine t LEFT JOIN Terminarten a ON a.ID = t.Terminart WHERE t.ID = '".$terminID."'"; - $res = $mysqli->query($qry); - $termin = $res->fetch_assoc(); - $qry = "SELECT Vornamen,Login FROM Personal p WHERE p.ID = '".$personalID."'"; - $res = $mysqli->query($qry); - if ($personal = $res->fetch_assoc()) - informParticipant($personal["Vornamen"], $personal["Login"]."@feuerwehr-bs.net", $can, $termin["Name"]." am ".date("d.m.Y H:i", strtotime($termin["Beginn"])), $termin["Verantwortliche"]); -} - -function markOrSendParticipantsList($mysqli, $terminID) { - - $mysqli->query("UPDATE Termine SET TeilnahmeGeändert=1 WHERE Beginn > NOW() + INTERVAL 1 DAY AND ID=".$terminID); - if ($mysqli->affected_rows==0) { - sendParticipantsListToResponsibles($mysqli, $terminID); - } -} - -function sendParticipantsListToResponsibles($mysqli, $terminID) { - $qry = "SELECT t.Beginn,IF(t.Beginn>=NOW(),1,0) nichtvorbei,t.Thema,t.Verantwortliche,a.Name as aName FROM Termine t " - ."LEFT JOIN Terminarten a ON a.ID=t.Terminart " - ."WHERE t.ID='".$terminID."'"; - $res = $mysqli->query($qry); - $tmrow = $res->fetch_assoc(); - - if ("1" == $tmrow["nichtvorbei"]) { - // Generate participants list - $qry = "SELECT p.ID,p.Login,p.Nachnamen,p.Vornamen,po.Name poolName,k.Kürzel kom,GROUP_CONCAT(a.Kürzel) ausbStr, tln.Status " - ."FROM Terminteilnahmen tln " - ."LEFT JOIN Personal p ON p.ID=tln.Personal " - ."LEFT JOIN Pools po ON po.ID=p.Pool " - ."LEFT JOIN Kommandofunktionen k ON k.ID=p.Kommandofkt " - ."LEFT JOIN link_Ausbildungen_Personal lap ON lap.Personal=p.ID " - ."LEFT JOIN Ausbildungen a ON a.ID=lap.Ausbildungen " - ."WHERE tln.Termin='".$terminID."' " - ."GROUP BY p.ID ORDER BY tln.Status DESC, p.Pool DESC"; - $res = $mysqli->query($qry); - - $status = ""; - $recipients = array(); - $liste = "

    Teilnahmeliste für ".$tmrow["aName"]." am ".date("d.m.Y H:i", strtotime($tmrow["Beginn"])).": ".$tmrow["Thema"]."

    \n\n"; - $markedCauser = false; - $liste.= "\n"; - while ($row = $res->fetch_assoc()) { - if ($status!=$row["Status"]) { - $status = $row["Status"]; - if ("2" == $status) { - $liste.= "\n"; - } else if ("1" == $status) { - $liste.= "\n"; - } else if ("0" == $status) { - $liste.= "\n"; - } - } - $liste.= "\n"; - - if ("2" == $row["Status"]) { - $recipients[] = $row["Login"]."@feuerwehr-bs.net"; - } - } - $liste.= "
    NameFunktionenCorona-Unterweisung
    Diensthabende
    Erlaubte Teilnehmer
    Weitere Interessenten
    ".$row["Nachnamen"].", ".$row["Vornamen"].""; - $ausb = explode(",", $row["ausbStr"]); - - $traits = array(); - if ($row["kom"]!=null) $traits[] = $row["kom"]; - if (in_array("KF", $ausb)) $traits[] = "KF"; - if (in_array("MA", $ausb)) $traits[] = "MA"; - if (in_array("AGT", $ausb)) $traits[] = "AGT"; - if (in_array("TH", $ausb)) $traits[] = "TH"; - if (!in_array("TM1", $ausb)) $traits[] = "Ohne TM1"; - if (count($traits)) $liste.= implode(", ", $traits); - - $liste.= "".(in_array("CU", $ausb) ? "Ja" : "Nein")."
    \n"; - - if (!in_array("nils.otterpohl@feuerwehr-bs.net", $recipients)) - $recipients[] = "nils.otterpohl@feuerwehr-bs.net"; - foreach ($recipients as $recipient) { - emlSendEmail($recipient, "Teilnahmeliste - Dienst ".strftime("%a, den %d.%m.%Y um %H:%M", strtotime($tmrow["Beginn"])), $liste); - } - $mysqli->query("UPDATE Termine SET TeilnahmeGeändert = 0 WHERE ID = ".$terminID); - - return $liste; - } - return ""; -} - -?> diff --git a/pgs/dienste/main.css b/pgs/dienste/main.css deleted file mode 100644 index d7f69bb..0000000 --- a/pgs/dienste/main.css +++ /dev/null @@ -1,79 +0,0 @@ -/* pgs/invite/invite.css */ -div.confirm { - padding: 1em; - background-color: yellow; - margin-bottom: 1em; -} -li img { - height: 0.8em; -} -.dienste_list_entry div { - border-bottom: 0; - border-left: 0.1em solid #000000; - border-right: 0.1em solid #000000; - border-top: 1px dashed #d0d0d0; - width: 100%; - padding: 0.2em; -} -.dienste_list_entry:last-of-type div:last-of-type { - border-bottom: 0.1em solid #000000; - width: 100%; - padding: 0.2em; -} -.dienste_list_entry div.dienste_title_row { - border-top: 0.1em solid #000000; - background-color: #d0d0d0; -} -.dienste_list_entry ul { - padding: 0; - margin: 0; - list-style: none; -} -.dienste_list_entry ul a { - text-decoration: none; - color: #000000; -} -.dienste_list_entry li { - display: inline-block; - padding: 0.2em; - margin: 0.2em; - background-color: #eeeeee; - border-radius: 0.2em; -} -.dienste_list_entry div.dienste_title_row li { - background-color: #ffffff; -} -.dienste_list_entry li img { - height: 0.8em; -} -.dienste_list_entry a li { - border: 1px solid #000000; -} -.dienste_list_entry .dienste_list_desc { - background-color: #ffffff; - font-weight: bold; -} -.dienste_list_entry .dienste_answer_good { - background-color: green; - font-weight: bold; -} -.dienste_list_entry .dienste_answer_bad { - background-color: red; -} -.dienste_list_entry .dienste_answer_pending { - background-color: lightblue; -} -.dienste_list_entry .dienste_answer_not { - background-color: white; -} -.dienste_list_entry .dienste_answer_lead { - background-color: orange; - font-weight: bold; -} -.dienste_list_entry .dienste_answer_free { - background-color: green; - font-weight: bold; -} -.dienste_list_entry .dienste_button { - /*float:right;*/ -} \ No newline at end of file diff --git a/pgs/dienste/main.html b/pgs/dienste/main.html deleted file mode 100644 index c33cefc..0000000 --- a/pgs/dienste/main.html +++ /dev/null @@ -1,69 +0,0 @@ - - - -
    -

    Anleitung

    - -
    - - -
    - -
    Bitte bestätige den Vorgang: ###DIENSTE.LIST.CONFIRM.TEXT###
    - -

    - Deine Abteilung(en): ###DIENSTE.LIST.DEPARTMENTS###
    - Deine Gruppe(n): ###DIENSTE.LIST.GROUPS###
    - Ältere Dienste anzeigen -

    - -
    -
    -
      -
    • ###DIENSTE.LIST.ENTRY.ALLOWED###
    • -
    • ###DIENSTE.LIST.ENTRY.BEGIN.DATE###
    • -
    • ###DIENSTE.LIST.ENTRY.BEGIN.TIME### - ###DIENSTE.LIST.ENTRY.END.TIME###
    • -
    • ###DIENSTE.LIST.ENTRY.TYPE###
    • -
    • ###DIENSTE.LIST.ENTRY.TOPIC###
    • -
    • ###DIENSTE.LIST.ENTRY.RESPONSIBLES###
    • -
    -
    - -
    -
      -
    • ↳ ###DIENSTE.LIST.ENTRY.RESTRICTIONS###
    • - -
    • Du darfst kommen
    • -
    • Auf Warteliste
    • -
    • Zur Auslosung angemeldet
    • -
    • Bei Interesse bitte anmelden
    • -
    • Du leitest diesen Dienst
    • - -
    • Noch ###DIENSTE.LIST.ENTRY.FREE.NUM### Plätze frei
    • - ###DIENSTE.LIST.ENTRY.ACTION### -
    -
    - - -
    • ↳ Dürfen:
    • ###DIENSTE.LIST.ENTRY.CANDIDATES.CHOSEN###
    - - -
    • ↳ Wollen:
    • ###DIENSTE.LIST.ENTRY.CANDIDATES.WANT###
    - - - -
    - -
    - - diff --git a/pgs/dienste/module.json b/pgs/dienste/module.json deleted file mode 100644 index 4ef4fd8..0000000 --- a/pgs/dienste/module.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "moduleName" : "Dienste", - "title" : "Dienste", - "show" : 1, - "useRight": null, - "adminRight": "DARF_DIENSTE_VERWALTEN" -} \ No newline at end of file diff --git a/pgs/dienstplaene/index.php b/pgs/dienstplaene/index.php deleted file mode 100644 index 2fd609b..0000000 --- a/pgs/dienstplaene/index.php +++ /dev/null @@ -1,116 +0,0 @@ - tplExtrSection(tplLoadFile("pgs/dienstplaene/main.html"), "DIENSTPLAENE"), - "plans" => "", - "add" => "", - "list" => "" -); - -addStyle("pgs/dienstplaene/main.css"); - - -if ($userID = lgnCheckLogin($mysqli)) { - // Lesezeichen zeigen - $tpl["plans"] = tplExtrSection($tpl["main"], "###DIENSTPLAENE.PLANS###"); - - // Dienstpläne abrufen - $res = $mysqli->query("SELECT d.*, a.Kürzel FROM Dienstpläne d LEFT JOIN Abteilungen a ON a.ID=d.Abteilung ORDER BY d.Jahr DESC, d.Name DESC, a.ID ASC"); - $dp_select_tpl = tplExtrSection($tpl["plans"], "###DIENSTPLAENE.PLANS.PLAN###"); - $dp_select = ""; - while ($row = $res->fetch_assoc()) { - $repl = array( - "###DIENSTPLAENE.PLANS.PLAN.NAME###" => $row["Kürzel"].": ".$row["Jahr"]." - ".$row["Name"], - "###DIENSTPLAENE.PLANS.PLAN.LINK###" => "#dienstplan_".$row["ID"] - ); - $dp_select.= tplReplMarkerArray($dp_select_tpl, $repl); - } - $tpl["plans"] = tplReplSection($tpl["plans"], "###DIENSTPLAENE.PLANS.PLAN###", $dp_select); - - // Dienstplan hinzufügen - $res = $mysqli->query("SELECT * FROM Abteilungen"); - $dp_addtp_tpl = tplExtrSection($tpl["plans"], "###DIENSTPLAENE.PLANS.ADD###"); - $dp_addtp_select = ""; - while ($row = $res->fetch_assoc()) { - $repl = array( - "###DIENSTPLAENE.PLANS.ADD.ABTEILUNG.ID###" => $row["ID"], - "###DIENSTPLAENE.PLANS.ADD.ABTEILUNG.NAME###" => $row["Name"] - ); - $dp_addtp_select.= tplReplMarkerArray($dp_addtp_tpl, $repl); - } - $tpl["plans"] = tplReplSection($tpl["plans"], "###DIENSTPLAENE.PLANS.ADD###", $dp_addtp_select); - -// Termin(e) hinzufügen - $tpl["add"] = tplExtrSection($tpl["main"], "###DIENSTPLAENE.ADD###"); - - // Termine auflisten und Anmeldestatus anzeigen - $tpl["list"] = tplExtrSection($tpl["main"], "###DIENSTPLAENE.LIST###"); - $dp_block_tpl = tplExtrSection($tpl["list"], "###DIENSTPLAENE.LIST.BLOCK###"); - $dp_entry_tpl = tplExtrSection($dp_block_tpl, "###DIENSTPLAENE.LIST.ENTRY###"); - $qry = "SELECT t.ID, t.Beginn, t.Ende, t.Thema, t.Ort, d.ID dID, d.Jahr, d.Name dName, " - ."a.Name aName, ta.Name taName, b.Name bName, tpv.Name tpvName, pg.Name pgName, " - ."GROUP_CONCAT(CONCAT(LEFT(p.Vornamen, 1), '. ', p.Nachnamen) SEPARATOR ', ') Verantwortliche " - ."FROM Termine t " - ."LEFT JOIN Dienstpläne d ON d.ID = t.Dienstplan " - ."LEFT JOIN Abteilungen a ON a.ID = d.Abteilung " - ."LEFT JOIN Terminarten ta ON ta.ID = t.Terminart " - ."LEFT JOIN Berechtigungen b ON b.ID = ta.Verwaltungsrecht " - ."LEFT JOIN Terminplatzvergabe tpv ON tpv.ID = t.Platzvergabe " - ."LEFT JOIN Personalgruppen pg ON pg.ID = t.Personalgruppe " - ."LEFT JOIN Terminteilnahmen tln ON tln.Termin = t.ID AND tln.Status >= 2 " - ."LEFT JOIN Personal p ON p.ID = tln.Personal " - ."GROUP BY t.ID " - ."ORDER BY d.Jahr DESC, d.Abteilung ASC, d.Name DESC, t.Beginn ASC "; - $res = $mysqli->query($qry); - $lastdID = null; - $dienstplaene = array(); - $entries = array(); - $current = null; - while ($row = $res->fetch_assoc()) { - if ($row["dID"]!=$lastdID) { - $repl = array( - "###DIENSTPLAENE.LIST.BLOCK.DID###" => $row["dID"], - "###DIENSTPLAENE.LIST.BLOCK.ANAME###" => $row["aName"], - "###DIENSTPLAENE.LIST.BLOCK.DJAHR###" => $row["Jahr"], - "###DIENSTPLAENE.LIST.BLOCK.DNAME###" => $row["dName"] - ); - $current = &$dienstplaene[]; - $current = array( - "tpl" => tplReplMarkerArray($dp_block_tpl, $repl), - "entries" => array() - ); - $lastdID = $row["dID"]; - } - - $repl = array( - "###DIENSTPLAENE.LIST.ENTRY.ID###" => $row["ID"], - "###DIENSTPLAENE.LIST.ENTRY.BEGIN###" => $row["Beginn"], - "###DIENSTPLAENE.LIST.ENTRY.BEGIN.DATE###" => strftime("%a, %d.%m.%Y", strtotime($row["Beginn"])), - "###DIENSTPLAENE.LIST.ENTRY.BEGIN.TIME###" => strftime("%H:%M", strtotime($row["Beginn"])), - "###DIENSTPLAENE.LIST.ENTRY.END###" => $row["Ende"], - "###DIENSTPLAENE.LIST.ENTRY.END.DATE###" => strftime("%a, %d.%m.%Y", strtotime($row["Ende"])), - "###DIENSTPLAENE.LIST.ENTRY.END.TIME###" => strftime("%H:%M", strtotime($row["Ende"])), - "###DIENSTPLAENE.LIST.ENTRY.TOPIC###" => $row["Thema"], - "###DIENSTPLAENE.LIST.ENTRY.PLACE###" => $row["Ort"], - "###DIENSTPLAENE.LIST.ENTRY.TYPE###" => $row["taName"], - "###DIENSTPLAENE.LIST.ENTRY.TPVNAME###" => $row["tpvName"], - "###DIENSTPLAENE.LIST.ENTRY.PGNAME###" => $row["pgName"], - "###DIENSTPLAENE.LIST.ENTRY.RESPONSIBLES###" => $row["Verantwortliche"] - ); - $current["entries"][] = tplReplMarkerArray($dp_entry_tpl, $repl); - } - $list = ""; - foreach ($dienstplaene as $dp) { - $list.= tplReplSection($dp["tpl"], "###DIENSTPLAENE.LIST.ENTRY###", implode("", $dp["entries"])); - } - $tpl["list"] = tplReplSection($tpl["list"], "###DIENSTPLAENE.LIST.BLOCK###", $list); -} - -// Template füllen -$tpl["main"] = tplReplSection($tpl["main"], "###DIENSTPLAENE.PLANS###", $tpl["plans"]); -$tpl["main"] = tplReplSection($tpl["main"], "###DIENSTPLAENE.LIST###", $tpl["list"]); -$tpl["main"] = tplReplSection($tpl["main"], "###DIENSTPLAENE.LIST###", $tpl["list"]); -$tpl["main"] = tplReplSection($tpl["main"], "###DIENSTPLAENE.ADD###", $tpl["add"]); -$output["main"] = $tpl["main"]; - -?> \ No newline at end of file diff --git a/pgs/dienstplaene/lib.php b/pgs/dienstplaene/lib.php deleted file mode 100644 index 01be8ab..0000000 --- a/pgs/dienstplaene/lib.php +++ /dev/null @@ -1,115 +0,0 @@ -".$val["Nachnamen"].", ".$val["Vornamen"].""; - $traits = array(); - - if ($val["ZF"]) $traits[] = "ZF"; - if ($val["GF"]) $traits[] = "GF"; - if ($val["KF"]) $traits[] = "KF"; - if ($val["AGT"]) $traits[] = "AGT"; - if ($val["TH"]) $traits[] = "TH"; - if (!$val["TM"]) $traits[] = "Kein Grundlehrgang"; - if (count($traits)) $ret.= implode(", ", $traits); - - $ret.= "Corona-Unterweisung: ".($val["CoronaUnt"] ? "Ja" : "Nein")."" - ."".($val["Teilnehmer"] ? "Dabei" : "Will")."\n"; - return $ret; -} - -function informParticipant($name, $mail, $can, $dienst, $verantwortliche) { - $text = "Hallo ".$name."!

    \nDu hast dich für ".$dienst." angemeldet.

    "; - if ($can) { - $text.= "Du wurdest zu diesem Dienst als Teilnehmer ausgelost und DARFST KOMMEN. Sei bitte pünktlich und bring eine Maske mit!
    " - ."Wenn Du dich am Tag des Dienstes nicht gesund fühlst, bleib zuhause! Wenn Du aus welchem Grund auch immer doch nicht kommen kannst, " - ."teile dieses bitte unverzüglich deinen Diensthabenden mit: ".$verantwortliche."

    \n"; - } else { - $text.= "Leider hattest Du diesmal Pech und DARFST N I C H T KOMMEN. Dafür wirst Du bei den nächsten Verlosungen bevorzugt.

    \n"; - } - $text.= "Viele Grüße vom Webserver der OF Innenstadt!"; - emlSendEmail($mail, "Ergebnis der Platzvergabe für ".$dienst, $text); -} -function informParticipantFromID($mysqli, $terminID, $personalID, $can) { - $qry = "SELECT Beginn,Thema,Verantwortliche,a.Name FROM Termine t LEFT JOIN Terminarten a ON a.ID = t.Terminart WHERE t.ID = '".$terminID."'"; - $res = $mysqli->query($qry); - $termin = $res->fetch_assoc(); - $qry = "SELECT Vornamen,Login FROM Personal p WHERE p.ID = '".$personalID."'"; - $res = $mysqli->query($qry); - if ($personal = $res->fetch_assoc()) - informParticipant($personal["Vornamen"], $personal["Login"]."@feuerwehr-bs.net", $can, $termin["Name"]." am ".date("d.m.Y H:i", strtotime($termin["Beginn"])), $termin["Verantwortliche"]); -} - -function markOrSendParticipantsList($mysqli, $terminID) { - - $mysqli->query("UPDATE Termine SET TeilnahmeGeändert=1 WHERE Beginn > NOW() + INTERVAL 1 DAY AND ID=".$terminID); - if ($mysqli->affected_rows==0) { - sendParticipantsListToResponsibles($mysqli, $terminID); - } -} - -function sendParticipantsListToResponsibles($mysqli, $terminID) { - $qry = "SELECT t.Beginn,t.Thema,t.Verantwortliche,a.Name as aName FROM Termine t " - ."LEFT JOIN Terminarten a ON a.ID=t.Terminart " - ."WHERE t.ID='".$terminID."'"; - $res = $mysqli->query($qry); - $tmrow = $res->fetch_assoc(); - - // Generate participants list - $qry = "SELECT p.ID,p.Login,p.Nachnamen,p.Vornamen,po.Name poolName,k.Kürzel kom,GROUP_CONCAT(a.Kürzel) ausbStr, tln.Status " - ."FROM Terminteilnahmen tln " - ."LEFT JOIN Personal p ON p.ID=tln.Personal " - ."LEFT JOIN Pools po ON po.ID=p.Pool " - ."LEFT JOIN Kommandofunktionen k ON k.ID=p.Kommandofkt " - ."LEFT JOIN link_Ausbildungen_Personal lap ON lap.Personal=p.ID " - ."LEFT JOIN Ausbildungen a ON a.ID=lap.Ausbildungen " - ."WHERE tln.Termin='".$terminID."' " - ."GROUP BY p.ID ORDER BY tln.Status DESC, p.Pool DESC"; - $res = $mysqli->query($qry); - - $status = ""; - $recipients = array(); - $liste = "

    Teilnahmeliste für ".$tmrow["aName"]." am ".date("d.m.Y H:i", strtotime($tmrow["Beginn"])).": ".$tmrow["Thema"]."

    \n\n"; - $markedCauser = false; - $liste.= "\n"; - while ($row = $res->fetch_assoc()) { - if ($status!=$row["Status"]) { - $status = $row["Status"]; - if ("2" == $status) { - $liste.= "\n"; - } else if ("1" == $status) { - $liste.= "\n"; - } else if ("0" == $status) { - $liste.= "\n"; - } - } - $liste.= "\n"; - - if ("2" == $row["Status"]) { - $recipients[] = $row["Login"]."@feuerwehr-bs.net"; - } - } - $liste.= "
    NameFunktionenCorona-Unterweisung
    Diensthabende
    Erlaubte Teilnehmer
    Weitere Interessenten
    ".$row["Nachnamen"].", ".$row["Vornamen"].""; - $ausb = explode(",", $row["ausbStr"]); - - $traits = array(); - if ($row["kom"]!=null) $traits[] = $row["kom"]; - if (in_array("KF", $ausb)) $traits[] = "KF"; - if (in_array("MA", $ausb)) $traits[] = "MA"; - if (in_array("AGT", $ausb)) $traits[] = "AGT"; - if (in_array("TH", $ausb)) $traits[] = "TH"; - if (!in_array("TM1", $ausb)) $traits[] = "Ohne TM1"; - if (count($traits)) $liste.= implode(", ", $traits); - - $liste.= "".(in_array("CU", $ausb) ? "Ja" : "Nein")."
    \n"; - - if (!in_array("nils.otterpohl@feuerwehr-bs.net", $recipients)) - $recipients[] = "nils.otterpohl@feuerwehr-bs.net"; - foreach ($recipients as $recipient) { - emlSendEmail($recipient, "Teilnahmeliste - Dienst ".strftime("%a, den %d.%m.%Y um %H:%M", strtotime($tmrow["Beginn"])), $liste); - } - $mysqli->query("UPDATE Termine SET TeilnahmeGeändert = 0 WHERE ID = ".$terminID); - - return $liste; -} - -?> \ No newline at end of file diff --git a/pgs/dienstplaene/main.css b/pgs/dienstplaene/main.css deleted file mode 100644 index 6885d8d..0000000 --- a/pgs/dienstplaene/main.css +++ /dev/null @@ -1,50 +0,0 @@ -/* pgs/dienstplaene/main.css */ - -label { - width: 6em; - float: left; -} -li img { - height: 0.8em; -} -.dienstplaene_list_header { - margin: 1em 0; -} -.dienstplaene_list_entry { - border-bottom: 0; - border-left: 0.1em solid #000000; - border-right: 0.1em solid #000000; - border-top: 0.1em solid #000000; - width: 100%; - padding: 0.2em; -} -.dienstplaene_list_entry:first-child { - -} -.dienstplaene_list_entry:last-of-type { - border-bottom: 0.1em solid #000000; - width: 100%; - padding: 0.2em; -} -.dienstplaene_list_entry ul { - padding: 0; - margin: 0; - list-style: none; -} -.dienstplaene_list_entry ul a { - text-decoration: none; - color: #000000; -} -.dienstplaene_list_entry li { - display: inline-block; - padding: 0.2em; - margin: 0.2em; - background-color: #eeeeee; - border-radius: 0.2em; -} -.dienstplaene_list_entry li img { - height: 0.8em; -} -.dienstplaene_list_entry a li { - border: 1px solid #000000; -} \ No newline at end of file diff --git a/pgs/dienstplaene/main.html b/pgs/dienstplaene/main.html deleted file mode 100644 index 20d4152..0000000 --- a/pgs/dienstplaene/main.html +++ /dev/null @@ -1,72 +0,0 @@ - - - -
    -

    - Springe zu Dienstplan: - -

    -

    Neuen Dienstplan erstellen

    - -
    - - -
    -

    Dienste hinzufügen

    - -
    - - -
    - - - - -
    - - diff --git a/pgs/dienstplaene/module.json b/pgs/dienstplaene/module.json deleted file mode 100644 index e1f3bb4..0000000 --- a/pgs/dienstplaene/module.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "moduleName" : "Dienstpläne", - "title" : "Dienstpläne", - "show" : false, - "useRight": "ADMIN", - "adminRight": "DARF_DIENSTE_VERWALTEN" -} \ No newline at end of file diff --git a/pgs/info/Anfahrtskizze.png b/pgs/info/Anfahrtskizze.png new file mode 100755 index 0000000000000000000000000000000000000000..6a9fc0df071fab2db517088a3c5f37ecfdf53368 GIT binary patch literal 227574 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 z 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 literal 0 HcmV?d00001 diff --git a/pgs/info/index.php b/pgs/info/index.php new file mode 100755 index 0000000..3f0d176 --- /dev/null +++ b/pgs/info/index.php @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/pgs/info/info.css b/pgs/info/info.css new file mode 100755 index 0000000..644ef87 --- /dev/null +++ b/pgs/info/info.css @@ -0,0 +1,32 @@ +#cimpressum { +} +#ccontact { + width: 300px; + /*height: 200px;*/ + float: right; + padding-left: 5px; + border-left: 1px solid #FF0000; +} +#ctechnical { + margin-top: 10px; +} +span.cheadline { + width: 100%; + display: block; + border-bottom: 1px solid #FF0000; + color: #FF0000; + font-size: 15px; + font-weight: bold; + margin-bottom: 5px; +} +span.cheadcorrect { + width: 660px; +} +span.cclabel { + width: 100px; + float: left; + font-weight: bold; +} +tr.gone { + text-decoration: line-through; +} \ No newline at end of file diff --git a/pgs/info/info.html b/pgs/info/info.html new file mode 100755 index 0000000..4395914 --- /dev/null +++ b/pgs/info/info.html @@ -0,0 +1,48 @@ +

    +

    Örtlichkeit

    +

    Die Trauung und die anschliessende Feier finden im wunderschönen Schloss Eldingen statt:

    +

    Schloss Eldingen im Landkreis Celle
    Website
    Bargfelder Straße 6
    29351 Eldingen

    +

    Auf Grund von Denkmal- und Naturschutz müssen wir beim Feiern ein paar Dinge beachten. So sind sowohl im Innen- als auch im Aussenbereich leider keine Haustiere erlaubt. Des Weiteren muss auf den Gebrauch von Konfetti, Reis, Wunderkerzen, Seifenblasen und Ähnlichem verzichtet werden.

    +

    Im Obergeschoss gibt es ein bis zwei "Ruheräume" für die jüngeren Gäste, die nicht bis zum Ende durchhalten. Wer diese nutzen möchte, bringt bitte "Betten" und alles Nötige selbst mit.

    +

    Anfahrt

    + + +

    Parkplätze sind auf dem Gelände in ausreichender Zahl vorhanden.

    +

    Dresscode

    +

    Wir bitten in Abendgarderobe zu erscheinen. Gerne in fröhlichen, sommerlichen Farben. :)

    +

    Geschenke

    +

    Wir planen unsere Flittermonate mit einer Weltreise zu verbringen. Daher würden wir uns über Beiträge zu unserer Reisekasse sehr freuen.

    +

    Kontakt

    +

    Für Rückmeldungen zur Einladung benutzt bitte die Eingabemaske unter Einladung. Anfragen, deren Beantwortung alle Gäste interessieren, stellt bitte auf der Seite Diskussionen. Dort gibt es auch die Möglichkeit mit anderen Gästen zu kommunizieren, ohne dass wir die Nachrichten lesen können. Ansonsten erreicht ihr uns folgendermaßen:

    + + + + + + + +
    Brautpaar
    Beide:brautpaar@###PAGEDOMAIN###
    Nur Nils:braeutigam@###PAGEDOMAIN### / 0163-6063613
    Nur Sophia:braut@###PAGEDOMAIN###
    Trauzeugen
    Beide:trauzeugen@###PAGEDOMAIN###
    Nur Norman:trauzeuge-norman@###PAGEDOMAIN###
    Nur Katharina:trauzeugin-katharina@###PAGEDOMAIN###
    +

    Übernachtungsmöglichkeiten

    +

    In der näheren Umgebung gibt es einige Übernachtungsmöglichkeiten, die wir hier aufgelistet haben. Bitte beachtet, dass wir die Informationen von unserem Veranstalter übernommen und nicht auf Richtigkeit geprüft haben, fragt also lieber genau nach. Falls etwas ausgebucht ist bzw. von euch gebucht wurde, sagt uns bitte Bescheid, dann können wir das Angebot von der Liste streichen und euch langes Telefonieren ersparen. Falls alles ausgebucht sein sollte, gibt es in Celle und Wienhausen (bis zu 20 km) mehrere große Hotels, die genug Kapazitäten bieten sollten.

    +

    Im Ort gibt es einen 24h Taxi-Service, der unter der Nummer 05148-9125445 erreichbar ist.

    + + + + + + + + + + + + + + + +
    KategorieInhaberOrtKontaktEntfernung zum SchlossAnzahl ZimmerPreis Zimmer
    PrivatzimmerFam. KnoopEldingen05148-910573
    reiner_knoop@web.de
    500 m1 DZ mit Badab 32,50€ p.P. inkl. Frühstück
    AppartmentConny PeeselEldingen0160-97568550
    conny.peesel@t-online.de
    600 m2 DZ28€ p.P. ohne Frühstück
    PrivatzimmerFam. SchraderEldingen05148-897
    h.w.schrader@gmx.de
    700 m1 DZ, 1 EZ mit Badab 25€ p.P. ohne Frühstück
    PrivatzimmerFam. HäringEldingen05148-835
    fam-haering@freenet.de
    700 m1 DZ mit Badab 25€ p.P. inkl. Frühstück
    PrivatzimmerFam. DeneckeEldingen05148-1473
    denecke@zahn-technik.com
    1000 m1 DZ mit Bad25€ p.P. ohne Frühstück
    PensionLandhaus SeverlohMetzingen05148-604
    0176-65544642
    norgard@severloh.de
    2 km4 DZ, 1 EZ mit 4 Bädernab 38€ inkl. Frühstück
    PrivatzimmerSchloteHohnhorst05145-1590
    i.schlote@web.de
    4 km1 DZ, 1 Zimmer mit franz. Bett und 1 Badab 34€ p.P. inkl. Frühstück
    PrivatzimmerFam. von WelckSteinhorst05148-910638
    karinvonwelck@gmx.de
    4 km2 DZ mit 2 Bädern40€ p.P. inkl. Frühstück
    AppartmentJennifer HarmsLuttern05145-2847530
    0172-4918271
    jenna.luttern@gmail.com
    4 km1 DZ30€ p.P. ohne Frühstück
    Pension und GasthausLandhaus Räderloh Rainer KirkRäderloh05148-810
    info@landhaus-raederloh.de
    www.landhaus-raederloh.de
    7 km8 DZab 40€ p.P. inkl. Frühstück
    Pension / FerienwohnungEichenhof Räderloh Familie RölingRäderloh05148-666
    webmaster@eichenhof-roeling.de
    www.eichenhof-roeling.de
    7 km4 DZ, 2 EZ, 3 Ferienwohnungenab 40€ p.P. inkl. Frühstück
    HotelDeutsches Haus H. FergelEschede05142-2236
    hartmutfergel@aol.com
    www.hotel-eschede.de
    10 km11 DZab 44€ p.P. inkl. Frühstück
    HotelHotel DierksRepke05832-977980
    hotel-dierks@t-online.de
    www.hotel-dierks.de
    12 km17 Zimmerab 38,50€ p.P. inkl. Frühstück
    +

    Falls ihr über das Internet auf die Pension "Wassermühle Eldingen" stoßen solltet, diese ist bereits von uns für die engsten Verwandten ausgebucht, hier braucht ihr also nicht anzufragen.

    +
    diff --git a/pgs/pics/index.php b/pgs/pics/index.php new file mode 100755 index 0000000..ae50abb --- /dev/null +++ b/pgs/pics/index.php @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/pic.php b/pic.php new file mode 100644 index 0000000..c212c82 --- /dev/null +++ b/pic.php @@ -0,0 +1,49 @@ + QRCode::OUTPUT_MARKUP_SVG, + 'imageBase64' => false, + 'eccLevel' => QRCode::ECC_L, + 'cssClass' => 'my-css-class', + 'svgOpacity' => 1.0, + 'addQuietzone' => false, + 'svgDefs' => + ' + + + + + + + + ', + ]); + + + + $qrcode = (new QRCode($options))->render($data, "qr".$data.".svg"); + + /*if($gzip === true){ + header('Vary: Accept-Encoding'); + header('Content-Encoding: gzip'); + $qrcode = gzencode($qrcode ,9); + }*/ + echo $qrcode; + } +} else { + http_response_code(400); +} + diff --git a/res/dark/active.png b/res/dark/active.png new file mode 100755 index 0000000000000000000000000000000000000000..228054e97dcc677175186ff5138cb344775b5715 GIT binary patch literal 1104 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 literal 0 HcmV?d00001 diff --git a/res/dark/alarm.png b/res/dark/alarm.png new file mode 100644 index 0000000000000000000000000000000000000000..7a25390fbd3ad1409b6c07330c4a209aa8ff674c GIT binary patch literal 1179 zcmV;M1Z4Y(P);X;M+KX73T0u?4jFfNP>V}uJsz=RYbgb>I|sB&BcLaaC-V$gofn|seqkvH~e zv^zVpW_ALZN&A=+$_?kUu0vR=gk#iGfn}o z2dXjVPTYlzF?age{HtKColw<%9gcl#?ZmkG9s@Ja0C=2(yt={sn3-qB&6|jbMC7un zzQ{{Hffpijd936CTv65NEy%}+09+|Nq5xXVTpwb0!L77sMOQ>FWcgy|I)K*Di~-n) zBMM-9kX^6WGpf2*0Qneuystq+E2UP_C;j9)9LukJg0A_=~v7= zpCoiY{zF6-!Z0)d9=e7%Qqfo`ntTiqS?SZI6~MzV42_5^#DNBIKaT!_x~>CY)4g~* z5t&=5MsJoS0KmU*BI z=xo0yBJw=%Qz9Z&y<4l*Y_hQ+2v(`!4PXj>5Cq4@L9JG^s(LrcEx~osC!$#K@2+e* z0lR%1ESE?=#>eT31ea!t>#R>ih}F9iPF=r9k76r)!bgHjnk)H4^wRyFcWQre&&z!p zDqX+;AIm9j@fvX8C(?7#m0!DZ?eOsMwNh(sJ@I0hn0LO2h{$n>SKgT0MJH&N09@_CgGaoOh0NSA#+U;DTSW9n6h&JZsr_UG-Djw;D2lc!l?oBj`^K09FHdVn zM@RnD)YP9uRL^5y01n&j_IuOQ(->x$Yf+k%IDB7 zWUZa3R4Ts`QK1)7Iq))yq7SRpYA?%ZXaEcs;2qxK|BhVefjm&vkcg@|&8_EowIci$HVdih z&!@26&1*X{0YvoWDQv$g&~Gv5cDn|^x5M@W0DcI=(45_432>iVzsVr~qlk>-Y>^+` tZr2B}4&Xce=l&)H@DqS9(zo43;BQ-d=$^vX>{tK*002ovPDHLkV1n9gEiwQA literal 0 HcmV?d00001 diff --git a/res/dark/barcode.png b/res/dark/barcode.png new file mode 100644 index 0000000000000000000000000000000000000000..9eccd9dbd44bf9d423f0fde48c01b1556b4169d5 GIT binary patch literal 204 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC&H|6fVg?4jBOuH;Rhv&5C|Kv| z;uw-~@9m9?Tn!35t%>5*|HI?L@9HdZyOH^&zP#-aU+}?W3=Dr}y1Gmen{o40)2gpI z+TE4Rj92{96TZsTYhAy+kC`Rl^J>n`#zi&fAMgIW>UG+!@&<;ie_yNZPk-I^o`LZS x#{xG7)91DdK=R&^ES7-B_g6?UGB5<(V)To0F&F5W26PAmgQu&X%Q~loCIFf|N}~V( literal 0 HcmV?d00001 diff --git a/res/cancel.png b/res/dark/cancel.png old mode 100644 new mode 100755 similarity index 100% rename from res/cancel.png rename to res/dark/cancel.png diff --git a/res/check.png b/res/dark/check.png old mode 100644 new mode 100755 similarity index 100% rename from res/check.png rename to res/dark/check.png diff --git a/res/dark/corona.png b/res/dark/corona.png new file mode 100755 index 0000000000000000000000000000000000000000..4fa084d59fcbcaabf96247c8eab86e5599d7ace1 GIT binary patch literal 1690 zcmV;L24(q)P)tNh~VmGaLg2--7i=SegWE>fLSv5 z!3Xdy&{o90(7dZkvn7r6-IdO{-XivC;+(5WS|&+Onh;C36tOQ90DS?}ey=TJTTfhn ztXV~DTk?hd3KW$AP0+~yRsp2Y7iV3>1mZ&L$^ zr3)n;OqW&ZnB;f_S4o;5OJ_+E31$AmPz2vfdZ^X8r3v$+lANp$V^tnrxu=kmMhE?K zl6|CI&XaF|GodQ&2yD*{bk4}jtH>HSF6d7K2Gu%k&V426jT|^{v^%%1)&a_rE>9{r z>4dzba!(;iQP3Y6OE*heTzgQK?v15Ek}6JGi?q`d>Oh(zsjV#CmjsEW>lA!lq~8kg z$|nZ5)(TFdZ3V(FlUsnJYLz%>*Ef@U&Dr=AM;N?*sQVa$XVWl&Gn>s{fHT;d5yVSH zsI)ZGRHBV*}dNi!v#mJ{<+ zC%qXbu2mqK+mEJ;{bXe%+6r}H}(oOBoeUp6NFMtZ1SCW=%V9`1hsUm&nos3t( zjbn!FuS%D-Id^dLcMud9Rg&ISI{DpB`bN?=4J>GBvb`#GwmNrqt8-^prA|rPbJ$fR zZS%f%r;HCSN$&w8`aSh2a%GSWmK)p&93SYmMbKsNvO$!QNp1)|8{C+o8yUP9L05Q~ z0ggAAZLlJ+S<&wtZZIn`xHFAFn)u?jI;9W|NzomWLVhJME{`vRnFhNOwzt-RO9q?$ zk#0ROCJ$hOSi8aNNn*V)AOZBkq=5WuMUSMwnFbrY{YJnkf=m2^-+-|hhNnhwNiR(F zyT@?6&ES&+xp#n;#CVIrlEnDO;dJqO@%POor>T|4>~(5a`T67 z-+t_c$tl324SEul`HL7H_U+4reGf1)wD%QyTSD)LI(+W(GiIKAS^qxy#!?KPPk#Qa zJDkMJ$ZQeJ%kUBIjTUC{0b2b_T`q&oF+7^3?7_nfasW6f)T_V+jRHu!KLv&x90+vl zZmA=9%wVGoDiK^>Pub7m4S|D2DSFOePn`gMCFL5@U~%x3)~BttAb=|kdXzOMQ=H66 zAv7n{%Q&DM+_9$M&P~ys-G~oxy1@bYbd(ZT1h6r{JINqUjPC(P<>XR|;G#Ub{Un0v2HoD_ zy8-C1lsB4em6U*Mhoo+QxAf0T1k((*_rk=0%h zUU8w5wp691PFg2vucRSP8imv)>0(J~<$j-}2U?taCBVEx($kU#r`W`jRyyfJq%9s} z7}8`()15Rz()}&Yy;d*Kegbs(H`kr<_QLju!81Td9n6!h?>h01oS5AaJOK>P!fZIN zfMKyTUD6CEO-AaFG+fetCvBte>ntrxOPq7LZk2(dv2=r^E+NVM{@}9P{83}i@#hC8KA7O^ws7Xl=>pSobH6WNIAz046^3&T+$IM!x7O=D z`nYFt-|_>Ju8()h%X~_F5OXPwFZglpbel6$AqyY%P5ETFJErKd=={b&#sla0Z{I6< ze4XzS`^jGM(+4iz&%c-X`1oH_&rgpG&&jUX|7Lxo`w_kAYbp#GKdd_$p74IX_nDat zlOJ17SgV%(d4K2%5uXOLqueVFbuQg~c4tfI<{vyW7;@RpJ9xbEm9;bWe$TII$E@Zc zExe$Y^FrDO*R;JCP5~9H5x;bdB_o+>iy`B!2>m5Mxnut>fcTY+=Av)6USWM=0t^TS MPgg&ebxsLQ0NJ#kLI3~& literal 0 HcmV?d00001 diff --git a/res/dark/delete.png b/res/dark/delete.png new file mode 100755 index 0000000000000000000000000000000000000000..54d2023344ebb83611a38ce3f225f672127b5cb4 GIT binary patch literal 327 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC&H|6fVg?4jBOuH;Rhv&5DEQOU z#W5t~-rJdud`$)duDA7UnC~3&-tn2|o}k{*UAH&Zmnf^4t=t&&+jq|Nl3=zU{cTJ~ zce*j`Sn=xZT($?7UhP?UwQI!}ECT-UnQj{(WeVQp<-aJ8#-L2q&@ssAfF;qr4{b@OoSRPe1Elr?cPIJ;s;7 z^oBw0!$G@ZuS_4!-g7&5CdbMy{azs`c}+@Cvg+#8qA+{*Pd{gbZvSd7Z6u_2;26t| z84S|G3CT=3J`KH`8w?rE)DA3*QuxpDJ~aGn_x|q59X$P_Ei1!gHJ7jT+YFX|#@EUF WtZvIC-`T)GVDNPHb6Mw<&;$UZ^@t7t literal 0 HcmV?d00001 diff --git a/res/dark/department.png b/res/dark/department.png new file mode 100755 index 0000000000000000000000000000000000000000..b9db731d1b4ac77a8e54378b2fe264f61611fb56 GIT binary patch literal 210 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC&H|6fVg?4jBOuH;Rhv&5DA?lZ z;uw-~@9mA#Tn!2gtQV*J`#*W@-o!w2$rj7%X3tN7H=WjQRhEp;*1h<{q#=#rEW<2D z6Xpyyk0jUhkJf)}6>Y!w>+I)}bTDoxiypJ(&e)i*yGCotsJ>-^c#{BNtUeeLAa v=No{UR5qTveffEY`_XyEzj@ChjJn|Gsi)w2~r1dAYub&&i8L99Y*Q3)y3Mi2zGu(%W&EOI$=LC(9~xq0t9n+sf?bII=Q>|Nn~ zu*K}n``-7>+hg|42IL8iMq_knXlNk_f}2D%OGFomXuS1vg@}F-(dTBf`Bp^UznYsy}g`>JWMG3A0r~NxVyWX>#2BSOdi0?6vFlO z!Wfh9iTHZGeg?p12O%W@Ya+7HXf)36@9*c!<#OIydtO8qT8~<}L+oa)R?EH;BJ$Lc zye1-#j4>lIsy8Ac%K&PcM?{`vDxR6I01%bAtP*`WJUmSOr>j&dIRIZ2_j26$Bm%Cf z@%qHX1kxHP6bc}sb#?nj76zu<2LRru6@LQPbXP>DBr)w}4#RNF7k3zjW9ktyabuHI z;Mh)CEEem&4D9UeXfFS|GJvpsm7*vr_~MSDsGuqk#*IxF-7eHqYPj$G+st-avbF=x~AGV`qFwbownZh(jg zz_v=Z;em5Qac*ZKo`^_9ZmVRH=IxQ0FYC8k5xJe2foipy1Mp3mc-<`@fY*xaTeVuv zwyAMcp(!G_y5PCx;K^?Fk5DR=asWQ4IRSzp8x5m{@;TgQa$&+`3F^F`!=KAE%Djwi|K9ROC9sI3#`ZmGGeeHBkc z#LUzBY{wWgs^=MFMgds$F6F;<>;?de>M^>m=ZMI4Wwhucx37)kqZ+%KovBk|`fA`< z2NeXtSv|pVFLu{8z<&V%pAvk~_~a{ZZ$Iq}FhFMv{sRO2?_lOB#|Jytb->Kt4u-u# zMCSD|ygoJ;k@Jk7+NP6kBePQUfVHL<8#&EF!jm_@F?sABJy9wW=<00000NkvXX Hu0mjfV;#6G literal 0 HcmV?d00001 diff --git a/res/show.png b/res/dark/filter_on.png old mode 100644 new mode 100755 similarity index 100% rename from res/show.png rename to res/dark/filter_on.png diff --git a/res/dark/group.png b/res/dark/group.png new file mode 100755 index 0000000000000000000000000000000000000000..fb28b7758906c3b360271cdd814ffe80f7b8da2a GIT binary patch literal 796 zcmV+%1LOROP)6Lnwq;)~p{5vB?9zMb6L?Gg)Y} z7tm-lW~l}`9{|r?)$4q3%BySQ$VEeSAq>N}MD*Gr_Ei{$A6;^~Xd5UX&+`v;S@Jyp zZdiZn5W8zw?>fZRYNI4crT|>nnoub#ifr>^-EtMKo8qD<62(`miFZ#IrxgO=nSn>;dA`EO*IjvX*$KsZ2ns6`eq^Mi?riO)p=S48A?9}ka22yusqNJ@D> z2!c;F{@+BMcp{=K%YK#~$0h!c+*y|WaPV(A{ZjUNy=07{wdi)c+27{$@bK{P@bK{X a-|!0qZA^Uwp^wr40000C9W5ipGSYm)x23Tdp zA|oy`;#Wq9884sji`%{tVw#C=c$+q5(qaYx0PVWNO!NfUlO~FfV4i8I0|tL@dx9&Z^>%)&s5rD#G74={5RG9{@7~W%7H(+ z0#7vebYLL4(uO$T*@ibnpA{!2+Md?&9Iy*-j1V7N0S}Bo#S*+{gg6}ROS|qq8xAa4 zfG-;<4+Q%$LL6hnJ2o7+o-+JHBjv6p_*1oA=xXW?7^2w};qPgs3iYWwom-p{)KpCZWFu?uLx>8PCg$DpAjgJ!}{?w+ruGvkDlzSMU6fwmXmJc4Z z8~p&tn{BA;Ow-6sGeDG@8?Dr?PI)>qMvS_ZSTR!WYl1(<^?RN0HFBw|@Y->PBhIdW z87X%*!JlfCPH5L1?vy1yyix@QxEBJlq?LNTUhmP^7%|c3ZR}8Ix(08g+|2+FLl)pI z?YcwtdbNwMD=pyxR)WH28~$w$yGBI(-p^+9^?IS|8Xf)f-GLY4C(`iT_42EjV@b* zf4X(6WTHzE>iSW0eMUUjL2`H23VgM{zmE}bgmhXlLcDJ+YH66C$qX>!k0J0SBjw&+ z^KEF_abAf?l^+&3LV8#y}p{#96AePhjA#JeozyVCcUdmZ4Grj;6J zfMQ^gEe6%~KVh|ey~2p|em0xyHBU#Tm74VOc_;37JzoQj2fqIc_h zW*3Vt#Z-RU*)SvJ)CLFl=jn))Q@!Tg*a;yHMcxq!(cK?~37k02h${h6Trol%x6#)# XAD)}2#{(o800000NkvXXu0mjfQokU5 literal 0 HcmV?d00001 diff --git a/res/dark/list.png b/res/dark/list.png new file mode 100644 index 0000000000000000000000000000000000000000..e2f2d743d76141734bccfbc4a81fd9c7c41dce1d GIT binary patch literal 161 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC&H|6fVg?4jBOuH;Rhv&5C>ZSN z;uw-~@9lL%z6J#b7RLww^WE$dwipz0r+YD-%snabA;0*2?VZ?&?6a#sFE5Xe{K~)x tLkty%>ldhjAOnNfKW0-#5OjFW()?UP^2OEjAArU)c)I$ztaD0e0syj4GQ$7> literal 0 HcmV?d00001 diff --git a/res/dark/location.png b/res/dark/location.png new file mode 100755 index 0000000000000000000000000000000000000000..6ce1085b3500004ff103955ec574b8762a19be55 GIT binary patch literal 992 zcmV<610Vc}P)e# zmnV&6>As%#c{6u2JF^jL((dl=S8*I)ilXQufRg~e1u$QHyba(DfWN%=Pn~m5I-SmT zUEY->B1cKCko-i_E88cMD72Y|wNb+?B@V)J| zb8fLM_zNUI)(AgoADwd-LV2P<_#dJudI}(EXnaQA`-^cL|51AY5&7B}^Cy6XhTtdq zhvX@1?R!nJ(G;z%tr=s?{TAQ>V8IykOTXV&v8iUjIrmc(MXN2qf0p-tDURbOwFDsf z9KhK&0{~bz#(ZB^R60!}axxHp7r-5oXNJRJZ#W$GNS*<3r}#{(vxRpxk-QPG6uuRa z1J`pAStR*3puZcHX8^!??Z}f{vev#hsK8qLg5*-bOq6kbFi}x+McHSmcWD5Uzbef-#+cQzjm#Lc3ZSFuFu?m@ z4F&^4aw}l>%t$Va$mujqlQc~e5jkBPKeK>-wg!WNY6aAc#O(%7U}f#LhE0`_2N;jXj{$79z`t2|)f=GK>xuXNR@3y} z`&+$UPqg(x*D9mY$acHk4FFAD32u(Z;}c1er~?G8vq_SO_x@T#@bKPW3xN*~0028X zJC6XYH^9GM^c|$2uh2x!xgVn_`mIiS@BO(rj(-pRzp1wB!sua*{12yr2d10>01%OH zj4^+s`aS80fEtcQ$H+OYu|bAZ&rkd_x|Rz@RgNiS%>7S3J+|rvMf_QS~sTR zeZf=#rg-yyV=QiOBI;a~>*^*AEGBeb#)X%Cf9Wa$_I(jV#N$v*uIDId^`aAFlR2 z!~a7h?|u>B?yPx&mFM|Bf&io@Kwon+2iPKj`W;wX z^E+n#1d0Iw4C6Sa)*vMS0^nhqro)Q+{VmOcuS9fg89)Gh5Yee+00HpH%x9JX1VCoy zYs&xvK$!W~G{El~a?WZt+X6tQH#DYOO4Cif>9LCG!Ir8`E(P%EbZhxPvet3{m&?^w YKbz;&fCX>RsQ>@~07*qoM6N<$f(VzLRsaA1 literal 0 HcmV?d00001 diff --git a/res/dark/main.css b/res/dark/main.css new file mode 100755 index 0000000..4f2300f --- /dev/null +++ b/res/dark/main.css @@ -0,0 +1,184 @@ +/* tpl/main.css */ +body { + font-family: arial; + font-size: 20px; + width: 100%; + height: 100%; + margin: 0; + padding: 0; + background-color: #000; + color: #fff; +} +header { + background: #000 url(../frontpage.jpg) center no-repeat; + background-size: cover; + width: 100%; + height: 100vh; +} +#loginbox { + position: absolute; + width: 18em; + left: calc(50% - 9em); + bottom: 5em; +} +#loginbox p { + background-color: #000; + text-align: center; + padding: 0.2em; + border-radius: 0.2em; +} +a {color: #fff; text-decoration: underline;} +ul {list-style: none; padding: 0; margin: 0;} +ul.inline { + display: inline; + margin: 0 0.5em; + position: relative; + bottom: 0.2em; +} +li { + display: inline-block; + padding: 0.2em; + margin: 0.1em; + border-radius: 0.2em; +} +li img {height: 0.8em;} +li > img {margin: 0 0.4em 0 0.2em;} +a > li > img, li > a {margin: 0 0.2em 0 0.4em;} +li a { + padding: 0 0.1em; + background-color: #000; + border-radius: 0.2em; + border: 0.05em solid #fff; +} +a li {border: 0.05em solid #fff; background-color: #000;} +nav { + vertical-align: middle; + text-align: left; + background-color: #9b0000; + position: sticky; + top: 0; + z-index: 100; +} +nav ul {padding: 0 0.5em;} +nav li { + padding: 0.5em 0.75em; + font-weight: bold; + margin: 0; + background-color: #9b0000; + border: 0; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} +nav li:hover {background-color: #f00;} +nav .current li {background-color: #000;} +#navigation_select { + display:none; + background-color: #9b0000; + font-weight: bold; + padding: 0.5em 0.75em; + width: 100%; +} +main {padding: 0 1.75em;} +article {margin: 0 0 2em 0; max-width: 60em;} +article:first-of-type {margin: 2em 0 2em 0;} +article img {max-width: 100%;} +h1 img {height: 0.8em;} +input, select {background-color: #000; color: #fff; font-size: 100%;} +input[type="submit"], button {background-color: #9b0000; color: #fff; font-size: 100%;} +.login { + width: 12em; + text-align: center; + border: 0.1em solid #fff; + padding: 0.2em; + margin: 0.1em; + box-sizing: content-box; +} +.disabled, input[type="submit"].disabled { + background-color: #333; +} +a.toggleVisibility {text-decoration: none;} +h1 { + background-color: #333; + display: inline; + padding: 0.3em 0.6em; + border-radius: 0.2em; +} +div.toggleVisibility { + padding: 1em; + border: 0.3em solid #333; + border-radius: 0.2em; +} +.group_title { + border-bottom: none; + border-left: 0.3em solid #333; + border-right: 0.3em solid #333; + padding: 0.5em; + border-top: 0.2em solid #333; + border-top-right-radius: 0.3em; + border-top-left-radius: 0.3em; + background-color: #333; +} +.group_title h1 { + padding-left: 0; +} +.list_entry_row { + border-bottom: 0.05em dashed #333; + border-left: 0.3em solid #333; + border-right: 0.3em solid #333; + border-top: 0; + padding: 0.2em; +} +.list_entry_row ul {display: inline;} +.list_entry_row .block {display: block;} +.list_entry {border-bottom: 0.05em dotted #333;} +.list_entry:last-of-type {border-bottom: none;} +.list_entry_title { + border-bottom: none; + border-left: 0.3em solid #333; + border-right: 0.3em solid #333; + padding: 0.2em; + border-top: 0.1em solid #333; + background-color: #333; +} +.list_entry .list_entry_row:last-of-type {border-bottom: none;} +.list_entry:last-of-type .list_entry_row:last-of-type {border-bottom: 0.3em solid #333;} +/*.list_entry:last-of-type .list_entry_title:last-of-type {border-bottom: 0.05em solid #888;}*/ +.list_entry_title li {background-color: #000;} +.list_entry:first-of-type .list_entry_title {border-top-right-radius: 0.2em;} +.list_entry:last-of-type div:last-of-type {border-bottom-right-radius: 0.2em; border-bottom-left-radius: 0.2em;} +.list_selected div {border-color: #9b0000;} +.list_selected .list_entry_title {background-color: #9b0000;} + +#qrscanner { + display: none; + position: fixed; + left: 2em; + right: 2em; + top: 2em; + bottom: 2em; + width: auto; + height: auto; + z-index: 100; + background-color: #555; + padding: 2em; + align-items: center; + flex-direction: row; + justify-content: space-around; +} +#qrscanner_text, #qrscanner_video {/*width:100%;*/} +#qrscanner_close {position: fixed; z-index: 999; right: 2.5em; top: 2.5em;} +#qrscanner_video {max-height: 80%; max-width: 80%;} + +@media only screen and (orientation: portrait) { + body {font-size: 4vw;} + nav {font-size: 6vw;} + #navigation_select {display:inline;font-size: 6vw;} + #navigation {display:none;} + main {padding: 0 1em;} + nav li {padding: 1em 0.35em;} + table {font-size: 4vw;} + input,button,select {font-size: 4vw;} + input[type=radio] {border: 0; height: 1em;} + #qrscanner {flex-direction: column; padding: 0;} + #qrscanner_video {max-height: 40%; max-width: 100%;} +} \ No newline at end of file diff --git a/res/dark/mechanism.png b/res/dark/mechanism.png new file mode 100755 index 0000000000000000000000000000000000000000..cfea2163db4710dc5b6b3559722cd13f2aa555fa GIT binary patch literal 823 zcmV-71IYY|P)0i>XA zuu)#1-TDj+o!|*jLb|pBo}f~@Pzfoz3?S@tP6r&6UalQq$BmnQl9zk^=l9vp^|2j* z$ReUXGfPz>qJHf5qKlb_HUrE&OwH$%QmVtuFHT0AQRq$2=001I#l$zRy#kK68rv~?7aT#c)ruJd6 z8Zawth%QBBmzg(;qF618VwIUUL}V8LE<-9r#MiY7nAqm3=8AbsMB7DCSUaUCij0W1 znfbP6-B-5QsS3VbGccRLdyg0q^#V+coKdXVj2wD~#N}9JyY93wBT+Xlx@P9XKSFJ@ zhaJw?Nx9O6YudP`6Ej}~wn@x9B%(eaGI--!%7@QbbNul$~g912;D}-&2&0 zW+1iZHqdIdo~I}q%|Pu{GE&(`17?Xo0{{+$*a`iNBH~UUHv_<#VSmulE@WjbZ75MP zvAn_D<0NA~2n{WWsIRqNACJe)@p#CPYqj^ zi0oG#?z-GA?*+%S3ELGDJRJ8mO-Q^8;a5zjB65$2aj%#vM&h5mNjOo8Fmtw>A3&^002ovPDHLkV1jm> BfK>nh literal 0 HcmV?d00001 diff --git a/res/dark/minus.png b/res/dark/minus.png new file mode 100644 index 0000000000000000000000000000000000000000..db99cc6670ab12a35ecb5770ceb6b53699398026 GIT binary patch literal 1050 zcmV+#1m*jQP){s%=b z@egS82MB=>*hA1$dMOw}ENF8AKqjR9fb`zQHn?92iCx(&<@9r8vBN>3_j-0J>cS+rEZ&`+_>1BfPr$ ztbP1=7{&7^gDw^qu~ys1(^Cf#X`*s^>R_$5?-h%SPX^w%tQ-A_%h-%eRD(dz8R%a}7_@N2L{A~1ks)@htPW^IuUFq|;wLj$Juqpb|uFl zX#V&|K05(2iv}uf^Xi$2RKeaHru}D&~9JckFodfa!GGS^_f7xKS06X#y-QNwFcja>86F#J>AfN}-^fYy%9| zf$!htUDDPTkfz1m=y$EJX#iVWa_|o`2LKR1etZJgz56hm1=!q-oBK|in?BP(uIn@3 zS5kk}4_75TKmQ;N$qTf-A$z;<>3bX{tFJU{;s`VWad*aG+ujurtDez-eO zqL0^yCX#%?G1f#9u9&3ml+;T;X<#SynsuN=Uvx{^Nb0KwK|Pn3JtEoY#QD0-Z)r#C UNMMN0&Hw-a07*qoM6N<$f}02X-v9sr literal 0 HcmV?d00001 diff --git a/res/dark/note.png b/res/dark/note.png new file mode 100755 index 0000000000000000000000000000000000000000..94915573cb2306f1358699ad858958ccda1d4120 GIT binary patch literal 549 zcmV+=0^0qFP))Df0l8N+n?CH2@D$FV4C7Xnf)@tLGuhhZ2Vck9#u zc>6`{g>!DVSAYgUY<2z86M)TpKHtb1z+@jWFCwyPt-Xs2)Bu=|>3sUtT407olX*LCPh#_H%Oieie0m6gZ4JkQ5mx&vep$g*q+0GT!P zF_}zCE*-f6Aw<+hjMb4F0DwFDPhHoc8!=W#hf+!+qO#BOvMlFZI&!qu*G?h&;?&uY zq>vC|W=1c2aGW*A;cSnF-E?nlveB!MqFP%d4$*J>kQ5{He10yv6 z?H94o`Vp(61rfJ)DpXaq;M9?lq66V0I)(a>{}&lZ(SaZ}08Yh5#HbEL2OS;zPJ)T- zKy=ofA}Rv=PJ*rN(t+r#J4JIJ&|2R}Dc>)d>=$V60SB7Z@SF~Pq_tn{aNehWx&T@g z+cwbq2$0+Zj4_W+C4J)5oul(9l(GXsVgTB$@C~z$jcIN> literal 0 HcmV?d00001 diff --git a/res/dark/person.png b/res/dark/person.png new file mode 100755 index 0000000000000000000000000000000000000000..8b3f280c1cbf3d06b3f7fe398f5f24f4db03f7ab GIT binary patch literal 883 zcmV-(1C0EMP)*6s_O1(IwpvSpacZ*0WRDqDk46DOJC?N zAcA{;gbPWvD*Xx>@2TFin z95>o3Ktv}>gcoKOB0Aa@_}ST6&CHW!3o!He#KeU2pIUjW{$8cj{VEoRnYTw#^w_1w z-B_t3Rloy)*7~q>jmJE@s}caPs~rLxD->|uHeBiwW06;`8 zl|?Timwju!E+GKO^E^qCWC}oUApfg8&$nb*=5;%jFGXM>g-1;(r_;fgkhQkQ81ow6kJ6W#&qTC7j^j@u z^9Sufv)N3IF;_g`0ieeibFC*2k4n zrvdCJc}*UR$W>;(9mnyK-;4ezP!z=)W6U0<)P4Yc0JfD3{kzlw42j5HA{t4OLP%xou>Uuo{Gp> zW6aPu0V3*GN?k*F&xNYPB67+Yb6vGstzND5a{yVVsT|W_<}F%ledZs82Y^g#eMSQ~ z*lCi09Mo7ocN(8;R?PebKxZE3;mH*C=< literal 0 HcmV?d00001 diff --git a/res/dark/preview.png b/res/dark/preview.png new file mode 100755 index 0000000000000000000000000000000000000000..f28be3d806ae23a6ec446247d238a7e23161f148 GIT binary patch literal 1116 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 bh#lcy#QjM4`ywOw00000NkvXXu0mjfU&*z8 literal 0 HcmV?d00001 diff --git a/res/dark/refresh.png b/res/dark/refresh.png new file mode 100755 index 0000000000000000000000000000000000000000..7feb5c1b11824a1bc8c5f9bca880b3bc5fab8c75 GIT binary patch literal 1500 zcmV<21ta>2P)0P+4b6iU}DDv2#E~=0)#g7Kr12ys7>3@ zBu=QRQq(V~D#U>UMI2iGg0=@lKg0o*ssdG2njWge4j(CL1t_A5a!8>~3ki@I6Cg28 z2!Z%xcc+I~e1u)wYcFu|?>KK~=J$I$^WK{oAcq`s$l+On%o@n!bCt`gT+2CM3!nl( z2?w`NO+w=Uf&l&|qE3;C#|OQki_cuZieqkRJa*?@&efe9e6_KOsf!W&)^3~K)LSzk zKXm~mEslDHtNQ`IBpW9X=ptjnu3$s>_)`&3=AV}zQ6dL8S3k^#_;fI0hisy4*QL4} z_nw#lkIz*cSK@6P`~@?~KOjThk|5O$ct?iQ?IRi?A5&td0A#gfQt=_8h%wP=pv*rn zKO#?_N$q(G5K$8&>W~C$@3Mkr!zxttkM$Kr1%O+l^ME8sRfFEp4bue_ zw-g*svE~B;345J+&gOHkUrHKLo^M|)j!uR*D_r>!KuMxGWMP)IfreX#Lu*O_Q_)88 z=?_3nR?)WOO8w1oBNH$37uln7^g9k-FEa7vs}13dPV{U0I zdix)}P|1jW<#xFDoLzrTHR?G4s5-fd4NYEKKIjegPIKBeg)2V*hzTTkgN>u@83|a> z;@GB64W#LLkJIyBrsVZd(&DI9xYB|L0cJvEV)gVtbl-`|2IE}asbdOQMcWRu$(Ob| z*C<^11&>C@d|8#-N?Qw;8xr90xytp*1A&CSM%R2QxLXU$WmWb8n4w{I$!h$B$LA`U zZqOAVt8%Tjg#ykzXS12)Jw8`)T#cUq;7X=3uEb9)^v!XmB_L5%K2D#gDOIR6f<^u! zdt8aP0a%#oTMk|kQ(|ppZFBQe3cyrJ{1_Nfhgsy89xb*-<>;?QN)rygCK8YQyzE$s zluAH}R-+_Xdtm}rom|51#_k^G;IA0%%fV~!#O{2*`nMHKO!ARk(`yCg!FY5KxOk`IZZv7`Ru@1n*L(Q^4!rNw(uR2}HB68#)w2zq}Vh57-*UiLN8^T=z z32y<20f0cl_F&`aBfrw)b5&GztV&vvC&QZ4l`JqC*vFy0_5td*OS67THby!}$}JpN zc&%~ti-+4wTb(b-s{99m{8rJr-ROp1JKs`3mw(fHM%?YG{Apwb-gi}xIW-ft# zNsuS6yK+d@hfN6)B=^#*#5%Puw40uO|^DKEA7_md9lP7k>Cfe2+O^}&iueUlk zs;cre2QSZ(dcQzycdBTkhm2!*upxZBAg^GhK*9$E>N47&K;4Xlk7iqEugsME)Ho)= zIpmPTv&H{ZzA|{8b<{)v0000NC}`ZbFXQ{W2d`fp;qFkdV5k>ZedY7re`(YA+?${MxzpgV=|SU0 z!$-EAPdLxa-Je%=x%U2(C7%3hjLbgoS|3!m*a_TWIJ~2S^@I-Ng^SDy(lc*w-MlCI zqW^)k|E^-4bxcePgc;^CylAric&T17sr8%oFHVjIKZX*hIE#ZigB9b2m*-`Gq%DJd XwB1Eb(?bzJe=&Hv`njxgN@xNAwSjV- literal 0 HcmV?d00001 diff --git a/res/dark/show.png b/res/dark/show.png new file mode 100755 index 0000000000000000000000000000000000000000..67de2219ea5b70b1ec18605e8586d79a4bf98034 GIT binary patch literal 1133 zcmV-z1d{uSP)J0MRTw?rot-gV*CgF;(#^Wr4b5soslPyr&{)Aj zOAMPvDfkD7DEJ^2eCUG@K36LueaU0rgsPjJ#-tBz4Hhg~0xE2aUFmnOUj9Sx{~*% z{~Gf|5{9M!2w+2I@|pbb^1?rH9F2g<&CdWF0T8d5#zc?W5%yYqkJ=HjJ1GVrWpeYP z6P_ajGLzp1XchoC_)*=|)!y-Fa5ql>WOsW~jii!lB-KBeXy2`E@3m-9H+2=@{Qy9q z8JWrNIMEhx(kPcMR}$IC8GCqR1e#~WtgUUH`YslHXgqw=;?^4g2G*);oA0r1>WF39 zN&s#%VqXX4;5YNH|54rSMaC=;=E3nYfW?3$59ZS46(`yp)j%EH+3+!oTkm!qh<$MP z^o#`n$F3gz7{szKO5QjNrPQ=bBmYNita%qx=e>b-QOC_)xm z$oeMYieVbxdLSMEo;FNltZyQ&?3n>g*UoeB;~t0y0C4c*ny#G};ktf>ddH)!8^%Tf zK&w{FC*5$4DJB>h~@j4Mcxw-6faG~kW z3AV-__$y~%hijYIzkxt^8lO#-Z?yo>?B6vG9`eHgf$F1-sq(FsowRJ{xI`?|_6rAp z)+YnME{&``=Y}Iv#6S5VUNp9A1B}?XU+P6-yEgE+5}E{1@j-vZj_t33xxqq}5gYYd zJtHq^5sq&L zLQ3cw+^q|m&3QBo%nlZ+PX7AVL7+Rc0;{fX25jVfYP*j|8lFs}b;L4lKXdRGcTGri zcj@ffOJ3#N`;UBl&ol1BSM1k-YwXv+e+-`1K#$tdshj#`4!+|#KY^|)lJb5oT^9bR z=c|D_;$sKTS={=ZgU4;*i;UQZi)UA_dY$V}EU{Ia(RWJI00000NkvXXu0mjf_){7B literal 0 HcmV?d00001 diff --git a/res/dark/skill.png b/res/dark/skill.png new file mode 100755 index 0000000000000000000000000000000000000000..8692d5b6a00ceb848d83a11ec37833dca9e276a6 GIT binary patch literal 1407 zcmV-_1%UdAP)Q>^dzX!af9xi1bi`5fy0=5>Y-# zne`AN2_e$M67-N#7~(@uA_hVsvG`C>&>syJmDos0U5y@E0>MNRSHw+iXJ_ur-gCb1 z>!CX~&fGh5?!7zh2M6w)`+dLj`tJmv(U&#~E^UQp85sA0ADQoSjMJHaZRy7gr?<4Wnc8`djOUqGpNg3bw{i6Wh z=AB0isyMJTmy7m=iJozEY`ZX1rvl$)P$MqVHmEMnVHedJe3mr za=l(Jq{-c%9cShpX1>z$`v5cl*(K&`rE%}*4kB$vvL>!j4@?qKHB!~ z3Ns%hqMbyvlbH{;3XR%PV@x@ku){8E?AoOVvUVw9OH5lrfLD7!+&*r5`i7fXRY-C0Lw*Wz2|vnT?7!(2Bp*)0C$=B-4?8# z2VSGmc&Jn=Rl1SuITLOEhMA>Wtq!?B2$S5GHqKISkR=N1+gN&rAa8>7BE#+cz=_{NxFj;^Cbv=IOn z78Xj(e9mRuFbs>m1bpDKn2a%_M6|W7t~uZ^L5EuWr-*2)F=mwAE8p?S$;spsnTVco z1ggaev(~Oo!nW3~Ng!Ht9J9F=c6Fp>^P$mbTyV_EQcRz(wSF%tKx@4R@jG4#DNHGK zh=?}C3K$$5v;e+J1K4J-*J`zn(l-c#0)VYKa9gdQlsaaueWXJG05J2B9N^`Ffq{-R zDijK<0XQFa4z^rteZPF^xDzw;NdPZo1V06!eal;s124%~YwZCsc_||Mlv0@n6p=qf zA;eCQD1dEQxO{szF7w5Up{$CXm;XTs1m3l}beq4GsMSU;~!kPH3%PihGfGG?&X|7Lk2R%{;OTNiVwI_UGs4 zCjs1CYW5;>CX;~S;b8`FdWrdm#+bw_tIL0n(+)oUw6n!xF~}@HM3y>*PIi0g@&zgm zKK(Mw%wOac;CyLcY!i|9ec!*{&Bx`0EIRlsrrieci->&cdEW6}&MpFa-gg(leif1Z z*4onp0|R%{1ojl5lv>$m^1oSYpDh#$L6%^bHSlmh*^9`YtmIt(&4O N002ovPDHLkV1lySmtX(@ literal 0 HcmV?d00001 diff --git a/res/dark/sort_asc.png b/res/dark/sort_asc.png new file mode 100755 index 0000000000000000000000000000000000000000..2df5645cca2e1244febb1c6c2b98d106427e9495 GIT binary patch literal 434 zcmV;j0ZsmiP)20zGNDmSq zfk06inxT>7w;m0^5Aa~iruf^WNDB}IK`6;;=muu?ed9{0K^uMcras@AKjquWfe0v# z&OPDMm~Yw3Eg&``pfuTYAa-4O`7a;>N+WfkG$Noh|E>;%4CTzre*qCt9A@4#vrlyF zQ~STN*4A3<1AzC)wtt9dZHzf56#xK4)F`D60Nx_my)yG!Ykf@VJaEqet@Y7+zl&wm zd%w%!JP_;)-DCD+q0Mil)MwY=)H)Cn)`f?Y2>CD=_pt>$EThJlGc#`hTxZz6GV>;N z(zXPJ7v|~(7%>V!Z literal 0 HcmV?d00001 diff --git a/res/dark/sort_desc.png b/res/dark/sort_desc.png new file mode 100755 index 0000000000000000000000000000000000000000..191a7283a8d3b12fee39dca44c47aa2ce5a21938 GIT binary patch literal 394 zcmV;50d@X~P)MH;>|ht z)q((wd5MSyL_7gN4*)$Po``5D*~p&?aL&C0!2a&h{`RbWy!QtYxh|c_6V1ZRqljGA z1c=CmnMdtD7a^iSM9vSIpU$}zKLm)#F{1hD9JTumcr^F9en_o5Kl6IOa^P;?_ldf{ zWAY(42M{snIas5!eV>X-J_G_5_I)aP`S8r#w~!AzfULP+BgzjYz|6T{qnaPEz}&A< z#Sfdm(_3qAzSeTK-VaD=&WoCO{j@0c}ix oHtIQ$>xq}Y0TW;thVj4o0l!?jH-r)F2LJ#707*qoM6N<$g2NE0=Kufz literal 0 HcmV?d00001 diff --git a/res/dark/star.png b/res/dark/star.png new file mode 100755 index 0000000000000000000000000000000000000000..8dfaea9a2b35cee0c6c9c4fa9673dcd3aa7e5b2c GIT binary patch literal 1049 zcmV+!1m^pRP)6IQ0PFbux~FgK;iT;Art2j|=Z$+uIoKd`sX zxrMUgmNo)m7=8<&RiJ4r48u!RBynb>X?lcYw?Os>)=ks&NExw983AkUHvrlmUD|n{ z1H&BDL7Jv>*4jS-_^vK5MC9W*j{Aoupxf=*R;#rf1i>nRHDk;t08RinJ!AZz0sN9> z*&hJ5NN)Ffy=U!qTV@u}>-CzAMq|Yovu2E01@I|=RRC)MRxo~(DibMy9ROPZwgLQ} zW!ZL?Wm`#-?99*4@4X{HRlhdId@)3F85Qi%C4m5*4a8+x_RxsPu^)m_=Lk~{<8 zLEX#&JRo_-TKjU`%Zcl~wf42Do&|8PM)LPm^{ln_^`r(@a%-l*z10C#I3e^*t{ zMN#x-TBCh;+$f6rs(JyytwSV#OI0sKQFNd}?;WIR8k4-~QS;AgH`6pNTyJ?*qkDUM zHjd*iiv4-bf?em_2aQIfa5d^xv;{%1SRr`;Xc=R?YBDbYVHh5(ko-(ByaX6yDnIM@ zjp1AOe_pi!-x$6EDxX5WF$xRl^?EUYjYANyvAerlco{7$pwVcoqx%100EnB-X5ky1 z!UBvjvrHf6<^`WvJ_39{;5#IblROUKj;Da~7YmZN3zh=+RrTa(e^ot6@_s=dx2q8F zbf2J)RrP$Q)0sG`olYlE)$=4D@8j!fspOL+S(p;+iK<@g_xrY}zka`ORrMmtCzJdp zNmAMoJXH1cm>{oI^>UIV%>yK+sj8Prz8dvEZW?mf!nsipWxFjz=IOOZgS8BYCYf$EtcoL=Nq&NJQ3D^~zzzs}=tMtn9B1 Tlh>><00000NkvXXu0mjf%XaBT literal 0 HcmV?d00001 diff --git a/res/dark/teacher.png b/res/dark/teacher.png new file mode 100755 index 0000000000000000000000000000000000000000..d5616cab5785af2133f8f35a65022b5239d63cc4 GIT binary patch literal 1204 zcmV;l1WWsgP)1aLkyaN zN~s_!>T@kV)h8=H`=A9yL_`FGNI)n)`XCw$qM}%-je+=s-9(7dY_hxFZf53uFa4Dc>7o_IE?F46Zo`JkL8xMECU=_bX;T76idYnnTe&koMh=!#xL%^+^76 zW_~0Hf<~58iF2UPzltCtQc6wuzQ0D<=Ry`PF!Mb@5QKS-MfX5_%_qd!NvA!}o9=-; z0eG$m`69&1LJ|=PAs*@>#;?Bbf7wq`r3BRLbxA}sPTij+WBfQM@A9UW|C!%jk#wfJ*cMCodb=H3f;3aGA(0@sQB%-6y^J~8EuUKo# z5*q9bSZiMpLfpyBuMiO#V?y6AbzSt&Km~Z7_qtoLwY3!v50}b#3my5pCLmrhIXP(n zw27#YiY}I1BGPiCyqqX)t%L~zE)db}3H5yukdY&0=0sTn#+~<%q?C^_^HV~Ixwvn$ z+4QNqd)8d!Wv^KRTr3e0S!=%);+g?zS1OfLM09pH1mtC}X#!fY_jMv7rPLn@8$2W; zQ1Z=zq@5%&ZtwJssPqp2&bxnE%>0C7YsPGMCB;xmjR9DW{64&DbXqM5;M2&qtdttd z<5X6_Coz)Kj&0es8DkEo#CS9ES=CyP$L+?Ln*nS^K5z9~z_~P%@&9IH%x&@Z%sk_W zpH1tBnV)t1W~g5P@PSKGDRrY`n|Ezm>#MF!2O)h_z%EZg;-@0E-( zQviMd@HaD`aBWJd;pi*XWaiTjfq4KLz(u80>HE* literal 0 HcmV?d00001 diff --git a/res/dark/time.png b/res/dark/time.png new file mode 100755 index 0000000000000000000000000000000000000000..1e50cb78f317f37feb68d5be923f62d310be954f GIT binary patch literal 1187 zcmV;U1YG-xP)72*n4V{5OiBm!66*J@xF9daxn2;}|8B9!wiz$w~rMvE=d0yy-z>Wjw4L z?d~X+KUjoDqxZh=&Ft)(H_H$JQp!2bd5tl48^A39^8hLUuGubK051U?0B9Ivwuopm zj^n>W_|HqaN<=F}v_nKD=e0vbD^kkpJ0q@?nj@lhBI*?&?q5A3T31TVjg7bvqD(|< zfr+OHSrbB(N9DyvjQS$y{1*U=L%I-vZ2+6bm`BE#XG*E&(a}){0IJpMdr=hKV2mv= z#+Cro0DJ*}53#pTMBheHv|l*#TI+j6bUY+t{}9otl=5a)yHd)VM6_ycq}e{!THh;5 z{=pFAZLRgP5F#lWAR$DewO%HocA77(^~1d69}XeEA*HMoC7v=O6(ZUQBEn7^-;mT= zFW2jJp2=7S)a!L_M?d{1kAcU;6%0(duNwL4ZyEnfIXyHq|&iF{`A zTI-*i&1UY=vLgJEcyi$qYu9;y=$5lOKRi6-MD(weve1LcPA7jVucdajPgsB0HuB7Q zDdn6M|78&Y^?IGB+}OR;C$>!w&MlRBR~xPMSJuXZA_8nMDk)3sy5FhlM?cThaf0!K zwew?90X881RO+22fE)lyrP6%>?#=OBDfLqUpP$;#g%AQPm*-AX*>WC4%uk6|i#Q~r z->sd)5CW{tRX-I6@aBedE}bX0@tnOnvnPajKZF3AJ874z-AM78*LORP;}>}y2_Y%~ zuAhC6qA18TvYfWvHqLpC+ijqW%_5Fc2nP|6#*Hy{o1?#n9l#j#sGyUNJtv=qVxPk8 z7Ds;r?sj@s#0g{U6R#=Q2&8bE=jc}t22e^h3;OxUk5aeWExd0S!mSeFP3Z#w&}y|h z1^s;Je=nEI{}E9Gz#f1dW6Z8nYHw<4>U9>wtyZfuJ3H$(U5i3Q#>0F{TLR#7d);S@ zA&z4Z(Sa4UYmC_;qCc|MiWm_c!x@Fs)6);i<#MLTxF8}4AWvXk0NCc7e>1GZ$;rv} zBuQR5P2C9nirFB$i=yZTfZPHA{089b3w}QV&;YOx;IT1gPiwuGB+1d+3|nq4UPkDb z`vw9SV++?S0;KrCOudz0&!Arn7ZpN6cu_SZjz|dsQE?c`!Uw$svo)B10 z?)G+fu;kh@`MHu|h^kvC2qBV`66DIDL+CAKXk4_V93bSTJ|srk)B|D5Dxr|6tOA59 zY=uIm!WIy=v>1SV_R=D7#f!U+fva0ycSKy>1C9|yO#Ts*BVwWt`Nn$8+HSWy05CH% zb9u+CXPDH3?##HduNwH6l$Sk5x(7xOb7`;J{10tGUsX7obMLDvIIJ0CGxFXmyPF|jMY!8Yi5O#Z#nr4wZQ`y{t!Zkv~4^?ui; zJ;C1_H*FR;+1RlrW!e4E($aaQk&W_|+PUHEE42!eO~QSq%Dr$BHhP>GSjB!@&Zqch)vL7~Z?>p@P`AGD{=4Xbm8&)uS>*y0Ob30QfiCbPjXm~Q5;rO+k+^h_5Ce~Q%grZz|X}u_?!eaXb!V-TWgE>I)UVxq#bwhXux)Me zRY8V^&lfYU>~;IwdVsru`L#|d>$^SQUthCSihaucptdaNjRZR|S{N8SUHx3vIVCg! E07A#UB>(^b literal 0 HcmV?d00001 diff --git a/res/dark/truck.png b/res/dark/truck.png new file mode 100755 index 0000000000000000000000000000000000000000..6c9fce6a6269c20925df7fa527dee2e11f262c1b GIT binary patch literal 583 zcmV-N0=WH&P)a?Blx$*jAZ9he6Ol8>EtzjwZwS!RGl zB9YiDB637>O42plrXq4wcm9gx6u`Zf#_PA%`hML8TuaFV0JPSsR=qZpZ-QiC-|Wpm z!0z>vxETCdII zw;A)>Xf(=1-eY&Q*6;j&ovFa451h63k=A+)z^r1#S0Hu+r3rZ$z{ln97Xb2rzD?m)B~G!UX+ko+tn&j7$=S#}QKe2u^Y z-Z5?qR%?AHWWF@550c}65|4w#Yt-L30?xTJrPPz<-&`s6h2+{r=A1hVHPEy^%ChW{ zoa``vC#wT?m-GPu*4p8gmrSg+!%E^U=wFYNh#W8H>|)u*B63`LWLnfuBoc{c`3nwt VsLa}c61e~X002ovPDHLkV1ih+67K*2 literal 0 HcmV?d00001 diff --git a/res/dark/type.png b/res/dark/type.png new file mode 100755 index 0000000000000000000000000000000000000000..00a17d7099f0eec3908373aae2c32abc2e724738 GIT binary patch literal 914 zcmV;D18w|?P)oGyAVty=iU$uODB?*(L`1BL_*Yax zyp~o(iijX0{t+Vh0}+qn!BYt$B@~fT>W_m5LGjS4loB_)JM-QfFB?e4ne6Y~^ua>d z%)Wd-JG0qMEM_Pok}O?qNhxQ?#>PIU>@&0~IreT^meoSUBfAw)2qJGl?ua4)xgv@J zZEa6rw0h}VheHRrsRCE`5*WQq6+0Q(K$dt=`CzMm~Z2+`0i zrx!89e*u7fnk9TgGxk+%KnUUk=X?MW-0Y$vHUMBobLMYq#`=hODG?wH0RRJt;M*w- zu?7Isn(#}Sv2LpHeTZoT;=eEnjQ`!p35zKL_{;} zctpHw2!A&B@Vyd3m=GI62qOX!@9Dw=Kyl%tAk>*?wOSP-(uMCJ;+ew3M?ie)A=>SB zg^2EtT=*ymA;b(KJ}`toU3T^;h(Ct#@qh1@i0I#T0ATdOM?~x(;>ofzMn$Y^!YBKu oVFVD{0I++)D~J{%9?!b>KPbX~*Jw-<#sB~S07*qoM6N<$f~ljLCIA2c literal 0 HcmV?d00001 diff --git a/res/dark/unavailable.png b/res/dark/unavailable.png new file mode 100755 index 0000000000000000000000000000000000000000..8e88e82dd71b5924017cce37aa058c6089572c34 GIT binary patch literal 1522 zcmVGxyzl zyU3gP=FNL=-pfqX9+<`4x%b@jx#!$p=MJF@qNFUdQsZRIUH~Hib^sWJwOarHME?T# z2f(iY9$4ldjO$)w`9x}``hUm5d?1nx>w+-`*l5*&o8SZ;t*)Y!-8YW&wxiVjjz?Y#ant}S z2_v>(m`^Gxhx6)HQf@cQCk?QWpnF9NakNw8KTS~nSTj%7N+qw;0jd>?o@Smfz+zlq zT8OEQ8b6h=a-3H^J%gPZ9^;WgLv+3?5JA|q8qa+0PNl-Rl;x1C)6=Ylm@t5ffyfq4 zzUz*r#Jtu*9NR2_^#OF8Lout}itoCksSRs|f;2?;+AMX?5<*47_g?A}8?5s!VPgRO zTp-rMDQeHD*vh`=m0R3KbpG~7AF&qV*hV0<5Qh!XvLX6ONtt`%U!9)jn2Eg_yJH8( zgQlf2yxL@esFg~N7UE;g{7J1)@C@)(qpt6|2kTq5^lQgCsHEJQ6+%fl*s{bj&qgZ^ zMMqyVPsWUBDufo|!%+Jv1Dpv17^3e2&wigPl-Bl%CNDG&fD8blUOx^XJUJfug~I1i zMMCRutPt-3Fri{5t-lT+wyl>Ey%cHASUY9|K(0fZ-{1cQfJdPs8Q2`0MXY_Nxhp>1 z^W;fAPFVo)ejEf@`&J&qvP#d=QXR~vn+gM)SxH%jwYx(<8SQy)kN>d@M z?e97T(WR!Z#_V;lc87i1FVT%WI)&DAS_qKVXAnBylQEM3x_aleL^mTBn33?xuvSTk zhk2B${{CX(oQUX765sPiv=HOfty@!%=P|bJfFWu+xK#%RwjqZY=4(pIA^>P1-i_HO z8vDSThUmv&ADC~n*Fqd#Z$or3t*`39z_!RqVFl5S=J)S+asjL=PyzUS>s>nlElh~}GO)$>NOnH~esfavXQKpanm0G>qJooUyX?|CDU zHuEqNx8i%0NKJR z)AdwIIUH@Pq%1ecnlsGIC%XpFC5Rx4*Ob`~|2Pv-xKJw=GiBWj(Vv?QQ7e@^6HP%f z&xG9*ccq-j2=HYlfDRxu^JLPMGVF!urG7C>CLzdXWb;A*QGW{2Hc=2<>K~_G>O+RK zq*bm?Pq#g8_?|axh-MAZLL1|k4bes4b=PlzX%KfRmF#JizzZ#jEiFW*Q0hdIAcCY? zw!{{Ym|9fYaSlBvh^PnewSB!wNbat_01)kyyCFq!>2;-rn8-3GHY#^26^;!XYUYWon_ZgJN+mB?=O1^~_z*;vN50Hwr_hKGcjJ+-+s~|* zEYZ!zGwb56T}ws?ynO3c_?dMNtbOB|J+n6CMSbYbE&toU8bswq`Ljo+IgkP7x&7Vd YKW)k3pd5oM{{R3007*qoM6N<$f<4O9NdN!< literal 0 HcmV?d00001 diff --git a/res/uncheck.png b/res/dark/uncheck.png old mode 100644 new mode 100755 similarity index 100% rename from res/uncheck.png rename to res/dark/uncheck.png diff --git a/res/dark/undo.png b/res/dark/undo.png new file mode 100755 index 0000000000000000000000000000000000000000..859696d4db31a5a2bea290dc7b1eb4a3b54f5ded GIT binary patch literal 1208 zcmV;p1V{UcP)4y=g9P!RRq2!X5jRn~My{4m(O1|YD4#uw@)lROfutc$GO`@6}MEcD0nrA$dWtahqo>?+v2m1pw+ z5G2;&vVVq8yFDctpD>v&Fq7<%?fQd-ole9TkZ$rlusM)t)9EzI(z9EJoGa-P1OO20 z_jP#wlhEC2vvj5}t)h7VSWntHufuBFk^lfeW)?z+B*C| zmTz)=BWd?Bg4qG)UHEUc#VfS)CV*xj)t@+P-*kpa9*;h-VW?v7Z_8fg+(D3tr1y{d+$Lw!zGiB?FY#%49_q=AjP!H@u+wx` z=e~MunymQke!I_~dF#tUsx>(VqLXR519`hvSxM=z+(|~CPSsZwFLO?b{~Ul6wT9wF z0pLAwI|k6NDZ0js0^p8DQnU>h6F_uP3(@6b0$8+FGtv2C0thaM6WZe&EGB@uc@fbW z>tHNe6aaRwzZ~FsS3FFz3n-F0Af4%k`7LxMTDf7MXaI=K^K)Ys@{Ni;Gso6~2T1mn zm4bQiEDa6(y{X}wyJ5itsAPN}fbu(G+z553=BdGZmj(q55dVCgqM7dz000*96%}%> z&CMxjfRflm6TtNV01^?|rn?vB6fA%f@db$W(V2(_of7|{RCxspAl>BK0IC4GpgrC_ zCC$;4r?P@P(CDywhK&0iK8Z~$(PRV`fm5{QOetF+lVIJM-*@qz-d zd;MNzPn~7Z=~%`3V{02na=OXBuZs0o3mulnby#g*Z7*5L?)7hRBHm!`BmJ-YtA7Cm Wuc4@VFH|)E0000'),this.element.appendChild(e));var l=e.getElementsByTagName("span")[0];return l&&(null!=l.textContent?l.textContent=this.options.dictFallbackMessage:null!=l.innerText&&(l.innerText=this.options.dictFallbackMessage)),this.element.appendChild(this.getFallbackForm())},resize:function(e,t,n,i){var r={srcX:0,srcY:0,srcWidth:e.width,srcHeight:e.height},o=e.width/e.height;null==t&&null==n?(t=r.srcWidth,n=r.srcHeight):null==t?t=n*o:null==n&&(n=t/o);var a=(t=Math.min(t,r.srcWidth))/(n=Math.min(n,r.srcHeight));if(r.srcWidth>t||r.srcHeight>n)if("crop"===i)a\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n \n Check\n \n \n \n \n
    \n
    \n \n Error\n \n \n \n \n \n \n
    \n',drop:function(){return this.element.classList.remove("dz-drag-hover")},dragstart:function(){},dragend:function(){return this.element.classList.remove("dz-drag-hover")},dragenter:function(){return this.element.classList.add("dz-drag-hover")},dragover:function(){return this.element.classList.add("dz-drag-hover")},dragleave:function(){return this.element.classList.remove("dz-drag-hover")},paste:function(){},reset:function(){return this.element.classList.remove("dz-started")},addedfile:function(t){var n=this;if(this.element===this.previewsContainer&&this.element.classList.add("dz-started"),this.previewsContainer){t.previewElement=C.createElement(this.options.previewTemplate.trim()),t.previewTemplate=t.previewElement,this.previewsContainer.appendChild(t.previewElement);var e=!0,i=!1,r=void 0;try{for(var o,a=t.previewElement.querySelectorAll("[data-dz-name]")[Symbol.iterator]();!(e=(o=a.next()).done);e=!0){var l=o.value;l.textContent=t.name}}catch(e){i=!0,r=e}finally{try{e||null==a.return||a.return()}finally{if(i)throw r}}var s=!0,u=!1,c=void 0;try{for(var d,p=t.previewElement.querySelectorAll("[data-dz-size]")[Symbol.iterator]();!(s=(d=p.next()).done);s=!0)(l=d.value).innerHTML=this.filesize(t.size)}catch(e){u=!0,c=e}finally{try{s||null==p.return||p.return()}finally{if(u)throw c}}this.options.addRemoveLinks&&(t._removeLink=C.createElement(''.concat(this.options.dictRemoveFile,"")),t.previewElement.appendChild(t._removeLink));var h=function(e){return e.preventDefault(),e.stopPropagation(),t.status===C.UPLOADING?C.confirm(n.options.dictCancelUploadConfirmation,function(){return n.removeFile(t)}):n.options.dictRemoveFileConfirmation?C.confirm(n.options.dictRemoveFileConfirmation,function(){return n.removeFile(t)}):n.removeFile(t)},f=!0,v=!1,m=void 0;try{for(var y,g=t.previewElement.querySelectorAll("[data-dz-remove]")[Symbol.iterator]();!(f=(y=g.next()).done);f=!0){y.value.addEventListener("click",h)}}catch(e){v=!0,m=e}finally{try{f||null==g.return||g.return()}finally{if(v)throw m}}}},removedfile:function(e){return null!=e.previewElement&&null!=e.previewElement.parentNode&&e.previewElement.parentNode.removeChild(e.previewElement),this._updateMaxFilesReachedClass()},thumbnail:function(e,t){if(e.previewElement){e.previewElement.classList.remove("dz-file-preview");var n=!0,i=!1,r=void 0;try{for(var o,a=e.previewElement.querySelectorAll("[data-dz-thumbnail]")[Symbol.iterator]();!(n=(o=a.next()).done);n=!0){var l=o.value;l.alt=e.name,l.src=t}}catch(e){i=!0,r=e}finally{try{n||null==a.return||a.return()}finally{if(i)throw r}}return setTimeout(function(){return e.previewElement.classList.add("dz-image-preview")},1)}},error:function(e,t){if(e.previewElement){e.previewElement.classList.add("dz-error"),"String"!=typeof t&&t.error&&(t=t.error);var n=!0,i=!1,r=void 0;try{for(var o,a=e.previewElement.querySelectorAll("[data-dz-errormessage]")[Symbol.iterator]();!(n=(o=a.next()).done);n=!0){o.value.textContent=t}}catch(e){i=!0,r=e}finally{try{n||null==a.return||a.return()}finally{if(i)throw r}}}},errormultiple:function(){},processing:function(e){if(e.previewElement&&(e.previewElement.classList.add("dz-processing"),e._removeLink))return e._removeLink.innerHTML=this.options.dictCancelUpload},processingmultiple:function(){},uploadprogress:function(e,t){if(e.previewElement){var n=!0,i=!1,r=void 0;try{for(var o,a=e.previewElement.querySelectorAll("[data-dz-uploadprogress]")[Symbol.iterator]();!(n=(o=a.next()).done);n=!0){var l=o.value;"PROGRESS"===l.nodeName?l.value=t:l.style.width="".concat(t,"%")}}catch(e){i=!0,r=e}finally{try{n||null==a.return||a.return()}finally{if(i)throw r}}}},totaluploadprogress:function(){},sending:function(){},sendingmultiple:function(){},success:function(e){if(e.previewElement)return e.previewElement.classList.add("dz-success")},successmultiple:function(){},canceled:function(e){return this.emit("error",e,this.options.dictUploadCanceled)},canceledmultiple:function(){},complete:function(e){if(e._removeLink&&(e._removeLink.innerHTML=this.options.dictRemoveFile),e.previewElement)return e.previewElement.classList.add("dz-complete")},completemultiple:function(){},maxfilesexceeded:function(){},maxfilesreached:function(){},queuecomplete:function(){},addedfiles:function(){}},this.prototype._thumbnailQueue=[],this.prototype._processingThumbnail=!1}},{key:"extend",value:function(e){for(var t=arguments.length,n=new Array(1"))),this.clickableElements.length){!function l(){return s.hiddenFileInput&&s.hiddenFileInput.parentNode.removeChild(s.hiddenFileInput),s.hiddenFileInput=document.createElement("input"),s.hiddenFileInput.setAttribute("type","file"),(null===s.options.maxFiles||1")),n+='');var i=C.createElement(n);return"FORM"!==this.element.tagName?(t=C.createElement('
    '))).appendChild(i):(this.element.setAttribute("enctype","multipart/form-data"),this.element.setAttribute("method",this.options.method)),null!=t?t:i}},{key:"getExistingFallback",value:function(){for(var e=function(e){var t=!0,n=!1,i=void 0;try{for(var r,o=e[Symbol.iterator]();!(t=(r=o.next()).done);t=!0){var a=r.value;if(/(^| )fallback($| )/.test(a.className))return a}}catch(e){n=!0,i=e}finally{try{t||null==o.return||o.return()}finally{if(n)throw i}}},t=0,n=["div","form"];t".concat(t," ").concat(this.options.dictFileSizeUnits[n])}},{key:"_updateMaxFilesReachedClass",value:function(){return null!=this.options.maxFiles&&this.getAcceptedFiles().length>=this.options.maxFiles?(this.getAcceptedFiles().length===this.options.maxFiles&&this.emit("maxfilesreached",this.files),this.element.classList.add("dz-max-files-reached")):this.element.classList.remove("dz-max-files-reached")}},{key:"drop",value:function(e){if(e.dataTransfer){this.emit("drop",e);for(var t=[],n=0;n1024*this.options.maxFilesize*1024?t(this.options.dictFileTooBig.replace("{{filesize}}",Math.round(e.size/1024/10.24)/100).replace("{{maxFilesize}}",this.options.maxFilesize)):C.isValidFile(e,this.options.acceptedFiles)?null!=this.options.maxFiles&&this.getAcceptedFiles().length>=this.options.maxFiles?(t(this.options.dictMaxFilesExceeded.replace("{{maxFiles}}",this.options.maxFiles)),this.emit("maxfilesexceeded",e)):this.options.accept.call(this,e,t):t(this.options.dictInvalidFileType)}},{key:"addFile",value:function(t){var n=this;t.upload={uuid:C.uuidv4(),progress:0,total:t.size,bytesSent:0,filename:this._renameFile(t)},this.files.push(t),t.status=C.ADDED,this.emit("addedfile",t),this._enqueueThumbnail(t),this.accept(t,function(e){e?(t.accepted=!1,n._errorProcessing([t],e)):(t.accepted=!0,n.options.autoQueue&&n.enqueueFile(t)),n._updateMaxFilesReachedClass()})}},{key:"enqueueFiles",value:function(e){var t=!0,n=!1,i=void 0;try{for(var r,o=e[Symbol.iterator]();!(t=(r=o.next()).done);t=!0){var a=r.value;this.enqueueFile(a)}}catch(e){n=!0,i=e}finally{try{t||null==o.return||o.return()}finally{if(n)throw i}}return null}},{key:"enqueueFile",value:function(e){var t=this;if(e.status!==C.ADDED||!0!==e.accepted)throw new Error("This file can't be queued because it has already been processed or was rejected.");if(e.status=C.QUEUED,this.options.autoProcessQueue)return setTimeout(function(){return t.processQueue()},0)}},{key:"_enqueueThumbnail",value:function(e){var t=this;if(this.options.createImageThumbnails&&e.type.match(/image.*/)&&e.size<=1024*this.options.maxThumbnailFilesize*1024)return this._thumbnailQueue.push(e),setTimeout(function(){return t._processThumbnailQueue()},0)}},{key:"_processThumbnailQueue",value:function(){var t=this;if(!this._processingThumbnail&&0!==this._thumbnailQueue.length){this._processingThumbnail=!0;var n=this._thumbnailQueue.shift();return this.createThumbnail(n,this.options.thumbnailWidth,this.options.thumbnailHeight,this.options.thumbnailMethod,!0,function(e){return t.emit("thumbnail",n,e),t._processingThumbnail=!1,t._processThumbnailQueue()})}}},{key:"removeFile",value:function(e){if(e.status===C.UPLOADING&&this.cancelUpload(e),this.files=without(this.files,e),this.emit("removedfile",e),0===this.files.length)return this.emit("reset")}},{key:"removeAllFiles",value:function(e){null==e&&(e=!1);var t=!0,n=!1,i=void 0;try{for(var r,o=this.files.slice()[Symbol.iterator]();!(t=(r=o.next()).done);t=!0){var a=r.value;a.status===C.UPLOADING&&!e||this.removeFile(a)}}catch(e){n=!0,i=e}finally{try{t||null==o.return||o.return()}finally{if(n)throw i}}return null}},{key:"resizeImage",value:function(r,e,t,n,o){var a=this;return this.createThumbnail(r,e,t,n,!0,function(e,t){if(null==t)return o(r);var n=a.options.resizeMimeType;null==n&&(n=r.type);var i=t.toDataURL(n,a.options.resizeQuality);return"image/jpeg"!==n&&"image/jpg"!==n||(i=ExifRestore.restore(r.dataURL,i)),o(C.dataURItoBlob(i))})}},{key:"createThumbnail",value:function(e,t,n,i,r,o){var a=this,l=new FileReader;l.onload=function(){e.dataURL=l.result,"image/svg+xml"!==e.type?a.createThumbnailFromUrl(e,t,n,i,r,o):null!=o&&o(l.result)},l.readAsDataURL(e)}},{key:"displayExistingFile",value:function(t,e,n,i,r){var o=this,a=!(4u.options.chunkSize),s[0].upload.totalChunkCount=Math.ceil(t.size/u.options.chunkSize)}if(s[0].upload.chunked){var r=s[0],o=e[0];r.upload.chunks=[];var i=function(){for(var e=0;void 0!==r.upload.chunks[e];)e++;if(!(e>=r.upload.totalChunkCount)){0;var t=e*u.options.chunkSize,n=Math.min(t+u.options.chunkSize,r.size),i={name:u._getParamName(0),data:o.webkitSlice?o.webkitSlice(t,n):o.slice(t,n),filename:r.upload.filename,chunkIndex:e};r.upload.chunks[e]={file:r,index:e,dataBlock:i,status:C.UPLOADING,progress:0,retries:0},u._uploadData(s,[i])}};if(r.upload.finishedChunkUpload=function(e){var t=!0;e.status=C.SUCCESS,e.dataBlock=null,e.xhr=null;for(var n=0;n>1}var s=l/t;return 0==s?1:s},drawImageIOSFix=function(e,t,n,i,r,o,a,l,s,u){var c=detectVerticalSquash(t);return e.drawImage(t,n,i,r,o,a,l,s,u/c)},ExifRestore=function(){function e(){_classCallCheck(this,e)}return _createClass(e,null,[{key:"initClass",value:function(){this.KEY_STR="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}},{key:"encode64",value:function(e){for(var t="",n=void 0,i=void 0,r="",o=void 0,a=void 0,l=void 0,s="",u=0;o=(n=e[u++])>>2,a=(3&n)<<4|(i=e[u++])>>4,l=(15&i)<<2|(r=e[u++])>>6,s=63&r,isNaN(i)?l=s=64:isNaN(r)&&(s=64),t=t+this.KEY_STR.charAt(o)+this.KEY_STR.charAt(a)+this.KEY_STR.charAt(l)+this.KEY_STR.charAt(s),n=i=r="",o=a=l=s="",ue.length)break}return n}},{key:"decode64",value:function(e){var t=void 0,n=void 0,i="",r=void 0,o=void 0,a="",l=0,s=[];for(/[^A-Za-z0-9\+\/\=]/g.exec(e)&&console.warn("There were invalid base64 characters in the input text.\nValid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\nExpect errors in decoding."),e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");t=this.KEY_STR.indexOf(e.charAt(l++))<<2|(r=this.KEY_STR.indexOf(e.charAt(l++)))>>4,n=(15&r)<<4|(o=this.KEY_STR.indexOf(e.charAt(l++)))>>2,i=(3&o)<<6|(a=this.KEY_STR.indexOf(e.charAt(l++))),s.push(t),64!==o&&s.push(n),64!==a&&s.push(i),t=n=i="",r=o=a="",l - -
    -Es sind Fehler aufgetreten:
    -
      -
    • ###ERRORMSG###
    • -
    - \ No newline at end of file diff --git a/res/frontpage.jpg b/res/frontpage.jpg old mode 100644 new mode 100755 diff --git a/res/light/active.png b/res/light/active.png new file mode 100755 index 0000000000000000000000000000000000000000..228054e97dcc677175186ff5138cb344775b5715 GIT binary patch literal 1104 zcmV-W1h4yvP)7+*eRj6+ak zHcFTu)M2Cp(~OWbUk05@Em17XYv7)IVf<1t+W0aK$Op8(P)suhIDIH1h~OkaPRV2R zcDE0ADJU;@`|LwK`|)O;{r`Tu|GnM)FMx@S>2xLckjh(MCla$_nAS1V=}P3R3Is2B zq_4Zu_tjKWVwut@)9GsDtm@zXQSjF%`u?oE@#Qq-@lZLuhptA!jt)CGNIZU<@}f$XQVDxBM6n62^9RTguhzK zd(X@co6D4=1a+}<2GZ&6xUS~%-kP+q*i1XjQCHxcAX<*JMEm7^-n#i?@|h+Ok~k{} zm6h0-(Av1Kt@im*8BG-kN-${&6ntY++qZk$YZr~kX}Z85iCjsEcaqxb_jcB249kkV z62y2&7;Z?)yy=-+9qF}0{$j^v29z|xH`{-#`>^Fw-VkQ%2mk;IzWM1Nj_+=0*l?HI zQUXB6u$o=Nuby zlu&-99H}v#E2$Fyyg;(Q!aI6=X0B!Sre+s*>r8I?@u4N++NLS^0?6Zm= zf2Ad&O0_b9fUaeeVA@1Q{4tV4Hxp+R*_QkgahY9-0MoS>LL)B)|Mz3liei`jF7-xW z{DI?eR0<6YG|RyMKOQ*p2YwYu%Ov0{e3PCu1P`Ea4R8*+u*xB+x2mChx0O|Xy1aNBr{xB|=Jph2zan`j+ zFt$GeUJ6mu=>2E#L!-Ash&LMGkGhr0h?X@;JdP{?iLu7acIG&_c9wWvZ6*UiJeH+W z?ph~xoGpz}XuJ^6SrQ{2#Zi?HA3;``NEJ52^bNQh^)lDMdiUMHScRrGcx z4uYk;|9Vjr65@#s8!a-CU8{}-We`M!ctMDliSOr_w5# za+I9p&kobfwv^c@7;Wm~0eF2U8Q5>l0Q~DsJ%Hh{isP)CI!H$1Cgprf3%u%BB^!lZ zV=(Vk8QTR_S;V8o*HT*K!`(4Qm^a{Y`_{XyS?CLnk3_;4{Fs~;^OA2Qu^084^{FiM sMfb>PEb6BQ*z4!QF>e4i6a!=Ey5Ba_X?)iOx=kvYi&kayjRaI?SwS`>GEx~(7_kV`hd!T0A3au&I8@Obv4IgGEYLgxC^?c<<$= zZ7Dr9$iW}7VT(yr^07+8?;C8XT}&^AIQU_k*6p10u8OWe$AG&wX(Yeq;JpI&>oSuM zRqPCO47nXiBl)Eu{7sq3zKB0QU6BCy4|}BKQt}c94+z*J8TbfLfm^6^*el&xyz?ms ze_X(>%1rK#_~Vny4>mQx{-F+@&KLHV;4EBrv&UXGL?OiK>T{{K;8gtVV6fY^-+skCv;OEX$!lW*8_j>Y8RbZ z_~(6#Th9pCV;T5A^9`;FunZ4iF92}xF5T2eTSKl^5%|8b!!#O?yk&9gtblzk13zA< zU`2pj_$+m#Eq$~#v~!=G*XTTMgM=u+CnamZsmo~ z){I2uo@kM#%W?;uuUp(YF93gAB9bqvB*uyr(k%FqBJcpvY*^{hJ)y<}#TvVV&hvus z^AeGcmI4m|Bn#fo_L!Hb)E5mTt`>lQ$>P=p0r;duq@Jjf__DIJXY?N9@1@0A-Y&2A~Q|xXt8d*b{7cGzsZ5}Y0{#@EtWOPSKL~j5-a@TmmnUu7J`2mTGQW2Jnxq(I ziW<@@-F+Ne>PFWYJ3F5)|FNw{7F^OzA0D3g8O#D zAG=*6)f^=tKbC1OixKvus%T%8^Np-|@Fx0W^L0{P9{~}%;&R}hRu%1wa>5r4001}o zXOeY}IzIvVR&)|Z*lAVKJ}WnTNdW-hM(@l*y;T1g0SO7fpHUU8oirNm zX*@*<{df)d7ga@jZ=>Ob0sz1tz6s;Lx|TDP&{c1k685sHXm4)@yl?;j_~ppBt8s3vMfJI<3|7h002ov JPDHLkV1jqVF3SJ_ literal 0 HcmV?d00001 diff --git a/res/date.png b/res/light/date.png old mode 100644 new mode 100755 similarity index 100% rename from res/date.png rename to res/light/date.png diff --git a/res/light/delete.png b/res/light/delete.png new file mode 100755 index 0000000000000000000000000000000000000000..cf3905447243a67c2dee5dcd879aee118905e2bb GIT binary patch literal 311 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC&H|6fVg?4jBOuH;Rhv&5DEQLT z#W5t~-rE_zd`$)-Ezc(&dKSwteQ)FRg5#2V7RPis?^q#yN0fDqY|m#^Uk;y#wW?2- zJ1EXtwv)*t`_>%Y;=4iWUYfD{Ca!h5y)B)ge9azahIhsCdWOgJS_~Lwn2G$)3Fb)b zFf5yYC1GZ5r>#MBmYx}Vgogvi!J~09*0+8uM87_7->P!JjVZ^Bd&bQd@6^lfXWop^ z-roMEe9!Lh=MU_ORo!mEkk4}MOX5?8KaXWBq=XWb8O_j$|LPNda;~3r+qtatz?r;v s_jXt3r)`hgxm0PZ)mfm?DhHl1#;z;8@8x|g9O!8VPgg&ebxsLQ0DKE~hX4Qo literal 0 HcmV?d00001 diff --git a/res/light/department.png b/res/light/department.png new file mode 100755 index 0000000000000000000000000000000000000000..44ced0dad7c5ea3a597a56503d8952a56033bda8 GIT binary patch literal 206 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC&H|6fVg?4jBOuH;Rhv&5DA?fX z;uw-~@9hmwz6J#W2FGI`{_DTKtD)CiruNcmcWFn1+v(`Z&)uIrNp)g4#W0J}ggJxl z0?&jaUT=@;zu7Nrw=?`_(^b literal 0 HcmV?d00001 diff --git a/res/light/edit.png b/res/light/edit.png new file mode 100755 index 0000000000000000000000000000000000000000..2cb2cc6c17be791f5ba030d7ff27f09e86410b97 GIT binary patch literal 890 zcmV-=1BLvFP)%5w!qW)J*z~hm1QTw8P%wQ# zn>cwU&}djvl~s8`nsQ3QlL(#p+7L>d3Adv2`Hj|jy~N3N0XaKd|HGd8+BhM>Xv0+j zLwF}7h_+NQoN`UT6yA4tSoz;$?0)O{))6$lc1*8)L<2fAqDVgTU*ixntl zhZ8J-@PLI1xDOxh8QxUDZFse1SK0Gx{DhC$gf|o@W`_q^;xSi z=n$dfr=xwLa`7cpemkh}KuZOVmq+^x&&Pzu^}zjK|EiJLT`+nbRCt{LE0?B(;-8hm zvr9S&#jb>l@HzqFd;%&@3-aMgYbD}#BwU8q2>|>G06^twq3D2w2k?3Uj^@Fds-{oJ zsVfPO;5C8crI8B&PwJjD;?%8#hwz#JtCT0f+dS2J!lH!7@R|T|ZhS7==n1n*_yDg7 zXbs#+qEnoFf(Pn<;?kp`eQ++B>(UD)IyfDl`KB~(6_zgck*f3$WOfd{h6eyDE{#a6 zT-tBj1BMdkr{go<6^koe9gK_`*l4IcEy#a$aq@Er#Q9~@Sp)#I2f`*mpEyyDswZIp zzE?p2xc&gS2Agk%RmI5W!0h&KzhMmoNCLwffN~)EtcsCbY<4^EH<;D&A1={&uHTBY Q0RR9107*qoM6N<$f_%M}j{pDw literal 0 HcmV?d00001 diff --git a/res/group.png b/res/light/group.png old mode 100644 new mode 100755 similarity index 100% rename from res/group.png rename to res/light/group.png diff --git a/res/light/hide.png b/res/light/hide.png new file mode 100755 index 0000000000000000000000000000000000000000..2c4020b7110c99d51c7471a6a6b37269881de99a GIT binary patch literal 1157 zcmV;01bX|4P)C9W5ipGSYm)x23Tdp zA|oy`;#Wq9884sji`%{tVw#C=c$+q5(qaYx0PVWNO!NfUlO~FfV4i8I0|tL@dx9&Z^>%)&s5rD#G74={5RG9{@7~W%7H(+ z0#7vebYLL4(uO$T*@ibnpA{!2+Md?&9Iy*-j1V7N0S}Bo#S*+{gg6}ROS|qq8xAa4 zfG-;<4+Q%$LL6hnJ2o7+o-+JHBjv6p_*1oA=xXW?7^2w};qPgs3iYWwom-p{)KpCZWFu?uLx>8PCg$DpAjgJ!}{?w+ruGvkDlzSMU6fwmXmJc4Z z8~p&tn{BA;Ow-6sGeDG@8?Dr?PI)>qMvS_ZSTR!WYl1(<^?RN0HFBw|@Y->PBhIdW z87X%*!JlfCPH5L1?vy1yyix@QxEBJlq?LNTUhmP^7%|c3ZR}8Ix(08g+|2+FLl)pI z?YcwtdbNwMD=pyxR)WH28~$w$yGBI(-p^+9^?IS|8Xf)f-GLY4C(`iT_42EjV@b* zf4X(6WTHzE>iSW0eMUUjL2`H23VgM{zmE}bgmhXlLcDJ+YH66C$qX>!k0J0SBjw&+ z^KEF_abAf?l^+&3LV8#y}p{#96AePhjA#JeozyVCcUdmZ4Grj;6J zfMQ^gEe6%~KVh|ey~2p|em0xyHBU#Tm74VOc_;37JzoQj2fqIc_h zW*3Vt#Z-RU*)SvJ)CLFl=jn))Q@!Tg*a;yHMcxq!(cK?~37k02h${h6Trol%x6#)# XAD)}2#{(o800000NkvXXu0mjfQokU5 literal 0 HcmV?d00001 diff --git a/res/location.png b/res/light/location.png old mode 100644 new mode 100755 similarity index 100% rename from res/location.png rename to res/light/location.png diff --git a/res/light/logout.png b/res/light/logout.png new file mode 100644 index 0000000000000000000000000000000000000000..c3b828a35f995eac56c44e6a1088d7a6a04635b3 GIT binary patch literal 323 zcmV-J0lfZ+P)g79~&xWl#yNPzhyF1SN3hxLgoY z-~#g6n}L1OUgJDD9xP z2;o#pDWk@FDV+y~5YF>FZ)gP`b(yAV%Pb%Ot~uu&vw#4&rIhx}0s=r%N(X8I0Ma35 z#|l6{X2%OaH)h`iK6(MA(ui480gae77if*yRS2}i>@wvVrgAm-C-h}eFXApS+KTx` z)?I+Qm7s3snA>UU0}b_&lJ`(geXT-$v1M?zxZGm~4y-Bggub2je`MCUfa5r}+yS~x Vt{@jko=gA$002ovPDHLkV1hnhf${(V literal 0 HcmV?d00001 diff --git a/res/main.css b/res/light/main.css old mode 100644 new mode 100755 similarity index 63% rename from res/main.css rename to res/light/main.css index 6d03dc9..ef3692e --- a/res/main.css +++ b/res/light/main.css @@ -8,29 +8,36 @@ body { padding: 0; } header { - background: #ffffff url(frontpage.jpg) center no-repeat; + background: #ffffff url(../frontpage.jpg) center no-repeat; background-size: cover; - /*padding: 1em;*/ width: 100%; -} -header.frontpage { height: 100vh; } -header.content { - display: none; -} -#login { +#loginbox { position: absolute; width: 18em; left: calc(50% - 9em); bottom: 5em; } -#login p { +#loginbox p { background-color: #ffffff; text-align: center; padding: 0.2em; border-radius: 0.2em; } +ul { + list-style: none; + padding: 0; + margin: 0; +} +li { + display: inline-block; + padding: 0.2em; + margin: 0.2em; + background-color: #eeeeee; + border-radius: 0.2em; +} +li img {height: 0.8em;} nav { vertical-align: middle; text-align: left; @@ -38,38 +45,34 @@ nav { position: sticky; top: 0; z-index: 100; - /*width: 100vw;*/ } nav ul { padding: 0 0.5em; - margin: 0; - list-style: none; } nav a { color: #ffffff; } nav li { - display: inline-block; padding: 0.5em 0.75em; font-weight: bold; margin: 0; - border-top-left-radius: 0.2em; - border-top-right-radius: 0.2em; + background-color: #9b0000; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} +nav li img { + height: 0.9em; } nav li:hover { background-color: #ff0000; } -nav a.current li { +nav .current li { background-color: #ffffff; color: #9b0000; } main { padding: 0 1.75em; } -footer { - padding: 0 2em; - background-color: #ffff00; -} article { margin: 0 0 2em 0; max-width: 60em; @@ -83,18 +86,14 @@ article img { article h1 img { height: 0.8em; } -input,button,select { - font-size: 1em; - width: 12em; -} -input[type="radio"],input[type="checkbox"] { +/*input[type="radio"],input[type="checkbox"] { width: auto; -} +}*/ input[type="submit"] { background-color: #9b0000; color: #ffffff; } -input.login { +.login { width: 12em; text-align: center; border: 0.1em solid #000000; @@ -118,9 +117,7 @@ a.toggleVisibility > * { border-radius: 0.2em; } div.toggleVisibility { -/* background-color: #eeeeee;*/ padding: 0.2em; -/* border-radius: 0.2em;*/ } div.toggleVisibility > * { margin-top: 1em; @@ -149,6 +146,41 @@ th { color: #ff0000; font-weight: bold; } +.hidden { + display: none; +} +.list_entry_row { + border-bottom: 0; + border-left: 2px solid #000000; + border-right: 2px solid #000000; + border-top: 1px dashed #d0d0d0; + padding: 0.2em; +} +.list_entry:last-of-type .list_entry_row:last-of-type { + border-bottom: 0.1em solid #000000; + padding: 0.2em; +} +.list_entry_title { + border-bottom: 0; + border-left: 2px solid #000000; + border-right: 2px solid #000000; + padding: 0.2em; + border-top: 0.1em solid #000000; + background-color: #d0d0d0; +} +.list_entry ul a { + text-decoration: none; + color: #000000; +} +.list_entry li a { + padding: 0em 0.1em; + background-color: #ffffff; + border-radius: 0.2em; + border: 1px solid #000000; +} +.list_entry_title li {background-color: #ffffff;} +.list_entry a li {border: 1px solid #000000;} + @media only screen and (orientation: portrait) { body { font-size: 5vw; @@ -157,7 +189,7 @@ th { font-size: 5vw; } main { - padding: 0 1em; + padding: 0 1em; } nav li { padding: 1em 0.35em; @@ -166,10 +198,10 @@ th { font-size: 5vw; } input,button,select { - font-size: 5vw; + font-size: 5vw; } input[type=radio] { - border: 0px; + border: 0; height: 1em; } } \ No newline at end of file diff --git a/res/mechanism.png b/res/light/mechanism.png old mode 100644 new mode 100755 similarity index 100% rename from res/mechanism.png rename to res/light/mechanism.png diff --git a/res/light/note.png b/res/light/note.png new file mode 100755 index 0000000000000000000000000000000000000000..52226715fd528a2d8b02a543959e22524c2aee01 GIT binary patch literal 561 zcmV-10?z%3P)w9yQlyA0*ZBb{(zthu1Y&GNz!;KTge1hcF-FLz^GdqaUgCYQ#i3c|eLLvw zf*wk!+`{;W^6h3(1pwb-iyBzexK!?c@}HkT0Pw8<;9CK}w`}f#X)5~7G}nFeq$l9} zh9;u_U;+Waw?Yc}R!AY=3IM(pQpmSL3b|CP)r#iXClkw?;y7+R=BLyX7!HR!nfR{*{e(FK5C zL_{J|6_Mvev?(I%4~zmIL}bsVhtmlF_>|G(v2_#2aXs@uiZ*DWZ?kUDS|9ZL{cb4$ zY?I{Ppi=KgqtVByzb_j=M0zv8o>eN9!(6~+0|2nSUAxAZw`rRGEfs)>JhLeK!_2P- zgTarvdXU=``b_zW(_`jW3muXxfFw!kL^RAX-`84iFWSc$fKuvRj`@_Cw~FZF1b~@$ ziD)#%{53PbD5_T>0G&=p)oQgBW`2412+KTq0O!V-Mp5Ro0GurVr%94ji!{G1fZtl{ z{bsZ2B*tBz`biW;t1gT?0|4+Hz){wFeo@^5WT*}qZENql00000NkvXXu0mjfZS?(9 literal 0 HcmV?d00001 diff --git a/res/light/number.png b/res/light/number.png new file mode 100644 index 0000000000000000000000000000000000000000..257fcef4fdb893eb75f4725b5f606b1350911559 GIT binary patch literal 555 zcmV+`0@VG9P)S-^I? zy=vTg;na~AP*v5^z7|3}bLz+o0N~7Ik|e$}8LFdWI-Q;X_`sK!H?!F+Bz~l>>RF- z-#B$PBo-=)V$rze<>OEtc>z)RUn#YK^;u&acCXa>0%ch?`;r)`t=1|)YrX9Etlvin zvHG?EH2RVlA?=mS)?fS6v<7TCQcTmev0kJ!%^8c19HrDH+|}WgQ`f~o`#{Hv<>k## z9eDxGjYvwl;?$92Hk8^5=5WrYBV~vLqKjY)4Us^Q7BEBtL0SNgAb}_mmO%8@kuy{R z@gqv93o!QZ6r*d!s{et%b`EG2ptZgk`t9~%p95M2;J=&$q?Gq?efhwt+xy(Uf~XRR z5KQ<~&!h>b*mR_r*w0?t)+Qcg(UFrR$sJrDKXU4P=rs#5`oC`h&QdF-^jg+Jb)<|5 t1VIAPg|~%bNFWX>U`!x}Odv)W`2_Z(f8-X1jKcr`002ovPDHLkV1n6q`3e94 literal 0 HcmV?d00001 diff --git a/res/light/person.png b/res/light/person.png new file mode 100755 index 0000000000000000000000000000000000000000..f8af1a3efbb626753a58afbcc7fa2d96ace7d56e GIT binary patch literal 789 zcmV+w1M2*VP)zMZ`k<01|?Ppg~dugkU2ENf8X<@>;kT5{P;`JF^oXc$oT;fPrL|rlxjO{@ zSCQP+S}#mbPphEtNs?qFUyKTVhRE|INwSde>$dPGB-WE8Y1axrKR>TXu2qE}mQw0z ztpZx>yRP7eWsJE~3;g8dq$0WPT7cx{;^LzJMcrsLZn%aYR-@6lT9&7@ah~V5eGMni z^IP5pMC7_J0TH?8T>!vkUjjD0Z3HfO6e!)>Mxg17UPMaok!%Exd&-P=ast1kfn zU+NI}ZySLRzUWDo?p<1-*n#>I@Yee{aU5TQpRGimrm4?c^r=aGbS+>zeXHFc z$!8vhvgW$yAJc3$ufXvq5Jl0&+60P;y>$go@=dMq0HC$L=SrY>!mBr(PNxZAuPQvr z-EOxV=A1|=wNzC=DfJ)-JOH%Y?G(W03Icmsmc_vY06=Sf-&P>#^oJ=X_{~D#Aj`5e zG(P}<FC(ka(g_MbHZ~SlIU^bfkpm?nGoeXr zBO)^jz(i<}3Yj3u?;;ZRp~5mGk4REPBs7by0Epi!`oB%sKU=sEAQ_s$IwbK6T$-Bb T({Ktd00000NkvXXu0mjfedB0W literal 0 HcmV?d00001 diff --git a/res/light/progress.png b/res/light/progress.png new file mode 100755 index 0000000000000000000000000000000000000000..14606f1a0e6d4d0d0400485f5fc93467c3b9c41a GIT binary patch literal 1543 zcmV+i2Kf1jP)msF;;-Um8E?l~iN)bsVs8uWI#$;n5l|sujZ!*riF1#<^ z_vTLK%}lJD`QX8uoAd7Z&N=s-d+rTU4?XnI!-oWRV-hLlSglr@iR1Vf5ls@&0U{bu zN)?ER0Q^Tpe-Y6OB6`fsE3WJQ5=GJa2eVvCIl#>40o*4d)yV_kJ~N+}QV#rY#C_i% zW#%hHwAm?f%d^SMSA5?eeQ(6WF!Y#tiHIt@NId&gn0YA-LoY9{Tsh#n?!@cYua}il zhnk4Q0Dc2-3&1@g#IwG>zCRBiKKu_6(dz1ISgBNo>h=1#QtGHu>QklEG!e0t6!5#_ zIHzm1+8i-y+S75T4-sBW2jLkMxMTrTGh zbu*O9Wlsokj)*oadg_`($K)G4!_3Q4%KjYRPXo9K;HD5_I!8qMnR(f!vuz`E=(3)# z2_epAWlN=!6hh21^N;2@fD?w%CzA2~`}Z?5Ul&5mhhZo!y3Z0(%@T=x%gJ@!32I#P zn~vjrW|L>;ZxcD!b&s?%z;T>8WBeQ2oLX15Ojk6w<_N>k1Mo2G`DWy`!Jj0u0KRW! z0Dzy9anJLb64E+TkpS>;#}cdSe0Ke%mW}JWfzuHRttxf5>&+adS-T&gS5fmAu{sD;eSCEO{b&3E+{r{WJ5|#y98m*c^bT0GQpz$BQ4j=WBH9FS$8ns` zn?+a%aT35CBKo^jDiw58$^cdk2V671(Hv4GR&z}W4NxX&bZySc^_$HbfIEdkp{V~h zPB|f^JfICP0=R3;ci&c`HJ4OTNi~4Xd_E(v)@+mVeSe>^=9LiQVqW4FViyhaPki6s zXOq)hQaiTh{1(}kSg%zgBAS?(Xy{iw&l@J9=Kz)m2M3*I1Pg`2XrWMO+F=e34mtpq ziRihW({$8usZ`qDC(QgwqLqYmEaUyU+1m&q&H`8wLVRgP#rOTuVzDS`2M8ff3L#GJ zBvULFrJ0nj>mCAdm58d$JfDnfPN~gRN;yWl8km;dH5Fu{^OBjDq?G$82blR1GhfOh z>p0FVfSXn?zvFV3(s_D@^)b*Cx|O{5_xBg*?NKnnP#njXwzjr%ky1(>QA!=jBU`W6 zPb;P73?AzMu1-!)vN3kc{3ed$V+7!K#;S&pd!9D|;5*X$gy(satq3hFEHHo#02>Pn z3*1WH^Snda>-U5ZU+mqxw;{JQH#0)F2|y~lciP^AAn11-XP$B(2!ie0((f(d`~LLe z;$l-{H8<0MH3E>@efR9y)3R001Km9)QSI(vqM^B&22?n?`bdx*1G|M%>Zt9#8%#}2 zrMM}j3Ju|k<9Ii8ky2{P_P*iK@e7})yvuOYPEVf2!gPixh>pYFcCdAN4iP4 zk&zLOqUgF(s-fyArA|drbbVxGq~oPz;r7_pO00CMz$~53o^DF2=9X$DY|WgKQg(Dl z3E+oT256bKp*dxFj&T%4>i`~@!dqKgXF5?rM0qM$M^!G%3BZFWiq={G_{scZ9LI~c zJDXMj@N73^vIxUa#&Nuundcp6+mTWq)Z2pVx*t>HrBv#QM$5DX^U{E9M@lWUeW(X; z!}Gj@?J6Q75<+B^nMv2SQ;3K>&pQaNC}`ZbFXQ{W2d`fp;qFkdV5k>ZedY7re`(YA+?${MxzpgV=|SU0 z!$-EAPdLxa-Je%=x%U2(C7%3hjLbgoS|3!m*a_TWIJ~2S^@I-Ng^SDy(lc*w-MlCI zqW^)k|E^-4bxcePgc;^CylAric&T17sr8%oFHVjIKZX*hIE#ZigB9b2m*-`Gq%DJd XwB1Eb(?bzJe=&Hv`njxgN@xNAwSjV- literal 0 HcmV?d00001 diff --git a/res/light/show.png b/res/light/show.png new file mode 100755 index 0000000000000000000000000000000000000000..67de2219ea5b70b1ec18605e8586d79a4bf98034 GIT binary patch literal 1133 zcmV-z1d{uSP)J0MRTw?rot-gV*CgF;(#^Wr4b5soslPyr&{)Aj zOAMPvDfkD7DEJ^2eCUG@K36LueaU0rgsPjJ#-tBz4Hhg~0xE2aUFmnOUj9Sx{~*% z{~Gf|5{9M!2w+2I@|pbb^1?rH9F2g<&CdWF0T8d5#zc?W5%yYqkJ=HjJ1GVrWpeYP z6P_ajGLzp1XchoC_)*=|)!y-Fa5ql>WOsW~jii!lB-KBeXy2`E@3m-9H+2=@{Qy9q z8JWrNIMEhx(kPcMR}$IC8GCqR1e#~WtgUUH`YslHXgqw=;?^4g2G*);oA0r1>WF39 zN&s#%VqXX4;5YNH|54rSMaC=;=E3nYfW?3$59ZS46(`yp)j%EH+3+!oTkm!qh<$MP z^o#`n$F3gz7{szKO5QjNrPQ=bBmYNita%qx=e>b-QOC_)xm z$oeMYieVbxdLSMEo;FNltZyQ&?3n>g*UoeB;~t0y0C4c*ny#G};ktf>ddH)!8^%Tf zK&w{FC*5$4DJB>h~@j4Mcxw-6faG~kW z3AV-__$y~%hijYIzkxt^8lO#-Z?yo>?B6vG9`eHgf$F1-sq(FsowRJ{xI`?|_6rAp z)+YnME{&``=Y}Iv#6S5VUNp9A1B}?XU+P6-yEgE+5}E{1@j-vZj_t33xxqq}5gYYd zJtHq^5sq&L zLQ3cw+^q|m&3QBo%nlZ+PX7AVL7+Rc0;{fX25jVfYP*j|8lFs}b;L4lKXdRGcTGri zcj@ffOJ3#N`;UBl&ol1BSM1k-YwXv+e+-`1K#$tdshj#`4!+|#KY^|)lJb5oT^9bR z=c|D_;$sKTS={=ZgU4;*i;UQZi)UA_dY$V}EU{Ia(RWJI00000NkvXXu0mjf_){7B literal 0 HcmV?d00001 diff --git a/res/light/star.png b/res/light/star.png new file mode 100755 index 0000000000000000000000000000000000000000..4aabfa0663440b61b8d123c47c946d04ccf3fee8 GIT binary patch literal 973 zcmV;;12X)HP)}V-LaDaGd~)Tw*ag=R(y;xX8^Q^3jokI#{8VO-$a=C;RyNuEIiEH z??{3mI1ONDTmb-f+&RUBnI9Y>-=BpCd3%l|48t0L?MVdy*mma@3ugW+fqZ`!{>0|3h9as*)0w*UZ}uJ5rBJ}0lNtjOKn-Ln8L z0k}>?H#?oq9{|p$$S!re-7Cy|j)<0o5I(MgQSDd@PS675wu#Zh5h~g zWozw{wRQ!-5`blE?E(OO+^aT$4iS9-@D{*3B3dV+cT&o?)oS&_#>U3pp#r3ozxR5* z%L9^U0C2{VX*nRG&;85HN$BBB>L$iIl9=-7KD06?i!3W(_G z4CSAeN~K^b@_j0miYB5bGmw80$8k3Mty--nk?giHt^9ViT9rOdUYoXdyL}o!Ig_gc zz*<}GbUI#7ExZcY+uOU4m3-O^uL7*KnLq3I&G0SYw;2@RmEn8ilKB$KEMtCtUSsq_ z+iAD9%bG4)>(v>^TL9K&B_i<>>h*eQruM)!FMP5R7vTHlBBJL?sf$Xfi$wI?r*9@d z7DV(6$^K1WNhz-m_m@&$C8Ade$9R@S0iPy>t_dM-G@H$_v)XJnSqO1s(jA}6njUc+ z*NzDMD1^9Guh$drVe0j|6hhnr@NwL@E^|6aDX)zP`O3_9;y6yd?TzC&VCFjjz7CH+ zY8j@6nQspazQfG-!!S&Dn>T_m4Ck2nJ_cS-xy#2OtL2fDKN$~-0Rq` v%bX5U%DYGxyzl zyU3gP=FNL=-pfqX9+<`4x%b@jx#!$p=MJF@qNFUdQsZRIUH~Hib^sWJwOarHME?T# z2f(iY9$4ldjO$)w`9x}``hUm5d?1nx>w+-`*l5*&o8SZ;t*)Y!-8YW&wxiVjjz?Y#ant}S z2_v>(m`^Gxhx6)HQf@cQCk?QWpnF9NakNw8KTS~nSTj%7N+qw;0jd>?o@Smfz+zlq zT8OEQ8b6h=a-3H^J%gPZ9^;WgLv+3?5JA|q8qa+0PNl-Rl;x1C)6=Ylm@t5ffyfq4 zzUz*r#Jtu*9NR2_^#OF8Lout}itoCksSRs|f;2?;+AMX?5<*47_g?A}8?5s!VPgRO zTp-rMDQeHD*vh`=m0R3KbpG~7AF&qV*hV0<5Qh!XvLX6ONtt`%U!9)jn2Eg_yJH8( zgQlf2yxL@esFg~N7UE;g{7J1)@C@)(qpt6|2kTq5^lQgCsHEJQ6+%fl*s{bj&qgZ^ zMMqyVPsWUBDufo|!%+Jv1Dpv17^3e2&wigPl-Bl%CNDG&fD8blUOx^XJUJfug~I1i zMMCRutPt-3Fri{5t-lT+wyl>Ey%cHASUY9|K(0fZ-{1cQfJdPs8Q2`0MXY_Nxhp>1 z^W;fAPFVo)ejEf@`&J&qvP#d=QXR~vn+gM)SxH%jwYx(<8SQy)kN>d@M z?e97T(WR!Z#_V;lc87i1FVT%WI)&DAS_qKVXAnBylQEM3x_aleL^mTBn33?xuvSTk zhk2B${{CX(oQUX765sPiv=HOfty@!%=P|bJfFWu+xK#%RwjqZY=4(pIA^>P1-i_HO z8vDSThUmv&ADC~n*Fqd#Z$or3t*`39z_!RqVFl5S=J)S+asjL=PyzUS>s>nlElh~}GO)$>NOnH~esfavXQKpanm0G>qJooUyX?|CDU zHuEqNx8i%0NKJR z)AdwIIUH@Pq%1ecnlsGIC%XpFC5Rx4*Ob`~|2Pv-xKJw=GiBWj(Vv?QQ7e@^6HP%f z&xG9*ccq-j2=HYlfDRxu^JLPMGVF!urG7C>CLzdXWb;A*QGW{2Hc=2<>K~_G>O+RK zq*bm?Pq#g8_?|axh-MAZLL1|k4bes4b=PlzX%KfRmF#JizzZ#jEiFW*Q0hdIAcCY? zw!{{Ym|9fYaSlBvh^PnewSB!wNbat_01)kyyCFq!>2;-rn8-3GHY#^26^;!XYUYWon_ZgJN+mB?=O1^~_z*;vN50Hwr_hKGcjJ+-+s~|* zEYZ!zGwb56T}ws?ynO3c_?dMNtbOB|J+n6CMSbYbE&toU8bswq`Ljo+IgkP7x&7Vd YKW)k3pd5oM{{R3007*qoM6N<$f<4O9NdN!< literal 0 HcmV?d00001 diff --git a/res/light/uncheck.png b/res/light/uncheck.png new file mode 100755 index 0000000000000000000000000000000000000000..237f321dac27d5d0aeb9a9ca10022bb427522954 GIT binary patch literal 1034 zcmV+l1oiugP)L_|uF;#owb6e&_lDbkB5?o5)Whi$vty1Sjc%&dVq&dcYU_v4%G6kx)#Nz(H| zJo>r3EZ{#ar_@6dV#~H#*MnZPNzx<4T>|(+LOkg&EXY~Idnq3fzzG5TA;gcBMO=VC zdxUuUYjJUABD|FM&*9IWDk8?h4+A{w&(Ak5!YOr+0KQLPm@Hx{{4f*G3u77+;iX(7 zfa9qQ<3v<~9|ljmohwsLlLiRyB#dTX?>dj zzA^XQC@z<^i>=1 z>k{#uP19^j?3)DemD_Jcr&BG9}>fLx^1Xw`IG1lMb7&ruMmemV?o{7O2nOGvk z&o#jB*jdAmWa0)Peu{wq5DOpoHyDyz!#e&z5fBv z`zbp9*>zgqoC&;5(~J8tpP!c`#B;6@`3gpK>f&4@Ja$Um8yoo7;-VzPXIulaNmAKG zZI;Ct;&(6Q{fj5Rupmi@r(Afi)Jjm30YKSqXN35cx#x+O@&Nz<{9IlZB*YVDpnV%* z{ih@rn{2xBw}u^tS6L4*+7PN}t^7i(PoZdZFD9#4b+3;4qZ{AlTmdH?_b07*qoM6N<$ Ef)xkqVE_OC literal 0 HcmV?d00001 diff --git a/res/light/undo.png b/res/light/undo.png new file mode 100755 index 0000000000000000000000000000000000000000..859696d4db31a5a2bea290dc7b1eb4a3b54f5ded GIT binary patch literal 1208 zcmV;p1V{UcP)4y=g9P!RRq2!X5jRn~My{4m(O1|YD4#uw@)lROfutc$GO`@6}MEcD0nrA$dWtahqo>?+v2m1pw+ z5G2;&vVVq8yFDctpD>v&Fq7<%?fQd-ole9TkZ$rlusM)t)9EzI(z9EJoGa-P1OO20 z_jP#wlhEC2vvj5}t)h7VSWntHufuBFk^lfeW)?z+B*C| zmTz)=BWd?Bg4qG)UHEUc#VfS)CV*xj)t@+P-*kpa9*;h-VW?v7Z_8fg+(D3tr1y{d+$Lw!zGiB?FY#%49_q=AjP!H@u+wx` z=e~MunymQke!I_~dF#tUsx>(VqLXR519`hvSxM=z+(|~CPSsZwFLO?b{~Ul6wT9wF z0pLAwI|k6NDZ0js0^p8DQnU>h6F_uP3(@6b0$8+FGtv2C0thaM6WZe&EGB@uc@fbW z>tHNe6aaRwzZ~FsS3FFz3n-F0Af4%k`7LxMTDf7MXaI=K^K)Ys@{Ni;Gso6~2T1mn zm4bQiEDa6(y{X}wyJ5itsAPN}fbu(G+z553=BdGZmj(q55dVCgqM7dz000*96%}%> z&CMxjfRflm6TtNV01^?|rn?vB6fA%f@db$W(V2(_of7|{RCxspAl>BK0IC4GpgrC_ zCC$;4r?P@P(CDywhK&0iK8Z~$(PRV`fm5{QOetF+lVIJM-*@qz-d zd;MNzPn~7Z=~%`3V{02na=OXBuZs0o3mulnby#g*Z7*5L?)7hRBHm!`BmJ-YtA7Cm Wuc4@VFH|)E0000 zkPvT8F!ApPK#dpP8|t63?OsSj1TWP>g1cSadA-=}GBZ2V&Y3xD!0_Dlo%fvQynQ;E zUuWRH{>Rek%7mId2Zre(!`fI49=iK`&;qjbloj>8a9b3RRE-jrUpvNow@N}NwFGb}wJOtH`0`8@woV4n>B{?*z~a%%As z@NKxIb5>1$e+LPyAwy4!;_H!tHeZfFkcZqLMy>(6$RMX8JANXy#^q?Q)apM0pM{Gu zqmw&}dCrh8fk9+w^N)8Tv0wZu!fK$B8!<8upi^Vp5s5xoFUaXDSCiI=X!@+8RKwUeOC0uyoFu`#RJa{%?f4tL7) zX`i~i!_TAoXs@(Pt2Lf>2sM@GP`woP_a?+#`6k*s@F&#$FyYTes+P#mekpKxfL#=e zFQ#4H^GbynG53HAWRMuR^X-5yC1QjIh(!kBQ+s6C`~`65zboM?&DAe$c8Em`PioyW z21?;&rNbd)5LW4Qj@cLki1~4aR%;xUL#Q00*?KztO&n0Cb1Z}y$|#f$hrIgN;y+BB zlaq^YTN^u+n({eRCIh9=hmt!9{8z|es|^rCAk~M7yG{MK7~KS-$Z+?o{}w}HKTO;k o@)6zd4ZLNzcjWX#$$e$jzcaJ4x}CwKGXMYp07*qoM6N<$f^>`$v;Y7A literal 0 HcmV?d00001 diff --git a/res/loading.gif b/res/loading.gif new file mode 100644 index 0000000000000000000000000000000000000000..762b0cb735708ab23d703aa00fa2510f9ab7b4bf GIT binary patch literal 112974 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

    !9g@S3df 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 U4Sah8-`>EtH}LHZ{Qd_14|WzZpa1{> literal 0 HcmV?d00001 diff --git a/res/main.html b/res/main.html old mode 100644 new mode 100755 index cd1f1ea..0875f4b --- a/res/main.html +++ b/res/main.html @@ -1,47 +1,42 @@ - - - ###TITLE### - - - + OF56-App (REST-Style) + + + + + + + + -

    - -
    -
    -
    -
    -
    - - -
    -
    +
    - -
    - ###ERRORS### -
    -
    - ###MAIN### -
    + +
    +
    + + +
    + +
    - \ No newline at end of file + diff --git a/res/main.js b/res/main.js old mode 100644 new mode 100755 index 6d8d7f2..c521884 --- a/res/main.js +++ b/res/main.js @@ -2,10 +2,942 @@ function toggleVisibility(idImg, idDiv) { var div = document.getElementById(idDiv); var img = document.getElementById(idImg); if (div.style.display === "none") { - div.style.display = "block"; - img.src = "res/hide.png"; + div.style.display = "flex"; + img.src = "res/dark/hide.png"; } else { div.style.display = "none"; - img.src = "res/show.png"; + img.src = "res/dark/show.png"; } -} \ No newline at end of file +} + +class APIScanner +{ + static api; + static settings; + static scanned; + + constructor(parent) { + APIScanner.api = parent; + this.qr = null; + this.cameras = []; + } + + Start(id, subroute, parser) { + APIScanner.settings = { + subroute: subroute, + parser: parser, + id: id + }; + APIScanner.scanned = {primary: {}, secondary: {}}; + for (let i in parser) { + if (i!=subroute) { + APIScanner.scanned.secondary[parser[i]] = null; + } } + + // Find already parsed IDs + const subData = APIScanner.api.activeRoute.resourcesIndex[id].data.SUB[parser[subroute]]; + for (let i in subData) { + APIScanner.scanned.primary[subData[i].ID] = true; + } + + this.qr = new QrScanner( + document.getElementById("qrscanner_video"), + APIScanner.parse, + {returnDetailedScanResult: true, highlightScanRegion: true, highlightCodeOutline: true} + ); + if (QrScanner.hasCamera()) { + let _this = this; + QrScanner.listCameras(true) + .then(result => _this.cameras = result) + .catch(error => alert(error || 'Camera detection failed.')); + } + this.cameraIndex = 0; + document.getElementById("qrscanner_text").innerHTML = ""; + + this.qr.start(); + } + Stop() { + this.qr.stop(); + this.qr.destroy(); + this.qr = null; + } + SwitchCamera() { + if (this.qr!==null && QrScanner.hasCamera()) { + ++this.cameraIndex; + if (this.cameraIndex>=this.cameras.length) { + this.cameraIndex = 0; + } + this.qr.setCamera(this.cameras[this.cameraIndex].id); + } + } + static parse(result) { + let scan = result.data.split("/"); + if (scan.length==3) { + let route = scan[1]; + let subid = scan[2]; + + // Is it a route we should parse? + if (typeof(APIScanner.settings.parser[route])!="undefined") { + const marker = APIScanner.settings.parser[route]; + + // Is it the primary route and if yes, has this ID been parsed before? + if (route==APIScanner.settings.subroute && typeof(APIScanner.scanned.primary[subid])=="undefined") { + APIScanner.scanned.primary[subid] = true; + + let index = -1; + + const options = APIScanner.api.activeRoute.options[marker]; + for (let i in options) { + if (options[i].ID==subid) { + index = i; + break; + } } + // Has the ID been found? + if (index>=0) { + document.getElementById("qrscanner_text").innerHTML += options[index].NAME + "
    "; + APIScanner.api.Request("POST", APIScanner.scanned.secondary, APIScanner.settings.id, APIScanner.settings.subroute, subid); + } + } else if(route!=APIScanner.settings.subroute) { // Is it a secondary field? + APIScanner.scanned.secondary[marker] = subid; + } } } } +} + +class APIResource // This holds ONE table record +{ + constructor(route, group, data) { + this.route = route; + this.group = group; + this.ID = data.ID; + group.resourcesIndex[this.ID] = this; + route.resourcesIndex[this.ID] = this; + + this.data = data; + this.show = false; + + // TODO: This SHOULD be determined by the client through comparing of data with privileges and not be preprocessed by server. Should it? + this.localAdmin = data.admin; + } + + Render(includingBox = false) { + var data = this.data; + data.SHOWBUTTON = this.show; + data.SHOWCONTENT = this.show; + data.SELECTBOX = ""; + + var ret = ""; + return (includingBox ? "
    " : "") + + this.route.tpl.Render(data, "LIST", (this.route.admin || this.localAdmin ? ":ADMIN" : "")) + + (includingBox ? "
    " : ""); + } +} + +class APIGroup +{ + constructor(route, id, resources) { + this.route = route; + this.ID = id; + this.resources = []; // List of APIResources + this.resourcesIndex = {}; // resources indexed by ID + + this.show = true; + + this.route.groupsIndex[id] = this; + for (var i in resources) { + this.Add(resources[i]); + } + } + Add(resource) { + this.resources.push(new APIResource(this.route, this, resource)); + } + Delete(id) { + var index = this.route.findIndexInEntries(id, this.resources); + delete this.resources[index]; + this.resources.splice(index, 1); + } + Clear() { + for (var i in this.resources) { + delete this.resources[i]; + } + this.resources = []; + this.resourcesIndex = {}; + } + Render() { + var ret = "
    " + this.route.tpl.Render({"GROUP": this.ID}, "GROUP_BEGIN", ""); + for (var k in this.resources) { + ret+= this.resources[k].Render(true); + } + ret+= this.route.tpl.Render({"GROUP": this.ID}, "GROUP_END", "") + "
    "; + return ret; + } +} + +class APIFilter // This holds ONE filter element +{ + constructor(data, type) { + this.Set(data, type); + } + Get() { + return {and: this.and, field: this.field, op: this.op, value: this.value}; + } + Set(data, type) { + this.and = typeof(data.and)!="undefined" ? data.and : "and"; + this.field = typeof(data.field)!="undefined" ? data.field : "none"; + this.op = typeof(data.op)!="undefined" ? data.op : ""; + this.value = typeof(data.value)!="undefined" ? data.value : ("Multiple"==type ? [] : ""); + } +} + +class APIRoute // This holds a list of resources +{ + constructor(parent, route, info) { + this.parent = parent; + this.route = route; + this.isPage = info.isPage; + this.mainFields = info.mainFields; + this.filter = []; + this.tplFile = info.template; + this.tpl = null; + this.image = typeof(info.image)!="undefined" ? info.image : null; + this.name = info.name; + this.admin = false; + this.options = []; + this.selected = []; + this.dropzones = {}; + + this.groups = []; // List of APIResourceGroups + this.groupsIndex = {}; + this.resourcesIndex = {}; // Index of APIResources by ID linking to entries inside their respective group + } + + Add() { + // Get JSON + var send = {}; + for (var i in this.mainFields) { + if (this.mainFields[i].add) { + var e = document.getElementById("ADD/"+i); + if (e!=null) { + if (this.mainFields[i].type=="Multiple") { + // Multiple values can be selected + send[i] = Array.from(e.selectedOptions).map(el=>el.value); + } else if (this.mainFields[i].type=="Checkbox") { + send[i] = e.checked; + } else if (e.value=="__NULL__") { + // Null is selected + send[i] = null; + } else { + // Only one value can be selected/input + send[i] = e.value; + } + } else if (this.mainFields[i].type=="DateTime") { + var eDate = document.getElementById("ADD/"+i+"/DATE"); + var eTime = document.getElementById("ADD/"+i+"/TIME"); + if (null!=eDate && null!=eTime) { + send[i] = eDate.value + " " + eTime.value; + } } } } + this.parent.Request("POST", send); + } + Save(id) { + // Get JSON + + var json = this.findEntry(id).data.MAIN; + var send = {}; + var element = document.getElementById("LIST/"+id); + element.className = "list_entry"; + + for (var i in this.mainFields) { + if (this.mainFields[i].edit) { + var e = document.getElementById("LIST/"+id+"/"+i); + + if (e!=null) { + if (this.mainFields[i].type=="Multiple") { + // Multiple values can be selected + send[i] = Array.from(e.selectedOptions).map(el=>el.value); + } else if (this.mainFields[i].type=="Checkbox") { + send[i] = e.checked; + } else if (e.value=="__NULL__") { + // Null is selected + send[i] = null; + } else { + // Only one value can be selected/input + send[i] = e.value; + } + } else if (this.mainFields[i].type=="DateTime") { + var eDate = document.getElementById("LIST/"+id+"/"+i+"/DATE"); + var eTime = document.getElementById("LIST/"+id+"/"+i+"/TIME"); + if (null!=eDate && null!=eTime) { + send[i] = eDate.value + " " + eTime.value; + } } } } + this.parent.Request("PATCH", send, id); + } + Edit(id) { + var _this = this; + var entry = this.findEntry(id); + var element = document.getElementById("LIST/"+id); + element.innerHTML = this.tpl.Render(entry.data, "LIST", ":EDIT"); + element.className = "list_entry list_edit"; + this.renderHelper(id); + } + Cancel(id) { + var entry = this.findEntry(id); + var element = document.getElementById("LIST/"+id); + element.innerHTML = this.tpl.Render(entry.data, "LIST", ":ADMIN"); + element.className = "list_entry"; + } + SubShowAdd(id, markers) { + var entry = this.findEntry(id); + + let marker; + var data = {"ID": id}; + if (Array.isArray(markers)) { + marker = markers[0]; + for (let i=1; iel.value); + } else if (this.mainFields[data.field].type=="Checkbox") { + data.value = eValue.checked; + } else if (eValue.value=="__NULL__") { + // Null is selected + data.value = null; + } else { + // Only one value can be selected/input + data.value = eValue.value; + } } } + + if ("undefined"!=typeof(this.filter[id])) { + this.filter[id].Set(data, "none"!=data.field ? this.mainFields[data.field].type : "none"); + } + this.parent.Request("GET"); + } + + SelectChange(id, state) { + var selectedIndex = this.selected.indexOf(id); + if (state && 0>selectedIndex) { + this.selected.push(id); + } else if (!state && -1" + this.renderEntry(this.resourcesIndex[responseJson.content.ID]) + "
    "; + var elList = document.getElementById("GROUP/" + responseJson.content.GROUP); + elList.insertAdjacentHTML("beforeend", entryHtml); + } else if (method=="GET") { + // Update everything + this.admin = responseJson.admin; + this.options = responseJson.options; + for (var k in this.filter) { + delete this.filter[k]; + } + this.selected = []; + if ("undefined"!=typeof(responseJson.selected)) { + this.selected = responseJson.selected; + } + this.filter = []; + for (var l in responseJson.filter) { + this.filter.push(new APIFilter(responseJson.filter[l], "none"!=responseJson.filter[l].field ? this.mainFields[responseJson.filter[l].field].type : "none")); + } + + for (var iG in this.groups) { + this.groups[iG].Clear(); + delete this.groups[iG]; + } + this.groups = []; + this.groupsIndex = {}; + + for (var groupID in responseJson.content) { + this.groups.push(new APIGroup(this, responseJson.content[groupID].ID, responseJson.content[groupID].ENTRIES)); + } + + if (this.tplFile!=null) { + this.reloadTemplate(this.tplFile); + } } } + + findIndexInEntries(id, data) { + for (var i in data) { + if (data[i].ID==id) { + return i; + } } + return null; + } + + findEntry(id) { + if (id in this.resourcesIndex) { + return this.resourcesIndex[id]; + } + return null; + } + + reloadTemplate() { + var _this = this; + var request = new XMLHttpRequest(); + request.open("GET", this.tplFile, true); + request.setRequestHeader("Accept", "text/html"); + request.onreadystatechange = function() { + if (request.readyState != 4 || request.status != 200) return; + _this.tpl = new TemplateEngine(request.responseText, _this.options); + _this.render(); + }; + request.send(); + } + + renderEntry(entry) { + var data = entry.data; + data.SHOWBUTTON = entry.show; + data.SHOWCONTENT = entry.show; + data.SELECTBOX = ""; + return this.tpl.Render(entry.data, "LIST", (this.admin || entry.localAdmin ? ":ADMIN" : "")); + } + + getFilter() { + var filter = []; + for (var i in this.filter) { + filter.push(this.filter[i].Get()); + } + return filter; + } + + renderFilterEntry(id) { + var html = ""; + var data = this.filter[id].Get(); + + // Render and/or combiner + if (id>0) { + html+= ""; + } else { + html+= ""; + } + + // Render Field selector + html+= ""; + if ("undefined"!=typeof(this.mainFields[data.field])) { + // Render operator + // Render value input + switch (this.mainFields[data.field].type) { + case "Checkbox": + html+= "ist "; + html+= ""; + break; + case "Multiple": + html+= "" + +""; + break; + case "Select": + html+= "" + +""; + break; + case "String": + html+= "" + +""; + break; + case "Integer": + html+= "" + +""; + break; + case "DateTime": + html+= ""; + var datetimesplit = data.value.split(" "); + html+= ""; + html+= ""; + break; + } } + // Render deletor + html+= ""; + + return html; + } + + renderFilter() { + var ret = "
    • Filter:
    • "; + for (var i in this.filter) { + ret+= "
    • "+this.renderFilterEntry(i)+"
    • "; + } + ret+= "
    • "; + if (this.filter.length>1) { + ret+= "
    • "; + } + return ret+"
    "; + } + + render() { + var metaHtml = "
    " + this.tpl.Render(this.meta, "META", "") + "
    "; + var entriesHtml = ""; + + for (var j in this.groups) { + entriesHtml+= this.groups[j].Render(); + } + var addHtml = (this.admin ? "
    " + this.tpl.Render(this.options, "ADD.MAIN", "") + "
    " : ""); + document.getElementById("content").innerHTML = metaHtml + addHtml + entriesHtml; + //this.renderHelper(); + } + + renderHelper(id = null) { + var _this = this; + if (null!==id && !!document.getElementById("dropzone_"+id)) { + this.dropzones[id] = new Dropzone("form#dropzone_"+id, { + url: document.getElementById("dropzone_"+id).action, + //url: this.route + "/" + id + "/Bilder", + createImageThumbnails: false, + headers: { + "Authorization": "Bearer " + _this.parent.jwt, + "Accept": "application/json" + }, + dictDefaultMessage: "Datei Drop " + }).on("sending", function(file, xhr, formData) { + _this.Cancel(id); + _this.parent.showMessages(["Datei wird hochgeladen! Dies kann je nach Größe eine Weile dauern."]); + formData.append("secToken", _this.parent.secToken); + }).on("complete", function(file) { + if (file.xhr.status==201) { + _this.parent.showMessages(["Datei erfolgreich hochgeladen!"]); + } + var json = _this.parent.parseResponse(file.xhr.responseText); + _this.parent.parseJson(json, file.xhr.status); + _this.parseContent(json, "GET", id); + }); + } } +} + +class APIManager +{ + constructor() { + this.jwt = this.getCookie("jwt"); + this.emulate = null; + this.secToken = this.getCookie("secToken"); + this.loggedIn = null; + this.root = "https://app.fw-innenstadt.de"; + + this.scanner = new APIScanner(this); + + this.routes = {"/index.php/": new APIRoute(this, "/index.php/", { + link: "/index.php/", name: "Start", image: "/wappen48.png", + template: "/res/main.html", isPage: true, marker: "START", + mainFields: []})}; + this.path = this.getCookie("path"); + + if (this.path=="") { + this.path = "/index.php/"; + this.activeRoute = this.routes[this.path]; + } + this.Request("GET"); + } + + Request(method, json = {}, id = null, sub = null, subid = null) { + var _this = this; + var request = new XMLHttpRequest(); + var path = this.path + (id!=null ? "/" + id + (sub!=null ? "/" + sub + (subid!=null ? "/"+subid : "") : "") : ""); + var accept = "application/json"; + var loadElement = document.getElementById("loadImage"); + if (null!=loadElement) { + loadElement.innerHTML = ""; + } + + json.secToken = typeof(this.secToken)!="undefined" ? this.secToken : ""; + + if ("undefined"!=typeof(this.activeRoute)) { + var hasParam = false; + // Append filter if exists + if (this.activeRoute.filter.length>0) { + path += "?filter="+encodeURI(JSON.stringify(this.activeRoute.getFilter())); + hasParam = true; + } + + // Append selection + if (this.activeRoute.selected.length>0) { + path += (hasParam ? "&" : "?")+"selected="+encodeURI(JSON.stringify(this.activeRoute.selected)); + hasParam = true; + } + + // Append print request + if (typeof(json.Print)!="undefined") { + path += (hasParam ? "&" : "?")+"print="+json.Print; + accept = "text/html"; + hasParam = true; + } + + // Append user emulation + if (this.emulate!=null) { + path += (hasParam ? "&" : "?")+"emulate="+this.emulate; + hasParam = true; + } + } + request.open(method, path, true); + if (this.jwt!="") { + request.setRequestHeader("Authorization", "Bearer " + this.jwt); + } + if (method!="GET") { + request.setRequestHeader("Content-Type", "application/json"); + } + request.setRequestHeader("Accept", accept); + + request.onreadystatechange = function() { + if (request.readyState != 4) return; + + var loadElement = document.getElementById("loadImage"); + if (null!=loadElement) { + loadElement.innerHTML = ""; + } + + if ("text/html"==accept) { + if (200==request.status) { + var windowUrl = 'about:blank'; + var uniqueName = new Date(); + var windowName = 'Print' + uniqueName.getTime(); + var printWindow = window.open(windowUrl, windowName, 'left=50000,top=50000,width=0,height=0'); + printWindow.document.write(""); + printWindow.document.write(request.responseText); + printWindow.document.write(""); + printWindow.document.close(); + printWindow.focus(); + } else { + _this.showMessages(["Es konnte kein Ausdruck abgerufen werden!"]); + } + } else if ("application/json"==accept) { + var responseJson = _this.parseResponse(request.responseText); + + _this.parseJson(responseJson, request.status); + if (request.status>=200 && request.status<300) { + if (typeof(_this.activeRoute)!="undefined") { + _this.activeRoute.parseContent(responseJson, method, id, sub); + } } } }; + + request.send(JSON.stringify(json)); + } + + Open(path) { + if (typeof(this.routes[path])!="undefined") { + this.path = path; + this.setCookie("path", path); + this.activeRoute = this.routes[path]; + this.Request("GET"); + } else if ("/index.php/Logout"==path) { + this.path = path; + this.setCookie("path", "/index.php/"); + this.activeRoute = this.routes["/index.php/"]; + this.Request("GET"); + } + } + + Login() { + var button = document.getElementById("loginButton"); + button.disabled = true; + button.className = "login disabled"; + var json = { + "login": document.getElementById("loginUser").value, + "password": document.getElementById("loginPassword").value + }; + + this.path = "/index.php/"; + this.activeRoute = this.routes[this.path]; + this.setCookie("path", this.path); + this.Request("POST", json); + } + + /* "Private" functions */ + + registerRoutes(routes) { + for (var i in routes) { + if (typeof(this.routes[routes[i].link])=="undefined") { + this.routes[routes[i].link] = new APIRoute(this, routes[i].link, routes[i]); + } } + if (typeof(this.activeRoute)=="undefined") { + this.activeRoute = this.routes[this.path]; + } + this.renderNavigation(); + } + + renderNavigation() { + let nav = document.getElementById("navigation"); + let selectnav = document.getElementById("navigation_select"); + nav.innerHTML = ""; + selectnav.innerHTML = ""; + for (let i in this.routes) { + if (this.routes[i].isPage) { + let selected = this.routes[i]==this.activeRoute ? " selected" : ""; + selectnav.innerHTML+= ""; + + let cssClass = this.routes[i]==this.activeRoute ? " class='current'" : ""; + if (this.routes[i].image!=null) { + nav.innerHTML+= "
  • "; + } else { + nav.innerHTML+= "
  • " + this.routes[i].name + "
  • "; + } } } + nav.innerHTML+= "
  • "; + selectnav.innerHTML+= ""; + } + + parseResponse(responseText) { + var json = {}; + try { + json = JSON.parse(responseText); + } catch (SyntaxError) { + this.showMessages(["Parsen der Antwort gescheitert. Es folgt die Antwort!", responseText]); + } + return json; + } + + parseJson(json, status) { + if (typeof(json.status.newjwt)!="undefined" && json.status.newjwt!=null) { + this.setCookie("jwt", json.status.newjwt); + this.jwt = json.status.newjwt; + } + if (typeof(json.status.secToken)!="undefined" && json.status.secToken!=null) { + this.setCookie("secToken", json.status.secToken); + this.secToken = json.status.secToken; + } + if (typeof(json.status.loggedIn)!="undefined" && json.status.loggedIn) { + if (json.status.loggedIn!=this.loggedIn) { + this.changeLoginScreen(true); + } + if (status>=300) { + this.showMessages(["Die Anfrage wurde mit Code " + status + " abgelehnt.
    (" + this.translateHttpStatus(status) + ")"]); + } + } else { + this.changeLoginScreen(false); + } + if (typeof(json.messages)!="undefined") { + this.showMessages(json.messages); + } + if (typeof(json.pages)!="undefined") { + this.registerRoutes(json.pages); + } + } + + translateHttpStatus(status) { + switch (status) { + case 200: return "OK"; + case 201: return "Erstellt"; + case 400: return "Fehlerhafte Anfrage"; + case 401: return "Anmeldung erforderlich"; + case 403: return "Keine Berechtigung"; + case 404: return "Nicht gefunden"; + case 500: return "Fehler auf Server"; + default: return "" + status + " = Unbekannt"; + } + } + + changeLoginScreen(newStatus) { + var s = document.getElementById('header').style; + if (this.loggedIn==null) { + if (!newStatus) { + s.display = "block"; + s.opacity = 1; + } + } else if (newStatus) { + (function fadeOut(){(s.opacity-=0.1)<0?s.display="none":setTimeout(fadeOut,40)})(); + } else { + var button = document.getElementById("loginButton"); + button.disabled = false; + button.className = "login"; + + s.display = "block"; + (function fadeIn(){(s.opacity-=-0.1)>1?s.opacity=1:setTimeout(fadeIn,40)})(); + } + this.loggedIn = newStatus; + + document.getElementById("navigation").className = (this.loggedIn ? "" : "hidden"); + document.getElementById("content").className = (this.loggedIn ? "" : "hidden"); + } + + showMessages(messages) { + for (var i in messages) { + Toastify({ + text: messages[i], + duration: 3000, + close: true, + gravity: "top", // `top` or `bottom` + position: "right", // `left`, `center` or `right` + backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)", + stopOnFocus: true, // Prevents dismissing of toast on hover + }).showToast(); + } } + + setCookie(cname, cvalue, exdays) { + var d = new Date(); + d.setTime(d.getTime() + (exdays*24*60*60*1000)); + var expires = "expires="+ d.toUTCString(); + document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/;SameSite=Strict;Secure"; + } + + getCookie(cname){ + var name = cname + "="; + var decodedCookie = decodeURIComponent(document.cookie); + var ca = decodedCookie.split(';'); + for(var i = 0; i - - -
  • ###NAVLABEL###
  • - - diff --git a/res/personal/AGT.svg b/res/personal/AGT.svg new file mode 100755 index 0000000..829a4a1 --- /dev/null +++ b/res/personal/AGT.svg @@ -0,0 +1,63 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/res/personal/CU.svg b/res/personal/CU.svg new file mode 100755 index 0000000..f1c7ed1 --- /dev/null +++ b/res/personal/CU.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/res/personal/FS.svg b/res/personal/FS.svg new file mode 100755 index 0000000..b2fc616 --- /dev/null +++ b/res/personal/FS.svg @@ -0,0 +1,53 @@ + +image/svg+xml \ No newline at end of file diff --git a/res/personal/FU.svg b/res/personal/FU.svg new file mode 100755 index 0000000..651cdfb --- /dev/null +++ b/res/personal/FU.svg @@ -0,0 +1,115 @@ + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/personal/Funktion.svg b/res/personal/Funktion.svg new file mode 100755 index 0000000..4be6d97 --- /dev/null +++ b/res/personal/Funktion.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/res/personal/KF.svg b/res/personal/KF.svg new file mode 100755 index 0000000..a6561f2 --- /dev/null +++ b/res/personal/KF.svg @@ -0,0 +1,63 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/res/personal/KS2.svg b/res/personal/KS2.svg new file mode 100755 index 0000000..20924b2 --- /dev/null +++ b/res/personal/KS2.svg @@ -0,0 +1,61 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/res/personal/KSA.svg b/res/personal/KSA.svg new file mode 100755 index 0000000..20924b2 --- /dev/null +++ b/res/personal/KSA.svg @@ -0,0 +1,61 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/res/personal/KSB.svg b/res/personal/KSB.svg new file mode 100755 index 0000000..20924b2 --- /dev/null +++ b/res/personal/KSB.svg @@ -0,0 +1,61 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/res/personal/MA.svg b/res/personal/MA.svg new file mode 100755 index 0000000..1830f55 --- /dev/null +++ b/res/personal/MA.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/res/personal/NS.svg b/res/personal/NS.svg new file mode 100755 index 0000000..b2fc616 --- /dev/null +++ b/res/personal/NS.svg @@ -0,0 +1,53 @@ + +image/svg+xml \ No newline at end of file diff --git a/res/personal/Nopic.svg b/res/personal/Nopic.svg new file mode 100755 index 0000000..bf8b849 --- /dev/null +++ b/res/personal/Nopic.svg @@ -0,0 +1,133 @@ + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/personal/RA.svg b/res/personal/RA.svg new file mode 100755 index 0000000..b2fc616 --- /dev/null +++ b/res/personal/RA.svg @@ -0,0 +1,53 @@ + +image/svg+xml \ No newline at end of file diff --git a/res/personal/RS.svg b/res/personal/RS.svg new file mode 100755 index 0000000..b2fc616 --- /dev/null +++ b/res/personal/RS.svg @@ -0,0 +1,53 @@ + +image/svg+xml \ No newline at end of file diff --git a/res/personal/TH.svg b/res/personal/TH.svg new file mode 100755 index 0000000..a4a109f --- /dev/null +++ b/res/personal/TH.svg @@ -0,0 +1,74 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/res/personal/TM1.svg b/res/personal/TM1.svg new file mode 100755 index 0000000..a0115b0 --- /dev/null +++ b/res/personal/TM1.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/res/qr-scanner-worker.min.js b/res/qr-scanner-worker.min.js new file mode 100644 index 0000000..8425f8b --- /dev/null +++ b/res/qr-scanner-worker.min.js @@ -0,0 +1,98 @@ +export const createWorker=()=>new Worker(URL.createObjectURL(new Blob([`class x{constructor(a,b){this.width=b;this.height=a.length/b;this.data=a}static createEmpty(a,b){return new x(new Uint8ClampedArray(a*b),a)}get(a,b){return 0>a||a>=this.width||0>b||b>=this.height?!1:!!this.data[b*this.width+a]}set(a,b,c){this.data[b*this.width+a]=c?1:0}setRegion(a,b,c,d,e){for(let f=b;fa||32this.available())throw Error("Cannot read "+a.toString()+" bits");var b=0;if(0>8-c<>b;a-=c;this.bitOffset+=c;8===this.bitOffset&&(this.bitOffset=0,this.byteOffset++)}if(0>c<>c, +this.bitOffset+=a)}return b}available(){return 8*(this.bytes.length-this.byteOffset)-this.bitOffset}}var B,C=B||(B={});C.Numeric="numeric";C.Alphanumeric="alphanumeric";C.Byte="byte";C.Kanji="kanji";C.ECI="eci";C.StructuredAppend="structuredappend";var D,E=D||(D={});E[E.Terminator=0]="Terminator";E[E.Numeric=1]="Numeric";E[E.Alphanumeric=2]="Alphanumeric";E[E.Byte=4]="Byte";E[E.Kanji=8]="Kanji";E[E.ECI=7]="ECI";E[E.StructuredAppend=3]="StructuredAppend";let F="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:".split(""); +function ca(a,b){let c=[],d="";b=a.readBits([8,16,16][b]);for(let e=0;e\`%\${("0"+e.toString(16)).substr(-2)}\`).join(""))}catch(e){}return{bytes:c,text:d}} +function da(a,b){a=new ba(a);let c=9>=b?0:26>=b?1:2;for(b={text:"",bytes:[],chunks:[],version:b};4<=a.available();){var d=a.readBits(4);if(d===D.Terminator)return b;if(d===D.ECI)0===a.readBits(1)?b.chunks.push({type:B.ECI,assignmentNumber:a.readBits(7)}):0===a.readBits(1)?b.chunks.push({type:B.ECI,assignmentNumber:a.readBits(14)}):0===a.readBits(1)?b.chunks.push({type:B.ECI,assignmentNumber:a.readBits(21)}):b.chunks.push({type:B.ECI,assignmentNumber:-1});else if(d===D.Numeric){var e=a,f=[];d="";for(var g= +e.readBits([10,12,14][c]);3<=g;){var h=e.readBits(10);if(1E3<=h)throw Error("Invalid numeric value above 999");var k=Math.floor(h/100),m=Math.floor(h/10)%10;h%=10;f.push(48+k,48+m,48+h);d+=k.toString()+m.toString()+h.toString();g-=3}if(2===g){g=e.readBits(7);if(100<=g)throw Error("Invalid numeric value above 99");e=Math.floor(g/10);g%=10;f.push(48+e,48+g);d+=e.toString()+g.toString()}else if(1===g){e=e.readBits(4);if(10<=e)throw Error("Invalid numeric value above 9");f.push(48+e);d+=e.toString()}b.text+= +d;b.bytes.push(...f);b.chunks.push({type:B.Numeric,text:d})}else if(d===D.Alphanumeric){e=a;f=[];d="";for(g=e.readBits([9,11,13][c]);2<=g;)m=e.readBits(11),k=Math.floor(m/45),m%=45,f.push(F[k].charCodeAt(0),F[m].charCodeAt(0)),d+=F[k]+F[m],g-=2;1===g&&(e=e.readBits(6),f.push(F[e].charCodeAt(0)),d+=F[e]);b.text+=d;b.bytes.push(...f);b.chunks.push({type:B.Alphanumeric,text:d})}else if(d===D.Byte)d=ca(a,c),b.text+=d.text,b.bytes.push(...d.bytes),b.chunks.push({type:B.Byte,bytes:d.bytes,text:d.text}); +else if(d===D.Kanji){f=a;d=[];e=f.readBits([8,10,12][c]);for(g=0;gk?k+33088:k+49472,d.push(k>>8,k&255);f=(new TextDecoder("shift-jis")).decode(Uint8Array.from(d));b.text+=f;b.bytes.push(...d);b.chunks.push({type:B.Kanji,bytes:d,text:f})}else d===D.StructuredAppend&&b.chunks.push({type:B.StructuredAppend,currentSequence:a.readBits(4),totalSequence:a.readBits(4),parity:a.readBits(8)})}if(0===a.available()||0===a.readBits(a.available()))return b} +class G{constructor(a,b){if(0===b.length)throw Error("No coefficients.");this.field=a;let c=b.length;if(1a.length&&([b,a]=[a,b]);let c=new Uint8ClampedArray(a.length),d=a.length-b.length;for(var e=0;ea)throw Error("Invalid degree less than 0");if(0===b)return this.field.zero;let c=this.coefficients.length;a=new Uint8ClampedArray(c+a);for(let d=0;d{b^=d}),b;b=this.coefficients[0];for(let d=1;d=this.size&&(a=(a^this.primitive)&this.size-1);for(a=0;aa)throw Error("Invalid monomial degree less than 0");if(0===b)return this.zero;a=new Uint8ClampedArray(a+1);a[0]=b;return new G(this,a)}log(a){if(0===a)throw Error("Can't take log(0)");return this.logTable[a]}exp(a){return this.expTable[a]}} +function fa(a,b,c,d){b.degree()=d/2;){var g=b;let h=e;b=c;e=f;if(b.isZero())return null;c=g;f=a.zero;g=b.getCoefficient(b.degree());for(g=a.inverse(g);c.degree()>=b.degree()&&!c.isZero();){let k=c.degree()-b.degree(),m=a.multiply(c.getCoefficient(c.degree()),g);f=f.addOrSubtract(a.buildMonomial(k,m));c=c.addOrSubtract(b.multiplyByMonomial(k,m))}f=f.multiplyPoly(e).addOrSubtract(h);if(c.degree()>=b.degree())return null}d=f.getCoefficient(0); +if(0===d)return null;a=a.inverse(d);return[f.multiply(a),c.multiply(a)]} +function ha(a,b){let c=new Uint8ClampedArray(a.length);c.set(a);a=new ea(285,256,0);var d=new G(a,c),e=new Uint8ClampedArray(b),f=!1;for(var g=0;gf)return null;c[f]^=d[e]}return c} +let I=[{infoBits:null,versionNumber:1,alignmentPatternCenters:[],errorCorrectionLevels:[{ecCodewordsPerBlock:7,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:19}]},{ecCodewordsPerBlock:10,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:16}]},{ecCodewordsPerBlock:13,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:13}]},{ecCodewordsPerBlock:17,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:9}]}]},{infoBits:null,versionNumber:2,alignmentPatternCenters:[6,18],errorCorrectionLevels:[{ecCodewordsPerBlock:10,ecBlocks:[{numBlocks:1, +dataCodewordsPerBlock:34}]},{ecCodewordsPerBlock:16,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:28}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:22}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:16}]}]},{infoBits:null,versionNumber:3,alignmentPatternCenters:[6,22],errorCorrectionLevels:[{ecCodewordsPerBlock:15,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:55}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:44}]},{ecCodewordsPerBlock:18, +ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:17}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:13}]}]},{infoBits:null,versionNumber:4,alignmentPatternCenters:[6,26],errorCorrectionLevels:[{ecCodewordsPerBlock:20,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:80}]},{ecCodewordsPerBlock:18,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:32}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:24}]},{ecCodewordsPerBlock:16,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:9}]}]}, +{infoBits:null,versionNumber:5,alignmentPatternCenters:[6,30],errorCorrectionLevels:[{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:108}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:43}]},{ecCodewordsPerBlock:18,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:15},{numBlocks:2,dataCodewordsPerBlock:16}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:11},{numBlocks:2,dataCodewordsPerBlock:12}]}]},{infoBits:null,versionNumber:6,alignmentPatternCenters:[6, +34],errorCorrectionLevels:[{ecCodewordsPerBlock:18,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:68}]},{ecCodewordsPerBlock:16,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:27}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:19}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:15}]}]},{infoBits:31892,versionNumber:7,alignmentPatternCenters:[6,22,38],errorCorrectionLevels:[{ecCodewordsPerBlock:20,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:78}]},{ecCodewordsPerBlock:18, +ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:31}]},{ecCodewordsPerBlock:18,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:14},{numBlocks:4,dataCodewordsPerBlock:15}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:13},{numBlocks:1,dataCodewordsPerBlock:14}]}]},{infoBits:34236,versionNumber:8,alignmentPatternCenters:[6,24,42],errorCorrectionLevels:[{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:97}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:38}, +{numBlocks:2,dataCodewordsPerBlock:39}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:18},{numBlocks:2,dataCodewordsPerBlock:19}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:14},{numBlocks:2,dataCodewordsPerBlock:15}]}]},{infoBits:39577,versionNumber:9,alignmentPatternCenters:[6,26,46],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:116}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:36}, +{numBlocks:2,dataCodewordsPerBlock:37}]},{ecCodewordsPerBlock:20,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:16},{numBlocks:4,dataCodewordsPerBlock:17}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:12},{numBlocks:4,dataCodewordsPerBlock:13}]}]},{infoBits:42195,versionNumber:10,alignmentPatternCenters:[6,28,50],errorCorrectionLevels:[{ecCodewordsPerBlock:18,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:68},{numBlocks:2,dataCodewordsPerBlock:69}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:4, +dataCodewordsPerBlock:43},{numBlocks:1,dataCodewordsPerBlock:44}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:6,dataCodewordsPerBlock:19},{numBlocks:2,dataCodewordsPerBlock:20}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:6,dataCodewordsPerBlock:15},{numBlocks:2,dataCodewordsPerBlock:16}]}]},{infoBits:48118,versionNumber:11,alignmentPatternCenters:[6,30,54],errorCorrectionLevels:[{ecCodewordsPerBlock:20,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:81}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:1, +dataCodewordsPerBlock:50},{numBlocks:4,dataCodewordsPerBlock:51}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:22},{numBlocks:4,dataCodewordsPerBlock:23}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:12},{numBlocks:8,dataCodewordsPerBlock:13}]}]},{infoBits:51042,versionNumber:12,alignmentPatternCenters:[6,32,58],errorCorrectionLevels:[{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:92},{numBlocks:2,dataCodewordsPerBlock:93}]}, +{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:6,dataCodewordsPerBlock:36},{numBlocks:2,dataCodewordsPerBlock:37}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:20},{numBlocks:6,dataCodewordsPerBlock:21}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:7,dataCodewordsPerBlock:14},{numBlocks:4,dataCodewordsPerBlock:15}]}]},{infoBits:55367,versionNumber:13,alignmentPatternCenters:[6,34,62],errorCorrectionLevels:[{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:107}]}, +{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:8,dataCodewordsPerBlock:37},{numBlocks:1,dataCodewordsPerBlock:38}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:8,dataCodewordsPerBlock:20},{numBlocks:4,dataCodewordsPerBlock:21}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:12,dataCodewordsPerBlock:11},{numBlocks:4,dataCodewordsPerBlock:12}]}]},{infoBits:58893,versionNumber:14,alignmentPatternCenters:[6,26,46,66],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:115}, +{numBlocks:1,dataCodewordsPerBlock:116}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:40},{numBlocks:5,dataCodewordsPerBlock:41}]},{ecCodewordsPerBlock:20,ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:16},{numBlocks:5,dataCodewordsPerBlock:17}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:12},{numBlocks:5,dataCodewordsPerBlock:13}]}]},{infoBits:63784,versionNumber:15,alignmentPatternCenters:[6,26,48,70],errorCorrectionLevels:[{ecCodewordsPerBlock:22, +ecBlocks:[{numBlocks:5,dataCodewordsPerBlock:87},{numBlocks:1,dataCodewordsPerBlock:88}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:5,dataCodewordsPerBlock:41},{numBlocks:5,dataCodewordsPerBlock:42}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:5,dataCodewordsPerBlock:24},{numBlocks:7,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:12},{numBlocks:7,dataCodewordsPerBlock:13}]}]},{infoBits:68472,versionNumber:16,alignmentPatternCenters:[6,26,50, +74],errorCorrectionLevels:[{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:5,dataCodewordsPerBlock:98},{numBlocks:1,dataCodewordsPerBlock:99}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:7,dataCodewordsPerBlock:45},{numBlocks:3,dataCodewordsPerBlock:46}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:15,dataCodewordsPerBlock:19},{numBlocks:2,dataCodewordsPerBlock:20}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:15},{numBlocks:13,dataCodewordsPerBlock:16}]}]},{infoBits:70749, +versionNumber:17,alignmentPatternCenters:[6,30,54,78],errorCorrectionLevels:[{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:107},{numBlocks:5,dataCodewordsPerBlock:108}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:10,dataCodewordsPerBlock:46},{numBlocks:1,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:22},{numBlocks:15,dataCodewordsPerBlock:23}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:14},{numBlocks:17, +dataCodewordsPerBlock:15}]}]},{infoBits:76311,versionNumber:18,alignmentPatternCenters:[6,30,56,82],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:5,dataCodewordsPerBlock:120},{numBlocks:1,dataCodewordsPerBlock:121}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:9,dataCodewordsPerBlock:43},{numBlocks:4,dataCodewordsPerBlock:44}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:22},{numBlocks:1,dataCodewordsPerBlock:23}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:2, +dataCodewordsPerBlock:14},{numBlocks:19,dataCodewordsPerBlock:15}]}]},{infoBits:79154,versionNumber:19,alignmentPatternCenters:[6,30,58,86],errorCorrectionLevels:[{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:113},{numBlocks:4,dataCodewordsPerBlock:114}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:44},{numBlocks:11,dataCodewordsPerBlock:45}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:21},{numBlocks:4,dataCodewordsPerBlock:22}]}, +{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:9,dataCodewordsPerBlock:13},{numBlocks:16,dataCodewordsPerBlock:14}]}]},{infoBits:84390,versionNumber:20,alignmentPatternCenters:[6,34,62,90],errorCorrectionLevels:[{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:107},{numBlocks:5,dataCodewordsPerBlock:108}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:41},{numBlocks:13,dataCodewordsPerBlock:42}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:15,dataCodewordsPerBlock:24}, +{numBlocks:5,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:15,dataCodewordsPerBlock:15},{numBlocks:10,dataCodewordsPerBlock:16}]}]},{infoBits:87683,versionNumber:21,alignmentPatternCenters:[6,28,50,72,94],errorCorrectionLevels:[{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:116},{numBlocks:4,dataCodewordsPerBlock:117}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:42}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:22}, +{numBlocks:6,dataCodewordsPerBlock:23}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:19,dataCodewordsPerBlock:16},{numBlocks:6,dataCodewordsPerBlock:17}]}]},{infoBits:92361,versionNumber:22,alignmentPatternCenters:[6,26,50,74,98],errorCorrectionLevels:[{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:111},{numBlocks:7,dataCodewordsPerBlock:112}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:46}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:7,dataCodewordsPerBlock:24}, +{numBlocks:16,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:34,dataCodewordsPerBlock:13}]}]},{infoBits:96236,versionNumber:23,alignmentPatternCenters:[6,30,54,74,102],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:121},{numBlocks:5,dataCodewordsPerBlock:122}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:47},{numBlocks:14,dataCodewordsPerBlock:48}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:24}, +{numBlocks:14,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:16,dataCodewordsPerBlock:15},{numBlocks:14,dataCodewordsPerBlock:16}]}]},{infoBits:102084,versionNumber:24,alignmentPatternCenters:[6,28,54,80,106],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:6,dataCodewordsPerBlock:117},{numBlocks:4,dataCodewordsPerBlock:118}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:6,dataCodewordsPerBlock:45},{numBlocks:14,dataCodewordsPerBlock:46}]},{ecCodewordsPerBlock:30, +ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:24},{numBlocks:16,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:30,dataCodewordsPerBlock:16},{numBlocks:2,dataCodewordsPerBlock:17}]}]},{infoBits:102881,versionNumber:25,alignmentPatternCenters:[6,32,58,84,110],errorCorrectionLevels:[{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:8,dataCodewordsPerBlock:106},{numBlocks:4,dataCodewordsPerBlock:107}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:8,dataCodewordsPerBlock:47},{numBlocks:13, +dataCodewordsPerBlock:48}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:7,dataCodewordsPerBlock:24},{numBlocks:22,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:22,dataCodewordsPerBlock:15},{numBlocks:13,dataCodewordsPerBlock:16}]}]},{infoBits:110507,versionNumber:26,alignmentPatternCenters:[6,30,58,86,114],errorCorrectionLevels:[{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:10,dataCodewordsPerBlock:114},{numBlocks:2,dataCodewordsPerBlock:115}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:19, +dataCodewordsPerBlock:46},{numBlocks:4,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:28,dataCodewordsPerBlock:22},{numBlocks:6,dataCodewordsPerBlock:23}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:33,dataCodewordsPerBlock:16},{numBlocks:4,dataCodewordsPerBlock:17}]}]},{infoBits:110734,versionNumber:27,alignmentPatternCenters:[6,34,62,90,118],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:8,dataCodewordsPerBlock:122},{numBlocks:4,dataCodewordsPerBlock:123}]}, +{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:22,dataCodewordsPerBlock:45},{numBlocks:3,dataCodewordsPerBlock:46}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:8,dataCodewordsPerBlock:23},{numBlocks:26,dataCodewordsPerBlock:24}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:12,dataCodewordsPerBlock:15},{numBlocks:28,dataCodewordsPerBlock:16}]}]},{infoBits:117786,versionNumber:28,alignmentPatternCenters:[6,26,50,74,98,122],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:117}, +{numBlocks:10,dataCodewordsPerBlock:118}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:45},{numBlocks:23,dataCodewordsPerBlock:46}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:24},{numBlocks:31,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:15},{numBlocks:31,dataCodewordsPerBlock:16}]}]},{infoBits:119615,versionNumber:29,alignmentPatternCenters:[6,30,54,78,102,126],errorCorrectionLevels:[{ecCodewordsPerBlock:30, +ecBlocks:[{numBlocks:7,dataCodewordsPerBlock:116},{numBlocks:7,dataCodewordsPerBlock:117}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:21,dataCodewordsPerBlock:45},{numBlocks:7,dataCodewordsPerBlock:46}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:23},{numBlocks:37,dataCodewordsPerBlock:24}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:19,dataCodewordsPerBlock:15},{numBlocks:26,dataCodewordsPerBlock:16}]}]},{infoBits:126325,versionNumber:30,alignmentPatternCenters:[6, +26,52,78,104,130],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:5,dataCodewordsPerBlock:115},{numBlocks:10,dataCodewordsPerBlock:116}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:19,dataCodewordsPerBlock:47},{numBlocks:10,dataCodewordsPerBlock:48}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:15,dataCodewordsPerBlock:24},{numBlocks:25,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:23,dataCodewordsPerBlock:15},{numBlocks:25,dataCodewordsPerBlock:16}]}]}, +{infoBits:127568,versionNumber:31,alignmentPatternCenters:[6,30,56,82,108,134],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:13,dataCodewordsPerBlock:115},{numBlocks:3,dataCodewordsPerBlock:116}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:46},{numBlocks:29,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:42,dataCodewordsPerBlock:24},{numBlocks:1,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:23,dataCodewordsPerBlock:15}, +{numBlocks:28,dataCodewordsPerBlock:16}]}]},{infoBits:133589,versionNumber:32,alignmentPatternCenters:[6,34,60,86,112,138],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:115}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:10,dataCodewordsPerBlock:46},{numBlocks:23,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:10,dataCodewordsPerBlock:24},{numBlocks:35,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:19, +dataCodewordsPerBlock:15},{numBlocks:35,dataCodewordsPerBlock:16}]}]},{infoBits:136944,versionNumber:33,alignmentPatternCenters:[6,30,58,86,114,142],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:115},{numBlocks:1,dataCodewordsPerBlock:116}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:14,dataCodewordsPerBlock:46},{numBlocks:21,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:29,dataCodewordsPerBlock:24},{numBlocks:19,dataCodewordsPerBlock:25}]}, +{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:15},{numBlocks:46,dataCodewordsPerBlock:16}]}]},{infoBits:141498,versionNumber:34,alignmentPatternCenters:[6,34,62,90,118,146],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:13,dataCodewordsPerBlock:115},{numBlocks:6,dataCodewordsPerBlock:116}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:14,dataCodewordsPerBlock:46},{numBlocks:23,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:44, +dataCodewordsPerBlock:24},{numBlocks:7,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:59,dataCodewordsPerBlock:16},{numBlocks:1,dataCodewordsPerBlock:17}]}]},{infoBits:145311,versionNumber:35,alignmentPatternCenters:[6,30,54,78,102,126,150],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:12,dataCodewordsPerBlock:121},{numBlocks:7,dataCodewordsPerBlock:122}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:12,dataCodewordsPerBlock:47},{numBlocks:26,dataCodewordsPerBlock:48}]}, +{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:39,dataCodewordsPerBlock:24},{numBlocks:14,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:22,dataCodewordsPerBlock:15},{numBlocks:41,dataCodewordsPerBlock:16}]}]},{infoBits:150283,versionNumber:36,alignmentPatternCenters:[6,24,50,76,102,128,154],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:6,dataCodewordsPerBlock:121},{numBlocks:14,dataCodewordsPerBlock:122}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:6, +dataCodewordsPerBlock:47},{numBlocks:34,dataCodewordsPerBlock:48}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:46,dataCodewordsPerBlock:24},{numBlocks:10,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:15},{numBlocks:64,dataCodewordsPerBlock:16}]}]},{infoBits:152622,versionNumber:37,alignmentPatternCenters:[6,28,54,80,106,132,158],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:122},{numBlocks:4,dataCodewordsPerBlock:123}]}, +{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:29,dataCodewordsPerBlock:46},{numBlocks:14,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:49,dataCodewordsPerBlock:24},{numBlocks:10,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:24,dataCodewordsPerBlock:15},{numBlocks:46,dataCodewordsPerBlock:16}]}]},{infoBits:158308,versionNumber:38,alignmentPatternCenters:[6,32,58,84,110,136,162],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:4, +dataCodewordsPerBlock:122},{numBlocks:18,dataCodewordsPerBlock:123}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:13,dataCodewordsPerBlock:46},{numBlocks:32,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:48,dataCodewordsPerBlock:24},{numBlocks:14,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:42,dataCodewordsPerBlock:15},{numBlocks:32,dataCodewordsPerBlock:16}]}]},{infoBits:161089,versionNumber:39,alignmentPatternCenters:[6,26,54,82,110,138,166], +errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:20,dataCodewordsPerBlock:117},{numBlocks:4,dataCodewordsPerBlock:118}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:40,dataCodewordsPerBlock:47},{numBlocks:7,dataCodewordsPerBlock:48}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:43,dataCodewordsPerBlock:24},{numBlocks:22,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:10,dataCodewordsPerBlock:15},{numBlocks:67,dataCodewordsPerBlock:16}]}]},{infoBits:167017, +versionNumber:40,alignmentPatternCenters:[6,30,58,86,114,142,170],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:19,dataCodewordsPerBlock:118},{numBlocks:6,dataCodewordsPerBlock:119}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:18,dataCodewordsPerBlock:47},{numBlocks:31,dataCodewordsPerBlock:48}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:34,dataCodewordsPerBlock:24},{numBlocks:34,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:20,dataCodewordsPerBlock:15}, +{numBlocks:61,dataCodewordsPerBlock:16}]}]}];function J(a,b){a^=b;for(b=0;a;)b++,a&=a-1;return b}function K(a,b){return b<<1|a} +let ia=[{bits:21522,formatInfo:{errorCorrectionLevel:1,dataMask:0}},{bits:20773,formatInfo:{errorCorrectionLevel:1,dataMask:1}},{bits:24188,formatInfo:{errorCorrectionLevel:1,dataMask:2}},{bits:23371,formatInfo:{errorCorrectionLevel:1,dataMask:3}},{bits:17913,formatInfo:{errorCorrectionLevel:1,dataMask:4}},{bits:16590,formatInfo:{errorCorrectionLevel:1,dataMask:5}},{bits:20375,formatInfo:{errorCorrectionLevel:1,dataMask:6}},{bits:19104,formatInfo:{errorCorrectionLevel:1,dataMask:7}},{bits:30660,formatInfo:{errorCorrectionLevel:0, +dataMask:0}},{bits:29427,formatInfo:{errorCorrectionLevel:0,dataMask:1}},{bits:32170,formatInfo:{errorCorrectionLevel:0,dataMask:2}},{bits:30877,formatInfo:{errorCorrectionLevel:0,dataMask:3}},{bits:26159,formatInfo:{errorCorrectionLevel:0,dataMask:4}},{bits:25368,formatInfo:{errorCorrectionLevel:0,dataMask:5}},{bits:27713,formatInfo:{errorCorrectionLevel:0,dataMask:6}},{bits:26998,formatInfo:{errorCorrectionLevel:0,dataMask:7}},{bits:5769,formatInfo:{errorCorrectionLevel:3,dataMask:0}},{bits:5054, +formatInfo:{errorCorrectionLevel:3,dataMask:1}},{bits:7399,formatInfo:{errorCorrectionLevel:3,dataMask:2}},{bits:6608,formatInfo:{errorCorrectionLevel:3,dataMask:3}},{bits:1890,formatInfo:{errorCorrectionLevel:3,dataMask:4}},{bits:597,formatInfo:{errorCorrectionLevel:3,dataMask:5}},{bits:3340,formatInfo:{errorCorrectionLevel:3,dataMask:6}},{bits:2107,formatInfo:{errorCorrectionLevel:3,dataMask:7}},{bits:13663,formatInfo:{errorCorrectionLevel:2,dataMask:0}},{bits:12392,formatInfo:{errorCorrectionLevel:2, +dataMask:1}},{bits:16177,formatInfo:{errorCorrectionLevel:2,dataMask:2}},{bits:14854,formatInfo:{errorCorrectionLevel:2,dataMask:3}},{bits:9396,formatInfo:{errorCorrectionLevel:2,dataMask:4}},{bits:8579,formatInfo:{errorCorrectionLevel:2,dataMask:5}},{bits:11994,formatInfo:{errorCorrectionLevel:2,dataMask:6}},{bits:11245,formatInfo:{errorCorrectionLevel:2,dataMask:7}}],ja=[a=>0===(a.y+a.x)%2,a=>0===a.y%2,a=>0===a.x%3,a=>0===(a.y+a.x)%3,a=>0===(Math.floor(a.y/2)+Math.floor(a.x/3))%2,a=>0===a.x*a.y% +2+a.x*a.y%3,a=>0===(a.y*a.x%2+a.y*a.x%3)%2,a=>0===((a.y+a.x)%2+a.y*a.x%3)%2]; +function ka(a,b,c){c=ja[c.dataMask];let d=a.height;var e=17+4*b.versionNumber;let f=x.createEmpty(e,e);f.setRegion(0,0,9,9,!0);f.setRegion(e-8,0,8,9,!0);f.setRegion(0,e-8,9,8,!0);for(var g of b.alignmentPatternCenters)for(var h of b.alignmentPatternCenters)6===g&&6===h||6===g&&h===e-7||g===e-7&&6===h||f.setRegion(g-2,h-2,5,5,!0);f.setRegion(6,9,1,e-17,!0);f.setRegion(9,6,e-17,1,!0);6n;n++){let q=k-n;if(!f.get(q,l)){h++;let r=a.get(q,l);c({y:l,x:q})&&(r=!r);g=g<<1|r;8===h&&(b.push(g),g=h=0)}}}e=!e}return b} +function la(a){var b=a.height,c=Math.floor((b-17)/4);if(6>=c)return I[c-1];c=0;for(var d=5;0<=d;d--)for(var e=b-9;e>=b-11;e--)c=K(a.get(e,d),c);d=0;for(e=5;0<=e;e--)for(let g=b-9;g>=b-11;g--)d=K(a.get(e,g),d);a=Infinity;let f;for(let g of I){if(g.infoBits===c||g.infoBits===d)return g;b=J(c,g.infoBits);b=a)return f} +function ma(a){let b=0;for(var c=0;8>=c;c++)6!==c&&(b=K(a.get(c,8),b));for(c=7;0<=c;c--)6!==c&&(b=K(a.get(8,c),b));var d=a.height;c=0;for(var e=d-1;e>=d-7;e--)c=K(a.get(8,e),c);for(e=d-8;e=a?d:null} +function na(a,b,c){let d=b.errorCorrectionLevels[c],e=[],f=0;d.ecBlocks.forEach(h=>{for(let k=0;ke+f.numDataCodewords,0);c=new Uint8ClampedArray(c);a=0;for(let e of d){d=ha(e.codewords,e.codewords.length-e.numDataCodewords);if(!d)return null;for(let f=0;f{const p=g*r+m*u+q;return{x:(e*r+h*u+l)/p,y:(f*r+k*u+n)/p}};for(let r=0;rMath.sqrt(Math.pow(b.x-a.x,2)+Math.pow(b.y-a.y,2));function O(a){return a.reduce((b,c)=>b+c)} +function qa(a,b,c){let d=N(a,b),e=N(b,c),f=N(a,c),g,h,k;e>=d&&e>=f?[g,h,k]=[b,a,c]:f>=e&&f>=d?[g,h,k]=[a,b,c]:[g,h,k]=[a,c,b];0>(k.x-h.x)*(g.y-h.y)-(k.y-h.y)*(g.x-h.x)&&([g,k]=[k,g]);return{bottomLeft:g,topLeft:h,topRight:k}} +function ra(a,b,c,d){d=(O(P(a,c,d,5))/7+O(P(a,b,d,5))/7+O(P(c,a,d,5))/7+O(P(b,a,d,5))/7)/4;if(1>d)throw Error("Invalid module size");b=Math.round(N(a,b)/d);a=Math.round(N(a,c)/d);a=Math.floor((b+a)/2)+7;switch(a%4){case 0:a++;break;case 2:a--}return{dimension:a,moduleSize:d}} +function Q(a,b,c,d){let e=[{x:Math.floor(a.x),y:Math.floor(a.y)}];var f=Math.abs(b.y-a.y)>Math.abs(b.x-a.x);if(f){var g=Math.floor(a.y);var h=Math.floor(a.x);a=Math.floor(b.y);b=Math.floor(b.x)}else g=Math.floor(a.x),h=Math.floor(a.y),a=Math.floor(b.x),b=Math.floor(b.y);let k=Math.abs(a-g),m=Math.abs(b-h),l=Math.floor(-k/2),n=g{d+=Math.pow(a[f]-e*c,2)});return{averageSize:c,error:d}} +function S(a,b,c){try{let d=P(a,{x:-1,y:a.y},c,b.length),e=P(a,{x:a.x,y:-1},c,b.length),f=P(a,{x:Math.max(0,a.x-a.y)-1,y:Math.max(0,a.y-a.x)-1},c,b.length),g=P(a,{x:Math.min(c.width,a.x+a.y)+1,y:Math.min(c.height,a.y+a.x)+1},c,b.length),h=R(d,b),k=R(e,b),m=R(f,b),l=R(g,b),n=(h.averageSize+k.averageSize+m.averageSize+l.averageSize)/4;return Math.sqrt(h.error*h.error+k.error*k.error+m.error*m.error+l.error*l.error)+(Math.pow(h.averageSize-n,2)+Math.pow(k.averageSize-n,2)+Math.pow(m.averageSize-n,2)+ +Math.pow(l.averageSize-n,2))/n}catch(d){return Infinity}}function T(a,b){for(var c=Math.round(b.x);a.get(c,Math.round(b.y));)c--;for(var d=Math.round(b.x);a.get(d,Math.round(b.y));)d++;c=(c+d)/2;for(d=Math.round(b.y);a.get(Math.round(c),d);)d--;for(b=Math.round(b.y);a.get(Math.round(c),b);)b++;return{x:c,y:(d+b)/2}} +function sa(a){var b=[],c=[];let d=[];var e=[];for(let p=0;p<=a.height;p++){var f=0,g=!1;let t=[0,0,0,0,0];for(let v=-1;v<=a.width;v++){var h=a.get(v,p);if(h===g)f++;else{t=[t[1],t[2],t[3],t[4],f];f=1;g=h;var k=O(t)/7;k=Math.abs(t[0]-k)y>=w.bottom.startX&& +y<=w.bottom.endX||z>=w.bottom.startX&&y<=w.bottom.endX||y<=w.bottom.startX&&z>=w.bottom.endX&&1.5>t[2]/(w.bottom.endX-w.bottom.startX)&&.5y>=w.bottom.startX&&y<=w.bottom.endX||z>=w.bottom.startX&&y<=w.bottom.endX||y<=w.bottom.startX&&z>=w.bottom.endX&&1.5>t[2]/(w.bottom.endX-w.bottom.startX)&&.5v.bottom.y!==p&&2<=v.bottom.y-v.top.y));c=c.filter(v=>v.bottom.y===p);d.push(...e.filter(v=>v.bottom.y!==p));e=e.filter(v=>v.bottom.y===p)}b.push(...c.filter(p=>2<=p.bottom.y-p.top.y));d.push(...e);c=[];for(var l of b)2>l.bottom.y-l.top.y||(b=(l.top.startX+l.top.endX+l.bottom.startX+l.bottom.endX)/4,e=(l.top.y+l.bottom.y+1)/2,a.get(Math.round(b),Math.round(e))&&(f=[l.top.endX-l.top.startX,l.bottom.endX-l.bottom.startX,l.bottom.y-l.top.y+ +1],f=O(f)/f.length,g=S({x:Math.round(b),y:Math.round(e)},[1,1,3,1,1],a),c.push({score:g,x:b,y:e,size:f})));if(3>c.length)return null;c.sort((p,t)=>p.score-t.score);l=[];for(b=0;bp.score-t.score);l.push({points:[e,f[0],f[1]],score:e.score+f[0].score+f[1].score})}l.sort((p,t)=>p.score-t.score);let {topRight:q,topLeft:r,bottomLeft:u}=qa(...l[0].points); +l=U(a,d,q,r,u);n=[];l&&n.push({alignmentPattern:{x:l.alignmentPattern.x,y:l.alignmentPattern.y},bottomLeft:{x:u.x,y:u.y},dimension:l.dimension,topLeft:{x:r.x,y:r.y},topRight:{x:q.x,y:q.y}});l=T(a,q);b=T(a,r);c=T(a,u);(a=U(a,d,l,b,c))&&n.push({alignmentPattern:{x:a.alignmentPattern.x,y:a.alignmentPattern.y},bottomLeft:{x:c.x,y:c.y},topLeft:{x:b.x,y:b.y},topRight:{x:l.x,y:l.y},dimension:a.dimension});return 0===n.length?null:n} +function U(a,b,c,d,e){let f,g;try{({dimension:f,moduleSize:g}=ra(d,c,e,a))}catch(l){return null}var h=c.x-d.x+e.x,k=c.y-d.y+e.y;c=(N(d,e)+N(d,c))/2/g;e=1-3/c;let m={x:d.x+e*(h-d.x),y:d.y+e*(k-d.y)};b=b.map(l=>{const n=(l.top.startX+l.top.endX+l.bottom.startX+l.bottom.endX)/4;l=(l.top.y+l.bottom.y+1)/2;if(a.get(Math.floor(n),Math.floor(l))){var q=S({x:Math.floor(n),y:Math.floor(l)},[1,1,1],a)+N({x:n,y:l},m);return{x:n,y:l,score:q}}}).filter(l=>!!l).sort((l,n)=>l.score-n.score);return{alignmentPattern:15<= +c&&b.length?b[0]:m,dimension:f}} +function V(a){var b=sa(a);if(!b)return null;for(let e of b){b=pa(a,e);var c=b.matrix;if(null==c)c=null;else{var d=L(c);if(d)c=d;else{for(d=0;d{a[c]=b[c]})} +function X(a,b,c,d={}){let e=Object.create(null);W(e,ta);W(e,d);d="onlyInvert"===e.inversionAttempts||"invertFirst"===e.inversionAttempts;var f="attemptBoth"===e.inversionAttempts||d;var g=e.greyScaleWeights,h=e.canOverwriteImage,k=b*c;if(a.length!==4*k)throw Error("Malformed data passed to binarizer.");var m=0;if(h){var l=new Uint8ClampedArray(a.buffer,m,k);m+=k}l=new A(b,c,l);if(g.useIntegerApproximation)for(var n=0;n>8)}else for(n=0;nv;v++)for(let w=0;8>w;w++){let aa=l.get(8*r+w,8*q+v);p=Math.min(p,aa);t=Math.max(t,aa)}v=(p+t)/2;v=Math.min(255,1.11*v);24>=t-p&&(v=p/2,0a?2:a>c?c:a;h=n-3;h=2>b?2:b>h?h:b;k=0;for(m=-2;2>=m;m++)for(p=-2;2>=p;p++)k+=u.get(c+m,h+p);c=k/25;for(h=0;8>h;h++)for(k=0;8>k;k++)m=8*a+h,p=8*b+k,t=l.get(m,p),q.set(m,p,t<=c),f&&r.set(m,p,!(t<=c))}f=f?{binarized:q,inverted:r}:{binarized:q};let {binarized:z,inverted:y}=f;(f=V(d? +y:z))||"attemptBoth"!==e.inversionAttempts&&"invertFirst"!==e.inversionAttempts||(f=V(d?z:y));return f}X.default=X;let Y="dontInvert",Z={red:77,green:150,blue:29,useIntegerApproximation:!0}; +self.onmessage=a=>{let b=a.data.id,c=a.data.data;switch(a.data.type){case "decode":(a=X(c.data,c.width,c.height,{inversionAttempts:Y,greyScaleWeights:Z}))?self.postMessage({id:b,type:"qrResult",data:a.data,cornerPoints:[a.location.topLeftCorner,a.location.topRightCorner,a.location.bottomRightCorner,a.location.bottomLeftCorner]}):self.postMessage({id:b,type:"qrResult",data:null});break;case "grayscaleWeights":Z.red=c.red;Z.green=c.green;Z.blue=c.blue;Z.useIntegerApproximation=c.useIntegerApproximation; +break;case "inversionMode":switch(c){case "original":Y="dontInvert";break;case "invert":Y="onlyInvert";break;case "both":Y="attemptBoth";break;default:throw Error("Invalid inversion mode");}break;case "close":self.close()}} +`]),{type:"application/javascript"}))//# sourceMappingURL=qr-scanner-worker.min.js.map diff --git a/res/qr-scanner-worker.min.js.map b/res/qr-scanner-worker.min.js.map new file mode 100644 index 0000000..618e36e --- /dev/null +++ b/res/qr-scanner-worker.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"qr-scanner-worker.min.js","sources":["node_modules/jsqr-es6/src/BitMatrix.ts","node_modules/jsqr-es6/src/binarizer/index.ts","node_modules/jsqr-es6/src/decoder/decodeData/BitStream.ts","node_modules/jsqr-es6/src/decoder/decodeData/index.ts","node_modules/jsqr-es6/src/decoder/reedsolomon/GenericGFPoly.ts","node_modules/jsqr-es6/src/decoder/reedsolomon/GenericGF.ts","node_modules/jsqr-es6/src/decoder/reedsolomon/index.ts","node_modules/jsqr-es6/src/decoder/version.ts","node_modules/jsqr-es6/src/decoder/decoder.ts","node_modules/jsqr-es6/src/extractor/index.ts","node_modules/jsqr-es6/src/locator/index.ts","node_modules/jsqr-es6/src/index.ts","src/worker.ts"],"sourcesContent":["export class BitMatrix {\n public static createEmpty(width: number, height: number) {\n return new BitMatrix(new Uint8ClampedArray(width * height), width);\n }\n\n public width: number;\n public height: number;\n private data: Uint8ClampedArray;\n\n constructor(data: Uint8ClampedArray, width: number) {\n this.width = width;\n this.height = data.length / width;\n this.data = data;\n }\n\n public get(x: number, y: number): boolean {\n if (x < 0 || x >= this.width || y < 0 || y >= this.height) {\n return false;\n }\n return !!this.data[y * this.width + x];\n }\n\n public set(x: number, y: number, v: boolean) {\n this.data[y * this.width + x] = v ? 1 : 0;\n }\n\n public setRegion(left: number, top: number, width: number, height: number, v: boolean) {\n for (let y = top; y < top + height; y++) {\n for (let x = left; x < left + width; x++) {\n this.set(x, y, !!v);\n }\n }\n }\n}\n","import {BitMatrix} from \"../BitMatrix\";\nimport {GreyscaleWeights} from \"../index\";\n\nconst REGION_SIZE = 8;\nconst MIN_DYNAMIC_RANGE = 24;\n\nfunction numBetween(value: number, min: number, max: number): number {\n return value < min ? min : value > max ? max : value;\n}\n\n// Like BitMatrix but accepts arbitry Uint8 values\nclass Matrix {\n private data: Uint8ClampedArray;\n private width: number;\n constructor(width: number, height: number, buffer?: Uint8ClampedArray) {\n this.width = width;\n const bufferSize = width * height;\n if (buffer && buffer.length !== bufferSize) {\n throw new Error(\"Wrong buffer size\");\n }\n this.data = buffer || new Uint8ClampedArray(bufferSize);\n }\n public get(x: number, y: number) {\n return this.data[y * this.width + x];\n }\n public set(x: number, y: number, value: number) {\n this.data[y * this.width + x] = value;\n }\n}\n\nexport function binarize(data: Uint8ClampedArray, width: number, height: number, returnInverted: boolean,\n greyscaleWeights: GreyscaleWeights, canOverwriteImage: boolean) {\n const pixelCount = width * height;\n if (data.length !== pixelCount * 4) {\n throw new Error(\"Malformed data passed to binarizer.\");\n }\n // assign the greyscale and binary image within the rgba buffer as the rgba image will not be needed after conversion\n let bufferOffset = 0;\n // Convert image to greyscale\n let greyscaleBuffer: Uint8ClampedArray;\n if (canOverwriteImage) {\n greyscaleBuffer = new Uint8ClampedArray(data.buffer, bufferOffset, pixelCount);\n bufferOffset += pixelCount;\n }\n const greyscalePixels = new Matrix(width, height, greyscaleBuffer);\n if (greyscaleWeights.useIntegerApproximation) {\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const pixelPosition = (y * width + x) * 4;\n const r = data[pixelPosition];\n const g = data[pixelPosition + 1];\n const b = data[pixelPosition + 2];\n greyscalePixels.set(x, y,\n // tslint:disable-next-line no-bitwise\n (greyscaleWeights.red * r + greyscaleWeights.green * g + greyscaleWeights.blue * b + 128) >> 8);\n }\n }\n } else {\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const pixelPosition = (y * width + x) * 4;\n const r = data[pixelPosition];\n const g = data[pixelPosition + 1];\n const b = data[pixelPosition + 2];\n greyscalePixels.set(x, y,\n greyscaleWeights.red * r + greyscaleWeights.green * g + greyscaleWeights.blue * b);\n }\n }\n }\n const horizontalRegionCount = Math.ceil(width / REGION_SIZE);\n const verticalRegionCount = Math.ceil(height / REGION_SIZE);\n const blackPointsCount = horizontalRegionCount * verticalRegionCount;\n\n let blackPointsBuffer: Uint8ClampedArray;\n if (canOverwriteImage) {\n blackPointsBuffer = new Uint8ClampedArray(data.buffer, bufferOffset, blackPointsCount);\n bufferOffset += blackPointsCount;\n }\n const blackPoints = new Matrix(horizontalRegionCount, verticalRegionCount, blackPointsBuffer);\n for (let verticalRegion = 0; verticalRegion < verticalRegionCount; verticalRegion++) {\n for (let hortizontalRegion = 0; hortizontalRegion < horizontalRegionCount; hortizontalRegion++) {\n let min = Infinity;\n let max = 0;\n for (let y = 0; y < REGION_SIZE; y++) {\n for (let x = 0; x < REGION_SIZE; x++) {\n const pixelLumosity =\n greyscalePixels.get(hortizontalRegion * REGION_SIZE + x, verticalRegion * REGION_SIZE + y);\n min = Math.min(min, pixelLumosity);\n max = Math.max(max, pixelLumosity);\n }\n }\n // We could also compute the real average of all pixels but following the assumption that the qr code consists\n // of bright and dark pixels and essentially not much in between, by (min + max)/2 we make the cut really between\n // those two classes. If using the average over all pixel in a block of mostly bright pixels and few dark pixels,\n // the avg would tend to the bright side and darker bright pixels could be interpreted as dark.\n let average = (min + max) / 2;\n // Small bias towards black by moving the threshold up. We do this, as in the finder patterns white holes tend\n // to appear which makes them undetectable.\n const blackBias = 1.11;\n average = Math.min(255, average * blackBias);\n if (max - min <= MIN_DYNAMIC_RANGE) {\n // If variation within the block is low, assume this is a block with only light or only\n // dark pixels. In that case we do not want to use the average, as it would divide this\n // low contrast area into black and white pixels, essentially creating data out of noise.\n //\n // Default the blackpoint for these blocks to be half the min - effectively white them out\n average = min / 2;\n\n if (verticalRegion > 0 && hortizontalRegion > 0) {\n // Correct the \"white background\" assumption for blocks that have neighbors by comparing\n // the pixels in this block to the previously calculated black points. This is based on\n // the fact that dark barcode symbology is always surrounded by some amount of light\n // background for which reasonable black point estimates were made. The bp estimated at\n // the boundaries is used for the interior.\n\n // The (min < bp) is arbitrary but works better than other heuristics that were tried.\n const averageNeighborBlackPoint = (\n blackPoints.get(hortizontalRegion, verticalRegion - 1) +\n (2 * blackPoints.get(hortizontalRegion - 1, verticalRegion)) +\n blackPoints.get(hortizontalRegion - 1, verticalRegion - 1)\n ) / 4;\n if (min < averageNeighborBlackPoint) {\n average = averageNeighborBlackPoint; // no need to apply black bias as already applied to neighbors\n }\n }\n }\n blackPoints.set(hortizontalRegion, verticalRegion, average);\n }\n }\n\n let binarized: BitMatrix;\n if (canOverwriteImage) {\n const binarizedBuffer = new Uint8ClampedArray(data.buffer, bufferOffset, pixelCount);\n bufferOffset += pixelCount;\n binarized = new BitMatrix(binarizedBuffer, width);\n } else {\n binarized = BitMatrix.createEmpty(width, height);\n }\n\n let inverted: BitMatrix = null;\n if (returnInverted) {\n if (canOverwriteImage) {\n const invertedBuffer = new Uint8ClampedArray(data.buffer, bufferOffset, pixelCount);\n inverted = new BitMatrix(invertedBuffer, width);\n } else {\n inverted = BitMatrix.createEmpty(width, height);\n }\n }\n\n for (let verticalRegion = 0; verticalRegion < verticalRegionCount; verticalRegion++) {\n for (let hortizontalRegion = 0; hortizontalRegion < horizontalRegionCount; hortizontalRegion++) {\n const left = numBetween(hortizontalRegion, 2, horizontalRegionCount - 3);\n const top = numBetween(verticalRegion, 2, verticalRegionCount - 3);\n let sum = 0;\n for (let xRegion = -2; xRegion <= 2; xRegion++) {\n for (let yRegion = -2; yRegion <= 2; yRegion++) {\n sum += blackPoints.get(left + xRegion, top + yRegion);\n }\n }\n const threshold = sum / 25;\n for (let xRegion = 0; xRegion < REGION_SIZE; xRegion++) {\n for (let yRegion = 0; yRegion < REGION_SIZE; yRegion++) {\n const x = hortizontalRegion * REGION_SIZE + xRegion;\n const y = verticalRegion * REGION_SIZE + yRegion;\n const lum = greyscalePixels.get(x, y);\n binarized.set(x, y, lum <= threshold);\n if (returnInverted) {\n inverted.set(x, y, !(lum <= threshold));\n }\n }\n }\n }\n }\n if (returnInverted) {\n return { binarized, inverted };\n }\n return { binarized };\n}\n","// tslint:disable:no-bitwise\n\nexport class BitStream {\n private bytes: Uint8ClampedArray;\n private byteOffset: number = 0;\n private bitOffset: number = 0;\n\n constructor(bytes: Uint8ClampedArray) {\n this.bytes = bytes;\n }\n\n public readBits(numBits: number): number {\n if (numBits < 1 || numBits > 32 || numBits > this.available()) {\n throw new Error(\"Cannot read \" + numBits.toString() + \" bits\");\n }\n\n let result = 0;\n // First, read remainder from current byte\n if (this.bitOffset > 0) {\n const bitsLeft = 8 - this.bitOffset;\n const toRead = numBits < bitsLeft ? numBits : bitsLeft;\n const bitsToNotRead = bitsLeft - toRead;\n const mask = (0xFF >> (8 - toRead)) << bitsToNotRead;\n result = (this.bytes[this.byteOffset] & mask) >> bitsToNotRead;\n numBits -= toRead;\n this.bitOffset += toRead;\n if (this.bitOffset === 8) {\n this.bitOffset = 0;\n this.byteOffset++;\n }\n }\n\n // Next read whole bytes\n if (numBits > 0) {\n while (numBits >= 8) {\n result = (result << 8) | (this.bytes[this.byteOffset] & 0xFF);\n this.byteOffset++;\n numBits -= 8;\n }\n\n // Finally read a partial byte\n if (numBits > 0) {\n const bitsToNotRead = 8 - numBits;\n const mask = (0xFF >> bitsToNotRead) << bitsToNotRead;\n result = (result << numBits) | ((this.bytes[this.byteOffset] & mask) >> bitsToNotRead);\n this.bitOffset += numBits;\n }\n }\n return result;\n }\n\n public available(): number {\n return 8 * (this.bytes.length - this.byteOffset) - this.bitOffset;\n }\n}\n","// tslint:disable:no-bitwise\nimport { BitStream } from \"./BitStream\";\n\nexport interface Chunk {\n type: Mode;\n text: string;\n}\n\nexport interface ByteChunk {\n type: Mode.Byte | Mode.Kanji;\n bytes: number[];\n}\n\nexport interface ECIChunk {\n type: Mode.ECI;\n assignmentNumber: number;\n}\n\nexport interface StructuredAppend {\n type: Mode.StructuredAppend;\n currentSequence: number;\n totalSequence: number;\n parity: number;\n}\n\nexport type Chunks = Array;\n\nexport interface DecodedQR {\n text: string;\n bytes: number[];\n chunks: Chunks;\n version: number;\n}\n\nexport enum Mode {\n Numeric = \"numeric\",\n Alphanumeric = \"alphanumeric\",\n Byte = \"byte\",\n Kanji = \"kanji\",\n ECI = \"eci\",\n StructuredAppend = \"structuredappend\",\n}\n\nenum ModeByte {\n Terminator = 0x0,\n Numeric = 0x1,\n Alphanumeric = 0x2,\n Byte = 0x4,\n Kanji = 0x8,\n ECI = 0x7,\n StructuredAppend = 0x3,\n // FNC1FirstPosition = 0x5,\n // FNC1SecondPosition = 0x9,\n}\n\nfunction decodeNumeric(stream: BitStream, size: number) {\n const bytes: number[] = [];\n let text = \"\";\n\n const characterCountSize = [10, 12, 14][size];\n let length = stream.readBits(characterCountSize);\n // Read digits in groups of 3\n while (length >= 3) {\n const num = stream.readBits(10);\n if (num >= 1000) {\n throw new Error(\"Invalid numeric value above 999\");\n }\n\n const a = Math.floor(num / 100);\n const b = Math.floor(num / 10) % 10;\n const c = num % 10;\n\n bytes.push(48 + a, 48 + b, 48 + c);\n text += a.toString() + b.toString() + c.toString();\n length -= 3;\n }\n\n // If the number of digits aren't a multiple of 3, the remaining digits are special cased.\n if (length === 2) {\n const num = stream.readBits(7);\n if (num >= 100) {\n throw new Error(\"Invalid numeric value above 99\");\n }\n\n const a = Math.floor(num / 10);\n const b = num % 10;\n\n bytes.push(48 + a, 48 + b);\n text += a.toString() + b.toString();\n } else if (length === 1) {\n const num = stream.readBits(4);\n if (num >= 10) {\n throw new Error(\"Invalid numeric value above 9\");\n }\n\n bytes.push(48 + num);\n text += num.toString();\n }\n\n return { bytes, text };\n}\n\nconst AlphanumericCharacterCodes = [\n \"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\",\n \"9\", \"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\",\n \"I\", \"J\", \"K\", \"L\", \"M\", \"N\", \"O\", \"P\", \"Q\",\n \"R\", \"S\", \"T\", \"U\", \"V\", \"W\", \"X\", \"Y\", \"Z\",\n \" \", \"$\", \"%\", \"*\", \"+\", \"-\", \".\", \"/\", \":\",\n];\n\nfunction decodeAlphanumeric(stream: BitStream, size: number) {\n const bytes: number[] = [];\n let text = \"\";\n\n const characterCountSize = [9, 11, 13][size];\n let length = stream.readBits(characterCountSize);\n while (length >= 2) {\n const v = stream.readBits(11);\n\n const a = Math.floor(v / 45);\n const b = v % 45;\n\n bytes.push(AlphanumericCharacterCodes[a].charCodeAt(0), AlphanumericCharacterCodes[b].charCodeAt(0));\n text += AlphanumericCharacterCodes[a] + AlphanumericCharacterCodes[b];\n length -= 2;\n }\n\n if (length === 1) {\n const a = stream.readBits(6);\n bytes.push(AlphanumericCharacterCodes[a].charCodeAt(0));\n text += AlphanumericCharacterCodes[a];\n }\n\n return { bytes, text };\n}\n\nfunction decodeByte(stream: BitStream, size: number) {\n const bytes: number[] = [];\n let text = \"\";\n\n const characterCountSize = [8, 16, 16][size];\n const length = stream.readBits(characterCountSize);\n for (let i = 0; i < length; i++) {\n const b = stream.readBits(8);\n bytes.push(b);\n }\n try {\n text += decodeURIComponent(bytes.map(b => `%${(\"0\" + b.toString(16)).substr(-2)}`).join(\"\"));\n } catch {\n // failed to decode\n }\n\n return { bytes, text };\n}\n\nfunction decodeKanji(stream: BitStream, size: number) {\n const bytes: number[] = [];\n\n const characterCountSize = [8, 10, 12][size];\n const length = stream.readBits(characterCountSize);\n for (let i = 0; i < length; i++) {\n const k = stream.readBits(13);\n\n let c = (Math.floor(k / 0xC0) << 8) | (k % 0xC0);\n if (c < 0x1F00) {\n c += 0x8140;\n } else {\n c += 0xC140;\n }\n\n bytes.push(c >> 8, c & 0xFF);\n }\n\n const text = new TextDecoder(\"shift-jis\").decode(Uint8Array.from(bytes));\n return { bytes, text };\n}\n\nexport function decode(data: Uint8ClampedArray, version: number): DecodedQR {\n const stream = new BitStream(data);\n\n // There are 3 'sizes' based on the version. 1-9 is small (0), 10-26 is medium (1) and 27-40 is large (2).\n const size = version <= 9 ? 0 : version <= 26 ? 1 : 2;\n\n const result: DecodedQR = {\n text: \"\",\n bytes: [],\n chunks: [],\n version,\n };\n\n while (stream.available() >= 4) {\n const mode = stream.readBits(4);\n if (mode === ModeByte.Terminator) {\n return result;\n } else if (mode === ModeByte.ECI) {\n if (stream.readBits(1) === 0) {\n result.chunks.push({\n type: Mode.ECI,\n assignmentNumber: stream.readBits(7),\n });\n } else if (stream.readBits(1) === 0) {\n result.chunks.push({\n type: Mode.ECI,\n assignmentNumber: stream.readBits(14),\n });\n } else if (stream.readBits(1) === 0) {\n result.chunks.push({\n type: Mode.ECI,\n assignmentNumber: stream.readBits(21),\n });\n } else {\n // ECI data seems corrupted\n result.chunks.push({\n type: Mode.ECI,\n assignmentNumber: -1,\n });\n }\n } else if (mode === ModeByte.Numeric) {\n const numericResult = decodeNumeric(stream, size);\n result.text += numericResult.text;\n result.bytes.push(...numericResult.bytes);\n result.chunks.push({\n type: Mode.Numeric,\n text: numericResult.text,\n });\n } else if (mode === ModeByte.Alphanumeric) {\n const alphanumericResult = decodeAlphanumeric(stream, size);\n result.text += alphanumericResult.text;\n result.bytes.push(...alphanumericResult.bytes);\n result.chunks.push({\n type: Mode.Alphanumeric,\n text: alphanumericResult.text,\n });\n } else if (mode === ModeByte.Byte) {\n const byteResult = decodeByte(stream, size);\n result.text += byteResult.text;\n result.bytes.push(...byteResult.bytes);\n result.chunks.push({\n type: Mode.Byte,\n bytes: byteResult.bytes,\n text: byteResult.text,\n });\n } else if (mode === ModeByte.Kanji) {\n const kanjiResult = decodeKanji(stream, size);\n result.text += kanjiResult.text;\n result.bytes.push(...kanjiResult.bytes);\n result.chunks.push({\n type: Mode.Kanji,\n bytes: kanjiResult.bytes,\n text: kanjiResult.text,\n });\n } else if (mode === ModeByte.StructuredAppend) {\n result.chunks.push({\n type: Mode.StructuredAppend,\n currentSequence: stream.readBits(4),\n totalSequence: stream.readBits(4),\n parity: stream.readBits(8),\n });\n }\n }\n\n // If there is no data left, or the remaining bits are all 0, then that counts as a termination marker\n if (stream.available() === 0 || stream.readBits(stream.available()) === 0) {\n return result;\n }\n}\n","import GenericGF, { addOrSubtractGF } from \"./GenericGF\";\n\nexport default class GenericGFPoly {\n private field: GenericGF;\n private coefficients: Uint8ClampedArray;\n\n constructor(field: GenericGF, coefficients: Uint8ClampedArray) {\n if (coefficients.length === 0) {\n throw new Error(\"No coefficients.\");\n }\n this.field = field;\n const coefficientsLength = coefficients.length;\n if (coefficientsLength > 1 && coefficients[0] === 0) {\n // Leading term must be non-zero for anything except the constant polynomial \"0\"\n let firstNonZero = 1;\n while (firstNonZero < coefficientsLength && coefficients[firstNonZero] === 0) {\n firstNonZero++;\n }\n if (firstNonZero === coefficientsLength) {\n this.coefficients = field.zero.coefficients;\n } else {\n this.coefficients = new Uint8ClampedArray(coefficientsLength - firstNonZero);\n for (let i = 0; i < this.coefficients.length; i++) {\n this.coefficients[i] = coefficients[firstNonZero + i];\n }\n }\n } else {\n this.coefficients = coefficients;\n }\n }\n\n public degree() {\n return this.coefficients.length - 1;\n }\n\n public isZero() {\n return this.coefficients[0] === 0;\n }\n\n public getCoefficient(degree: number) {\n return this.coefficients[this.coefficients.length - 1 - degree];\n }\n\n public addOrSubtract(other: GenericGFPoly) {\n if (this.isZero()) {\n return other;\n }\n if (other.isZero()) {\n return this;\n }\n\n let smallerCoefficients = this.coefficients;\n let largerCoefficients = other.coefficients;\n if (smallerCoefficients.length > largerCoefficients.length) {\n [smallerCoefficients, largerCoefficients] = [largerCoefficients, smallerCoefficients];\n }\n const sumDiff = new Uint8ClampedArray(largerCoefficients.length);\n const lengthDiff = largerCoefficients.length - smallerCoefficients.length;\n for (let i = 0; i < lengthDiff; i++) {\n sumDiff[i] = largerCoefficients[i];\n }\n\n for (let i = lengthDiff; i < largerCoefficients.length; i++) {\n sumDiff[i] = addOrSubtractGF(smallerCoefficients[i - lengthDiff], largerCoefficients[i]);\n }\n\n return new GenericGFPoly(this.field, sumDiff);\n }\n\n public multiply(scalar: number) {\n if (scalar === 0) {\n return this.field.zero;\n }\n if (scalar === 1) {\n return this;\n }\n const size = this.coefficients.length;\n const product = new Uint8ClampedArray(size);\n for (let i = 0; i < size; i++) {\n product[i] = this.field.multiply(this.coefficients[i], scalar);\n }\n\n return new GenericGFPoly(this.field, product);\n }\n\n public multiplyPoly(other: GenericGFPoly): GenericGFPoly {\n if (this.isZero() || other.isZero()) {\n return this.field.zero;\n }\n const aCoefficients = this.coefficients;\n const aLength = aCoefficients.length;\n const bCoefficients = other.coefficients;\n const bLength = bCoefficients.length;\n const product = new Uint8ClampedArray(aLength + bLength - 1);\n for (let i = 0; i < aLength; i++) {\n const aCoeff = aCoefficients[i];\n for (let j = 0; j < bLength; j++) {\n product[i + j] = addOrSubtractGF(product[i + j],\n this.field.multiply(aCoeff, bCoefficients[j]));\n }\n }\n return new GenericGFPoly(this.field, product);\n }\n\n public multiplyByMonomial(degree: number, coefficient: number) {\n if (degree < 0) {\n throw new Error(\"Invalid degree less than 0\");\n }\n if (coefficient === 0) {\n return this.field.zero;\n }\n const size = this.coefficients.length;\n const product = new Uint8ClampedArray(size + degree);\n for (let i = 0; i < size; i++) {\n product[i] = this.field.multiply(this.coefficients[i], coefficient);\n }\n return new GenericGFPoly(this.field, product);\n }\n\n public evaluateAt(a: number) {\n let result = 0;\n if (a === 0) {\n // Just return the x^0 coefficient\n return this.getCoefficient(0);\n }\n const size = this.coefficients.length;\n if (a === 1) {\n // Just the sum of the coefficients\n this.coefficients.forEach((coefficient) => {\n result = addOrSubtractGF(result, coefficient);\n });\n return result;\n }\n result = this.coefficients[0];\n for (let i = 1; i < size; i++) {\n result = addOrSubtractGF(this.field.multiply(a, result), this.coefficients[i]);\n }\n return result;\n }\n}\n","import GenericGFPoly from \"./GenericGFPoly\";\n\nexport function addOrSubtractGF(a: number, b: number) {\n return a ^ b; // tslint:disable-line:no-bitwise\n}\n\nexport default class GenericGF {\n public primitive: number;\n public size: number;\n public generatorBase: number;\n public zero: GenericGFPoly;\n public one: GenericGFPoly;\n\n private expTable: number[];\n private logTable: number[];\n\n constructor(primitive: number, size: number, genBase: number) {\n this.primitive = primitive;\n this.size = size;\n this.generatorBase = genBase;\n this.expTable = new Array(this.size);\n this.logTable = new Array(this.size);\n\n let x = 1;\n for (let i = 0; i < this.size; i++) {\n this.expTable[i] = x;\n x = x * 2;\n if (x >= this.size) {\n x = (x ^ this.primitive) & (this.size - 1); // tslint:disable-line:no-bitwise\n }\n }\n\n for (let i = 0; i < this.size - 1; i++) {\n this.logTable[this.expTable[i]] = i;\n }\n this.zero = new GenericGFPoly(this, Uint8ClampedArray.from([0]));\n this.one = new GenericGFPoly(this, Uint8ClampedArray.from([1]));\n }\n\n public multiply(a: number, b: number) {\n if (a === 0 || b === 0) {\n return 0;\n }\n return this.expTable[(this.logTable[a] + this.logTable[b]) % (this.size - 1)];\n }\n\n public inverse(a: number) {\n if (a === 0) {\n throw new Error(\"Can't invert 0\");\n }\n return this.expTable[this.size - this.logTable[a] - 1];\n }\n\n public buildMonomial(degree: number, coefficient: number): GenericGFPoly {\n if (degree < 0) {\n throw new Error(\"Invalid monomial degree less than 0\");\n }\n if (coefficient === 0) {\n return this.zero;\n }\n const coefficients = new Uint8ClampedArray(degree + 1);\n coefficients[0] = coefficient;\n return new GenericGFPoly(this, coefficients);\n }\n\n public log(a: number) {\n if (a === 0) {\n throw new Error(\"Can't take log(0)\");\n }\n return this.logTable[a];\n }\n\n public exp(a: number) {\n return this.expTable[a];\n }\n}\n","import GenericGF, { addOrSubtractGF } from \"./GenericGF\";\nimport GenericGFPoly from \"./GenericGFPoly\";\n\nfunction runEuclideanAlgorithm(field: GenericGF, a: GenericGFPoly, b: GenericGFPoly, R: number): GenericGFPoly[] {\n // Assume a's degree is >= b's\n if (a.degree() < b.degree()) {\n [a, b] = [b, a];\n }\n\n let rLast = a;\n let r = b;\n let tLast = field.zero;\n let t = field.one;\n\n // Run Euclidean algorithm until r's degree is less than R/2\n while (r.degree() >= R / 2) {\n const rLastLast = rLast;\n const tLastLast = tLast;\n rLast = r;\n tLast = t;\n\n // Divide rLastLast by rLast, with quotient in q and remainder in r\n if (rLast.isZero()) {\n // Euclidean algorithm already terminated?\n return null;\n }\n r = rLastLast;\n let q = field.zero;\n const denominatorLeadingTerm = rLast.getCoefficient(rLast.degree());\n const dltInverse = field.inverse(denominatorLeadingTerm);\n while (r.degree() >= rLast.degree() && !r.isZero()) {\n const degreeDiff = r.degree() - rLast.degree();\n const scale = field.multiply(r.getCoefficient(r.degree()), dltInverse);\n q = q.addOrSubtract(field.buildMonomial(degreeDiff, scale));\n r = r.addOrSubtract(rLast.multiplyByMonomial(degreeDiff, scale));\n }\n\n t = q.multiplyPoly(tLast).addOrSubtract(tLastLast);\n\n if (r.degree() >= rLast.degree()) {\n return null;\n }\n }\n\n const sigmaTildeAtZero = t.getCoefficient(0);\n if (sigmaTildeAtZero === 0) {\n return null;\n }\n\n const inverse = field.inverse(sigmaTildeAtZero);\n return [t.multiply(inverse), r.multiply(inverse)];\n}\n\nfunction findErrorLocations(field: GenericGF, errorLocator: GenericGFPoly): number[] {\n // This is a direct application of Chien's search\n const numErrors = errorLocator.degree();\n if (numErrors === 1) {\n return [errorLocator.getCoefficient(1)];\n }\n const result: number[] = new Array(numErrors);\n let errorCount = 0;\n for (let i = 1; i < field.size && errorCount < numErrors; i++) {\n if (errorLocator.evaluateAt(i) === 0) {\n result[errorCount] = field.inverse(i);\n errorCount++;\n }\n }\n if (errorCount !== numErrors) {\n return null;\n }\n return result;\n}\n\nfunction findErrorMagnitudes(field: GenericGF, errorEvaluator: GenericGFPoly, errorLocations: number[]): number[] {\n // This is directly applying Forney's Formula\n const s = errorLocations.length;\n const result: number[] = new Array(s);\n for (let i = 0; i < s; i++) {\n const xiInverse = field.inverse(errorLocations[i]);\n let denominator = 1;\n for (let j = 0; j < s; j++) {\n if (i !== j) {\n denominator = field.multiply(denominator, addOrSubtractGF(1, field.multiply(errorLocations[j], xiInverse)));\n }\n }\n result[i] = field.multiply(errorEvaluator.evaluateAt(xiInverse), field.inverse(denominator));\n if (field.generatorBase !== 0) {\n result[i] = field.multiply(result[i], xiInverse);\n }\n }\n return result;\n}\n\nexport function decode(bytes: number[], twoS: number) {\n const outputBytes = new Uint8ClampedArray(bytes.length);\n outputBytes.set(bytes);\n\n const field = new GenericGF(0x011D, 256, 0); // x^8 + x^4 + x^3 + x^2 + 1\n const poly = new GenericGFPoly(field, outputBytes);\n\n const syndromeCoefficients = new Uint8ClampedArray(twoS);\n let error = false;\n for (let s = 0; s < twoS; s++) {\n const evaluation = poly.evaluateAt(field.exp(s + field.generatorBase));\n syndromeCoefficients[syndromeCoefficients.length - 1 - s] = evaluation;\n if (evaluation !== 0) {\n error = true;\n }\n }\n if (!error) {\n return outputBytes;\n }\n\n const syndrome = new GenericGFPoly(field, syndromeCoefficients);\n\n const sigmaOmega = runEuclideanAlgorithm(field, field.buildMonomial(twoS, 1), syndrome, twoS);\n if (sigmaOmega === null) {\n return null;\n }\n\n const errorLocations = findErrorLocations(field, sigmaOmega[0]);\n if (errorLocations == null) {\n return null;\n }\n\n const errorMagnitudes = findErrorMagnitudes(field, sigmaOmega[1], errorLocations);\n for (let i = 0; i < errorLocations.length; i++) {\n const position = outputBytes.length - 1 - field.log(errorLocations[i]);\n if (position < 0) {\n return null;\n }\n outputBytes[position] = addOrSubtractGF(outputBytes[position], errorMagnitudes[i]);\n }\n\n return outputBytes;\n}\n","export interface Version {\n infoBits: number;\n versionNumber: number;\n alignmentPatternCenters: number[];\n errorCorrectionLevels: Array<{\n ecCodewordsPerBlock: number;\n ecBlocks: Array<{\n numBlocks: number;\n dataCodewordsPerBlock: number;\n }>\n }>;\n}\n\nexport const VERSIONS: Version[] = [\n {\n infoBits: null,\n versionNumber: 1,\n alignmentPatternCenters: [],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 7,\n ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 19 }],\n },\n {\n ecCodewordsPerBlock: 10,\n ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 16 }],\n },\n {\n ecCodewordsPerBlock: 13,\n ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 13 }],\n },\n {\n ecCodewordsPerBlock: 17,\n ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 9 }],\n },\n ],\n },\n {\n infoBits: null,\n versionNumber: 2,\n alignmentPatternCenters: [6, 18],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 10,\n ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 34 }],\n },\n {\n ecCodewordsPerBlock: 16,\n ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 28 }],\n },\n {\n ecCodewordsPerBlock: 22,\n ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 22 }],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 16 }],\n },\n ],\n },\n {\n infoBits: null,\n versionNumber: 3,\n alignmentPatternCenters: [6, 22],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 15,\n ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 55 }],\n },\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 44 }],\n },\n {\n ecCodewordsPerBlock: 18,\n ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 17 }],\n },\n {\n ecCodewordsPerBlock: 22,\n ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 13 }],\n },\n ],\n },\n {\n infoBits: null,\n versionNumber: 4,\n alignmentPatternCenters: [6, 26],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 20,\n ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 80 }],\n },\n {\n ecCodewordsPerBlock: 18,\n ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 32 }],\n },\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 24 }],\n },\n {\n ecCodewordsPerBlock: 16,\n ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 9 }],\n },\n ],\n },\n {\n infoBits: null,\n versionNumber: 5,\n alignmentPatternCenters: [6, 30],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 108 }],\n },\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 43 }],\n },\n {\n ecCodewordsPerBlock: 18,\n ecBlocks: [\n { numBlocks: 2, dataCodewordsPerBlock: 15 },\n { numBlocks: 2, dataCodewordsPerBlock: 16 },\n ],\n },\n {\n ecCodewordsPerBlock: 22,\n ecBlocks: [\n { numBlocks: 2, dataCodewordsPerBlock: 11 },\n { numBlocks: 2, dataCodewordsPerBlock: 12 },\n ],\n },\n ],\n },\n {\n infoBits: null,\n versionNumber: 6,\n alignmentPatternCenters: [6, 34],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 18,\n ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 68 }],\n },\n {\n ecCodewordsPerBlock: 16,\n ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 27 }],\n },\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 19 }],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 15 }],\n },\n ],\n },\n {\n infoBits: 0x07C94,\n versionNumber: 7,\n alignmentPatternCenters: [6, 22, 38],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 20,\n ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 78 }],\n },\n {\n ecCodewordsPerBlock: 18,\n ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 31 }],\n },\n {\n ecCodewordsPerBlock: 18,\n ecBlocks: [\n { numBlocks: 2, dataCodewordsPerBlock: 14 },\n { numBlocks: 4, dataCodewordsPerBlock: 15 },\n ],\n },\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 13 },\n { numBlocks: 1, dataCodewordsPerBlock: 14 },\n ],\n },\n ],\n },\n {\n infoBits: 0x085BC,\n versionNumber: 8,\n alignmentPatternCenters: [6, 24, 42],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 97 }],\n },\n {\n ecCodewordsPerBlock: 22,\n ecBlocks: [\n { numBlocks: 2, dataCodewordsPerBlock: 38 },\n { numBlocks: 2, dataCodewordsPerBlock: 39 },\n ],\n },\n {\n ecCodewordsPerBlock: 22,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 18 },\n { numBlocks: 2, dataCodewordsPerBlock: 19 },\n ],\n },\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 14 },\n { numBlocks: 2, dataCodewordsPerBlock: 15 },\n ],\n },\n ],\n },\n {\n infoBits: 0x09A99,\n versionNumber: 9,\n alignmentPatternCenters: [6, 26, 46],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 116 }],\n },\n {\n ecCodewordsPerBlock: 22,\n ecBlocks: [\n { numBlocks: 3, dataCodewordsPerBlock: 36 },\n { numBlocks: 2, dataCodewordsPerBlock: 37 },\n ],\n },\n {\n ecCodewordsPerBlock: 20,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 16 },\n { numBlocks: 4, dataCodewordsPerBlock: 17 },\n ],\n },\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 12 },\n { numBlocks: 4, dataCodewordsPerBlock: 13 },\n ],\n },\n ],\n },\n {\n infoBits: 0x0A4D3,\n versionNumber: 10,\n alignmentPatternCenters: [6, 28, 50],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 18,\n ecBlocks: [\n { numBlocks: 2, dataCodewordsPerBlock: 68 },\n { numBlocks: 2, dataCodewordsPerBlock: 69 },\n ],\n },\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 43 },\n { numBlocks: 1, dataCodewordsPerBlock: 44 },\n ],\n },\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [\n { numBlocks: 6, dataCodewordsPerBlock: 19 },\n { numBlocks: 2, dataCodewordsPerBlock: 20 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 6, dataCodewordsPerBlock: 15 },\n { numBlocks: 2, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x0BBF6,\n versionNumber: 11,\n alignmentPatternCenters: [6, 30, 54],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 20,\n ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 81 }],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 1, dataCodewordsPerBlock: 50 },\n { numBlocks: 4, dataCodewordsPerBlock: 51 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 22 },\n { numBlocks: 4, dataCodewordsPerBlock: 23 },\n ],\n },\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [\n { numBlocks: 3, dataCodewordsPerBlock: 12 },\n { numBlocks: 8, dataCodewordsPerBlock: 13 },\n ],\n },\n ],\n },\n {\n infoBits: 0x0C762,\n versionNumber: 12,\n alignmentPatternCenters: [6, 32, 58],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [\n { numBlocks: 2, dataCodewordsPerBlock: 92 },\n { numBlocks: 2, dataCodewordsPerBlock: 93 },\n ],\n },\n {\n ecCodewordsPerBlock: 22,\n ecBlocks: [\n { numBlocks: 6, dataCodewordsPerBlock: 36 },\n { numBlocks: 2, dataCodewordsPerBlock: 37 },\n ],\n },\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 20 },\n { numBlocks: 6, dataCodewordsPerBlock: 21 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 7, dataCodewordsPerBlock: 14 },\n { numBlocks: 4, dataCodewordsPerBlock: 15 },\n ],\n },\n ],\n },\n {\n infoBits: 0x0D847,\n versionNumber: 13,\n alignmentPatternCenters: [6, 34, 62],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 107 }],\n },\n {\n ecCodewordsPerBlock: 22,\n ecBlocks: [\n { numBlocks: 8, dataCodewordsPerBlock: 37 },\n { numBlocks: 1, dataCodewordsPerBlock: 38 },\n ],\n },\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [\n { numBlocks: 8, dataCodewordsPerBlock: 20 },\n { numBlocks: 4, dataCodewordsPerBlock: 21 },\n ],\n },\n {\n ecCodewordsPerBlock: 22,\n ecBlocks: [\n { numBlocks: 12, dataCodewordsPerBlock: 11 },\n { numBlocks: 4, dataCodewordsPerBlock: 12 },\n ],\n },\n ],\n },\n {\n infoBits: 0x0E60D,\n versionNumber: 14,\n alignmentPatternCenters: [6, 26, 46, 66],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 3, dataCodewordsPerBlock: 115 },\n { numBlocks: 1, dataCodewordsPerBlock: 116 },\n ],\n },\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 40 },\n { numBlocks: 5, dataCodewordsPerBlock: 41 },\n ],\n },\n {\n ecCodewordsPerBlock: 20,\n ecBlocks: [\n { numBlocks: 11, dataCodewordsPerBlock: 16 },\n { numBlocks: 5, dataCodewordsPerBlock: 17 },\n ],\n },\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [\n { numBlocks: 11, dataCodewordsPerBlock: 12 },\n { numBlocks: 5, dataCodewordsPerBlock: 13 },\n ],\n },\n ],\n },\n {\n infoBits: 0x0F928,\n versionNumber: 15,\n alignmentPatternCenters: [6, 26, 48, 70],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 22,\n ecBlocks: [\n { numBlocks: 5, dataCodewordsPerBlock: 87 },\n { numBlocks: 1, dataCodewordsPerBlock: 88 },\n ],\n },\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [\n { numBlocks: 5, dataCodewordsPerBlock: 41 },\n { numBlocks: 5, dataCodewordsPerBlock: 42 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 5, dataCodewordsPerBlock: 24 },\n { numBlocks: 7, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [\n { numBlocks: 11, dataCodewordsPerBlock: 12 },\n { numBlocks: 7, dataCodewordsPerBlock: 13 },\n ],\n },\n ],\n },\n {\n infoBits: 0x10B78,\n versionNumber: 16,\n alignmentPatternCenters: [6, 26, 50, 74],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [\n { numBlocks: 5, dataCodewordsPerBlock: 98 },\n { numBlocks: 1, dataCodewordsPerBlock: 99 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 7, dataCodewordsPerBlock: 45 },\n { numBlocks: 3, dataCodewordsPerBlock: 46 },\n ],\n },\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [\n { numBlocks: 15, dataCodewordsPerBlock: 19 },\n { numBlocks: 2, dataCodewordsPerBlock: 20 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 3, dataCodewordsPerBlock: 15 },\n { numBlocks: 13, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x1145D,\n versionNumber: 17,\n alignmentPatternCenters: [6, 30, 54, 78],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 1, dataCodewordsPerBlock: 107 },\n { numBlocks: 5, dataCodewordsPerBlock: 108 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 10, dataCodewordsPerBlock: 46 },\n { numBlocks: 1, dataCodewordsPerBlock: 47 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 1, dataCodewordsPerBlock: 22 },\n { numBlocks: 15, dataCodewordsPerBlock: 23 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 2, dataCodewordsPerBlock: 14 },\n { numBlocks: 17, dataCodewordsPerBlock: 15 },\n ],\n },\n ],\n },\n {\n infoBits: 0x12A17,\n versionNumber: 18,\n alignmentPatternCenters: [6, 30, 56, 82],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 5, dataCodewordsPerBlock: 120 },\n { numBlocks: 1, dataCodewordsPerBlock: 121 },\n ],\n },\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [\n { numBlocks: 9, dataCodewordsPerBlock: 43 },\n { numBlocks: 4, dataCodewordsPerBlock: 44 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 17, dataCodewordsPerBlock: 22 },\n { numBlocks: 1, dataCodewordsPerBlock: 23 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 2, dataCodewordsPerBlock: 14 },\n { numBlocks: 19, dataCodewordsPerBlock: 15 },\n ],\n },\n ],\n },\n {\n infoBits: 0x13532,\n versionNumber: 19,\n alignmentPatternCenters: [6, 30, 58, 86],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 3, dataCodewordsPerBlock: 113 },\n { numBlocks: 4, dataCodewordsPerBlock: 114 },\n ],\n },\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [\n { numBlocks: 3, dataCodewordsPerBlock: 44 },\n { numBlocks: 11, dataCodewordsPerBlock: 45 },\n ],\n },\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [\n { numBlocks: 17, dataCodewordsPerBlock: 21 },\n { numBlocks: 4, dataCodewordsPerBlock: 22 },\n ],\n },\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [\n { numBlocks: 9, dataCodewordsPerBlock: 13 },\n { numBlocks: 16, dataCodewordsPerBlock: 14 },\n ],\n },\n ],\n },\n {\n infoBits: 0x149A6,\n versionNumber: 20,\n alignmentPatternCenters: [6, 34, 62, 90],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 3, dataCodewordsPerBlock: 107 },\n { numBlocks: 5, dataCodewordsPerBlock: 108 },\n ],\n },\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [\n { numBlocks: 3, dataCodewordsPerBlock: 41 },\n { numBlocks: 13, dataCodewordsPerBlock: 42 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 15, dataCodewordsPerBlock: 24 },\n { numBlocks: 5, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 15, dataCodewordsPerBlock: 15 },\n { numBlocks: 10, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x15683,\n versionNumber: 21,\n alignmentPatternCenters: [6, 28, 50, 72, 94],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 116 },\n { numBlocks: 4, dataCodewordsPerBlock: 117 },\n ],\n },\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [{ numBlocks: 17, dataCodewordsPerBlock: 42 }],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 17, dataCodewordsPerBlock: 22 },\n { numBlocks: 6, dataCodewordsPerBlock: 23 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 19, dataCodewordsPerBlock: 16 },\n { numBlocks: 6, dataCodewordsPerBlock: 17 },\n ],\n },\n ],\n },\n {\n infoBits: 0x168C9,\n versionNumber: 22,\n alignmentPatternCenters: [6, 26, 50, 74, 98],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 2, dataCodewordsPerBlock: 111 },\n { numBlocks: 7, dataCodewordsPerBlock: 112 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [{ numBlocks: 17, dataCodewordsPerBlock: 46 }],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 7, dataCodewordsPerBlock: 24 },\n { numBlocks: 16, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 24,\n ecBlocks: [{ numBlocks: 34, dataCodewordsPerBlock: 13 }],\n },\n ],\n },\n {\n infoBits: 0x177EC,\n versionNumber: 23,\n alignmentPatternCenters: [6, 30, 54, 74, 102],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 121 },\n { numBlocks: 5, dataCodewordsPerBlock: 122 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 47 },\n { numBlocks: 14, dataCodewordsPerBlock: 48 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 11, dataCodewordsPerBlock: 24 },\n { numBlocks: 14, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 16, dataCodewordsPerBlock: 15 },\n { numBlocks: 14, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x18EC4,\n versionNumber: 24,\n alignmentPatternCenters: [6, 28, 54, 80, 106],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 6, dataCodewordsPerBlock: 117 },\n { numBlocks: 4, dataCodewordsPerBlock: 118 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 6, dataCodewordsPerBlock: 45 },\n { numBlocks: 14, dataCodewordsPerBlock: 46 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 11, dataCodewordsPerBlock: 24 },\n { numBlocks: 16, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 30, dataCodewordsPerBlock: 16 },\n { numBlocks: 2, dataCodewordsPerBlock: 17 },\n ],\n },\n ],\n },\n {\n infoBits: 0x191E1,\n versionNumber: 25,\n alignmentPatternCenters: [6, 32, 58, 84, 110],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 26,\n ecBlocks: [\n { numBlocks: 8, dataCodewordsPerBlock: 106 },\n { numBlocks: 4, dataCodewordsPerBlock: 107 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 8, dataCodewordsPerBlock: 47 },\n { numBlocks: 13, dataCodewordsPerBlock: 48 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 7, dataCodewordsPerBlock: 24 },\n { numBlocks: 22, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 22, dataCodewordsPerBlock: 15 },\n { numBlocks: 13, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x1AFAB,\n versionNumber: 26,\n alignmentPatternCenters: [6, 30, 58, 86, 114],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 10, dataCodewordsPerBlock: 114 },\n { numBlocks: 2, dataCodewordsPerBlock: 115 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 19, dataCodewordsPerBlock: 46 },\n { numBlocks: 4, dataCodewordsPerBlock: 47 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 28, dataCodewordsPerBlock: 22 },\n { numBlocks: 6, dataCodewordsPerBlock: 23 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 33, dataCodewordsPerBlock: 16 },\n { numBlocks: 4, dataCodewordsPerBlock: 17 },\n ],\n },\n ],\n },\n {\n infoBits: 0x1B08E,\n versionNumber: 27,\n alignmentPatternCenters: [6, 34, 62, 90, 118],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 8, dataCodewordsPerBlock: 122 },\n { numBlocks: 4, dataCodewordsPerBlock: 123 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 22, dataCodewordsPerBlock: 45 },\n { numBlocks: 3, dataCodewordsPerBlock: 46 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 8, dataCodewordsPerBlock: 23 },\n { numBlocks: 26, dataCodewordsPerBlock: 24 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 12, dataCodewordsPerBlock: 15 },\n { numBlocks: 28, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x1CC1A,\n versionNumber: 28,\n alignmentPatternCenters: [6, 26, 50, 74, 98, 122],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 3, dataCodewordsPerBlock: 117 },\n { numBlocks: 10, dataCodewordsPerBlock: 118 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 3, dataCodewordsPerBlock: 45 },\n { numBlocks: 23, dataCodewordsPerBlock: 46 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 24 },\n { numBlocks: 31, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 11, dataCodewordsPerBlock: 15 },\n { numBlocks: 31, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x1D33F,\n versionNumber: 29,\n alignmentPatternCenters: [6, 30, 54, 78, 102, 126],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 7, dataCodewordsPerBlock: 116 },\n { numBlocks: 7, dataCodewordsPerBlock: 117 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 21, dataCodewordsPerBlock: 45 },\n { numBlocks: 7, dataCodewordsPerBlock: 46 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 1, dataCodewordsPerBlock: 23 },\n { numBlocks: 37, dataCodewordsPerBlock: 24 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 19, dataCodewordsPerBlock: 15 },\n { numBlocks: 26, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x1ED75,\n versionNumber: 30,\n alignmentPatternCenters: [6, 26, 52, 78, 104, 130],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 5, dataCodewordsPerBlock: 115 },\n { numBlocks: 10, dataCodewordsPerBlock: 116 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 19, dataCodewordsPerBlock: 47 },\n { numBlocks: 10, dataCodewordsPerBlock: 48 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 15, dataCodewordsPerBlock: 24 },\n { numBlocks: 25, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 23, dataCodewordsPerBlock: 15 },\n { numBlocks: 25, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x1F250,\n versionNumber: 31,\n alignmentPatternCenters: [6, 30, 56, 82, 108, 134],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 13, dataCodewordsPerBlock: 115 },\n { numBlocks: 3, dataCodewordsPerBlock: 116 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 2, dataCodewordsPerBlock: 46 },\n { numBlocks: 29, dataCodewordsPerBlock: 47 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 42, dataCodewordsPerBlock: 24 },\n { numBlocks: 1, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 23, dataCodewordsPerBlock: 15 },\n { numBlocks: 28, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x209D5,\n versionNumber: 32,\n alignmentPatternCenters: [6, 34, 60, 86, 112, 138],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [{ numBlocks: 17, dataCodewordsPerBlock: 115 }],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 10, dataCodewordsPerBlock: 46 },\n { numBlocks: 23, dataCodewordsPerBlock: 47 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 10, dataCodewordsPerBlock: 24 },\n { numBlocks: 35, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 19, dataCodewordsPerBlock: 15 },\n { numBlocks: 35, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x216F0,\n versionNumber: 33,\n alignmentPatternCenters: [6, 30, 58, 86, 114, 142],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 17, dataCodewordsPerBlock: 115 },\n { numBlocks: 1, dataCodewordsPerBlock: 116 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 14, dataCodewordsPerBlock: 46 },\n { numBlocks: 21, dataCodewordsPerBlock: 47 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 29, dataCodewordsPerBlock: 24 },\n { numBlocks: 19, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 11, dataCodewordsPerBlock: 15 },\n { numBlocks: 46, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x228BA,\n versionNumber: 34,\n alignmentPatternCenters: [6, 34, 62, 90, 118, 146],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 13, dataCodewordsPerBlock: 115 },\n { numBlocks: 6, dataCodewordsPerBlock: 116 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 14, dataCodewordsPerBlock: 46 },\n { numBlocks: 23, dataCodewordsPerBlock: 47 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 44, dataCodewordsPerBlock: 24 },\n { numBlocks: 7, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 59, dataCodewordsPerBlock: 16 },\n { numBlocks: 1, dataCodewordsPerBlock: 17 },\n ],\n },\n ],\n },\n {\n infoBits: 0x2379F,\n versionNumber: 35,\n alignmentPatternCenters: [6, 30, 54, 78, 102, 126, 150],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 12, dataCodewordsPerBlock: 121 },\n { numBlocks: 7, dataCodewordsPerBlock: 122 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 12, dataCodewordsPerBlock: 47 },\n { numBlocks: 26, dataCodewordsPerBlock: 48 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 39, dataCodewordsPerBlock: 24 },\n { numBlocks: 14, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 22, dataCodewordsPerBlock: 15 },\n { numBlocks: 41, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x24B0B,\n versionNumber: 36,\n alignmentPatternCenters: [ 6, 24, 50, 76, 102, 128, 154 ],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 6, dataCodewordsPerBlock: 121 },\n { numBlocks: 14, dataCodewordsPerBlock: 122 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 6, dataCodewordsPerBlock: 47 },\n { numBlocks: 34, dataCodewordsPerBlock: 48 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 46, dataCodewordsPerBlock: 24 },\n { numBlocks: 10, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 2, dataCodewordsPerBlock: 15 },\n { numBlocks: 64, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x2542E,\n versionNumber: 37,\n alignmentPatternCenters: [ 6, 28, 54, 80, 106, 132, 158 ],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 17, dataCodewordsPerBlock: 122 },\n { numBlocks: 4, dataCodewordsPerBlock: 123 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 29, dataCodewordsPerBlock: 46 },\n { numBlocks: 14, dataCodewordsPerBlock: 47 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 49, dataCodewordsPerBlock: 24 },\n { numBlocks: 10, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 24, dataCodewordsPerBlock: 15 },\n { numBlocks: 46, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x26A64,\n versionNumber: 38,\n alignmentPatternCenters: [ 6, 32, 58, 84, 110, 136, 162 ],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 4, dataCodewordsPerBlock: 122 },\n { numBlocks: 18, dataCodewordsPerBlock: 123 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 13, dataCodewordsPerBlock: 46 },\n { numBlocks: 32, dataCodewordsPerBlock: 47 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 48, dataCodewordsPerBlock: 24 },\n { numBlocks: 14, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 42, dataCodewordsPerBlock: 15 },\n { numBlocks: 32, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x27541,\n versionNumber: 39,\n alignmentPatternCenters: [ 6, 26, 54, 82, 110, 138, 166 ],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 20, dataCodewordsPerBlock: 117 },\n { numBlocks: 4, dataCodewordsPerBlock: 118 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 40, dataCodewordsPerBlock: 47 },\n { numBlocks: 7, dataCodewordsPerBlock: 48 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 43, dataCodewordsPerBlock: 24 },\n { numBlocks: 22, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 10, dataCodewordsPerBlock: 15 },\n { numBlocks: 67, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n {\n infoBits: 0x28C69,\n versionNumber: 40,\n alignmentPatternCenters: [ 6, 30, 58, 86, 114, 142, 170 ],\n errorCorrectionLevels: [\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 19, dataCodewordsPerBlock: 118 },\n { numBlocks: 6, dataCodewordsPerBlock: 119 },\n ],\n },\n {\n ecCodewordsPerBlock: 28,\n ecBlocks: [\n { numBlocks: 18, dataCodewordsPerBlock: 47 },\n { numBlocks: 31, dataCodewordsPerBlock: 48 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 34, dataCodewordsPerBlock: 24 },\n { numBlocks: 34, dataCodewordsPerBlock: 25 },\n ],\n },\n {\n ecCodewordsPerBlock: 30,\n ecBlocks: [\n { numBlocks: 20, dataCodewordsPerBlock: 15 },\n { numBlocks: 61, dataCodewordsPerBlock: 16 },\n ],\n },\n ],\n },\n];\n","import { BitMatrix } from \"../BitMatrix\";\nimport { Point } from \"../Point\";\nimport { decode as decodeData, DecodedQR } from \"./decodeData\";\nimport { decode as rsDecode } from \"./reedsolomon\";\nimport { Version, VERSIONS } from \"./version\";\n\n// tslint:disable:no-bitwise\nfunction numBitsDiffering(x: number, y: number) {\n let z = x ^ y;\n let bitCount = 0;\n while (z) {\n bitCount++;\n z &= z - 1;\n }\n return bitCount;\n}\n\nfunction pushBit(bit: any, byte: number) {\n return (byte << 1) | bit;\n}\n// tslint:enable:no-bitwise\n\nconst FORMAT_INFO_TABLE = [\n { bits: 0x5412, formatInfo: { errorCorrectionLevel: 1, dataMask: 0 } },\n { bits: 0x5125, formatInfo: { errorCorrectionLevel: 1, dataMask: 1 } },\n { bits: 0x5E7C, formatInfo: { errorCorrectionLevel: 1, dataMask: 2 } },\n { bits: 0x5B4B, formatInfo: { errorCorrectionLevel: 1, dataMask: 3 } },\n { bits: 0x45F9, formatInfo: { errorCorrectionLevel: 1, dataMask: 4 } },\n { bits: 0x40CE, formatInfo: { errorCorrectionLevel: 1, dataMask: 5 } },\n { bits: 0x4F97, formatInfo: { errorCorrectionLevel: 1, dataMask: 6 } },\n { bits: 0x4AA0, formatInfo: { errorCorrectionLevel: 1, dataMask: 7 } },\n { bits: 0x77C4, formatInfo: { errorCorrectionLevel: 0, dataMask: 0 } },\n { bits: 0x72F3, formatInfo: { errorCorrectionLevel: 0, dataMask: 1 } },\n { bits: 0x7DAA, formatInfo: { errorCorrectionLevel: 0, dataMask: 2 } },\n { bits: 0x789D, formatInfo: { errorCorrectionLevel: 0, dataMask: 3 } },\n { bits: 0x662F, formatInfo: { errorCorrectionLevel: 0, dataMask: 4 } },\n { bits: 0x6318, formatInfo: { errorCorrectionLevel: 0, dataMask: 5 } },\n { bits: 0x6C41, formatInfo: { errorCorrectionLevel: 0, dataMask: 6 } },\n { bits: 0x6976, formatInfo: { errorCorrectionLevel: 0, dataMask: 7 } },\n { bits: 0x1689, formatInfo: { errorCorrectionLevel: 3, dataMask: 0 } },\n { bits: 0x13BE, formatInfo: { errorCorrectionLevel: 3, dataMask: 1 } },\n { bits: 0x1CE7, formatInfo: { errorCorrectionLevel: 3, dataMask: 2 } },\n { bits: 0x19D0, formatInfo: { errorCorrectionLevel: 3, dataMask: 3 } },\n { bits: 0x0762, formatInfo: { errorCorrectionLevel: 3, dataMask: 4 } },\n { bits: 0x0255, formatInfo: { errorCorrectionLevel: 3, dataMask: 5 } },\n { bits: 0x0D0C, formatInfo: { errorCorrectionLevel: 3, dataMask: 6 } },\n { bits: 0x083B, formatInfo: { errorCorrectionLevel: 3, dataMask: 7 } },\n { bits: 0x355F, formatInfo: { errorCorrectionLevel: 2, dataMask: 0 } },\n { bits: 0x3068, formatInfo: { errorCorrectionLevel: 2, dataMask: 1 } },\n { bits: 0x3F31, formatInfo: { errorCorrectionLevel: 2, dataMask: 2 } },\n { bits: 0x3A06, formatInfo: { errorCorrectionLevel: 2, dataMask: 3 } },\n { bits: 0x24B4, formatInfo: { errorCorrectionLevel: 2, dataMask: 4 } },\n { bits: 0x2183, formatInfo: { errorCorrectionLevel: 2, dataMask: 5 } },\n { bits: 0x2EDA, formatInfo: { errorCorrectionLevel: 2, dataMask: 6 } },\n { bits: 0x2BED, formatInfo: { errorCorrectionLevel: 2, dataMask: 7 } },\n];\n\nconst DATA_MASKS = [\n (p: Point) => ((p.y + p.x) % 2) === 0,\n (p: Point) => (p.y % 2) === 0,\n (p: Point) => p.x % 3 === 0,\n (p: Point) => (p.y + p.x) % 3 === 0,\n (p: Point) => (Math.floor(p.y / 2) + Math.floor(p.x / 3)) % 2 === 0,\n (p: Point) => ((p.x * p.y) % 2) + ((p.x * p.y) % 3) === 0,\n (p: Point) => ((((p.y * p.x) % 2) + (p.y * p.x) % 3) % 2) === 0,\n (p: Point) => ((((p.y + p.x) % 2) + (p.y * p.x) % 3) % 2) === 0,\n];\n\ninterface FormatInformation {\n errorCorrectionLevel: number;\n dataMask: number;\n}\n\nfunction buildFunctionPatternMask(version: Version): BitMatrix {\n const dimension = 17 + 4 * version.versionNumber;\n const matrix = BitMatrix.createEmpty(dimension, dimension);\n\n matrix.setRegion(0, 0, 9, 9, true); // Top left finder pattern + separator + format\n matrix.setRegion(dimension - 8, 0, 8, 9, true); // Top right finder pattern + separator + format\n matrix.setRegion(0, dimension - 8, 9, 8, true); // Bottom left finder pattern + separator + format\n\n // Alignment patterns\n for (const x of version.alignmentPatternCenters) {\n for (const y of version.alignmentPatternCenters) {\n if (!(x === 6 && y === 6 || x === 6 && y === dimension - 7 || x === dimension - 7 && y === 6)) {\n matrix.setRegion(x - 2, y - 2, 5, 5, true);\n }\n }\n }\n\n matrix.setRegion(6, 9, 1, dimension - 17, true); // Vertical timing pattern\n matrix.setRegion(9, 6, dimension - 17, 1, true); // Horizontal timing pattern\n\n if (version.versionNumber > 6) {\n matrix.setRegion(dimension - 11, 0, 3, 6, true); // Version info, top right\n matrix.setRegion(0, dimension - 11, 6, 3, true); // Version info, bottom left\n }\n\n return matrix;\n}\n\nfunction readCodewords(matrix: BitMatrix, version: Version, formatInfo: FormatInformation) {\n const dataMask = DATA_MASKS[formatInfo.dataMask];\n const dimension = matrix.height;\n\n const functionPatternMask = buildFunctionPatternMask(version);\n\n const codewords: number[] = [];\n let currentByte = 0;\n let bitsRead = 0;\n\n // Read columns in pairs, from right to left\n let readingUp = true;\n for (let columnIndex = dimension - 1; columnIndex > 0; columnIndex -= 2) {\n if (columnIndex === 6) { // Skip whole column with vertical alignment pattern;\n columnIndex--;\n }\n for (let i = 0; i < dimension; i++) {\n const y = readingUp ? dimension - 1 - i : i;\n for (let columnOffset = 0; columnOffset < 2; columnOffset++) {\n const x = columnIndex - columnOffset;\n if (!functionPatternMask.get(x, y)) {\n bitsRead++;\n let bit = matrix.get(x, y);\n if (dataMask({y, x})) {\n bit = !bit;\n }\n currentByte = pushBit(bit, currentByte);\n if (bitsRead === 8) { // Whole bytes\n codewords.push(currentByte);\n bitsRead = 0;\n currentByte = 0;\n }\n }\n }\n }\n readingUp = !readingUp;\n }\n return codewords;\n}\n\nfunction readVersion(matrix: BitMatrix): Version {\n const dimension = matrix.height;\n\n const provisionalVersion = Math.floor((dimension - 17) / 4);\n if (provisionalVersion <= 6) { // 6 and under dont have version info in the QR code\n return VERSIONS[provisionalVersion - 1];\n }\n\n let topRightVersionBits = 0;\n for (let y = 5; y >= 0; y--) {\n for (let x = dimension - 9; x >= dimension - 11; x--) {\n topRightVersionBits = pushBit(matrix.get(x, y), topRightVersionBits);\n }\n }\n\n let bottomLeftVersionBits = 0;\n for (let x = 5; x >= 0; x--) {\n for (let y = dimension - 9; y >= dimension - 11; y--) {\n bottomLeftVersionBits = pushBit(matrix.get(x, y), bottomLeftVersionBits);\n }\n }\n\n let bestDifference = Infinity;\n let bestVersion: Version;\n for (const version of VERSIONS) {\n if (version.infoBits === topRightVersionBits || version.infoBits === bottomLeftVersionBits) {\n return version;\n }\n\n let difference = numBitsDiffering(topRightVersionBits, version.infoBits);\n if (difference < bestDifference) {\n bestVersion = version;\n bestDifference = difference;\n }\n\n difference = numBitsDiffering(bottomLeftVersionBits, version.infoBits);\n if (difference < bestDifference) {\n bestVersion = version;\n bestDifference = difference;\n }\n }\n // We can tolerate up to 3 bits of error since no two version info codewords will\n // differ in less than 8 bits.\n if (bestDifference <= 3) {\n return bestVersion;\n }\n}\n\nfunction readFormatInformation(matrix: BitMatrix) {\n let topLeftFormatInfoBits = 0;\n for (let x = 0; x <= 8; x++) {\n if (x !== 6) { // Skip timing pattern bit\n topLeftFormatInfoBits = pushBit(matrix.get(x, 8), topLeftFormatInfoBits);\n }\n }\n for (let y = 7; y >= 0; y--) {\n if (y !== 6) { // Skip timing pattern bit\n topLeftFormatInfoBits = pushBit(matrix.get(8, y), topLeftFormatInfoBits);\n }\n }\n\n const dimension = matrix.height;\n let topRightBottomRightFormatInfoBits = 0;\n for (let y = dimension - 1; y >= dimension - 7; y--) { // bottom left\n topRightBottomRightFormatInfoBits = pushBit(matrix.get(8, y), topRightBottomRightFormatInfoBits);\n }\n for (let x = dimension - 8; x < dimension; x++) { // top right\n topRightBottomRightFormatInfoBits = pushBit(matrix.get(x, 8), topRightBottomRightFormatInfoBits);\n }\n\n let bestDifference = Infinity;\n let bestFormatInfo = null;\n for (const {bits, formatInfo} of FORMAT_INFO_TABLE) {\n if (bits === topLeftFormatInfoBits || bits === topRightBottomRightFormatInfoBits) {\n return formatInfo;\n }\n let difference = numBitsDiffering(topLeftFormatInfoBits, bits);\n if (difference < bestDifference) {\n bestFormatInfo = formatInfo;\n bestDifference = difference;\n }\n if (topLeftFormatInfoBits !== topRightBottomRightFormatInfoBits) { // also try the other option\n difference = numBitsDiffering(topRightBottomRightFormatInfoBits, bits);\n if (difference < bestDifference) {\n bestFormatInfo = formatInfo;\n bestDifference = difference;\n }\n }\n }\n // Hamming distance of the 32 masked codes is 7, by construction, so <= 3 bits differing means we found a match\n if (bestDifference <= 3) {\n return bestFormatInfo;\n }\n return null;\n}\n\nfunction getDataBlocks(codewords: number[], version: Version, ecLevel: number) {\n const ecInfo = version.errorCorrectionLevels[ecLevel];\n const dataBlocks: Array<{\n numDataCodewords: number;\n codewords: number[];\n }> = [];\n\n let totalCodewords = 0;\n ecInfo.ecBlocks.forEach(block => {\n for (let i = 0; i < block.numBlocks; i++) {\n dataBlocks.push({ numDataCodewords: block.dataCodewordsPerBlock, codewords: [] });\n totalCodewords += block.dataCodewordsPerBlock + ecInfo.ecCodewordsPerBlock;\n }\n });\n\n // In some cases the QR code will be malformed enough that we pull off more or less than we should.\n // If we pull off less there's nothing we can do.\n // If we pull off more we can safely truncate\n if (codewords.length < totalCodewords) {\n return null;\n }\n codewords = codewords.slice(0, totalCodewords);\n\n const shortBlockSize = ecInfo.ecBlocks[0].dataCodewordsPerBlock;\n // Pull codewords to fill the blocks up to the minimum size\n for (let i = 0; i < shortBlockSize; i++) {\n for (const dataBlock of dataBlocks) {\n dataBlock.codewords.push(codewords.shift());\n }\n }\n\n // If there are any large blocks, pull codewords to fill the last element of those\n if (ecInfo.ecBlocks.length > 1) {\n const smallBlockCount = ecInfo.ecBlocks[0].numBlocks;\n const largeBlockCount = ecInfo.ecBlocks[1].numBlocks;\n for (let i = 0; i < largeBlockCount; i++) {\n dataBlocks[smallBlockCount + i].codewords.push(codewords.shift());\n }\n }\n\n // Add the rest of the codewords to the blocks. These are the error correction codewords.\n while (codewords.length > 0) {\n for (const dataBlock of dataBlocks) {\n dataBlock.codewords.push(codewords.shift());\n }\n }\n\n return dataBlocks;\n}\n\nfunction decodeMatrix(matrix: BitMatrix) {\n const version = readVersion(matrix);\n if (!version) {\n return null;\n }\n\n const formatInfo = readFormatInformation(matrix);\n if (!formatInfo) {\n return null;\n }\n\n const codewords = readCodewords(matrix, version, formatInfo);\n const dataBlocks = getDataBlocks(codewords, version, formatInfo.errorCorrectionLevel);\n if (!dataBlocks) {\n return null;\n }\n\n // Count total number of data bytes\n const totalBytes = dataBlocks.reduce((a, b) => a + b.numDataCodewords, 0);\n const resultBytes = new Uint8ClampedArray(totalBytes);\n\n let resultIndex = 0;\n for (const dataBlock of dataBlocks) {\n const correctedBytes = rsDecode(dataBlock.codewords, dataBlock.codewords.length - dataBlock.numDataCodewords);\n if (!correctedBytes) {\n return null;\n }\n for (let i = 0; i < dataBlock.numDataCodewords; i++) {\n resultBytes[resultIndex++] = correctedBytes[i];\n }\n }\n\n try {\n return decodeData(resultBytes, version.versionNumber);\n } catch {\n return null;\n }\n}\n\nexport function decode(matrix: BitMatrix): DecodedQR {\n if (matrix == null) {\n return null;\n }\n const result = decodeMatrix(matrix);\n if (result) {\n return result;\n }\n // Decoding didn't work, try mirroring the QR across the topLeft -> bottomRight line.\n for (let x = 0; x < matrix.width; x++) {\n for (let y = x + 1; y < matrix.height; y++) {\n if (matrix.get(x, y) !== matrix.get(y, x)) {\n matrix.set(x, y, !matrix.get(x, y));\n matrix.set(y, x, !matrix.get(y, x));\n }\n }\n }\n return decodeMatrix(matrix);\n}\n","import {BitMatrix} from \"../BitMatrix\";\nimport {Point, QRLocation} from \"../locator\";\n\ninterface PerspectiveTransform {\n a11: number;\n a21: number;\n a31: number;\n a12: number;\n a22: number;\n a32: number;\n a13: number;\n a23: number;\n a33: number;\n}\n\nfunction squareToQuadrilateral(p1: Point, p2: Point, p3: Point, p4: Point): PerspectiveTransform {\n const dx3 = p1.x - p2.x + p3.x - p4.x;\n const dy3 = p1.y - p2.y + p3.y - p4.y;\n if (dx3 === 0 && dy3 === 0) { // Affine\n return {\n a11: p2.x - p1.x,\n a12: p2.y - p1.y,\n a13: 0,\n a21: p3.x - p2.x,\n a22: p3.y - p2.y,\n a23: 0,\n a31: p1.x,\n a32: p1.y,\n a33: 1,\n };\n } else {\n const dx1 = p2.x - p3.x;\n const dx2 = p4.x - p3.x;\n const dy1 = p2.y - p3.y;\n const dy2 = p4.y - p3.y;\n const denominator = dx1 * dy2 - dx2 * dy1;\n const a13 = (dx3 * dy2 - dx2 * dy3) / denominator;\n const a23 = (dx1 * dy3 - dx3 * dy1) / denominator;\n return {\n a11: p2.x - p1.x + a13 * p2.x,\n a12: p2.y - p1.y + a13 * p2.y,\n a13,\n a21: p4.x - p1.x + a23 * p4.x,\n a22: p4.y - p1.y + a23 * p4.y,\n a23,\n a31: p1.x,\n a32: p1.y,\n a33: 1,\n };\n }\n}\n\nfunction quadrilateralToSquare(p1: Point, p2: Point, p3: Point, p4: Point): PerspectiveTransform {\n // Here, the adjoint serves as the inverse:\n const sToQ = squareToQuadrilateral(p1, p2, p3, p4);\n return {\n a11: sToQ.a22 * sToQ.a33 - sToQ.a23 * sToQ.a32,\n a12: sToQ.a13 * sToQ.a32 - sToQ.a12 * sToQ.a33,\n a13: sToQ.a12 * sToQ.a23 - sToQ.a13 * sToQ.a22,\n a21: sToQ.a23 * sToQ.a31 - sToQ.a21 * sToQ.a33,\n a22: sToQ.a11 * sToQ.a33 - sToQ.a13 * sToQ.a31,\n a23: sToQ.a13 * sToQ.a21 - sToQ.a11 * sToQ.a23,\n a31: sToQ.a21 * sToQ.a32 - sToQ.a22 * sToQ.a31,\n a32: sToQ.a12 * sToQ.a31 - sToQ.a11 * sToQ.a32,\n a33: sToQ.a11 * sToQ.a22 - sToQ.a12 * sToQ.a21,\n };\n}\n\nfunction times(a: PerspectiveTransform, b: PerspectiveTransform): PerspectiveTransform {\n return {\n a11: a.a11 * b.a11 + a.a21 * b.a12 + a.a31 * b.a13,\n a12: a.a12 * b.a11 + a.a22 * b.a12 + a.a32 * b.a13,\n a13: a.a13 * b.a11 + a.a23 * b.a12 + a.a33 * b.a13,\n a21: a.a11 * b.a21 + a.a21 * b.a22 + a.a31 * b.a23,\n a22: a.a12 * b.a21 + a.a22 * b.a22 + a.a32 * b.a23,\n a23: a.a13 * b.a21 + a.a23 * b.a22 + a.a33 * b.a23,\n a31: a.a11 * b.a31 + a.a21 * b.a32 + a.a31 * b.a33,\n a32: a.a12 * b.a31 + a.a22 * b.a32 + a.a32 * b.a33,\n a33: a.a13 * b.a31 + a.a23 * b.a32 + a.a33 * b.a33,\n };\n}\n\nexport function extract(image: BitMatrix, location: QRLocation) {\n const qToS = quadrilateralToSquare(\n {x: 3.5, y: 3.5},\n {x: location.dimension - 3.5, y: 3.5},\n {x: location.dimension - 6.5, y: location.dimension - 6.5},\n {x: 3.5, y: location.dimension - 3.5},\n );\n const sToQ = squareToQuadrilateral(location.topLeft, location.topRight, location.alignmentPattern, location.bottomLeft);\n const transform = times(sToQ, qToS);\n\n const matrix = BitMatrix.createEmpty(location.dimension, location.dimension);\n const mappingFunction = (x: number, y: number) => {\n const denominator = transform.a13 * x + transform.a23 * y + transform.a33;\n return {\n x: (transform.a11 * x + transform.a21 * y + transform.a31) / denominator,\n y: (transform.a12 * x + transform.a22 * y + transform.a32) / denominator,\n };\n };\n\n for (let y = 0; y < location.dimension; y++) {\n for (let x = 0; x < location.dimension; x++) {\n const xValue = x + 0.5;\n const yValue = y + 0.5;\n const sourcePixel = mappingFunction(xValue, yValue);\n matrix.set(x, y, image.get(Math.floor(sourcePixel.x), Math.floor(sourcePixel.y)));\n }\n }\n\n return {\n matrix,\n mappingFunction,\n };\n}\n","import { BitMatrix } from \"../BitMatrix\";\n\nconst MAX_FINDERPATTERNS_TO_SEARCH = 5;\nconst MIN_QUAD_RATIO = 0.5;\nconst MAX_QUAD_RATIO = 1.5;\n\nexport interface Point {\n x: number;\n y: number;\n}\n\nexport interface QRLocation {\n topRight: Point;\n bottomLeft: Point;\n topLeft: Point;\n alignmentPattern: Point;\n dimension: number;\n}\n\nconst distance = (a: Point, b: Point) => Math.sqrt((b.x - a.x) ** 2 + (b.y - a.y) ** 2);\n\nfunction sum(values: number[]) {\n return values.reduce((a, b) => a + b);\n}\n\n// Takes three finder patterns and organizes them into topLeft, topRight, etc\nfunction reorderFinderPatterns(pattern1: Point, pattern2: Point, pattern3: Point) {\n // Find distances between pattern centers\n const oneTwoDistance = distance(pattern1, pattern2);\n const twoThreeDistance = distance(pattern2, pattern3);\n const oneThreeDistance = distance(pattern1, pattern3);\n\n let bottomLeft: Point;\n let topLeft: Point;\n let topRight: Point;\n\n // Assume one closest to other two is B; A and C will just be guesses at first\n if (twoThreeDistance >= oneTwoDistance && twoThreeDistance >= oneThreeDistance) {\n [bottomLeft, topLeft, topRight] = [pattern2, pattern1, pattern3];\n } else if (oneThreeDistance >= twoThreeDistance && oneThreeDistance >= oneTwoDistance) {\n [bottomLeft, topLeft, topRight] = [pattern1, pattern2, pattern3];\n } else {\n [bottomLeft, topLeft, topRight] = [pattern1, pattern3, pattern2];\n }\n\n // Use cross product to figure out whether bottomLeft (A) and topRight (C) are correct or flipped in relation to topLeft (B)\n // This asks whether BC x BA has a positive z component, which is the arrangement we want. If it's negative, then\n // we've got it flipped around and should swap topRight and bottomLeft.\n if (((topRight.x - topLeft.x) * (bottomLeft.y - topLeft.y)) - ((topRight.y - topLeft.y) * (bottomLeft.x - topLeft.x)) < 0) {\n [bottomLeft, topRight] = [topRight, bottomLeft];\n }\n\n return { bottomLeft, topLeft, topRight };\n}\n\n// Computes the dimension (number of modules on a side) of the QR Code based on the position of the finder patterns\nfunction computeDimension(topLeft: Point, topRight: Point, bottomLeft: Point, matrix: BitMatrix) {\n const moduleSize = (\n sum(countBlackWhiteRun(topLeft, bottomLeft, matrix, 5)) / 7 + // Divide by 7 since the ratio is 1:1:3:1:1\n sum(countBlackWhiteRun(topLeft, topRight, matrix, 5)) / 7 +\n sum(countBlackWhiteRun(bottomLeft, topLeft, matrix, 5)) / 7 +\n sum(countBlackWhiteRun(topRight, topLeft, matrix, 5)) / 7\n ) / 4;\n\n if (moduleSize < 1) {\n throw new Error(\"Invalid module size\");\n }\n\n const topDimension = Math.round(distance(topLeft, topRight) / moduleSize);\n const sideDimension = Math.round(distance(topLeft, bottomLeft) / moduleSize);\n let dimension = Math.floor((topDimension + sideDimension) / 2) + 7;\n switch (dimension % 4) {\n case 0:\n dimension++;\n break;\n case 2:\n dimension--;\n break;\n }\n return { dimension, moduleSize };\n}\n\n// Takes an origin point and an end point and counts the sizes of the black white run from the origin towards the end point.\n// Returns an array of elements, representing the pixel size of the black white run.\n// Uses a variant of http://en.wikipedia.org/wiki/Bresenham's_line_algorithm\nfunction countBlackWhiteRunTowardsPoint(origin: Point, end: Point, matrix: BitMatrix, length: number) {\n const switchPoints: Point[] = [{x: Math.floor(origin.x), y: Math.floor(origin.y)}];\n const steep = Math.abs(end.y - origin.y) > Math.abs(end.x - origin.x);\n\n let fromX: number;\n let fromY: number;\n let toX: number;\n let toY: number;\n if (steep) {\n fromX = Math.floor(origin.y);\n fromY = Math.floor(origin.x);\n toX = Math.floor(end.y);\n toY = Math.floor(end.x);\n } else {\n fromX = Math.floor(origin.x);\n fromY = Math.floor(origin.y);\n toX = Math.floor(end.x);\n toY = Math.floor(end.y);\n }\n\n const dx = Math.abs(toX - fromX);\n const dy = Math.abs(toY - fromY);\n let error = Math.floor(-dx / 2);\n const xStep = fromX < toX ? 1 : -1;\n const yStep = fromY < toY ? 1 : -1;\n\n let currentPixel = true;\n // Loop up until x == toX, but not beyond\n for (let x = fromX, y = fromY; x !== toX + xStep; x += xStep) {\n // Does current pixel mean we have moved white to black or vice versa?\n // Scanning black in state 0,2 and white in state 1, so if we find the wrong\n // color, advance to next state or end if we are in state 2 already\n const realX = steep ? y : x;\n const realY = steep ? x : y;\n if (matrix.get(realX, realY) !== currentPixel) {\n currentPixel = !currentPixel;\n switchPoints.push({x: realX, y: realY});\n if (switchPoints.length === length + 1) {\n break;\n }\n }\n error += dy;\n if (error > 0) {\n if (y === toY) {\n break;\n }\n y += yStep;\n error -= dx;\n }\n }\n const distances: number[] = [];\n for (let i = 0; i < length; i++) {\n if (switchPoints[i] && switchPoints[i + 1]) {\n distances.push(distance(switchPoints[i], switchPoints[i + 1]));\n } else {\n distances.push(0);\n }\n }\n return distances;\n}\n\n// Takes an origin point and an end point and counts the sizes of the black white run in the origin point\n// along the line that intersects with the end point. Returns an array of elements, representing the pixel sizes\n// of the black white run. Takes a length which represents the number of switches from black to white to look for.\nfunction countBlackWhiteRun(origin: Point, end: Point, matrix: BitMatrix, length: number) {\n const rise = end.y - origin.y;\n const run = end.x - origin.x;\n\n const towardsEnd = countBlackWhiteRunTowardsPoint(origin, end, matrix, Math.ceil(length / 2));\n const awayFromEnd = countBlackWhiteRunTowardsPoint(origin, {x: origin.x - run, y: origin.y - rise}, matrix, Math.ceil(length / 2));\n\n const middleValue = towardsEnd.shift() + awayFromEnd.shift() - 1; // Substract one so we don't double count a pixel\n return awayFromEnd.concat(middleValue).concat(...towardsEnd);\n}\n\n// Takes in a black white run and an array of expected ratios. Returns the average size of the run as well as the \"error\" -\n// that is the amount the run diverges from the expected ratio\nfunction scoreBlackWhiteRun(sequence: number[], ratios: number[]) {\n const averageSize = sum(sequence) / sum(ratios);\n let error = 0;\n ratios.forEach((ratio, i) => {\n error += (sequence[i] - ratio * averageSize) ** 2;\n });\n\n return { averageSize, error };\n}\n\n// Takes an X,Y point and an array of sizes and scores the point against those ratios.\n// For example for a finder pattern takes the ratio list of 1:1:3:1:1 and checks horizontal, vertical and diagonal ratios\n// against that.\nfunction scorePattern(point: Point, ratios: number[], matrix: BitMatrix) {\n try {\n const horizontalRun = countBlackWhiteRun(point, {x: -1, y: point.y}, matrix, ratios.length);\n const verticalRun = countBlackWhiteRun(point, {x: point.x, y: -1}, matrix, ratios.length);\n\n const topLeftPoint = {\n x: Math.max(0, point.x - point.y) - 1,\n y: Math.max(0, point.y - point.x) - 1,\n };\n const topLeftBottomRightRun = countBlackWhiteRun(point, topLeftPoint, matrix, ratios.length);\n\n const bottomLeftPoint = {\n x: Math.min(matrix.width, point.x + point.y) + 1,\n y: Math.min(matrix.height, point.y + point.x) + 1,\n };\n const bottomLeftTopRightRun = countBlackWhiteRun(point, bottomLeftPoint, matrix, ratios.length);\n\n const horzError = scoreBlackWhiteRun(horizontalRun, ratios);\n const vertError = scoreBlackWhiteRun(verticalRun, ratios);\n const diagDownError = scoreBlackWhiteRun(topLeftBottomRightRun, ratios);\n const diagUpError = scoreBlackWhiteRun(bottomLeftTopRightRun, ratios);\n\n const ratioError = Math.sqrt(horzError.error * horzError.error +\n vertError.error * vertError.error +\n diagDownError.error * diagDownError.error +\n diagUpError.error * diagUpError.error);\n\n const avgSize = (horzError.averageSize + vertError.averageSize + diagDownError.averageSize + diagUpError.averageSize) / 4;\n\n const sizeError = ((horzError.averageSize - avgSize) ** 2 +\n (vertError.averageSize - avgSize) ** 2 +\n (diagDownError.averageSize - avgSize) ** 2 +\n (diagUpError.averageSize - avgSize) ** 2) / avgSize;\n return ratioError + sizeError;\n } catch {\n return Infinity;\n }\n}\n\nfunction recenterLocation(matrix: BitMatrix, p: Point): Point {\n let leftX = Math.round(p.x);\n while (matrix.get(leftX, Math.round(p.y))) {\n leftX--;\n }\n let rightX = Math.round(p.x);\n while (matrix.get(rightX, Math.round(p.y))) {\n rightX++;\n }\n const x = (leftX + rightX) / 2;\n\n let topY = Math.round(p.y);\n while (matrix.get(Math.round(x), topY)) {\n topY--;\n }\n let bottomY = Math.round(p.y);\n while (matrix.get(Math.round(x), bottomY)) {\n bottomY++;\n }\n const y = (topY + bottomY) / 2;\n\n return { x, y };\n}\n\ninterface Quad {\n top: {\n startX: number;\n endX: number;\n y: number;\n };\n bottom: {\n startX: number;\n endX: number;\n y: number;\n };\n}\n\nexport function locate(matrix: BitMatrix): QRLocation[] {\n const finderPatternQuads: Quad[] = [];\n let activeFinderPatternQuads: Quad[] = [];\n const alignmentPatternQuads: Quad[] = [];\n let activeAlignmentPatternQuads: Quad[] = [];\n\n for (let y = 0; y <= matrix.height; y++) {\n let length = 0;\n let lastBit = false;\n let scans = [0, 0, 0, 0, 0];\n\n for (let x = -1; x <= matrix.width; x++) {\n const v = matrix.get(x, y);\n if (v === lastBit) {\n length++;\n } else {\n scans = [scans[1], scans[2], scans[3], scans[4], length];\n length = 1;\n lastBit = v;\n\n // Do the last 5 color changes ~ match the expected ratio for a finder pattern? 1:1:3:1:1 of b:w:b:w:b\n const averageFinderPatternBlocksize = sum(scans) / 7;\n const validFinderPattern =\n Math.abs(scans[0] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize &&\n Math.abs(scans[1] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize &&\n Math.abs(scans[2] - 3 * averageFinderPatternBlocksize) < 3 * averageFinderPatternBlocksize &&\n Math.abs(scans[3] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize &&\n Math.abs(scans[4] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize &&\n !v; // And make sure the current pixel is white since finder patterns are bordered in white\n\n // Do the last 3 color changes ~ match the expected ratio for an alignment pattern? 1:1:1 of w:b:w\n const averageAlignmentPatternBlocksize = sum(scans.slice(-3)) / 3;\n const validAlignmentPattern =\n Math.abs(scans[2] - averageAlignmentPatternBlocksize) < averageAlignmentPatternBlocksize &&\n Math.abs(scans[3] - averageAlignmentPatternBlocksize) < averageAlignmentPatternBlocksize &&\n Math.abs(scans[4] - averageAlignmentPatternBlocksize) < averageAlignmentPatternBlocksize &&\n v; // Is the current pixel black since alignment patterns are bordered in black\n\n if (validFinderPattern) {\n // Compute the start and end x values of the large center black square\n const endX = x - scans[3] - scans[4];\n const startX = endX - scans[2];\n\n const line = { startX, endX, y };\n // Is there a quad directly above the current spot? If so, extend it with the new line. Otherwise, create a new quad with\n // that line as the starting point.\n const matchingQuads = activeFinderPatternQuads.filter(q =>\n (startX >= q.bottom.startX && startX <= q.bottom.endX) ||\n (endX >= q.bottom.startX && startX <= q.bottom.endX) ||\n (startX <= q.bottom.startX && endX >= q.bottom.endX && (\n (scans[2] / (q.bottom.endX - q.bottom.startX)) < MAX_QUAD_RATIO &&\n (scans[2] / (q.bottom.endX - q.bottom.startX)) > MIN_QUAD_RATIO\n )),\n );\n if (matchingQuads.length > 0) {\n matchingQuads[0].bottom = line;\n } else {\n activeFinderPatternQuads.push({ top: line, bottom: line });\n }\n }\n if (validAlignmentPattern) {\n // Compute the start and end x values of the center black square\n const endX = x - scans[4];\n const startX = endX - scans[3];\n\n const line = { startX, y, endX };\n // Is there a quad directly above the current spot? If so, extend it with the new line. Otherwise, create a new quad with\n // that line as the starting point.\n const matchingQuads = activeAlignmentPatternQuads.filter(q =>\n (startX >= q.bottom.startX && startX <= q.bottom.endX) ||\n (endX >= q.bottom.startX && startX <= q.bottom.endX) ||\n (startX <= q.bottom.startX && endX >= q.bottom.endX && (\n (scans[2] / (q.bottom.endX - q.bottom.startX)) < MAX_QUAD_RATIO &&\n (scans[2] / (q.bottom.endX - q.bottom.startX)) > MIN_QUAD_RATIO\n )),\n );\n if (matchingQuads.length > 0) {\n matchingQuads[0].bottom = line;\n } else {\n activeAlignmentPatternQuads.push({ top: line, bottom: line });\n }\n }\n }\n }\n finderPatternQuads.push(...activeFinderPatternQuads.filter(q => q.bottom.y !== y && q.bottom.y - q.top.y >= 2));\n activeFinderPatternQuads = activeFinderPatternQuads.filter(q => q.bottom.y === y);\n\n alignmentPatternQuads.push(...activeAlignmentPatternQuads.filter(q => q.bottom.y !== y));\n activeAlignmentPatternQuads = activeAlignmentPatternQuads.filter(q => q.bottom.y === y);\n\n }\n\n finderPatternQuads.push(...activeFinderPatternQuads.filter(q => q.bottom.y - q.top.y >= 2));\n alignmentPatternQuads.push(...activeAlignmentPatternQuads);\n\n // Refactored from cozmo/jsQR to (hopefully) circumvent an issue in Safari 13+ on both Mac and iOS (also including\n // iOS Chrome and other Safari iOS derivatives). Safari was very occasionally and apparently not deterministically\n // throwing a \"RangeError: Array size is not a small enough positive integer.\" exception seemingly within the second\n // .map of the original code (here the second for-loop). This second .map contained a nested .map call over the same\n // array instance which was the chained result from previous calls to .map, .filter and .sort which potentially caused\n // this bug in Safari?\n // Also see https://github.com/cozmo/jsQR/issues/157 and https://bugs.webkit.org/show_bug.cgi?id=211619#c3\n const scoredFinderPatternPositions: Array = [];\n for (const quad of finderPatternQuads) {\n if (quad.bottom.y - quad.top.y < 2) {\n // All quads must be at least 2px tall since the center square is larger than a block\n continue;\n }\n\n // calculate quad center\n const x = (quad.top.startX + quad.top.endX + quad.bottom.startX + quad.bottom.endX) / 4;\n const y = (quad.top.y + quad.bottom.y + 1) / 2;\n if (!matrix.get(Math.round(x), Math.round(y))) {\n continue;\n }\n\n const lengths = [quad.top.endX - quad.top.startX, quad.bottom.endX - quad.bottom.startX, quad.bottom.y - quad.top.y + 1];\n const size = sum(lengths) / lengths.length;\n // Initial scoring of finder pattern quads by looking at their ratios, not taking into account position\n const score = scorePattern({x: Math.round(x), y: Math.round(y)}, [1, 1, 3, 1, 1], matrix);\n scoredFinderPatternPositions.push({ score, x, y, size });\n }\n if (scoredFinderPatternPositions.length < 3) {\n // A QR code has 3 finder patterns, therefore we need at least 3 candidates.\n return null;\n }\n scoredFinderPatternPositions.sort((a, b) => a.score - b.score);\n\n // Now take the top finder pattern options and try to find 2 other options with a similar size.\n const finderPatternGroups: Array<{ points: [Point, Point, Point], score: number }> = [];\n for (let i = 0; i < Math.min(scoredFinderPatternPositions.length, MAX_FINDERPATTERNS_TO_SEARCH); ++i) {\n const point = scoredFinderPatternPositions[i];\n const otherPoints: typeof scoredFinderPatternPositions = [];\n\n for (const otherPoint of scoredFinderPatternPositions) {\n if (otherPoint === point) {\n continue;\n }\n otherPoints.push({\n ...otherPoint,\n score: otherPoint.score + ((otherPoint.size - point.size) ** 2) / point.size, // score similarity of sizes\n });\n }\n otherPoints.sort((a, b) => a.score - b.score);\n\n finderPatternGroups.push({\n points: [point, otherPoints[0], otherPoints[1]], // note that otherPoints.length >= 2 as scoredFinderPatternPositions.length >= 3\n score: point.score + otherPoints[0].score + otherPoints[1].score, // total combined score of the three points in the group\n });\n }\n finderPatternGroups.sort((a, b) => a.score - b.score);\n const bestFinderPatternGroup = finderPatternGroups[0];\n\n const { topRight, topLeft, bottomLeft } = reorderFinderPatterns(...bestFinderPatternGroup.points);\n const alignment = findAlignmentPattern(matrix, alignmentPatternQuads, topRight, topLeft, bottomLeft);\n const result: QRLocation[] = [];\n if (alignment) {\n result.push({\n alignmentPattern: { x: alignment.alignmentPattern.x, y: alignment.alignmentPattern.y },\n bottomLeft: {x: bottomLeft.x, y: bottomLeft.y },\n dimension: alignment.dimension,\n topLeft: {x: topLeft.x, y: topLeft.y },\n topRight: {x: topRight.x, y: topRight.y },\n });\n }\n\n // We normally use the center of the quads as the location of the tracking points, which is optimal for most cases and will account\n // for a skew in the image. However, In some cases, a slight skew might not be real and instead be caused by image compression\n // errors and/or low resolution. For those cases, we'd be better off centering the point exactly in the middle of the black area. We\n // compute and return the location data for the naively centered points as it is little additional work and allows for multiple\n // attempts at decoding harder images.\n const midTopRight = recenterLocation(matrix, topRight);\n const midTopLeft = recenterLocation(matrix, topLeft);\n const midBottomLeft = recenterLocation(matrix, bottomLeft);\n const centeredAlignment = findAlignmentPattern(matrix, alignmentPatternQuads, midTopRight, midTopLeft, midBottomLeft);\n if (centeredAlignment) {\n result.push({\n alignmentPattern: { x: centeredAlignment.alignmentPattern.x, y: centeredAlignment.alignmentPattern.y },\n bottomLeft: { x: midBottomLeft.x, y: midBottomLeft. y },\n topLeft: { x: midTopLeft.x, y: midTopLeft. y },\n topRight: { x: midTopRight.x, y: midTopRight. y },\n dimension: centeredAlignment.dimension,\n });\n }\n\n if (result.length === 0) {\n return null;\n }\n\n return result;\n}\n\nfunction findAlignmentPattern(matrix: BitMatrix, alignmentPatternQuads: Quad[], topRight: Point, topLeft: Point, bottomLeft: Point) {\n // Now that we've found the three finder patterns we can determine the blockSize and the size of the QR code.\n // We'll use these to help find the alignment pattern but also later when we do the extraction.\n let dimension: number;\n let moduleSize: number;\n try {\n ({ dimension, moduleSize } = computeDimension(topLeft, topRight, bottomLeft, matrix));\n } catch (e) {\n return null;\n }\n\n // Now find the alignment pattern\n const bottomRightFinderPattern = { // Best guess at where a bottomRight finder pattern would be\n x: topRight.x - topLeft.x + bottomLeft.x,\n y: topRight.y - topLeft.y + bottomLeft.y,\n };\n const modulesBetweenFinderPatterns = ((distance(topLeft, bottomLeft) + distance(topLeft, topRight)) / 2 / moduleSize);\n const correctionToTopLeft = 1 - (3 / modulesBetweenFinderPatterns);\n const expectedAlignmentPattern = {\n x: topLeft.x + correctionToTopLeft * (bottomRightFinderPattern.x - topLeft.x),\n y: topLeft.y + correctionToTopLeft * (bottomRightFinderPattern.y - topLeft.y),\n };\n\n const alignmentPatterns = alignmentPatternQuads\n .map(q => {\n const x = (q.top.startX + q.top.endX + q.bottom.startX + q.bottom.endX) / 4;\n const y = (q.top.y + q.bottom.y + 1) / 2;\n if (!matrix.get(Math.floor(x), Math.floor(y))) {\n return;\n }\n\n const sizeScore = scorePattern({x: Math.floor(x), y: Math.floor(y)}, [1, 1, 1], matrix);\n const score = sizeScore + distance({x, y}, expectedAlignmentPattern);\n return { x, y, score };\n })\n .filter(v => !!v)\n .sort((a, b) => a.score - b.score);\n\n // If there are less than 15 modules between finder patterns it's a version 1 QR code and as such has no alignmemnt pattern\n // so we can only use our best guess.\n const alignmentPattern = modulesBetweenFinderPatterns >= 15 && alignmentPatterns.length ? alignmentPatterns[0] : expectedAlignmentPattern;\n\n return { alignmentPattern, dimension };\n}\n","import {binarize} from \"./binarizer\";\nimport {BitMatrix} from \"./BitMatrix\";\nimport {Chunks} from \"./decoder/decodeData\";\nimport {decode} from \"./decoder/decoder\";\nimport { Version } from \"./decoder/version\";\nimport {extract} from \"./extractor\";\nimport {locate, Point} from \"./locator\";\n\nexport interface QRCode {\n binaryData: number[];\n data: string;\n chunks: Chunks;\n version: number;\n location: {\n topRightCorner: Point;\n topLeftCorner: Point;\n bottomRightCorner: Point;\n bottomLeftCorner: Point;\n\n topRightFinderPattern: Point;\n topLeftFinderPattern: Point;\n bottomLeftFinderPattern: Point;\n\n bottomRightAlignmentPattern?: Point;\n };\n matrix: BitMatrix;\n}\n\nfunction scan(matrix: BitMatrix): QRCode | null {\n const locations = locate(matrix);\n if (!locations) {\n return null;\n }\n\n for (const location of locations) {\n const extracted = extract(matrix, location);\n const decoded = decode(extracted.matrix);\n if (decoded) {\n return {\n binaryData: decoded.bytes,\n data: decoded.text,\n chunks: decoded.chunks,\n version: decoded.version,\n location: {\n topRightCorner: extracted.mappingFunction(location.dimension, 0),\n topLeftCorner: extracted.mappingFunction(0, 0),\n bottomRightCorner: extracted.mappingFunction(location.dimension, location.dimension),\n bottomLeftCorner: extracted.mappingFunction(0, location.dimension),\n\n topRightFinderPattern: location.topRight,\n topLeftFinderPattern: location.topLeft,\n bottomLeftFinderPattern: location.bottomLeft,\n\n bottomRightAlignmentPattern: location.alignmentPattern,\n },\n matrix: extracted.matrix,\n };\n }\n }\n return null;\n}\n\nexport interface Options {\n inversionAttempts?: \"dontInvert\" | \"onlyInvert\" | \"attemptBoth\" | \"invertFirst\";\n greyScaleWeights?: GreyscaleWeights;\n canOverwriteImage?: boolean;\n}\n\nexport interface GreyscaleWeights {\n red: number;\n green: number;\n blue: number;\n useIntegerApproximation?: boolean;\n}\n\nconst defaultOptions: Options = {\n inversionAttempts: \"attemptBoth\",\n greyScaleWeights: {\n red: 0.2126,\n green: 0.7152,\n blue: 0.0722,\n useIntegerApproximation: false,\n },\n canOverwriteImage: true,\n};\n\nfunction mergeObject(target: any, src: any) {\n Object.keys(src).forEach(opt => { // Sad implementation of Object.assign since we target es5 not es6\n target[opt] = src[opt];\n });\n}\n\nfunction jsQR(data: Uint8ClampedArray, width: number, height: number, providedOptions: Options = {}): QRCode | null {\n const options = Object.create(null);\n mergeObject(options, defaultOptions);\n mergeObject(options, providedOptions);\n\n const tryInvertedFirst = options.inversionAttempts === \"onlyInvert\" || options.inversionAttempts === \"invertFirst\";\n const shouldInvert = options.inversionAttempts === \"attemptBoth\" || tryInvertedFirst;\n const {binarized, inverted} = binarize(data, width, height, shouldInvert, options.greyScaleWeights,\n options.canOverwriteImage);\n let result = scan(tryInvertedFirst ? inverted : binarized);\n if (!result && (options.inversionAttempts === \"attemptBoth\" || options.inversionAttempts === \"invertFirst\")) {\n result = scan(tryInvertedFirst ? binarized : inverted);\n }\n return result;\n}\n\n(jsQR as any).default = jsQR;\nexport default jsQR;\n","// @ts-ignore jsqr-es6 does not provide types currently\nimport jsQR from '../node_modules/jsqr-es6/dist/jsQR.js';\n\ntype GrayscaleWeights = {\n red: number,\n green: number,\n blue: number,\n useIntegerApproximation: boolean,\n};\n\nlet inversionAttempts: 'dontInvert' | 'onlyInvert' | 'attemptBoth' = 'dontInvert';\nlet grayscaleWeights: GrayscaleWeights = {\n // weights for quick luma integer approximation (https://en.wikipedia.org/wiki/YUV#Full_swing_for_BT.601)\n red: 77,\n green: 150,\n blue: 29,\n useIntegerApproximation: true,\n};\n\nself.onmessage = event => {\n const id = event['data']['id'];\n const type = event['data']['type'];\n const data = event['data']['data'];\n\n switch (type) {\n case 'decode':\n decode(data, id);\n break;\n case 'grayscaleWeights':\n setGrayscaleWeights(data);\n break;\n case 'inversionMode':\n setInversionMode(data);\n break;\n case 'close':\n // close after earlier messages in the event loop finished processing\n self.close();\n break;\n }\n};\n\nfunction decode(data: { data: Uint8ClampedArray, width: number, height: number }, requestId: number): void {\n const rgbaData = data['data'];\n const width = data['width'];\n const height = data['height'];\n const result = jsQR(rgbaData, width, height, {\n inversionAttempts: inversionAttempts,\n greyScaleWeights: grayscaleWeights,\n });\n if (!result) {\n (self as unknown as Worker).postMessage({\n id: requestId,\n type: 'qrResult',\n data: null,\n });\n return;\n }\n\n (self as unknown as Worker).postMessage({\n id: requestId,\n type: 'qrResult',\n data: result.data,\n // equivalent to cornerPoints of native BarcodeDetector\n cornerPoints: [\n result.location.topLeftCorner,\n result.location.topRightCorner,\n result.location.bottomRightCorner,\n result.location.bottomLeftCorner,\n ],\n });\n}\n\nfunction setGrayscaleWeights(data: GrayscaleWeights) {\n // update grayscaleWeights in a closure compiler compatible fashion\n grayscaleWeights.red = data['red'];\n grayscaleWeights.green = data['green'];\n grayscaleWeights.blue = data['blue'];\n grayscaleWeights.useIntegerApproximation = data['useIntegerApproximation'];\n}\n\nfunction setInversionMode(inversionMode: 'original' | 'invert' | 'both') {\n switch (inversionMode) {\n case 'original':\n inversionAttempts = 'dontInvert';\n break;\n case 'invert':\n inversionAttempts = 'onlyInvert';\n break;\n case 'both':\n inversionAttempts = 'attemptBoth';\n break;\n default:\n throw new Error('Invalid inversion mode');\n }\n}\n"],"names":["BitMatrix","constructor","data","width","height","length","createEmpty","Uint8ClampedArray","get","x","y","set","v","setRegion","left","top","Matrix","buffer","bufferSize","Error","value","BitStream","bytes","readBits","numBits","available","toString","result","bitOffset","byteOffset","bitsToNotRead","toRead","Mode","ModeByte","decodeByte","stream","size","text","i","push","b","decodeURIComponent","map","substr","join","decode","version","chunks","mode","Terminator","ECI","type","assignmentNumber","Numeric","num","a","c","Alphanumeric","AlphanumericCharacterCodes","charCodeAt","Byte","byteResult","Kanji","Math","floor","k","StructuredAppend","currentSequence","totalSequence","parity","GenericGFPoly","field","coefficients","coefficientsLength","firstNonZero","zero","degree","isZero","getCoefficient","addOrSubtract","other","smallerCoefficients","largerCoefficients","lengthDiff","sumDiff","multiply","scalar","product","multiplyPoly","aLength","j","bLength","addOrSubtractGF","aCoeff","bCoefficients","multiplyByMonomial","coefficient","evaluateAt","forEach","GenericGF","primitive","genBase","generatorBase","expTable","Array","logTable","from","one","inverse","buildMonomial","log","exp","runEuclideanAlgorithm","R","tLast","t","r","rLast","rLastLast","q","dltInverse","degreeDiff","scale","tLastLast","sigmaTildeAtZero","twoS","outputBytes","error","s","syndromeCoefficients","evaluation","syndrome","sigmaOmega","numErrors","errorLocator","errorCount","errorLocations","denominator","xiInverse","errorEvaluator","position","infoBits","versionNumber","alignmentPatternCenters","errorCorrectionLevels","ecCodewordsPerBlock","ecBlocks","numBlocks","dataCodewordsPerBlock","numBitsDiffering","z","bitCount","pushBit","bit","byte","bits","formatInfo","errorCorrectionLevel","dataMask","p","readCodewords","matrix","dimension","bitsRead","currentByte","readingUp","columnIndex","columnOffset","codewords","readVersion","provisionalVersion","VERSIONS","topRightVersionBits","bottomLeftVersionBits","bestDifference","Infinity","bestVersion","difference","readFormatInformation","topLeftFormatInfoBits","topRightBottomRightFormatInfoBits","bestFormatInfo","getDataBlocks","ecLevel","totalCodewords","ecInfo","block","dataBlocks","numDataCodewords","slice","shortBlockSize","dataBlock","shift","largeBlockCount","smallBlockCount","decodeMatrix","resultIndex","correctedBytes","resultBytes","decodeData","squareToQuadrilateral","p1","p2","p3","p4","dx3","dy3","a11","a12","a13","a21","a22","a23","a31","a32","a33","quadrilateralToSquare","sToQ","extract","image","location","qToS","sourcePixel","mappingFunction","sum","values","reduce","reorderFinderPatterns","pattern1","pattern2","pattern3","bottomLeft","topLeft","topRight","twoThreeDistance","oneTwoDistance","oneThreeDistance","computeDimension","countBlackWhiteRun","moduleSize","topDimension","sideDimension","countBlackWhiteRunTowardsPoint","origin","end","steep","fromX","fromY","toX","toY","dx","currentPixel","xStep","realX","realY","switchPoints","dy","yStep","distances","distance","awayFromEnd","concat","middleValue","towardsEnd","scoreBlackWhiteRun","sequence","ratios","ratio","averageSize","scorePattern","point","max","min","vertError","diagDownError","diagUpError","avgSize","recenterLocation","leftX","round","rightX","topY","bottomY","locate","activeFinderPatternQuads","activeAlignmentPatternQuads","lastBit","scans","abs","averageFinderPatternBlocksize","averageAlignmentPatternBlocksize","validFinderPattern","startX","endX","bottom","matchingQuads","line","validAlignmentPattern","finderPatternQuads","filter","alignmentPatternQuads","quad","scoredFinderPatternPositions","score","sort","otherPoint","otherPoints","finderPatternGroups","points","alignment","alignmentPattern","midTopRight","midTopLeft","midBottomLeft","centeredAlignment","findAlignmentPattern","e","correctionToTopLeft","sizeScore","expectedAlignmentPattern","scan","locations","decoded","binaryData","topRightCorner","extracted","topLeftCorner","bottomRightCorner","bottomLeftCorner","topRightFinderPattern","topLeftFinderPattern","bottomLeftFinderPattern","bottomRightAlignmentPattern","inversionAttempts","greyScaleWeights","red","green","blue","useIntegerApproximation","canOverwriteImage","mergeObject","target","src","Object","keys","opt","jsQR","providedOptions","options","defaultOptions","shouldInvert","pixelCount","bufferOffset","greyscaleBuffer","greyscaleWeights","greyscalePixels","blackPointsBuffer","blackPointsCount","verticalRegionCount","verticalRegion","hortizontalRegion","horizontalRegionCount","pixelLumosity","average","blackPoints","averageNeighborBlackPoint","binarized","binarizedBuffer","inverted","returnInverted","invertedBuffer","xRegion","yRegion","lum","threshold","tryInvertedFirst","default","grayscaleWeights","self","onmessage","event","self.onmessage","postMessage","id","cornerPoints","close"],"mappings":"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"} \ No newline at end of file diff --git a/res/qr-scanner.umd.min.js b/res/qr-scanner.umd.min.js new file mode 100644 index 0000000..667ac2f --- /dev/null +++ b/res/qr-scanner.umd.min.js @@ -0,0 +1,31 @@ +'use strict';(function(e,a){"object"===typeof exports&&"undefined"!==typeof module?module.exports=a():"function"===typeof define&&define.amd?define(a):(e="undefined"!==typeof globalThis?globalThis:e||self,e.QrScanner=a())})(this,function(){class e{constructor(a,b,c,d,f){this._legacyCanvasSize=e.DEFAULT_CANVAS_SIZE;this._preferredCamera="environment";this._maxScansPerSecond=25;this._lastScanTimestamp=-1;this._destroyed=this._flashOn=this._paused=this._active=!1;this.$video=a;this.$canvas=document.createElement("canvas"); +c&&"object"===typeof c?this._onDecode=b:(c||d||f?console.warn("You're using a deprecated version of the QrScanner constructor which will be removed in the future"):console.warn("Note that the type of the scan result passed to onDecode will change in the future. To already switch to the new api today, you can pass returnDetailedScanResult: true."),this._legacyOnDecode=b);b="object"===typeof c?c:{};this._onDecodeError=b.onDecodeError||("function"===typeof c?c:this._onDecodeError);this._calculateScanRegion= +b.calculateScanRegion||("function"===typeof d?d:this._calculateScanRegion);this._preferredCamera=b.preferredCamera||f||this._preferredCamera;this._legacyCanvasSize="number"===typeof c?c:"number"===typeof d?d:this._legacyCanvasSize;this._maxScansPerSecond=b.maxScansPerSecond||this._maxScansPerSecond;this._onPlay=this._onPlay.bind(this);this._onLoadedMetaData=this._onLoadedMetaData.bind(this);this._onVisibilityChange=this._onVisibilityChange.bind(this);this._updateOverlay=this._updateOverlay.bind(this); +a.disablePictureInPicture=!0;a.playsInline=!0;a.muted=!0;let h=!1;a.hidden&&(a.hidden=!1,h=!0);document.body.contains(a)||(document.body.appendChild(a),h=!0);c=a.parentElement;if(b.highlightScanRegion||b.highlightCodeOutline){d=!!b.overlay;this.$overlay=b.overlay||document.createElement("div");f=this.$overlay.style;f.position="absolute";f.display="none";f.pointerEvents="none";this.$overlay.classList.add("scan-region-highlight");if(!d&&b.highlightScanRegion){this.$overlay.innerHTML=''; +try{this.$overlay.firstElementChild.animate({transform:["scale(.98)","scale(1.01)"]},{duration:400,iterations:Infinity,direction:"alternate",easing:"ease-in-out"})}catch(m){}c.insertBefore(this.$overlay,this.$video.nextSibling)}b.highlightCodeOutline&&(this.$overlay.insertAdjacentHTML("beforeend",''), +this.$codeOutlineHighlight=this.$overlay.lastElementChild)}this._scanRegion=this._calculateScanRegion(a);requestAnimationFrame(()=>{let m=window.getComputedStyle(a);"none"===m.display&&(a.style.setProperty("display","block","important"),h=!0);"visible"!==m.visibility&&(a.style.setProperty("visibility","visible","important"),h=!0);h&&(console.warn("QrScanner has overwritten the video hiding style to avoid Safari stopping the playback."),a.style.opacity="0",a.style.width="0",a.style.height="0",this.$overlay&& +this.$overlay.parentElement&&this.$overlay.parentElement.removeChild(this.$overlay),delete this.$overlay,delete this.$codeOutlineHighlight);this.$overlay&&this._updateOverlay()});a.addEventListener("play",this._onPlay);a.addEventListener("loadedmetadata",this._onLoadedMetaData);document.addEventListener("visibilitychange",this._onVisibilityChange);window.addEventListener("resize",this._updateOverlay);this._qrEnginePromise=e.createQrEngine()}static set WORKER_PATH(a){console.warn("Setting QrScanner.WORKER_PATH is not required and not supported anymore. Have a look at the README for new setup instructions.")}static async hasCamera(){try{return!!(await e.listCameras(!1)).length}catch(a){return!1}}static async listCameras(a= +!1){if(!navigator.mediaDevices)return[];let b=async()=>(await navigator.mediaDevices.enumerateDevices()).filter(d=>"videoinput"===d.kind),c;try{a&&(await b()).every(d=>!d.label)&&(c=await navigator.mediaDevices.getUserMedia({audio:!1,video:!0}))}catch(d){}try{return(await b()).map((d,f)=>({id:d.deviceId,label:d.label||(0===f?"Default Camera":`Camera ${f+1}`)}))}finally{c&&(console.warn("Call listCameras after successfully starting a QR scanner to avoid creating a temporary video stream"),e._stopVideoStream(c))}}async hasFlash(){let a; +try{if(this.$video.srcObject){if(!(this.$video.srcObject instanceof MediaStream))return!1;a=this.$video.srcObject}else a=(await this._getCameraStream()).stream;return"torch"in a.getVideoTracks()[0].getSettings()}catch(b){return!1}finally{a&&a!==this.$video.srcObject&&(console.warn("Call hasFlash after successfully starting the scanner to avoid creating a temporary video stream"),e._stopVideoStream(a))}}isFlashOn(){return this._flashOn}async toggleFlash(){this._flashOn?await this.turnFlashOff():await this.turnFlashOn()}async turnFlashOn(){if(!this._flashOn&& +!this._destroyed&&(this._flashOn=!0,this._active&&!this._paused))try{if(!await this.hasFlash())throw"No flash available";await this.$video.srcObject.getVideoTracks()[0].applyConstraints({advanced:[{torch:!0}]})}catch(a){throw this._flashOn=!1,a;}}async turnFlashOff(){this._flashOn&&(this._flashOn=!1,await this._restartVideoStream())}destroy(){this.$video.removeEventListener("loadedmetadata",this._onLoadedMetaData);this.$video.removeEventListener("play",this._onPlay);document.removeEventListener("visibilitychange", +this._onVisibilityChange);window.removeEventListener("resize",this._updateOverlay);this._destroyed=!0;this._flashOn=!1;this.stop();e._postWorkerMessage(this._qrEnginePromise,"close")}async start(){if(this._destroyed)throw Error("The QR scanner can not be started as it had been destroyed.");if(!this._active||this._paused)if("https:"!==window.location.protocol&&console.warn("The camera stream is only accessible if the page is transferred via https."),this._active=!0,!document.hidden)if(this._paused= +!1,this.$video.srcObject)await this.$video.play();else try{let {stream:a,facingMode:b}=await this._getCameraStream();!this._active||this._paused?e._stopVideoStream(a):(this._setVideoMirror(b),this.$video.srcObject=a,await this.$video.play(),this._flashOn&&(this._flashOn=!1,this.turnFlashOn().catch(()=>{})))}catch(a){if(!this._paused)throw this._active=!1,a;}}stop(){this.pause();this._active=!1}async pause(a=!1){this._paused=!0;if(!this._active)return!0;this.$video.pause();this.$overlay&&(this.$overlay.style.display= +"none");let b=()=>{this.$video.srcObject instanceof MediaStream&&(e._stopVideoStream(this.$video.srcObject),this.$video.srcObject=null)};if(a)return b(),!0;await new Promise(c=>setTimeout(c,300));if(!this._paused)return!1;b();return!0}async setCamera(a){a!==this._preferredCamera&&(this._preferredCamera=a,await this._restartVideoStream())}static async scanImage(a,b,c,d,f=!1,h=!1){let m,n=!1;b&&("scanRegion"in b||"qrEngine"in b||"canvas"in b||"disallowCanvasResizing"in b||"alsoTryWithoutScanRegion"in +b||"returnDetailedScanResult"in b)?(m=b.scanRegion,c=b.qrEngine,d=b.canvas,f=b.disallowCanvasResizing||!1,h=b.alsoTryWithoutScanRegion||!1,n=!0):b||c||d||f||h?console.warn("You're using a deprecated api for scanImage which will be removed in the future."):console.warn("Note that the return type of scanImage will change in the future. To already switch to the new api today, you can pass returnDetailedScanResult: true.");b=!!c;try{let p,k;[c,p]=await Promise.all([c||e.createQrEngine(),e._loadImage(a)]); +[d,k]=e._drawToCanvas(p,m,d,f);let q;if(c instanceof Worker){let g=c;b||e._postWorkerMessageSync(g,"inversionMode","both");q=await new Promise((l,v)=>{let w,u,r,y=-1;u=t=>{t.data.id===y&&(g.removeEventListener("message",u),g.removeEventListener("error",r),clearTimeout(w),null!==t.data.data?l({data:t.data.data,cornerPoints:e._convertPoints(t.data.cornerPoints,m)}):v(e.NO_QR_CODE_FOUND))};r=t=>{g.removeEventListener("message",u);g.removeEventListener("error",r);clearTimeout(w);v("Scanner error: "+(t? +t.message||t:"Unknown Error"))};g.addEventListener("message",u);g.addEventListener("error",r);w=setTimeout(()=>r("timeout"),1E4);let x=k.getImageData(0,0,d.width,d.height);y=e._postWorkerMessageSync(g,"decode",x,[x.data.buffer])})}else q=await Promise.race([new Promise((g,l)=>window.setTimeout(()=>l("Scanner error: timeout"),1E4)),(async()=>{try{var [g]=await c.detect(d);if(!g)throw e.NO_QR_CODE_FOUND;return{data:g.rawValue,cornerPoints:e._convertPoints(g.cornerPoints,m)}}catch(l){g=l.message||l; +if(/not implemented|service unavailable/.test(g))return e._disableBarcodeDetector=!0,e.scanImage(a,{scanRegion:m,canvas:d,disallowCanvasResizing:f,alsoTryWithoutScanRegion:h});throw`Scanner error: ${g}`;}})()]);return n?q:q.data}catch(p){if(!m||!h)throw p;let k=await e.scanImage(a,{qrEngine:c,canvas:d,disallowCanvasResizing:f});return n?k:k.data}finally{b||e._postWorkerMessage(c,"close")}}setGrayscaleWeights(a,b,c,d=!0){e._postWorkerMessage(this._qrEnginePromise,"grayscaleWeights",{red:a,green:b, +blue:c,useIntegerApproximation:d})}setInversionMode(a){e._postWorkerMessage(this._qrEnginePromise,"inversionMode",a)}static async createQrEngine(a){a&&console.warn("Specifying a worker path is not required and not supported anymore.");a=()=>import("./qr-scanner-worker.min.js").then(c=>c.createWorker());if(!(!e._disableBarcodeDetector&&"BarcodeDetector"in window&&BarcodeDetector.getSupportedFormats&&(await BarcodeDetector.getSupportedFormats()).includes("qr_code")))return a();let b=navigator.userAgentData; +return b&&b.brands.some(({brand:c})=>/Chromium/i.test(c))&&/mac ?OS/i.test(b.platform)&&await b.getHighEntropyValues(["architecture","platformVersion"]).then(({architecture:c,platformVersion:d})=>/arm/i.test(c||"arm")&&13<=parseInt(d||"13")).catch(()=>!0)?a():new BarcodeDetector({formats:["qr_code"]})}_onPlay(){this._scanRegion=this._calculateScanRegion(this.$video);this._updateOverlay();this.$overlay&&(this.$overlay.style.display="");this._scanFrame()}_onLoadedMetaData(){this._scanRegion=this._calculateScanRegion(this.$video); +this._updateOverlay()}_onVisibilityChange(){document.hidden?this.pause():this._active&&this.start()}_calculateScanRegion(a){let b=Math.round(2/3*Math.min(a.videoWidth,a.videoHeight));return{x:Math.round((a.videoWidth-b)/2),y:Math.round((a.videoHeight-b)/2),width:b,height:b,downScaledWidth:this._legacyCanvasSize,downScaledHeight:this._legacyCanvasSize}}_updateOverlay(){requestAnimationFrame(()=>{if(this.$overlay){var a=this.$video,b=a.videoWidth,c=a.videoHeight,d=a.offsetWidth,f=a.offsetHeight,h=a.offsetLeft, +m=a.offsetTop,n=window.getComputedStyle(a),p=n.objectFit,k=b/c,q=d/f;switch(p){case "none":var g=b;var l=c;break;case "fill":g=d;l=f;break;default:("cover"===p?k>q:k{const x=parseFloat(r);return r.endsWith("%")?(y?f-l:d-g)*x/100:x});n=this._scanRegion.width||b;q=this._scanRegion.height||c;p=this._scanRegion.x||0;var u=this._scanRegion.y||0;k=this.$overlay.style;k.width= +`${n/b*g}px`;k.height=`${q/c*l}px`;k.top=`${m+w+u/c*l}px`;c=/scaleX\(-1\)/.test(a.style.transform);k.left=`${h+(c?d-v-g:v)+(c?b-p-n:p)/b*g}px`;k.transform=a.style.transform}})}static _convertPoints(a,b){if(!b)return a;let c=b.x||0,d=b.y||0,f=b.width&&b.downScaledWidth?b.width/b.downScaledWidth:1;b=b.height&&b.downScaledHeight?b.height/b.downScaledHeight:1;for(let h of a)h.x=h.x*f+c,h.y=h.y*b+d;return a}_scanFrame(){!this._active||this.$video.paused||this.$video.ended||("requestVideoFrameCallback"in +this.$video?this.$video.requestVideoFrameCallback.bind(this.$video):requestAnimationFrame)(async()=>{if(!(1>=this.$video.readyState)){var a=Date.now()-this._lastScanTimestamp,b=1E3/this._maxScansPerSecond;asetTimeout(d,b-a));this._lastScanTimestamp=Date.now();try{var c=await e.scanImage(this.$video,{scanRegion:this._scanRegion,qrEngine:this._qrEnginePromise,canvas:this.$canvas})}catch(d){if(!this._active)return;this._onDecodeError(d)}!e._disableBarcodeDetector||await this._qrEnginePromise instanceof +Worker||(this._qrEnginePromise=e.createQrEngine());c?(this._onDecode?this._onDecode(c):this._legacyOnDecode&&this._legacyOnDecode(c.data),this.$codeOutlineHighlight&&(clearTimeout(this._codeOutlineHighlightRemovalTimeout),this._codeOutlineHighlightRemovalTimeout=void 0,this.$codeOutlineHighlight.setAttribute("viewBox",`${this._scanRegion.x||0} `+`${this._scanRegion.y||0} `+`${this._scanRegion.width||this.$video.videoWidth} `+`${this._scanRegion.height||this.$video.videoHeight}`),this.$codeOutlineHighlight.firstElementChild.setAttribute("points", +c.cornerPoints.map(({x:d,y:f})=>`${d},${f}`).join(" ")),this.$codeOutlineHighlight.style.display="")):this.$codeOutlineHighlight&&!this._codeOutlineHighlightRemovalTimeout&&(this._codeOutlineHighlightRemovalTimeout=setTimeout(()=>this.$codeOutlineHighlight.style.display="none",100))}this._scanFrame()})}_onDecodeError(a){a!==e.NO_QR_CODE_FOUND&&console.log(a)}async _getCameraStream(){if(!navigator.mediaDevices)throw"Camera not found.";let a=/^(environment|user)$/.test(this._preferredCamera)?"facingMode": +"deviceId",b=[{width:{min:1024}},{width:{min:768}},{}],c=b.map(d=>Object.assign({},d,{[a]:{exact:this._preferredCamera}}));for(let d of[...c,...b])try{let f=await navigator.mediaDevices.getUserMedia({video:d,audio:!1}),h=this._getFacingMode(f)||(d.facingMode?this._preferredCamera:"environment"===this._preferredCamera?"user":"environment");return{stream:f,facingMode:h}}catch(f){}throw"Camera not found.";}async _restartVideoStream(){let a=this._paused;await this.pause(!0)&&!a&&this._active&&await this.start()}static _stopVideoStream(a){for(let b of a.getTracks())b.stop(), +a.removeTrack(b)}_setVideoMirror(a){this.$video.style.transform="scaleX("+("user"===a?-1:1)+")"}_getFacingMode(a){return(a=a.getVideoTracks()[0])?/rear|back|environment/i.test(a.label)?"environment":/front|user|face/i.test(a.label)?"user":null:null}static _drawToCanvas(a,b,c,d=!1){c=c||document.createElement("canvas");let f=b&&b.x?b.x:0,h=b&&b.y?b.y:0,m=b&&b.width?b.width:a.videoWidth||a.width,n=b&&b.height?b.height:a.videoHeight||a.height;d||(d=b&&b.downScaledWidth?b.downScaledWidth:m,b=b&&b.downScaledHeight? +b.downScaledHeight:n,c.width!==d&&(c.width=d),c.height!==b&&(c.height=b));b=c.getContext("2d",{alpha:!1});b.imageSmoothingEnabled=!1;b.drawImage(a,f,h,m,n,0,0,c.width,c.height);return[c,b]}static async _loadImage(a){if(a instanceof Image)return await e._awaitImageLoad(a),a;if(a instanceof HTMLVideoElement||a instanceof HTMLCanvasElement||a instanceof SVGImageElement||"OffscreenCanvas"in window&&a instanceof OffscreenCanvas||"ImageBitmap"in window&&a instanceof ImageBitmap)return a;if(a instanceof +File||a instanceof Blob||a instanceof URL||"string"===typeof a){let b=new Image;b.src=a instanceof File||a instanceof Blob?URL.createObjectURL(a):a.toString();try{return await e._awaitImageLoad(b),b}finally{(a instanceof File||a instanceof Blob)&&URL.revokeObjectURL(b.src)}}else throw"Unsupported image type.";}static async _awaitImageLoad(a){a.complete&&0!==a.naturalWidth||await new Promise((b,c)=>{let d=f=>{a.removeEventListener("load",d);a.removeEventListener("error",d);f instanceof ErrorEvent? +c("Image load error"):b()};a.addEventListener("load",d);a.addEventListener("error",d)})}static async _postWorkerMessage(a,b,c,d){return e._postWorkerMessageSync(await a,b,c,d)}static _postWorkerMessageSync(a,b,c,d){if(!(a instanceof Worker))return-1;let f=e._workerMessageId++;a.postMessage({id:f,type:b,data:c},d);return f}}e.DEFAULT_CANVAS_SIZE=400;e.NO_QR_CODE_FOUND="No QR code found";e._disableBarcodeDetector=!1;e._workerMessageId=0;return e}) +//# sourceMappingURL=qr-scanner.umd.min.js.map diff --git a/res/qr-scanner.umd.min.js.map b/res/qr-scanner.umd.min.js.map new file mode 100644 index 0000000..924569c --- /dev/null +++ b/res/qr-scanner.umd.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"qr-scanner.umd.min.js","sources":["src/qr-scanner.ts"],"sourcesContent":["class QrScanner {\n static readonly DEFAULT_CANVAS_SIZE = 400;\n static readonly NO_QR_CODE_FOUND = 'No QR code found';\n private static _disableBarcodeDetector = false;\n private static _workerMessageId = 0;\n\n /** @deprecated */\n static set WORKER_PATH(workerPath: string) {\n console.warn('Setting QrScanner.WORKER_PATH is not required and not supported anymore. '\n + 'Have a look at the README for new setup instructions.');\n }\n\n static async hasCamera(): Promise {\n try {\n return !!(await QrScanner.listCameras(false)).length;\n } catch (e) {\n return false;\n }\n }\n\n static async listCameras(requestLabels = false): Promise> {\n if (!navigator.mediaDevices) return [];\n\n const enumerateCameras = async (): Promise> =>\n (await navigator.mediaDevices.enumerateDevices()).filter((device) => device.kind === 'videoinput');\n\n // Note that enumerateDevices can always be called and does not prompt the user for permission.\n // However, enumerateDevices only includes device labels if served via https and an active media stream exists\n // or permission to access the camera was given. Therefore, if we're not getting labels but labels are requested\n // ask for camera permission by opening a stream.\n let openedStream: MediaStream | undefined;\n try {\n if (requestLabels && (await enumerateCameras()).every((camera) => !camera.label)) {\n openedStream = await navigator.mediaDevices.getUserMedia({ audio: false, video: true });\n }\n } catch (e) {\n // Fail gracefully, especially if the device has no camera or on mobile when the camera is already in use\n // and some browsers disallow a second stream.\n }\n\n try {\n return (await enumerateCameras()).map((camera, i) => ({\n id: camera.deviceId,\n label: camera.label || (i === 0 ? 'Default Camera' : `Camera ${i + 1}`),\n }));\n } finally {\n // close the stream we just opened for getting camera access for listing the device labels\n if (openedStream) {\n console.warn('Call listCameras after successfully starting a QR scanner to avoid creating '\n + 'a temporary video stream');\n QrScanner._stopVideoStream(openedStream);\n }\n }\n }\n\n readonly $video: HTMLVideoElement;\n readonly $canvas: HTMLCanvasElement;\n readonly $overlay?: HTMLDivElement;\n private readonly $codeOutlineHighlight?: SVGSVGElement;\n private readonly _onDecode?: (result: QrScanner.ScanResult) => void;\n private readonly _legacyOnDecode?: (result: string) => void;\n private readonly _legacyCanvasSize: number = QrScanner.DEFAULT_CANVAS_SIZE;\n private _preferredCamera: QrScanner.FacingMode | QrScanner.DeviceId = 'environment';\n private readonly _maxScansPerSecond: number = 25;\n private _lastScanTimestamp: number = -1;\n private _scanRegion: QrScanner.ScanRegion;\n private _codeOutlineHighlightRemovalTimeout?: number;\n private _qrEnginePromise: Promise\n private _active: boolean = false;\n private _paused: boolean = false;\n private _flashOn: boolean = false;\n private _destroyed: boolean = false;\n\n constructor(\n video: HTMLVideoElement,\n onDecode: (result: QrScanner.ScanResult) => void,\n options: {\n onDecodeError?: (error: Error | string) => void,\n calculateScanRegion?: (video: HTMLVideoElement) => QrScanner.ScanRegion,\n preferredCamera?: QrScanner.FacingMode | QrScanner.DeviceId,\n maxScansPerSecond?: number;\n highlightScanRegion?: boolean,\n highlightCodeOutline?: boolean,\n overlay?: HTMLDivElement,\n /** just a temporary flag until we switch entirely to the new api */\n returnDetailedScanResult?: true,\n },\n );\n /** @deprecated */\n constructor(\n video: HTMLVideoElement,\n onDecode: (result: string) => void,\n onDecodeError?: (error: Error | string) => void,\n calculateScanRegion?: (video: HTMLVideoElement) => QrScanner.ScanRegion,\n preferredCamera?: QrScanner.FacingMode | QrScanner.DeviceId,\n );\n /** @deprecated */\n constructor(\n video: HTMLVideoElement,\n onDecode: (result: string) => void,\n onDecodeError?: (error: Error | string) => void,\n canvasSize?: number,\n preferredCamera?: QrScanner.FacingMode | QrScanner.DeviceId,\n );\n /** @deprecated */\n constructor(video: HTMLVideoElement, onDecode: (result: string) => void, canvasSize?: number);\n constructor(\n video: HTMLVideoElement,\n onDecode: ((result: QrScanner.ScanResult) => void) | ((result: string) => void),\n canvasSizeOrOnDecodeErrorOrOptions?: number | ((error: Error | string) => void) | {\n onDecodeError?: (error: Error | string) => void,\n calculateScanRegion?: (video: HTMLVideoElement) => QrScanner.ScanRegion,\n preferredCamera?: QrScanner.FacingMode | QrScanner.DeviceId,\n maxScansPerSecond?: number;\n highlightScanRegion?: boolean,\n highlightCodeOutline?: boolean,\n overlay?: HTMLDivElement,\n /** just a temporary flag until we switch entirely to the new api */\n returnDetailedScanResult?: true,\n },\n canvasSizeOrCalculateScanRegion?: number | ((video: HTMLVideoElement) => QrScanner.ScanRegion),\n preferredCamera?: QrScanner.FacingMode | QrScanner.DeviceId,\n ) {\n this.$video = video;\n this.$canvas = document.createElement('canvas');\n\n if (canvasSizeOrOnDecodeErrorOrOptions && typeof canvasSizeOrOnDecodeErrorOrOptions === 'object') {\n // we got an options object using the new api\n this._onDecode = onDecode as QrScanner['_onDecode'];\n } else {\n if (canvasSizeOrOnDecodeErrorOrOptions || canvasSizeOrCalculateScanRegion || preferredCamera) {\n console.warn('You\\'re using a deprecated version of the QrScanner constructor which will be removed in '\n + 'the future');\n } else {\n // Only video and onDecode were specified and we can't distinguish between new or old api usage. For\n // backwards compatibility we have to assume the old api for now. The options object is marked as non-\n // optional in the parameter list above to make clear that ScanResult instead of string is only passed\n // if an options object was provided. However, in the future once legacy support is removed, the options\n // object should become optional.\n console.warn('Note that the type of the scan result passed to onDecode will change in the future. '\n + 'To already switch to the new api today, you can pass returnDetailedScanResult: true.');\n }\n this._legacyOnDecode = onDecode as QrScanner['_legacyOnDecode'];\n }\n\n const options = typeof canvasSizeOrOnDecodeErrorOrOptions === 'object'\n ? canvasSizeOrOnDecodeErrorOrOptions\n : {};\n this._onDecodeError = options.onDecodeError || (typeof canvasSizeOrOnDecodeErrorOrOptions === 'function'\n ? canvasSizeOrOnDecodeErrorOrOptions\n : this._onDecodeError);\n this._calculateScanRegion = options.calculateScanRegion || (typeof canvasSizeOrCalculateScanRegion==='function'\n ? canvasSizeOrCalculateScanRegion\n : this._calculateScanRegion);\n this._preferredCamera = options.preferredCamera || preferredCamera || this._preferredCamera;\n this._legacyCanvasSize = typeof canvasSizeOrOnDecodeErrorOrOptions === 'number'\n ? canvasSizeOrOnDecodeErrorOrOptions\n : typeof canvasSizeOrCalculateScanRegion === 'number'\n ? canvasSizeOrCalculateScanRegion\n : this._legacyCanvasSize;\n this._maxScansPerSecond = options.maxScansPerSecond || this._maxScansPerSecond;\n\n this._onPlay = this._onPlay.bind(this);\n this._onLoadedMetaData = this._onLoadedMetaData.bind(this);\n this._onVisibilityChange = this._onVisibilityChange.bind(this);\n this._updateOverlay = this._updateOverlay.bind(this);\n\n // @ts-ignore\n video.disablePictureInPicture = true;\n // Allow inline playback on iPhone instead of requiring full screen playback,\n // see https://webkit.org/blog/6784/new-video-policies-for-ios/\n // @ts-ignore\n video.playsInline = true;\n // Allow play() on iPhone without requiring a user gesture. Should not really be needed as camera stream\n // includes no audio, but just to be safe.\n video.muted = true;\n\n // Avoid Safari stopping the video stream on a hidden video.\n // See https://github.com/cozmo/jsQR/issues/185\n let shouldHideVideo = false;\n if (video.hidden) {\n video.hidden = false;\n shouldHideVideo = true;\n }\n if (!document.body.contains(video)) {\n document.body.appendChild(video);\n shouldHideVideo = true;\n }\n const videoContainer = video.parentElement!;\n\n if (options.highlightScanRegion || options.highlightCodeOutline) {\n const gotExternalOverlay = !!options.overlay;\n this.$overlay = options.overlay || document.createElement('div');\n const overlayStyle = this.$overlay.style;\n overlayStyle.position = 'absolute';\n overlayStyle.display = 'none';\n overlayStyle.pointerEvents = 'none';\n this.$overlay.classList.add('scan-region-highlight');\n if (!gotExternalOverlay && options.highlightScanRegion) {\n // default style; can be overwritten via css, e.g. by changing the svg's stroke color, hiding the\n // .scan-region-highlight-svg, setting a border, outline, background, etc.\n this.$overlay.innerHTML = ''\n + '';\n try {\n this.$overlay.firstElementChild!.animate({ transform: ['scale(.98)', 'scale(1.01)'] }, {\n duration: 400,\n iterations: Infinity,\n direction: 'alternate',\n easing: 'ease-in-out',\n });\n } catch (e) {}\n videoContainer.insertBefore(this.$overlay, this.$video.nextSibling);\n }\n if (options.highlightCodeOutline) {\n // default style; can be overwritten via css\n this.$overlay.insertAdjacentHTML(\n 'beforeend',\n '',\n );\n this.$codeOutlineHighlight = this.$overlay.lastElementChild as SVGSVGElement;\n }\n }\n this._scanRegion = this._calculateScanRegion(video);\n\n requestAnimationFrame(() => {\n // Checking in requestAnimationFrame which should avoid a potential additional re-flow for getComputedStyle.\n const videoStyle = window.getComputedStyle(video);\n if (videoStyle.display === 'none') {\n video.style.setProperty('display', 'block', 'important');\n shouldHideVideo = true;\n }\n if (videoStyle.visibility !== 'visible') {\n video.style.setProperty('visibility', 'visible', 'important');\n shouldHideVideo = true;\n }\n if (shouldHideVideo) {\n // Hide the video in a way that doesn't cause Safari to stop the playback.\n console.warn('QrScanner has overwritten the video hiding style to avoid Safari stopping the playback.');\n video.style.opacity = '0';\n video.style.width = '0';\n video.style.height = '0';\n if (this.$overlay && this.$overlay.parentElement) {\n this.$overlay.parentElement.removeChild(this.$overlay);\n }\n // @ts-ignore\n delete this.$overlay!;\n // @ts-ignore\n delete this.$codeOutlineHighlight!;\n }\n\n if (this.$overlay) {\n this._updateOverlay();\n }\n });\n\n video.addEventListener('play', this._onPlay);\n video.addEventListener('loadedmetadata', this._onLoadedMetaData);\n document.addEventListener('visibilitychange', this._onVisibilityChange);\n window.addEventListener('resize', this._updateOverlay);\n\n this._qrEnginePromise = QrScanner.createQrEngine();\n }\n\n async hasFlash(): Promise {\n let stream: MediaStream | undefined;\n try {\n if (this.$video.srcObject) {\n if (!(this.$video.srcObject instanceof MediaStream)) return false; // srcObject is not a camera stream\n stream = this.$video.srcObject;\n } else {\n stream = (await this._getCameraStream()).stream;\n }\n return 'torch' in stream.getVideoTracks()[0].getSettings();\n } catch (e) {\n return false;\n } finally {\n // close the stream we just opened for detecting whether it supports flash\n if (stream && stream !== this.$video.srcObject) {\n console.warn('Call hasFlash after successfully starting the scanner to avoid creating '\n + 'a temporary video stream');\n QrScanner._stopVideoStream(stream);\n }\n }\n }\n\n isFlashOn(): boolean {\n return this._flashOn;\n }\n\n async toggleFlash(): Promise {\n if (this._flashOn) {\n await this.turnFlashOff();\n } else {\n await this.turnFlashOn();\n }\n }\n\n async turnFlashOn(): Promise {\n if (this._flashOn || this._destroyed) return;\n this._flashOn = true;\n if (!this._active || this._paused) return; // flash will be turned on later on .start()\n try {\n if (!await this.hasFlash()) throw 'No flash available';\n // Note that the video track is guaranteed to exist and to be a MediaStream due to the check in hasFlash\n await (this.$video.srcObject as MediaStream).getVideoTracks()[0].applyConstraints({\n // @ts-ignore: constraint 'torch' is unknown to ts\n advanced: [{ torch: true }],\n });\n } catch (e) {\n this._flashOn = false;\n throw e;\n }\n }\n\n async turnFlashOff(): Promise {\n if (!this._flashOn) return;\n // applyConstraints with torch: false does not work to turn the flashlight off, as a stream's torch stays\n // continuously on, see https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints#torch. Therefore,\n // we have to stop the stream to turn the flashlight off.\n this._flashOn = false;\n await this._restartVideoStream();\n }\n\n destroy(): void {\n this.$video.removeEventListener('loadedmetadata', this._onLoadedMetaData);\n this.$video.removeEventListener('play', this._onPlay);\n document.removeEventListener('visibilitychange', this._onVisibilityChange);\n window.removeEventListener('resize', this._updateOverlay);\n\n this._destroyed = true;\n this._flashOn = false;\n this.stop(); // sets this._paused = true and this._active = false\n QrScanner._postWorkerMessage(this._qrEnginePromise, 'close');\n }\n\n async start(): Promise {\n if (this._destroyed) throw new Error('The QR scanner can not be started as it had been destroyed.');\n if (this._active && !this._paused) return;\n\n if (window.location.protocol !== 'https:') {\n // warn but try starting the camera anyways\n console.warn('The camera stream is only accessible if the page is transferred via https.');\n }\n\n this._active = true;\n if (document.hidden) return; // camera will be started as soon as tab is in foreground\n this._paused = false;\n if (this.$video.srcObject) {\n // camera stream already/still set\n await this.$video.play();\n return;\n }\n\n try {\n const { stream, facingMode } = await this._getCameraStream();\n if (!this._active || this._paused) {\n // was stopped in the meantime\n QrScanner._stopVideoStream(stream);\n return;\n }\n this._setVideoMirror(facingMode);\n this.$video.srcObject = stream;\n await this.$video.play();\n\n // Restart the flash if it was previously on\n if (this._flashOn) {\n this._flashOn = false; // force turnFlashOn to restart the flash\n this.turnFlashOn().catch(() => {});\n }\n } catch (e) {\n if (this._paused) return;\n this._active = false;\n throw e;\n }\n }\n\n stop(): void {\n this.pause();\n this._active = false;\n }\n\n async pause(stopStreamImmediately = false): Promise {\n this._paused = true;\n if (!this._active) return true;\n this.$video.pause();\n\n if (this.$overlay) {\n this.$overlay.style.display = 'none';\n }\n\n const stopStream = () => {\n if (this.$video.srcObject instanceof MediaStream) {\n // revoke srcObject only if it's a stream which was likely set by us\n QrScanner._stopVideoStream(this.$video.srcObject);\n this.$video.srcObject = null;\n }\n };\n\n if (stopStreamImmediately) {\n stopStream();\n return true;\n }\n\n await new Promise((resolve) => setTimeout(resolve, 300));\n if (!this._paused) return false;\n stopStream();\n return true;\n }\n\n async setCamera(facingModeOrDeviceId: QrScanner.FacingMode | QrScanner.DeviceId): Promise {\n if (facingModeOrDeviceId === this._preferredCamera) return;\n this._preferredCamera = facingModeOrDeviceId;\n // Restart the scanner with the new camera which will also update the video mirror and the scan region.\n await this._restartVideoStream();\n }\n\n static async scanImage(\n imageOrFileOrBlobOrUrl: HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | ImageBitmap\n | SVGImageElement | File | Blob | URL | String,\n options: {\n scanRegion?: QrScanner.ScanRegion | null,\n qrEngine?: Worker | BarcodeDetector | Promise | null,\n canvas?: HTMLCanvasElement | null,\n disallowCanvasResizing?: boolean,\n alsoTryWithoutScanRegion?: boolean,\n /** just a temporary flag until we switch entirely to the new api */\n returnDetailedScanResult?: true,\n },\n ): Promise;\n /** @deprecated */\n static async scanImage(\n imageOrFileOrBlobOrUrl: HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | ImageBitmap\n | SVGImageElement | File | Blob | URL | String,\n scanRegion?: QrScanner.ScanRegion | null,\n qrEngine?: Worker | BarcodeDetector | Promise | null,\n canvas?: HTMLCanvasElement | null,\n disallowCanvasResizing?: boolean,\n alsoTryWithoutScanRegion?: boolean,\n ): Promise;\n static async scanImage(\n imageOrFileOrBlobOrUrl: HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | ImageBitmap\n | SVGImageElement | File | Blob | URL | String,\n scanRegionOrOptions?: QrScanner.ScanRegion | {\n scanRegion?: QrScanner.ScanRegion | null,\n qrEngine?: Worker | BarcodeDetector | Promise | null,\n canvas?: HTMLCanvasElement | null,\n disallowCanvasResizing?: boolean,\n alsoTryWithoutScanRegion?: boolean,\n /** just a temporary flag until we switch entirely to the new api */\n returnDetailedScanResult?: true,\n } | null,\n qrEngine?: Worker | BarcodeDetector | Promise | null,\n canvas?: HTMLCanvasElement | null,\n disallowCanvasResizing: boolean = false,\n alsoTryWithoutScanRegion: boolean = false,\n ): Promise {\n let scanRegion: QrScanner.ScanRegion | null | undefined;\n let returnDetailedScanResult = false;\n if (scanRegionOrOptions && (\n 'scanRegion' in scanRegionOrOptions\n || 'qrEngine' in scanRegionOrOptions\n || 'canvas' in scanRegionOrOptions\n || 'disallowCanvasResizing' in scanRegionOrOptions\n || 'alsoTryWithoutScanRegion' in scanRegionOrOptions\n || 'returnDetailedScanResult' in scanRegionOrOptions\n )) {\n // we got an options object using the new api\n scanRegion = scanRegionOrOptions.scanRegion;\n qrEngine = scanRegionOrOptions.qrEngine;\n canvas = scanRegionOrOptions.canvas;\n disallowCanvasResizing = scanRegionOrOptions.disallowCanvasResizing || false;\n alsoTryWithoutScanRegion = scanRegionOrOptions.alsoTryWithoutScanRegion || false;\n returnDetailedScanResult = true;\n } else if (scanRegionOrOptions || qrEngine || canvas || disallowCanvasResizing || alsoTryWithoutScanRegion) {\n console.warn('You\\'re using a deprecated api for scanImage which will be removed in the future.');\n } else {\n // Only imageOrFileOrBlobOrUrl was specified and we can't distinguish between new or old api usage. For\n // backwards compatibility we have to assume the old api for now. The options object is marked as non-\n // optional in the parameter list above to make clear that ScanResult instead of string is only returned if\n // an options object was provided. However, in the future once legacy support is removed, the options object\n // should become optional.\n console.warn('Note that the return type of scanImage will change in the future. To already switch to the '\n + 'new api today, you can pass returnDetailedScanResult: true.');\n }\n\n const gotExternalEngine = !!qrEngine;\n\n try {\n let image: HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | ImageBitmap\n | SVGImageElement;\n let canvasContext: CanvasRenderingContext2D;\n [qrEngine, image] = await Promise.all([\n qrEngine || QrScanner.createQrEngine(),\n QrScanner._loadImage(imageOrFileOrBlobOrUrl),\n ]);\n [canvas, canvasContext] = QrScanner._drawToCanvas(image, scanRegion, canvas, disallowCanvasResizing);\n let detailedScanResult: QrScanner.ScanResult;\n\n if (qrEngine instanceof Worker) {\n const qrEngineWorker = qrEngine; // for ts to know that it's still a worker later in the event listeners\n if (!gotExternalEngine) {\n // Enable scanning of inverted color qr codes.\n QrScanner._postWorkerMessageSync(qrEngineWorker, 'inversionMode', 'both');\n }\n detailedScanResult = await new Promise((resolve, reject) => {\n let timeout: number;\n let onMessage: (event: MessageEvent) => void;\n let onError: (error: ErrorEvent | string) => void;\n let expectedResponseId = -1;\n onMessage = (event: MessageEvent) => {\n if (event.data.id !== expectedResponseId) {\n return;\n }\n qrEngineWorker.removeEventListener('message', onMessage);\n qrEngineWorker.removeEventListener('error', onError);\n clearTimeout(timeout);\n if (event.data.data !== null) {\n resolve({\n data: event.data.data,\n cornerPoints: QrScanner._convertPoints(event.data.cornerPoints, scanRegion),\n });\n } else {\n reject(QrScanner.NO_QR_CODE_FOUND);\n }\n };\n onError = (error: ErrorEvent | string) => {\n qrEngineWorker.removeEventListener('message', onMessage);\n qrEngineWorker.removeEventListener('error', onError);\n clearTimeout(timeout);\n const errorMessage = !error ? 'Unknown Error' : ((error as ErrorEvent).message || error);\n reject('Scanner error: ' + errorMessage);\n };\n qrEngineWorker.addEventListener('message', onMessage);\n qrEngineWorker.addEventListener('error', onError);\n timeout = setTimeout(() => onError('timeout'), 10000);\n const imageData = canvasContext.getImageData(0, 0, canvas!.width, canvas!.height);\n expectedResponseId = QrScanner._postWorkerMessageSync(\n qrEngineWorker,\n 'decode',\n imageData,\n [imageData.data.buffer],\n );\n });\n } else {\n detailedScanResult = await Promise.race([\n new Promise((resolve, reject) => window.setTimeout(\n () => reject('Scanner error: timeout'),\n 10000,\n )),\n (async (): Promise => {\n try {\n const [scanResult] = await qrEngine.detect(canvas!);\n if (!scanResult) throw QrScanner.NO_QR_CODE_FOUND;\n return {\n data: scanResult.rawValue,\n cornerPoints: QrScanner._convertPoints(scanResult.cornerPoints, scanRegion),\n };\n } catch (e) {\n const errorMessage = (e as Error).message || e as string;\n if (/not implemented|service unavailable/.test(errorMessage)) {\n // Not implemented can apparently for some reason happen even though getSupportedFormats\n // in createQrScanner reported that it's supported, see issue #98.\n // Service unavailable can happen after some time when the BarcodeDetector crashed and\n // can theoretically be recovered from by creating a new BarcodeDetector. However, in\n // newer browsers this issue does not seem to be present anymore and therefore we do not\n // apply this optimization anymore but just set _disableBarcodeDetector in both cases.\n // Also note that if we got an external qrEngine that crashed, we should possibly notify\n // the caller about it, but we also don't do this here, as it's such an unlikely case.\n QrScanner._disableBarcodeDetector = true;\n // retry without passing the broken BarcodeScanner instance\n return QrScanner.scanImage(imageOrFileOrBlobOrUrl, {\n scanRegion,\n canvas,\n disallowCanvasResizing,\n alsoTryWithoutScanRegion,\n });\n }\n throw `Scanner error: ${errorMessage}`;\n }\n })(),\n ]);\n }\n return returnDetailedScanResult ? detailedScanResult : detailedScanResult.data;\n } catch (e) {\n if (!scanRegion || !alsoTryWithoutScanRegion) throw e;\n const detailedScanResult = await QrScanner.scanImage(\n imageOrFileOrBlobOrUrl,\n { qrEngine, canvas, disallowCanvasResizing },\n );\n return returnDetailedScanResult ? detailedScanResult : detailedScanResult.data;\n } finally {\n if (!gotExternalEngine) {\n QrScanner._postWorkerMessage(qrEngine!, 'close');\n }\n }\n }\n\n setGrayscaleWeights(red: number, green: number, blue: number, useIntegerApproximation: boolean = true): void {\n // Note that for the native BarcodeDecoder or if the worker was destroyed, this is a no-op. However, the native\n // implementations work also well with colored qr codes.\n QrScanner._postWorkerMessage(\n this._qrEnginePromise,\n 'grayscaleWeights',\n { red, green, blue, useIntegerApproximation }\n );\n }\n\n setInversionMode(inversionMode: QrScanner.InversionMode): void {\n // Note that for the native BarcodeDecoder or if the worker was destroyed, this is a no-op. However, the native\n // implementations scan normal and inverted qr codes by default\n QrScanner._postWorkerMessage(this._qrEnginePromise, 'inversionMode', inversionMode);\n }\n\n static async createQrEngine(): Promise;\n /** @deprecated */\n static async createQrEngine(workerPath: string): Promise;\n static async createQrEngine(workerPath?: string): Promise {\n if (workerPath) {\n console.warn('Specifying a worker path is not required and not supported anymore.');\n }\n\n // @ts-ignore no types defined for import\n const createWorker = () => (import('./qr-scanner-worker.min.js') as Promise<{ createWorker: () => Worker }>)\n .then((module) => module.createWorker());\n\n const useBarcodeDetector = !QrScanner._disableBarcodeDetector\n && 'BarcodeDetector' in window\n && BarcodeDetector.getSupportedFormats\n && (await BarcodeDetector.getSupportedFormats()).includes('qr_code');\n\n if (!useBarcodeDetector) return createWorker();\n\n // On Macs with an M1/M2 processor and macOS Ventura (macOS version 13), the BarcodeDetector is broken in\n // Chromium based browsers, regardless of the version. For that constellation, the BarcodeDetector does not\n // error but does not detect QR codes. Macs without an M1/M2 or before Ventura are fine.\n // See issue #209 and https://bugs.chromium.org/p/chromium/issues/detail?id=1382442\n // TODO update this once the issue in macOS is fixed\n const userAgentData = navigator.userAgentData;\n const isChromiumOnMacWithArmVentura = userAgentData // all Chromium browsers support userAgentData\n && userAgentData.brands.some(({ brand }) => /Chromium/i.test(brand))\n && /mac ?OS/i.test(userAgentData.platform)\n // Does it have an ARM chip (e.g. M1/M2) and Ventura? Check this last as getHighEntropyValues can\n // theoretically trigger a browser prompt, although no browser currently does seem to show one.\n // If browser or user refused to return the requested values, assume broken ARM Ventura, to be safe.\n && await userAgentData.getHighEntropyValues(['architecture', 'platformVersion'])\n .then(({ architecture, platformVersion }) =>\n /arm/i.test(architecture || 'arm') && parseInt(platformVersion || '13') >= /* Ventura */ 13)\n .catch(() => true);\n if (isChromiumOnMacWithArmVentura) return createWorker();\n\n return new BarcodeDetector({ formats: ['qr_code'] });\n }\n\n private _onPlay(): void {\n this._scanRegion = this._calculateScanRegion(this.$video);\n this._updateOverlay();\n if (this.$overlay) {\n this.$overlay.style.display = '';\n }\n this._scanFrame();\n }\n\n private _onLoadedMetaData(): void {\n this._scanRegion = this._calculateScanRegion(this.$video);\n this._updateOverlay();\n }\n\n private _onVisibilityChange(): void {\n if (document.hidden) {\n this.pause();\n } else if (this._active) {\n this.start();\n }\n }\n\n private _calculateScanRegion(video: HTMLVideoElement): QrScanner.ScanRegion {\n // Default scan region calculation. Note that this can be overwritten in the constructor.\n const smallestDimension = Math.min(video.videoWidth, video.videoHeight);\n const scanRegionSize = Math.round(2 / 3 * smallestDimension);\n return {\n x: Math.round((video.videoWidth - scanRegionSize) / 2),\n y: Math.round((video.videoHeight - scanRegionSize) / 2),\n width: scanRegionSize,\n height: scanRegionSize,\n downScaledWidth: this._legacyCanvasSize,\n downScaledHeight: this._legacyCanvasSize,\n };\n }\n\n private _updateOverlay(): void {\n requestAnimationFrame(() => {\n // Running in requestAnimationFrame which should avoid a potential additional re-flow for getComputedStyle\n // and offsetWidth, offsetHeight, offsetLeft, offsetTop.\n if (!this.$overlay) return;\n const video = this.$video;\n const videoWidth = video.videoWidth;\n const videoHeight = video.videoHeight;\n const elementWidth = video.offsetWidth;\n const elementHeight = video.offsetHeight;\n const elementX = video.offsetLeft;\n const elementY = video.offsetTop;\n\n const videoStyle = window.getComputedStyle(video);\n const videoObjectFit = videoStyle.objectFit;\n const videoAspectRatio = videoWidth / videoHeight;\n const elementAspectRatio = elementWidth / elementHeight;\n let videoScaledWidth: number;\n let videoScaledHeight: number;\n switch (videoObjectFit) {\n case 'none':\n videoScaledWidth = videoWidth;\n videoScaledHeight = videoHeight;\n break;\n case 'fill':\n videoScaledWidth = elementWidth;\n videoScaledHeight = elementHeight;\n break;\n default: // 'cover', 'contains', 'scale-down'\n if (videoObjectFit === 'cover'\n ? videoAspectRatio > elementAspectRatio\n : videoAspectRatio < elementAspectRatio) {\n // The scaled height is the element height\n // - for 'cover' if the video aspect ratio is wider than the element aspect ratio\n // (scaled height matches element height and scaled width overflows element width)\n // - for 'contains'/'scale-down' if element aspect ratio is wider than the video aspect ratio\n // (scaled height matched element height and element width overflows scaled width)\n videoScaledHeight = elementHeight;\n videoScaledWidth = videoScaledHeight * videoAspectRatio;\n } else {\n videoScaledWidth = elementWidth;\n videoScaledHeight = videoScaledWidth / videoAspectRatio;\n }\n if (videoObjectFit === 'scale-down') {\n // for 'scale-down' the dimensions are the minimum of 'contains' and 'none'\n videoScaledWidth = Math.min(videoScaledWidth, videoWidth);\n videoScaledHeight = Math.min(videoScaledHeight, videoHeight);\n }\n }\n\n // getComputedStyle is so nice to convert keywords (left, center, right, top, bottom) to percent and makes\n // sure to set the default of 50% if only one or no component was provided, therefore we can be sure that\n // both components are set. Additionally, it converts units other than px (e.g. rem) to px.\n const [videoX, videoY] = videoStyle.objectPosition.split(' ').map((length, i) => {\n const lengthValue = parseFloat(length);\n return length.endsWith('%')\n ? (!i ? elementWidth - videoScaledWidth : elementHeight - videoScaledHeight) * lengthValue / 100\n : lengthValue;\n });\n\n const regionWidth = this._scanRegion.width || videoWidth;\n const regionHeight = this._scanRegion.height || videoHeight;\n const regionX = this._scanRegion.x || 0;\n const regionY = this._scanRegion.y || 0;\n\n const overlayStyle = this.$overlay.style;\n overlayStyle.width = `${regionWidth / videoWidth * videoScaledWidth}px`;\n overlayStyle.height = `${regionHeight / videoHeight * videoScaledHeight}px`;\n overlayStyle.top = `${elementY + videoY + regionY / videoHeight * videoScaledHeight}px`;\n const isVideoMirrored = /scaleX\\(-1\\)/.test(video.style.transform!);\n overlayStyle.left = `${elementX\n + (isVideoMirrored ? elementWidth - videoX - videoScaledWidth : videoX)\n + (isVideoMirrored ? videoWidth - regionX - regionWidth : regionX) / videoWidth * videoScaledWidth}px`;\n // apply same mirror as on video\n overlayStyle.transform = video.style.transform;\n });\n }\n\n private static _convertPoints(\n points: QrScanner.Point[],\n scanRegion?: QrScanner.ScanRegion | null,\n ): QrScanner.Point[] {\n if (!scanRegion) return points;\n const offsetX = scanRegion.x || 0;\n const offsetY = scanRegion.y || 0;\n const scaleFactorX = scanRegion.width && scanRegion.downScaledWidth\n ? scanRegion.width / scanRegion.downScaledWidth\n : 1;\n const scaleFactorY = scanRegion.height && scanRegion.downScaledHeight\n ? scanRegion.height / scanRegion.downScaledHeight\n : 1;\n for (const point of points) {\n point.x = point.x * scaleFactorX + offsetX;\n point.y = point.y * scaleFactorY + offsetY;\n }\n return points;\n }\n\n private _scanFrame(): void {\n if (!this._active || this.$video.paused || this.$video.ended) return;\n // If requestVideoFrameCallback is available use that to avoid unnecessary scans on the same frame as the\n // camera's framerate can be lower than the screen refresh rate and this._maxScansPerSecond, especially in dark\n // settings where the exposure time is longer. Both, requestVideoFrameCallback and requestAnimationFrame are not\n // being fired if the tab is in the background, which is what we want.\n const requestFrame = 'requestVideoFrameCallback' in this.$video\n // @ts-ignore\n ? this.$video.requestVideoFrameCallback.bind(this.$video)\n : requestAnimationFrame;\n requestFrame(async () => {\n if (this.$video.readyState <= 1) {\n // Skip scans until the video is ready as drawImage() only works correctly on a video with readyState\n // > 1, see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage#Notes.\n // This also avoids false positives for videos paused after a successful scan which remains visible on\n // the canvas until the video is started again and ready.\n this._scanFrame();\n return;\n }\n\n const timeSinceLastScan = Date.now() - this._lastScanTimestamp;\n const minimumTimeBetweenScans = 1000 / this._maxScansPerSecond;\n if (timeSinceLastScan < minimumTimeBetweenScans) {\n await new Promise((resolve) => setTimeout(resolve, minimumTimeBetweenScans - timeSinceLastScan));\n }\n // console.log('Scan rate:', Math.round(1000 / (Date.now() - this._lastScanTimestamp)));\n this._lastScanTimestamp = Date.now();\n\n let result: QrScanner.ScanResult | undefined;\n try {\n result = await QrScanner.scanImage(this.$video, {\n scanRegion: this._scanRegion,\n qrEngine: this._qrEnginePromise,\n canvas: this.$canvas,\n });\n } catch (error) {\n if (!this._active) return;\n this._onDecodeError(error as Error | string);\n }\n\n if (QrScanner._disableBarcodeDetector && !(await this._qrEnginePromise instanceof Worker)) {\n // replace the disabled BarcodeDetector\n this._qrEnginePromise = QrScanner.createQrEngine();\n }\n\n if (result) {\n if (this._onDecode) {\n this._onDecode(result);\n } else if (this._legacyOnDecode) {\n this._legacyOnDecode(result.data);\n }\n\n if (this.$codeOutlineHighlight) {\n clearTimeout(this._codeOutlineHighlightRemovalTimeout);\n this._codeOutlineHighlightRemovalTimeout = undefined;\n this.$codeOutlineHighlight.setAttribute(\n 'viewBox',\n `${this._scanRegion.x || 0} `\n + `${this._scanRegion.y || 0} `\n + `${this._scanRegion.width || this.$video.videoWidth} `\n + `${this._scanRegion.height || this.$video.videoHeight}`,\n );\n const polygon = this.$codeOutlineHighlight.firstElementChild!;\n polygon.setAttribute('points', result.cornerPoints.map(({x, y}) => `${x},${y}`).join(' '));\n this.$codeOutlineHighlight.style.display = '';\n }\n } else if (this.$codeOutlineHighlight && !this._codeOutlineHighlightRemovalTimeout) {\n // hide after timeout to make it flash less when on some frames the QR code is detected and on some not\n this._codeOutlineHighlightRemovalTimeout = setTimeout(\n () => this.$codeOutlineHighlight!.style.display = 'none',\n 100,\n );\n }\n\n this._scanFrame();\n });\n }\n\n private _onDecodeError(error: Error | string): void {\n // default error handler; can be overwritten in the constructor\n if (error === QrScanner.NO_QR_CODE_FOUND) return;\n console.log(error);\n }\n\n private async _getCameraStream(): Promise<{ stream: MediaStream, facingMode: QrScanner.FacingMode }> {\n if (!navigator.mediaDevices) throw 'Camera not found.';\n\n const preferenceType = /^(environment|user)$/.test(this._preferredCamera)\n ? 'facingMode'\n : 'deviceId';\n const constraintsWithoutCamera: Array = [{\n width: { min: 1024 }\n }, {\n width: { min: 768 }\n }, {}];\n const constraintsWithCamera = constraintsWithoutCamera.map((constraint) => Object.assign({}, constraint, {\n [preferenceType]: { exact: this._preferredCamera },\n }));\n\n for (const constraints of [...constraintsWithCamera, ...constraintsWithoutCamera]) {\n try {\n const stream = await navigator.mediaDevices.getUserMedia({ video: constraints, audio: false });\n // Try to determine the facing mode from the stream, otherwise use a guess or 'environment' as\n // default. Note that the guess is not always accurate as Safari returns cameras of different facing\n // mode, even for exact facingMode constraints.\n const facingMode = this._getFacingMode(stream)\n || (constraints.facingMode\n ? this._preferredCamera as QrScanner.FacingMode // a facing mode we were able to fulfill\n : (this._preferredCamera === 'environment'\n ? 'user' // switch as _preferredCamera was environment but we are not able to fulfill it\n : 'environment' // switch from unfulfilled user facingMode or default to environment\n )\n );\n return { stream, facingMode };\n } catch (e) {}\n }\n\n throw 'Camera not found.';\n }\n\n private async _restartVideoStream(): Promise {\n // Note that we always pause the stream and not only if !this._paused as even if this._paused === true, the\n // stream might still be running, as it's by default only stopped after a delay of 300ms.\n const wasPaused = this._paused;\n const paused = await this.pause(true);\n if (!paused || wasPaused || !this._active) return;\n await this.start();\n }\n\n private static _stopVideoStream(stream : MediaStream): void {\n for (const track of stream.getTracks()) {\n track.stop(); // note that this will also automatically turn the flashlight off\n stream.removeTrack(track);\n }\n }\n\n private _setVideoMirror(facingMode: QrScanner.FacingMode): void {\n // in user facing mode mirror the video to make it easier for the user to position the QR code\n const scaleFactor = facingMode === 'user'? -1 : 1;\n this.$video.style.transform = 'scaleX(' + scaleFactor + ')';\n }\n\n private _getFacingMode(videoStream: MediaStream): QrScanner.FacingMode | null {\n const videoTrack = videoStream.getVideoTracks()[0];\n if (!videoTrack) return null; // unknown\n // inspired by https://github.com/JodusNodus/react-qr-reader/blob/master/src/getDeviceId.js#L13\n return /rear|back|environment/i.test(videoTrack.label)\n ? 'environment'\n : /front|user|face/i.test(videoTrack.label)\n ? 'user'\n : null; // unknown\n }\n\n private static _drawToCanvas(\n image: HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | ImageBitmap\n | SVGImageElement,\n scanRegion?: QrScanner.ScanRegion | null,\n canvas?: HTMLCanvasElement | null,\n disallowCanvasResizing= false,\n ): [HTMLCanvasElement, CanvasRenderingContext2D] {\n canvas = canvas || document.createElement('canvas');\n const scanRegionX = scanRegion && scanRegion.x ? scanRegion.x : 0;\n const scanRegionY = scanRegion && scanRegion.y ? scanRegion.y : 0;\n const scanRegionWidth = scanRegion && scanRegion.width\n ? scanRegion.width\n : (image as HTMLVideoElement).videoWidth || image.width as number;\n const scanRegionHeight = scanRegion && scanRegion.height\n ? scanRegion.height\n : (image as HTMLVideoElement).videoHeight || image.height as number;\n\n if (!disallowCanvasResizing) {\n const canvasWidth = scanRegion && scanRegion.downScaledWidth\n ? scanRegion.downScaledWidth\n : scanRegionWidth;\n const canvasHeight = scanRegion && scanRegion.downScaledHeight\n ? scanRegion.downScaledHeight\n : scanRegionHeight;\n // Setting the canvas width or height clears the canvas, even if the values didn't change, therefore only\n // set them if they actually changed.\n if (canvas.width !== canvasWidth) {\n canvas.width = canvasWidth;\n }\n if (canvas.height !== canvasHeight) {\n canvas.height = canvasHeight;\n }\n }\n\n const context = canvas.getContext('2d', { alpha: false })!;\n context.imageSmoothingEnabled = false; // gives less blurry images\n context.drawImage(\n image,\n scanRegionX, scanRegionY, scanRegionWidth, scanRegionHeight,\n 0, 0, canvas.width, canvas.height,\n );\n return [canvas, context];\n }\n\n private static async _loadImage(\n imageOrFileOrBlobOrUrl: HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | ImageBitmap\n | SVGImageElement | File | Blob | URL | String,\n ): Promise {\n if (imageOrFileOrBlobOrUrl instanceof Image) {\n await QrScanner._awaitImageLoad(imageOrFileOrBlobOrUrl);\n return imageOrFileOrBlobOrUrl;\n } else if (imageOrFileOrBlobOrUrl instanceof HTMLVideoElement\n || imageOrFileOrBlobOrUrl instanceof HTMLCanvasElement\n || imageOrFileOrBlobOrUrl instanceof SVGImageElement\n || 'OffscreenCanvas' in window && imageOrFileOrBlobOrUrl instanceof OffscreenCanvas\n || 'ImageBitmap' in window && imageOrFileOrBlobOrUrl instanceof ImageBitmap) {\n return imageOrFileOrBlobOrUrl;\n } else if (imageOrFileOrBlobOrUrl instanceof File || imageOrFileOrBlobOrUrl instanceof Blob\n || imageOrFileOrBlobOrUrl instanceof URL || typeof imageOrFileOrBlobOrUrl === 'string') {\n const image = new Image();\n if (imageOrFileOrBlobOrUrl instanceof File || imageOrFileOrBlobOrUrl instanceof Blob) {\n image.src = URL.createObjectURL(imageOrFileOrBlobOrUrl);\n } else {\n image.src = imageOrFileOrBlobOrUrl.toString();\n }\n try {\n await QrScanner._awaitImageLoad(image);\n return image;\n } finally {\n if (imageOrFileOrBlobOrUrl instanceof File || imageOrFileOrBlobOrUrl instanceof Blob) {\n URL.revokeObjectURL(image.src);\n }\n }\n } else {\n throw 'Unsupported image type.';\n }\n }\n\n private static async _awaitImageLoad(image: HTMLImageElement): Promise {\n if (image.complete && image.naturalWidth !== 0) return; // already loaded\n await new Promise((resolve, reject) => {\n const listener = (event: ErrorEvent | Event) => {\n image.removeEventListener('load', listener);\n image.removeEventListener('error', listener);\n if (event instanceof ErrorEvent) {\n reject('Image load error');\n } else {\n resolve();\n }\n };\n image.addEventListener('load', listener);\n image.addEventListener('error', listener);\n });\n }\n\n private static async _postWorkerMessage(\n qrEngineOrQrEnginePromise: Worker | BarcodeDetector | Promise,\n type: string,\n data?: any,\n transfer?: Transferable[],\n ): Promise {\n return QrScanner._postWorkerMessageSync(await qrEngineOrQrEnginePromise, type, data, transfer);\n }\n\n // sync version of _postWorkerMessage without performance overhead of async functions\n private static _postWorkerMessageSync(\n qrEngine: Worker | BarcodeDetector,\n type: string,\n data?: any,\n transfer?: Transferable[],\n ): number {\n if (!(qrEngine instanceof Worker)) return -1;\n const id = QrScanner._workerMessageId++;\n qrEngine.postMessage({\n id,\n type,\n data,\n }, transfer);\n return id;\n }\n}\n\ndeclare namespace QrScanner {\n export interface ScanRegion {\n x?: number;\n y?: number;\n width?: number;\n height?: number;\n downScaledWidth?: number;\n downScaledHeight?: number;\n }\n\n export type FacingMode = 'environment' | 'user';\n export type DeviceId = string;\n\n export interface Camera {\n id: DeviceId;\n label: string;\n }\n\n export type InversionMode = 'original' | 'invert' | 'both';\n\n export interface Point {\n x: number;\n y: number;\n }\n\n export interface ScanResult {\n data: string;\n // In clockwise order, starting at top left, but this might not be guaranteed in the future.\n cornerPoints: QrScanner.Point[];\n }\n}\n\n// simplified from https://wicg.github.io/shape-detection-api/#barcode-detection-api\ndeclare class BarcodeDetector {\n constructor(options?: { formats: string[] });\n static getSupportedFormats(): Promise;\n detect(image: ImageBitmapSource): Promise>;\n}\n\n// simplified from https://github.com/lukewarlow/user-agent-data-types/blob/master/index.d.ts\ndeclare global {\n interface Navigator {\n readonly userAgentData?: {\n readonly platform: string;\n readonly brands: Array<{\n readonly brand: string;\n readonly version: string;\n }>;\n getHighEntropyValues(hints: string[]): Promise<{\n readonly architecture?: string;\n readonly platformVersion?: string;\n }>;\n };\n }\n}\n\nexport default QrScanner;\n"],"names":["QrScanner","constructor","video","onDecode","canvasSizeOrOnDecodeErrorOrOptions","canvasSizeOrCalculateScanRegion","preferredCamera","DEFAULT_CANVAS_SIZE","$video","$canvas","document","createElement","_onDecode","console","warn","_legacyOnDecode","_onDecodeError","options","onDecodeError","_calculateScanRegion","calculateScanRegion","_preferredCamera","_legacyCanvasSize","_maxScansPerSecond","maxScansPerSecond","_onPlay","bind","_onLoadedMetaData","_onVisibilityChange","_updateOverlay","disablePictureInPicture","playsInline","muted","shouldHideVideo","hidden","body","contains","appendChild","highlightScanRegion","highlightCodeOutline","$overlay","overlay","overlayStyle","position","display","pointerEvents","classList","add","gotExternalOverlay","innerHTML","firstElementChild","animate","transform","duration","iterations","Infinity","direction","easing","e","videoContainer","insertBefore","nextSibling","insertAdjacentHTML","$codeOutlineHighlight","lastElementChild","_scanRegion","requestAnimationFrame","videoStyle","style","setProperty","visibility","opacity","width","height","parentElement","removeChild","addEventListener","window","_qrEnginePromise","createQrEngine","workerPath","hasCamera","length","listCameras","requestLabels","navigator","mediaDevices","filter","device","openedStream","every","enumerateCameras","camera","label","getUserMedia","audio","map","i","id","deviceId","_stopVideoStream","hasFlash","stream","srcObject","MediaStream","_getCameraStream","getVideoTracks","getSettings","isFlashOn","_flashOn","toggleFlash","turnFlashOff","turnFlashOn","_destroyed","_active","_paused","applyConstraints","advanced","torch","_restartVideoStream","destroy","removeEventListener","stop","_postWorkerMessage","start","Error","location","protocol","play","facingMode","_setVideoMirror","catch","pause","stopStreamImmediately","stopStream","Promise","resolve","setTimeout","setCamera","facingModeOrDeviceId","scanImage","imageOrFileOrBlobOrUrl","scanRegionOrOptions","qrEngine","canvas","disallowCanvasResizing","alsoTryWithoutScanRegion","scanRegion","returnDetailedScanResult","image","canvasContext","all","_loadImage","_drawToCanvas","detailedScanResult","Worker","gotExternalEngine","_postWorkerMessageSync","qrEngineWorker","reject","timeout","onMessage","onError","expectedResponseId","event","data","clearTimeout","cornerPoints","_convertPoints","NO_QR_CODE_FOUND","error","imageData","buffer","race","scanResult","rawValue","message","test","errorMessage","_disableBarcodeDetector","setGrayscaleWeights","red","green","blue","useIntegerApproximation","setInversionMode","inversionMode","then","module","createWorker","BarcodeDetector","getSupportedFormats","includes","userAgentData","brands","some","brand","platform","getHighEntropyValues","architecture","platformVersion","parseInt","formats","_scanFrame","x","Math","round","videoWidth","scanRegionSize","y","videoHeight","downScaledWidth","downScaledHeight","videoObjectFit","videoScaledWidth","videoScaledHeight","elementWidth","elementHeight","videoAspectRatio","elementAspectRatio","min","videoY","lengthValue","parseFloat","endsWith","regionWidth","regionHeight","top","elementY","regionY","left","elementX","isVideoMirrored","videoX","regionX","points","point","scaleFactorX","offsetX","scaleFactorY","offsetY","paused","ended","requestVideoFrameCallback","readyState","timeSinceLastScan","minimumTimeBetweenScans","_lastScanTimestamp","Date","now","result","_codeOutlineHighlightRemovalTimeout","undefined","setAttribute","join","log","constraint","preferenceType","exact","constraints","wasPaused","track","removeTrack","_getFacingMode","videoStream","videoTrack","scanRegionWidth","scanRegionHeight","canvasWidth","canvasHeight","alpha","context","imageSmoothingEnabled","drawImage","scanRegionX","scanRegionY","Image","_awaitImageLoad","HTMLVideoElement","HTMLCanvasElement","SVGImageElement","OffscreenCanvas","ImageBitmap","File","Blob","URL","src","createObjectURL","toString","revokeObjectURL","complete","naturalWidth","listener","ErrorEvent","qrEngineOrQrEnginePromise","type","transfer","postMessage"],"mappings":"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"} \ No newline at end of file diff --git a/res/template.js b/res/template.js new file mode 100755 index 0000000..f17a2d1 --- /dev/null +++ b/res/template.js @@ -0,0 +1,271 @@ +class TemplateEngine +{ + constructor(tpl, adminData) { + this.tpl = tpl; + this.adminData = adminData; + this.modeFallback = { + ":EDIT": ":ADMIN", + ":ADMIN": "", + "": null + }; + } + + Render(content, marker, mode = "") { + return this.render(marker, content, this.extractSection(this.tpl, marker, mode), mode); + } + + render(sections, content, tpl, mode = "") { + // content has to be an object of `marker` => `data` + // data can be a primitive, an array, or an object + // Boolean corresponds to a conditional section, call replaceCondition + // String and number correspond to a simple marker, call replaceMarker for it + // Array and object always correspond to a section + // Object can be handed recursively to a new instance of render. Be sure to extract the correct section of tpl though + // If data is an array, iterate over it and hand every entry to a new instance like with object. Concatenate the results + if (typeof(content)!="object" || tpl=="") + return ""; + var ret = tpl; + for (var marker in content) { + var sectionMarker = (sections!="" ? sections+"."+marker : marker); + var type = typeof(content[marker]); + + if (mode==":EDIT" && sections.indexOf("MAIN")!=-1 && typeof(this.adminData[marker])!="undefined") { + var data = this.adminData[marker]; + var admin_tpl = this.extractSection(ret, sectionMarker, mode); + var admin_ret = ""; + for (var i in data) { + if (content[marker]==null) { + data[i].SELECTED = data[i].ID=="__NULL__"; + } else if (Array.isArray(content[marker])) { + var selected = false; + for (var j in content[marker]) { + if (data[i].ID==content[marker][j].ID) { + selected = true; + } + } + data[i].SELECTED = selected; + } else { + data[i].SELECTED = data[i].ID==content[marker].ID; + } + + admin_ret+= this.render(sectionMarker, data[i], admin_tpl, ""); + } + ret = this.replaceSection(ret, sectionMarker, admin_ret, ""); + } else { + if (content[marker]==null) { + ret = this.replaceSection(ret, sectionMarker, "", mode); + ret = this.replaceMarker(ret, sectionMarker, "__NULL__", mode); + } if (type=="boolean") { + ret = this.replaceCondition(ret, sectionMarker, content[marker], mode); + } else if (type=="string" && "__CASE__:"==content[marker].substr(0, 9)) { + ret = this.replaceSwitch(ret, sectionMarker, content[marker].split(":"), mode); + } else if (type=="string" || type=="number") { + ret = this.replaceMarker(ret, sectionMarker, content[marker], mode); + } else if (type=="object" && Array.isArray(content[marker])) { + var arr_tpl = this.extractSection(ret, sectionMarker, mode); + var arr_ret = ""; + for (var ind in content[marker]) { + arr_ret+= this.render(sectionMarker, content[marker][ind], arr_tpl, mode); + } + ret = this.replaceSection(ret, sectionMarker, arr_ret, mode); + } else if (type=="object") { // Hopefully a JSON + ret = this.replaceSection(ret, sectionMarker, this.render(sectionMarker, content[marker], this.extractSection(ret, sectionMarker, mode), mode), mode); + } + } + } + return ret; + } + + makeMarker(marker) { + return "###" + marker + "###"; + } + + makeSectionMarker(marker, pos) { //creates START or END marker of section + return ""; + } + + findMarkerModes(tpl, section) { + var ret = []; + var sectionMarker = this.makeMarker(section+":"); + var markerLength = 5 + sectionMarker.length - 3; // 5 = " + // True text + // + // False text + // + var modeTpl = this.findAndDeleteUnneededModes(tpl, section, mode); + + var sectionMarker = this.makeMarker(section + modeTpl.mode); + var ifMarker = this.makeSectionMarker(sectionMarker, "IF"); + var elseMarker = this.makeSectionMarker(sectionMarker, "ELSE"); + var endMarker = this.makeSectionMarker(sectionMarker, "END"); + + var startPos = modeTpl.tpl.indexOf(ifMarker); + var else_startPos = modeTpl.tpl.indexOf(elseMarker); + var else_endPos = else_startPos + elseMarker.length; + var endPos = modeTpl.tpl.lastIndexOf(endMarker) + endMarker.length; + + if ((startPos==-1) || (else_startPos==-1) || (endPos==-1) || (endPos<=startPos)) { + if (bool) { + return modeTpl.tpl; + } else { + return this.replaceSection(modeTpl.tpl, section, "", modeTpl.mode); + } + } + + var value = ""; + if (bool) { + // Show if-part + value = modeTpl.tpl.substr(startPos, else_startPos - startPos); + } else { + // Show else-part + value = modeTpl.tpl.substr(else_endPos, endPos - else_endPos - endMarker.length); + } + + var ret = (startPos>0 ? modeTpl.tpl.substr(0, startPos) : ""); + ret+= value; + if (endPos + // Default text + // + // Text A + // + // Text B + // + var modeTpl = this.findAndDeleteUnneededModes(tpl, section, mode); + var sectionMarker = this.makeMarker(section + modeTpl.mode); + + var switchMarker = this.makeSectionMarker(sectionMarker, "SWITCH"); + var endMarker = this.makeSectionMarker(sectionMarker, "END"); + var anyMarker = this.makeSectionMarker(sectionMarker, "").substr(0, 5 + sectionMarker.length); // 5 = "