diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml index 42cebf1..90f454f 100644 --- a/.gitea/workflows/build.yml +++ b/.gitea/workflows/build.yml @@ -34,6 +34,7 @@ jobs: - run: node tools/backup-test.js # backup restore (unsafe archives refused, old data kept) and personal export - run: node tools/listening-test.js # listening stats: real listening counted, seeks not, streak and finished books - run: node tools/moviefam-test.js # Movies & TV: favorites and the family movie night vote + - run: node tools/pantry-test.js # pantry: counts, low levels, barcodes (several per item), kids can only take - run: node tools/automations-test.js # automations: validation, triggers, daily cap, privacy - run: node tools/signal-test.js # Signal: linking, messages, sending, live updates diff --git a/docs/v2-roadmap.md b/docs/v2-roadmap.md index 5effb22..fe5cd0f 100644 --- a/docs/v2-roadmap.md +++ b/docs/v2-roadmap.md @@ -46,7 +46,7 @@ Not planned: voice and video calls, stories, usernames and phone-number lookup, - [x] **Shared lists and notes (M): done (notes.js, the Notes tab):** a real Notes and Lists tab the whole family edits (grocery, packing, gift ideas, house to-dos) - [x] **Chores and routines (M):** recurring chores per person, check-offs, optional points and a weekly summary; kids see their own **Done: chores.js and the Chores tab: repeats, points, weekly and monthly board.** - [x] **Family calendar (M):** **Done: the Family calendar shows each event in the colour of whoever added it (Settings > Look sets yours); birthdays and anniversaries come from Contacts; inviting people puts the event on their calendar and tells them (no accept or decline). The week view already existed.** -- [x] **Meal planning (M):** **Done: a shared week plan (Recipes > Meal plan) that adds the week's ingredients to the shopping list, and a Pantry (items with a count and a running-low level) that the plan checks against. Pantry counts are kept by hand; they do not go down when you cook.** +- [x] **Meal planning (M):** **Done: a shared week plan (Recipes > Meal plan) that adds the week's ingredients to the shopping list, and a Pantry (items with a count and a running-low level) that the plan checks against. Pantry counts are kept by hand and by scanning; they do not go down when you cook. The Pantry lives at Recipes > Pantry and works without Mealie. A phone can scan a barcode to add or use one (several barcodes can belong to one item, so different brands of corn share a count), and a Take one screen lets anyone, children included, tap an item to take one; children can do nothing else to the pantry.** - [x] **Worship and devotion (S):** a shared daily verse, a Bible reading plan with check-ins, a family prayer list **Done: Bible > Devotion (devotion-view.js, bible.js).** ## 3. Kids and safety diff --git a/pantry.js b/pantry.js new file mode 100644 index 0000000..807f9ca --- /dev/null +++ b/pantry.js @@ -0,0 +1,98 @@ +// The pantry: what the family keeps in the kitchen, one shared list. Each item has a name, how many are left (blank when you do not count it), the level it counts as running low +// at (blank: never), and any number of barcodes linked to it, so Green Giant corn and the store brand are both "Corn" with one count. Scanning a barcode (on a phone) looks the product +// up in Open Food Facts (through this server, so the phone never contacts it) and adds or uses one; the first time a barcode is seen the person says which item it is. +// An item going low starts the "pantry item runs low" automations. +const fs = require('fs'), path = require('path'), crypto = require('crypto'); +const atomicWrite = require('./atomic'); +const users = require('./users'); +const { readBody } = require('./body'); + +const DATA = () => process.env.DATA_DIR || path.join(__dirname, 'data'); +const file = () => path.join(DATA(), 'pantry.json'), cacheFile = () => path.join(DATA(), 'barcode-cache.json'); +const OFF = () => (process.env.OPENFOODFACTS_URL || 'https://world.openfoodfacts.org').replace(/\/+$/, ''); +const json = (res, code, o) => { res.writeHead(code, { 'content-type': 'application/json', 'cache-control': 'no-store' }); res.end(JSON.stringify(o)); }; +const fail = (code, message) => Object.assign(new Error(message), { code }); +const num = v => v === '' || v == null || !isFinite(+v) || +v < 0 ? null : Math.min(100000, Math.round(+v * 100) / 100); +const CODE = /^\d{8,14}$/; + +const read = () => { try { const a = JSON.parse(fs.readFileSync(file(), 'utf8')); return (Array.isArray(a) ? a : []).map(x => typeof x === 'string' ? { id: crypto.randomBytes(4).toString('hex'), name: x, qty: null, low: null, codes: [] } : { ...x, codes: Array.isArray(x.codes) ? x.codes : [] }).filter(x => x && x.name); } catch { return []; } }; +const write = l => atomicWrite(file(), JSON.stringify(l), { mode: 0o600 }); +const isLow = x => x.qty != null && x.low != null && x.qty <= x.low; +const view = l => l.map(x => ({ id: x.id, name: x.name, qty: x.qty, low: x.low, isLow: isLow(x), codes: x.codes })).sort((a, b) => b.isLow - a.isLow || a.name.localeCompare(b.name)); +// Who took what: the last few uses, so parents can see where the snacks went. +const logFile = () => path.join(DATA(), 'pantry-log.json'); +const readLog = () => { try { const a = JSON.parse(fs.readFileSync(logFile(), 'utf8')); return Array.isArray(a) ? a : []; } catch { return []; } }; +function logUse(me, it, delta) { const l = readLog(); l.unshift({ t: Date.now(), who: me.name, item: it.name, delta }); atomicWrite(logFile(), JSON.stringify(l.slice(0, 60)), { mode: 0o600 }); } +const isKid = u => !!(u && u.kid && u.kid.on); +/** An item has just gone low: tell the automations of everyone who asked to hear about it. */ +function lowNow(it) { try { require('./automations').fireAll('pantry.low', { title: it.name }); } catch (e) { console.warn('[pantry] rules failed:', e.message); } } +/** Change an item's count, firing the "went low" rules when it crosses into low. */ +function bump(it, delta) { const before = isLow(it); it.qty = Math.max(0, Math.round(((it.qty || 0) + delta) * 100) / 100); if (isLow(it) && !before) lowNow(it); } + +// ---- matching words: "3 cups flour" has "flour"; "Green Giant Sweet Corn" has "Corn" +const stem = w => w.replace(/(ies)$/, 'y').replace(/(es|s)$/, ''); +const wordsOf = t => (String(t).toLowerCase().match(/[a-z]+/g) || []).map(stem); +/** The pantry names (from items or strings) that every word of is in `text`. */ +function inPantry(text, items) { const have = new Set(wordsOf(text)); return items.map(x => typeof x === 'string' ? x : x.name).filter(n => { const ws = wordsOf(n); return ws.length && ws.every(w => have.has(w)); }); } +/** A short name for a product: the brand and the size taken off ("Heinz Tomato Ketchup 500 ml" -> "Tomato Ketchup"). */ +function shortName(name, brand) { + let n = String(name || '').replace(/\b\d+([.,]\d+)?\s?(x\s?\d+\s?)?(ml|cl|l|g|kg|oz|fl\.?\s?oz|lb|lbs|ct|count|pack|pk)\b\.?/gi, ' '); + for (const b of String(brand || '').split(',').map(x => x.trim()).filter(Boolean)) n = n.replace(new RegExp('\\b' + b.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '\\b', 'ig'), ' '); + n = n.replace(/[()\[\],]/g, ' ').replace(/\s+/g, ' ').trim(); return (n || String(name || '').trim()).replace(/\b\w/g, c => c.toUpperCase()).slice(0, 60); +} + +// ---- the product database (Open Food Facts), remembered so a barcode is only looked up once +const loadCache = () => { try { return JSON.parse(fs.readFileSync(cacheFile(), 'utf8')) || {}; } catch { return {}; } }; +async function product(code) { + const c = loadCache(), hit = c[code]; if (hit && (hit.found || Date.now() - hit.t < 24 * 3600e3)) return hit.found ? hit : null; // (a miss is tried again after a day) + let found = null; + try { + const r = await fetch(`${OFF()}/api/v2/product/${code}.json?fields=product_name,brands,quantity,generic_name`, { headers: { 'user-agent': 'NE-Hub/1.0 (family pantry)', accept: 'application/json' }, signal: AbortSignal.timeout(6000) }); + if (r.ok) { const j = await r.json(), p = j && j.status === 1 && j.product; if (p && (p.product_name || p.generic_name)) found = { name: String(p.product_name || p.generic_name).slice(0, 120), brand: String(p.brands || '').slice(0, 80), quantity: String(p.quantity || '').slice(0, 30) }; } + } catch { return undefined; } // (could not ask: not remembered) + c[code] = found ? { found: true, t: Date.now(), ...found } : { found: false, t: Date.now() }; + const keys = Object.keys(c); if (keys.length > 3000) for (const k of keys.sort((a, b) => c[a].t - c[b].t).slice(0, 500)) delete c[k]; + fs.mkdirSync(DATA(), { recursive: true }); atomicWrite(cacheFile(), JSON.stringify(c), { mode: 0o600 }); return found ? c[code] : null; +} + +async function handle(req, res) { + const me = users.current(), u = new URL(req.url, 'http://x'), p = u.pathname.slice('/api/pantry'.length) || '/'; + try { + if (!me) throw fail(401, 'Sign in'); + if (p === '/' && req.method === 'GET') return json(res, 200, { items: view(read()), recent: readLog().slice(0, 12), kid: isKid(me) }); + if (p === '/lookup' && req.method === 'GET') { // what is this barcode? Linked to an item already, or which products and items it might be + const code = u.searchParams.get('code') || ''; if (!CODE.test(code)) throw fail(400, 'That is not a barcode number (8 to 14 digits)'); + const l = read(), linked = l.find(x => x.codes.includes(code)); if (linked) return json(res, 200, { code, linked: { id: linked.id, name: linked.name } }); + const pr = await product(code), name = pr ? shortName(pr.name, pr.brand) : ''; + return json(res, 200, { code, linked: null, product: pr ? { name: pr.name, brand: pr.brand, quantity: pr.quantity, short: name } : null, lookedUp: pr !== undefined, matches: pr ? view(l.filter(x => inPantry(pr.name, [x.name]).length)).map(x => ({ id: x.id, name: x.name })) : [] }); + } + if (req.method !== 'POST') throw fail(404, 'Not found'); + const b = JSON.parse(await readBody(req, 4e3) || '{}'), l = read(); + if (p === '/use') { // the simple way: take one (or put it back, to undo). Open to everyone, children included. + const it = l.find(x => x.id === b.id); if (!it) throw fail(404, 'That item is gone'); const delta = b.undo ? 1 : -1; + if (it.qty != null) { if (delta < 0 && it.qty <= 0) throw fail(409, 'There is none left of ' + it.name); bump(it, delta); write(l); } + logUse(me, it, b.undo ? 0 : -1); return json(res, 200, { item: { id: it.id, name: it.name, qty: it.qty, isLow: isLow(it) }, items: view(l), recent: readLog().slice(0, 12) }); + } + if (isKid(me) && !(p === '/scan' && b.mode === 'use' && l.some(x => x.codes.includes(String(b.code))))) throw fail(403, 'Ask a grown-up to change the pantry. You can tap an item to take one.'); + if (p === '/item') { // add an item, or change one (the same name changes the existing item) + const name = String(b.name || '').replace(/[\u0000-\u001f]/g, '').trim().slice(0, 60); if (!name) throw fail(400, 'Give the item a name'); + const i = b.id ? l.findIndex(x => x.id === b.id) : l.findIndex(x => x.name.toLowerCase() === name.toLowerCase()); if (b.id && i < 0) throw fail(404, 'That item is gone'); if (i < 0 && l.length >= 400) throw fail(400, 'The pantry is full'); + const before = i >= 0 ? isLow(l[i]) : false, it = { id: i >= 0 ? l[i].id : crypto.randomBytes(4).toString('hex'), name: i >= 0 && !b.id ? l[i].name : name, qty: num(b.qty), low: num(b.low), codes: i >= 0 ? l[i].codes : [] }; + if (i >= 0) l[i] = it; else l.push(it); write(l); if (isLow(it) && !before) lowNow(it); return json(res, 200, { items: view(l) }); + } + if (p === '/adjust') { const it = l.find(x => x.id === b.id); if (!it) throw fail(404, 'That item is gone'); bump(it, +b.delta || 0); write(l); return json(res, 200, { items: view(l) }); } + if (p === '/delete') { const k = l.filter(x => x.id !== b.id); write(k); return json(res, 200, { items: view(k) }); } + if (p === '/scan') { // one scanned: add one ("add") or use one ("use"). A new barcode must say which item it is (itemId) or name a new one (name). + const code = String(b.code || ''); if (!CODE.test(code)) throw fail(400, 'That is not a barcode number (8 to 14 digits)'); const delta = b.mode === 'use' ? -1 : 1; + let it = l.find(x => x.codes.includes(code)), made = false; + if (!it && b.itemId) { it = l.find(x => x.id === b.itemId); if (!it) throw fail(404, 'That item is gone'); } + if (!it && String(b.name || '').trim()) { const name = String(b.name).replace(/[\u0000-\u001f]/g, '').trim().slice(0, 60); it = l.find(x => x.name.toLowerCase() === name.toLowerCase()); if (!it) { if (l.length >= 400) throw fail(400, 'The pantry is full'); it = { id: crypto.randomBytes(4).toString('hex'), name, qty: 0, low: null, codes: [] }; l.push(it); made = true; } } + if (!it) throw fail(400, 'Say which item this is'); + if (!it.codes.includes(code)) { for (const x of l) x.codes = x.codes.filter(c => c !== code); it.codes.push(code); it.codes = it.codes.slice(-30); } + bump(it, delta); write(l); if (delta < 0) logUse(me, it, -1); return json(res, 200, { item: { id: it.id, name: it.name, qty: it.qty, isLow: isLow(it) }, made, items: view(l), recent: readLog().slice(0, 12) }); + } + if (p === '/unlink') { const it = l.find(x => x.id === b.id); if (!it) throw fail(404, 'That item is gone'); it.codes = it.codes.filter(c => c !== String(b.code)); write(l); return json(res, 200, { items: view(l) }); } + throw fail(404, 'Not found'); + } catch (e) { json(res, e.code && e.code < 600 ? e.code : 400, { error: e.message }); } +} +module.exports = { handle, read, isLow, inPantry, shortName }; diff --git a/public/index.html b/public/index.html index 9ab2e84..eab398b 100644 --- a/public/index.html +++ b/public/index.html @@ -81,6 +81,7 @@ + diff --git a/public/pantry-view.js b/public/pantry-view.js new file mode 100644 index 0000000..8224220 --- /dev/null +++ b/public/pantry-view.js @@ -0,0 +1,91 @@ +'use strict'; +// ---- Pantry (Recipes > Pantry): what you keep in the kitchen, how many are left, and the level that counts as running low. A phone can scan a barcode to add one or use one; +// the first time a barcode is seen you say which item it is (so Green Giant corn and the store brand are both "Corn"). Low items go on the shopping list in a tap. +const paApi = (p, o) => jfetch('/api/pantry' + p, o), paOpt = o => ({ method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(o) }); +const paAgo = t => { const m = Math.round((Date.now() - t) / 60000); return m < 1 ? 'just now' : m < 60 ? m + ' min ago' : m < 1440 ? Math.round(m / 60) + ' h ago' : new Date(t).toLocaleDateString(undefined, { weekday: 'short' }); }; +const paRecent = r => r.length ? `

Recently

${r.map(x => `
${esc(x.who)} ${x.delta < 0 ? 'took' : 'put back'} ${esc(x.item)}${esc(paAgo(x.t))}
`).join('')}
` : ''; +/** The simple way to use things: a big tile for each item, tap to take one (with Undo). Children see only this. */ +async function viewPantryTake() { + let st; const v = $('#view'), kid = !!(ME && ME.kid && ME.kid.on); + try { st = await paApi('/'); } catch (e) { v.innerHTML = `

Pantry

${esc(e.message)}

`; return; } + if (!location.hash.startsWith('#/recipes')) return; + const draw = () => { + v.innerHTML = `

${kid ? 'Pantry' : 'Take one'}

${kid ? '' : `Manage`}
+

Tap what you are taking. It counts one off so the family knows when to buy more.

+
${st.items.map(x => ``).join('') || '

Nothing in the pantry yet.

'}
+
${paRecent(st.recent || [])}
`; + v.querySelectorAll('[data-u]').forEach(b => b.onclick = async () => { b.disabled = true; try { const r = await paApi('/use', paOpt({ id: b.dataset.u })); st.items = r.items; st.recent = r.recent; draw(); const it = r.item; + toast(`Took one ${it.name}${it.qty != null ? ': ' + it.qty + ' left' : ''}`, { label: 'Undo', run: async () => { try { const u = await paApi('/use', paOpt({ id: it.id, undo: true })); st.items = u.items; st.recent = u.recent; if ($('.paTiles')) draw(); toast('Put back'); } catch (e) { toast(e.message); } } }); } catch (e) { b.disabled = false; toast(e.message); } }); + $('#pasuse').onclick = () => pantryScan('use', list => { st.items = list; draw(); }, () => st.items); + }; + draw(); +} +async function viewPantry(sub) { + if (sub === 'take' || (ME && ME.kid && ME.kid.on)) return viewPantryTake(); + let items = [], recent = []; const v = $('#view'); + try { const r = await paApi('/'); items = r.items; recent = r.recent || []; } catch (e) { v.innerHTML = `

Pantry

${esc(e.message)}

`; return; } + if (!location.hash.startsWith('#/recipes/pantry')) return; + const draw = () => { + v.innerHTML = `

Recipes

${typeof rcTabs === 'function' ? rcTabs('pantry') : ''} +
Take one
+
+
${items.map(x => `
${esc(x.name)}${x.isLow ? ' running low' : ''}${x.qty == null ? 'not counted' : x.qty + ' left'}${x.low != null ? ' · low at ' + x.low : ''}${x.codes.length ? ' · ' + x.codes.length + ' barcode' + (x.codes.length === 1 ? '' : 's') : ''} + ${x.isLow && typeof rcApi === 'function' ? `` : ''}${x.codes.length ? `` : ''}${x.qty != null ? `` : ''}
`).join('') || '
Nothing yet. Add what you keep in the kitchen, or scan a barcode.
'}
+

Counts are kept by hand (and by scanning); they do not go down when you cook. The meal plan points out ingredients you already have.

${paRecent(recent)}
`; + const go = async (p, o) => { try { items = (await paApi(p, paOpt(o))).items; draw(); } catch (e) { toast(e.message); } }; + $('#paf').onsubmit = e => { e.preventDefault(); go('/item', { name: $('#pan').value, qty: $('#paq').value, low: $('#paw').value }); }; + v.querySelectorAll('[data-d]').forEach(b => b.onclick = () => { const [id, d] = b.dataset.d.split(':'); go('/adjust', { id, delta: +d }); }); + v.querySelectorAll('[data-x]').forEach(b => b.onclick = () => go('/delete', { id: b.dataset.x })); + v.querySelectorAll('[data-shop]').forEach(b => b.onclick = async () => { const it = items.find(x => x.id === b.dataset.shop); try { await rcApi('/shopping/add', rcOpt('POST', { text: it.name })); toast(it.name + ' added to the shopping list'); } catch (e) { toast(e.message); } }); + v.querySelectorAll('[data-bc]').forEach(b => b.onclick = () => { const it = items.find(x => x.id === b.dataset.bc), el = openSheet('Barcodes for ' + it.name, 'Scanning any of these counts as ' + it.name + '.', `
${it.codes.map(c => `
${esc(c)}
`).join('')}
`); el.querySelectorAll('[data-u]').forEach(u => u.onclick = async () => { closeSheet(); go('/unlink', { id: it.id, code: u.dataset.u }); }); }); + $('#pasadd').onclick = () => pantryScan('add', list => { items = list; draw(); }, () => items); $('#pasuse').onclick = () => pantryScan('use', list => { items = list; draw(); }, () => items); + }; + draw(); +} + +/** The scanner: the camera looks for barcodes and each one found adds one (or uses one). Keeps going so a bag of shopping can be done in a row. */ +let paZx = null; +const paLoadZx = () => paZx || (paZx = new Promise((ok, no) => { if (window.ZXing) return ok(window.ZXing); const s = document.createElement('script'); s.src = '/vendor/zxing/zxing.min.js'; s.onload = () => ok(window.ZXing); s.onerror = () => { paZx = null; no(new Error('Could not load the scanner')); }; document.head.appendChild(s); })); +function pantryScan(mode, onChange, getItems) { + const el = openSheet(mode === 'use' ? 'Scan to use one' : 'Scan to add', mode === 'use' ? 'Each barcode takes one off the count.' : 'Each barcode adds one to the count.', ` +

Starting the camera…

+
`); + const video = el.querySelector('#pscv'), status = t => { const s = el.querySelector('#pscs'); if (s) s.textContent = t; }; + let stream = null, stopped = false, busy = false, last = '', lastAt = 0, reader = null, timer = 0; + const stop = () => { stopped = true; clearInterval(timer); try { reader && reader.reset(); } catch { /* not started */ } if (stream) stream.getTracks().forEach(t => t.stop()); }; + const alive = () => !stopped && el.isConnected; + const resume = () => { busy = false; if (alive()) { el.querySelector('#pscq').innerHTML = ''; status('Point the camera at a barcode'); } }; + const finish = (r, said) => { onChange(r.items); status(said); toast(said); try { navigator.vibrate && navigator.vibrate(60); } catch { /* no vibration */ } setTimeout(resume, 1300); }; + const found = async code => { + if (busy || !alive() || (code === last && Date.now() - lastAt < 4000)) return; busy = true; last = code; lastAt = Date.now(); status('Looking up ' + code + '…'); + try { + const r = await paApi('/lookup?code=' + code); if (!alive()) return; + if (r.linked) { const o = await paApi('/scan', paOpt({ code, mode })); return finish(o, `${o.item.name}: ${o.item.qty} left${o.item.isLow ? ' (running low)' : ''}`); } + const list = (getItems() || []), matches = (r.matches || []).map(m => m.id), sorted = [...list.filter(x => matches.includes(x.id)), ...list.filter(x => !matches.includes(x.id))]; + el.querySelector('#pscq').innerHTML = `

${esc(r.product ? r.product.name : 'Barcode ' + code)}${r.product && r.product.brand ? ' · ' + esc(r.product.brand) + '' : ''}

+ ${!r.product ? `

${r.lookedUp ? 'The product database does not know this one.' : 'Could not reach the product database.'} Say what it is once and it is remembered.

` : '

First time this barcode is seen. Which item is it?

'} + +
+
`; + const sel = el.querySelector('#pscw'), nw = el.querySelector('#pscnw'); sel.onchange = () => { nw.hidden = !!sel.value; }; if (sel.value === '' ) nw.hidden = false; status('Which item is this?'); + el.querySelector('#pscx').onclick = resume; + el.querySelector('#pscf').onsubmit = async e => { e.preventDefault(); try { const o = await paApi('/scan', paOpt({ code, mode, itemId: sel.value || undefined, name: sel.value ? undefined : el.querySelector('#pscnn').value })); finish(o, `${o.item.name}: ${o.item.qty} left${o.made ? ' (new item)' : ''}`); } catch (er) { el.querySelector('#psce').textContent = er.message; } }; + } catch (e) { status(e.message); toast(e.message); setTimeout(resume, 1500); } + }; + el.querySelector('#pscm').onsubmit = e => { e.preventDefault(); const c = el.querySelector('#pscn').value.replace(/\D/g, ''); el.querySelector('#pscn').value = ''; if (/^\d{8,14}$/.test(c)) { last = ''; found(c); } else status('A barcode is 8 to 14 digits.'); }; + (async () => { + if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) return status('This browser cannot use the camera here (it needs a secure page). Type the number instead.'); + try { stream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: { ideal: 'environment' } }, audio: false }); } catch (e) { return status(e && e.name === 'NotAllowedError' ? 'The camera is blocked. Allow it for this site, or type the number instead.' : 'No camera could be started. Type the number instead.'); } + if (!alive()) return stop(); video.srcObject = stream; try { await video.play(); } catch { /* autoplay is allowed on a tap */ } status('Point the camera at a barcode'); + if ('BarcodeDetector' in window) { // Chrome and Android have a built-in reader + let det; try { det = new BarcodeDetector({ formats: ['ean_13', 'ean_8', 'upc_a', 'upc_e'] }); } catch { det = null; } + if (det) { timer = setInterval(async () => { if (!alive()) return stop(); if (busy || video.readyState < 2) return; try { const r = await det.detect(video); if (r[0] && r[0].rawValue) found(r[0].rawValue); } catch { /* a frame that cannot be read */ } }, 300); return; } + } + try { // everything else (iPhone Safari): a reader written in JavaScript, loaded only now + const Z = await paLoadZx(), hints = new Map(); hints.set(Z.DecodeHintType.POSSIBLE_FORMATS, [Z.BarcodeFormat.EAN_13, Z.BarcodeFormat.EAN_8, Z.BarcodeFormat.UPC_A, Z.BarcodeFormat.UPC_E]); reader = new Z.BrowserMultiFormatReader(hints); + timer = setInterval(() => { if (!alive()) stop(); }, 500); + reader.decodeFromVideoElement(video, (res) => { if (res && alive() && !busy) found(res.getText()); }); + } catch (e) { status(e.message + ' Type the number instead.'); } + })(); + new MutationObserver((_, ob) => { if (!el.isConnected) { stop(); ob.disconnect(); } }).observe(document.body, { childList: true }); +} diff --git a/public/recipes-view.js b/public/recipes-view.js index df0612c..649fe06 100644 --- a/public/recipes-view.js +++ b/public/recipes-view.js @@ -4,7 +4,7 @@ const rcApi = (p, opts) => jfetch('/api/recipes' + p, opts); const rcOpt = (m, o) => ({ method: m, headers: { 'content-type': 'application/json' }, body: o ? JSON.stringify(o) : undefined }); const rcTime = m => { m = +m || 0; if (!m) return ''; const h = Math.floor(m / 60); return h ? h + ' h' + (m % 60 ? ' ' + (m % 60) + ' min' : '') : m + ' min'; }; -const rcTabs = on => `
${icon('chef')}Recipes${icon('cal')}Meal plan${icon('check')}Shopping list
`; +const rcTabs = on => `
${icon('chef')}Recipes${icon('cal')}Meal plan${icon('list')}Pantry${icon('check')}Shopping list
`; let rcQuery = '', rcPage = 1; async function viewRecipes(args = []) { @@ -12,12 +12,14 @@ async function viewRecipes(args = []) { v.innerHTML = '

Recipes

Loading…

'; try { if (args[0] === 'r' && args[1]) return await rcOne(decodeURIComponent(args[1])); + if (args[0] === 'pantry') return await viewPantry(args[1]); + if (ME && ME.kid && ME.kid.on && !args[0]) return await viewPantry('take'); // children see the pantry to take from if (args[0] === 'shop') return await rcShop(); if (args[0] === 'plan') return await rcPlan(args[1]); return await rcHome(); } catch (e) { if (!location.hash.startsWith('#/recipes')) return; - v.innerHTML = `

Recipes

${esc(e.message)}

`; + v.innerHTML = `

Recipes

${rcTabs('')}

${esc(e.message)}

`; // (the Pantry does not need Mealie, so its tab is here even when recipes are not set up) $('#rcretry').onclick = () => route(); } } @@ -122,7 +124,7 @@ async function rcPlan(start) {
`; document.querySelectorAll('[data-add]').forEach(b => b.onclick = () => rcPlanPick(null, '', '', b.dataset.add)); document.querySelectorAll('[data-rm]').forEach(b => b.onclick = async () => { try { await rcApi('/plan/remove', rcOpt('POST', { id: b.dataset.rm })); rcPlan(rcYmd(mon)); } catch (e) { toast(e.message); } }); - $('#rcpantry').onclick = () => rcPantry(() => rcPlan(rcYmd(mon))); + $('#rcpantry').onclick = () => { location.hash = '#/recipes/pantry'; }; if (count) rcApi(`/plan/pantry?from=${from}&to=${to}`).then(r => { const box = $('#rcphave'); if (!box || !r.items.length) return; const names = [...new Set(r.items.map(i => i.have))]; box.innerHTML = `

You may already have ${esc(names.slice(0, 8).join(', '))}${names.length > 8 ? '…' : ''} (${r.items.length} ingredient${r.items.length === 1 ? '' : 's'} this week). They still go on the shopping list; tick them off there.

`; }).catch(() => {}); $('#rcpshop').onclick = async e => { const b = e.currentTarget; b.disabled = true; try { const o = await rcApi('/plan/shop', rcOpt('POST', { from, to })); toast(`Ingredients for ${o.recipes} recipe${o.recipes === 1 ? '' : 's'} added`, { label: 'Open', run: () => { location.hash = '#/recipes/shop'; } }); } catch (er) { toast(er.message); } b.disabled = false; }; } @@ -137,22 +139,3 @@ function rcPlanPick(slug, name, rid, date) { let t = 0; const find = async () => { try { const r = await rcApi('/?page=1&q=' + encodeURIComponent(el.querySelector('#rcpq').value)); el.querySelector('#rcpr').innerHTML = r.items.slice(0, 8).map(x => `${esc(x.name)}`).join('') || '
No recipes found
'; el.querySelectorAll('#rcpr [data-s]').forEach(a => a.onclick = ev => { ev.preventDefault(); save(a.dataset.s, a.dataset.n, a.dataset.i); }); } catch (e) { el.querySelector('#rcpe').textContent = e.message; } }; el.querySelector('#rcpq').oninput = () => { clearTimeout(t); t = setTimeout(find, 250); }; find(); } - -/** The pantry: what you keep in stock, how many are left, and the level that counts as running low (low ones go on the shopping list in a tap). */ -async function rcPantry(onClose) { - let items = []; try { items = (await rcApi('/pantry')).items; } catch (e) { return toast(e.message); } - const el = openSheet('Pantry', 'What you keep in stock. The meal plan points out ingredients you have, and an item running low can start an automation.', '
'); - const draw = () => { - el.querySelector('#pyl').innerHTML = `
-
${items.map(x => `
${esc(x.name)}${x.isLow ? ' running low' : ''}${x.qty == null ? 'not counted' : x.qty + ' left'}${x.low != null ? ' · low at ' + x.low : ''} - ${x.isLow ? `` : ''}${x.qty != null ? `` : ''}
`).join('') || '
Nothing yet. Add what you keep in the kitchen.
'}
-
`; - const go = async (p, o) => { try { items = (await rcApi(p, rcOpt('POST', o))).items; draw(); } catch (e) { toast(e.message); } }; - el.querySelector('#pyf').onsubmit = e => { e.preventDefault(); go('/pantry/item', { name: el.querySelector('#pyn').value, qty: el.querySelector('#pyq').value, low: el.querySelector('#pyw').value }); }; - el.querySelectorAll('[data-d]').forEach(b => b.onclick = () => { const [id, d] = b.dataset.d.split(':'); go('/pantry/adjust', { id, delta: +d }); }); - el.querySelectorAll('[data-x]').forEach(b => b.onclick = () => go('/pantry/delete', { id: b.dataset.x })); - el.querySelectorAll('[data-shop]').forEach(b => b.onclick = async () => { const it = items.find(x => x.id === b.dataset.shop); try { await rcApi('/shopping/add', rcOpt('POST', { text: it.name })); toast(it.name + ' added to the shopping list'); } catch (e) { toast(e.message); } }); - el.querySelector('#pydone').onclick = () => { closeSheet(); if (onClose) onClose(); }; - }; - draw(); -} diff --git a/public/style.css b/public/style.css index 085b230..0d1f20c 100644 --- a/public/style.css +++ b/public/style.css @@ -1106,3 +1106,4 @@ body:has(#sheet) #simplehome, body:has(#sheet) #kidreq, body:has(#lyr) #simpleho html.rm *, html.rm *::before, html.rm *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; scroll-behavior: auto !important; } html.hc #view a:not(.btn):not(.row):not(.vcard):not(.seg a):not(.sgrp a) { text-decoration: underline; } html.hc .btn.ghost, html.hc select, html.hc input[type=text], html.hc input[type=search], html.hc textarea { border: 2px solid var(--line); } html.hc :focus-visible { outline-width: 3px; } #offnote { position: fixed; left: 50%; transform: translateX(-50%); bottom: calc(var(--sab) + 70px); z-index: 90; max-width: min(92vw, 460px); padding: 10px 16px; border-radius: 12px; background: var(--panel); border: 1px solid var(--line); box-shadow: 0 6px 24px rgba(0, 0, 0, .3); font-size: 14px; text-align: center; } #offnote[hidden] { display: none; } +.paTiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 10px; margin: 8px 0 16px; } .paTile { min-height: 84px; padding: 12px; border-radius: 16px; border: 1px solid var(--line); background: var(--panel); text-align: center; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; font-size: 17px; } .paTile small { color: var(--muted); font-size: 14px; } .paTile:active { transform: scale(.97); } .paTile.low { border-color: var(--danger); } .paTile.out { opacity: .45; } diff --git a/public/sw.js b/public/sw.js index 114a780..cfc30e0 100644 --- a/public/sw.js +++ b/public/sw.js @@ -1,5 +1,5 @@ // App-shell cache only; Seafile/API traffic always goes to the network. -const CACHE = 'hub-v122'; +const CACHE = 'hub-v125'; const KEEP = /^hub-(offline|share|who|data-)/; // caches that outlive a new version const SHARE = 'hub-share'; // files shared into the app from other apps, held until the person picks a folder const SHELL = ['/icon.svg', '/manifest.webmanifest', '/icons/icon-192.png', '/icons/apple-touch-icon.png']; diff --git a/public/vendor/zxing/LICENSE.txt b/public/vendor/zxing/LICENSE.txt new file mode 100644 index 0000000..4bcbdae --- /dev/null +++ b/public/vendor/zxing/LICENSE.txt @@ -0,0 +1,245 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +======================================================================== +jai-imageio +======================================================================== + +Copyright (c) 2005 Sun Microsystems, Inc. +Copyright © 2010-2014 University of Manchester +Copyright © 2010-2015 Stian Soiland-Reyes +Copyright © 2015 Peter Hull +All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +- Redistribution of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +- Redistribution in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +Neither the name of Sun Microsystems, Inc. or the names of +contributors may be used to endorse or promote products derived +from this software without specific prior written permission. + +This software is provided "AS IS," without a warranty of any +kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND +WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY +EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL +NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF +USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS +DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR +ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, +CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND +REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR +INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +You acknowledge that this software is not designed or intended for +use in the design, construction, operation or maintenance of any +nuclear facility. diff --git a/public/vendor/zxing/zxing.min.js b/public/vendor/zxing/zxing.min.js new file mode 100644 index 0000000..f85dd18 --- /dev/null +++ b/public/vendor/zxing/zxing.min.js @@ -0,0 +1 @@ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).ZXing={})}(this,(function(t){"use strict";var e,r,n=(e=function(t,r){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r])},e(t,r)},function(t,r){if("function"!=typeof r&&null!==r)throw new TypeError("Class extends value "+String(r)+" is not a constructor or null");function n(){this.constructor=t}e(t,r),t.prototype=null===r?Object.create(r):(n.prototype=r.prototype,new n)}),i=function(t){function e(e,r){var n,i,s,o=this.constructor,a=t.call(this,e,r)||this;return Object.defineProperty(a,"name",{value:o.name,enumerable:!1,configurable:!0}),n=a,i=o.prototype,(s=Object.setPrototypeOf)?s(n,i):n.__proto__=i,function(t,e){void 0===e&&(e=t.constructor);var r=Error.captureStackTrace;r&&r(t,e)}(a),a}return n(e,t),e}(Error);class s extends i{constructor(t=void 0){super(t),this.message=t}getKind(){return this.constructor.kind}}s.kind="Exception";class o extends s{}o.kind="ArgumentException";class a extends s{}a.kind="IllegalArgumentException";class h{constructor(t){if(this.binarizer=t,null===t)throw new a("Binarizer must be non-null.")}getWidth(){return this.binarizer.getWidth()}getHeight(){return this.binarizer.getHeight()}getBlackRow(t,e){return this.binarizer.getBlackRow(t,e)}getBlackMatrix(){return null!==this.matrix&&void 0!==this.matrix||(this.matrix=this.binarizer.getBlackMatrix()),this.matrix}isCropSupported(){return this.binarizer.getLuminanceSource().isCropSupported()}crop(t,e,r,n){const i=this.binarizer.getLuminanceSource().crop(t,e,r,n);return new h(this.binarizer.createBinarizer(i))}isRotateSupported(){return this.binarizer.getLuminanceSource().isRotateSupported()}rotateCounterClockwise(){const t=this.binarizer.getLuminanceSource().rotateCounterClockwise();return new h(this.binarizer.createBinarizer(t))}rotateCounterClockwise45(){const t=this.binarizer.getLuminanceSource().rotateCounterClockwise45();return new h(this.binarizer.createBinarizer(t))}toString(){try{return this.getBlackMatrix().toString()}catch(t){return""}}}class l extends s{static getChecksumInstance(){return new l}}l.kind="ChecksumException";class c{constructor(t){this.source=t}getLuminanceSource(){return this.source}getWidth(){return this.source.getWidth()}getHeight(){return this.source.getHeight()}}class d{static arraycopy(t,e,r,n,i){for(;i--;)r[n++]=t[e++]}static currentTimeMillis(){return Date.now()}}class u extends s{}u.kind="IndexOutOfBoundsException";class g extends u{constructor(t=void 0,e=void 0){super(e),this.index=t,this.message=e}}g.kind="ArrayIndexOutOfBoundsException";class f{static fill(t,e){for(let r=0,n=t.length;rr)throw new a("fromIndex("+e+") > toIndex("+r+")");if(e<0)throw new g(e);if(r>t)throw new g(r)}static asList(...t){return t}static create(t,e,r){return Array.from({length:t}).map((t=>Array.from({length:e}).fill(r)))}static createInt32Array(t,e,r){return Array.from({length:t}).map((t=>Int32Array.from({length:e}).fill(r)))}static equals(t,e){if(!t)return!1;if(!e)return!1;if(!t.length)return!1;if(!e.length)return!1;if(t.length!==e.length)return!1;for(let r=0,n=t.length;r>1,o=r(e,t[s]);if(o>0)n=s+1;else{if(!(o<0))return s;i=s-1}}return-n-1}static numberComparator(t,e){return t-e}}class w{static numberOfTrailingZeros(t){let e;if(0===t)return 32;let r=31;return e=t<<16,0!==e&&(r-=16,t=e),e=t<<8,0!==e&&(r-=8,t=e),e=t<<4,0!==e&&(r-=4,t=e),e=t<<2,0!==e&&(r-=2,t=e),r-(t<<1>>>31)}static numberOfLeadingZeros(t){if(0===t)return 32;let e=1;return t>>>16==0&&(e+=16,t<<=16),t>>>24==0&&(e+=8,t<<=8),t>>>28==0&&(e+=4,t<<=4),t>>>30==0&&(e+=2,t<<=2),e-=t>>>31,e}static toHexString(t){return t.toString(16)}static toBinaryString(t){return String(parseInt(String(t),2))}static bitCount(t){return t=(t=(858993459&(t-=t>>>1&1431655765))+(t>>>2&858993459))+(t>>>4)&252645135,t+=t>>>8,63&(t+=t>>>16)}static truncDivision(t,e){return Math.trunc(t/e)}static parseInt(t,e=void 0){return parseInt(t,e)}}w.MIN_VALUE_32_BITS=-2147483648,w.MAX_VALUE=Number.MAX_SAFE_INTEGER;class C{constructor(t,e){void 0===t?(this.size=0,this.bits=new Int32Array(1)):(this.size=t,this.bits=null==e?C.makeArray(t):e)}getSize(){return this.size}getSizeInBytes(){return Math.floor((this.size+7)/8)}ensureCapacity(t){if(t>32*this.bits.length){const e=C.makeArray(t);d.arraycopy(this.bits,0,e,0,this.bits.length),this.bits=e}}get(t){return!!(this.bits[Math.floor(t/32)]&1<<(31&t))}set(t){this.bits[Math.floor(t/32)]|=1<<(31&t)}flip(t){this.bits[Math.floor(t/32)]^=1<<(31&t)}getNextSet(t){const e=this.size;if(t>=e)return e;const r=this.bits;let n=Math.floor(t/32),i=r[n];i&=~((1<<(31&t))-1);const s=r.length;for(;0===i;){if(++n===s)return e;i=r[n]}const o=32*n+w.numberOfTrailingZeros(i);return o>e?e:o}getNextUnset(t){const e=this.size;if(t>=e)return e;const r=this.bits;let n=Math.floor(t/32),i=~r[n];i&=~((1<<(31&t))-1);const s=r.length;for(;0===i;){if(++n===s)return e;i=~r[n]}const o=32*n+w.numberOfTrailingZeros(i);return o>e?e:o}setBulk(t,e){this.bits[Math.floor(t/32)]=e}setRange(t,e){if(ethis.size)throw new a;if(e===t)return;e--;const r=Math.floor(t/32),n=Math.floor(e/32),i=this.bits;for(let s=r;s<=n;s++){const o=(2<<(sr?0:31&t));i[s]|=o}}clear(){const t=this.bits.length,e=this.bits;for(let r=0;rthis.size)throw new a;if(e===t)return!0;e--;const n=Math.floor(t/32),i=Math.floor(e/32),s=this.bits;for(let o=n;o<=i;o++){const a=(2<<(on?0:31&t))&4294967295;if((s[o]&a)!==(r?a:0))return!1}return!0}appendBit(t){this.ensureCapacity(this.size+1),t&&(this.bits[Math.floor(this.size/32)]|=1<<(31&this.size)),this.size++}appendBits(t,e){if(e<0||e>32)throw new a("Num bits must be between 0 and 32");this.ensureCapacity(this.size+e);for(let r=e;r>0;r--)this.appendBit(1==(t>>r-1&1))}appendBitArray(t){const e=t.size;this.ensureCapacity(this.size+e);for(let r=0;r>1&1431655765|(1431655765&r)<<1,r=r>>2&858993459|(858993459&r)<<2,r=r>>4&252645135|(252645135&r)<<4,r=r>>8&16711935|(16711935&r)<<8,r=r>>16&65535|(65535&r)<<16,t[e-i]=r}if(this.size!==32*r){const e=32*r-this.size;let n=t[0]>>>e;for(let i=1;i>>e}t[r-1]=n}this.bits=t}static makeArray(t){return new Int32Array(Math.floor((t+31)/32))}equals(t){if(!(t instanceof C))return!1;const e=t;return this.size===e.size&&f.equals(this.bits,e.bits)}hashCode(){return 31*this.size+f.hashCode(this.bits)}toString(){let t="";for(let e=0,r=this.size;e=900)throw new m("incorect value");const e=I.VALUES_TO_ECI.get(t);if(void 0===e)throw new m("incorect value");return e}static getCharacterSetECIByName(t){const e=I.NAME_TO_ECI.get(t);if(void 0===e)throw new m("incorect value");return e}equals(t){if(!(t instanceof I))return!1;const e=t;return this.getName()===e.getName()}}I.VALUE_IDENTIFIER_TO_ECI=new Map,I.VALUES_TO_ECI=new Map,I.NAME_TO_ECI=new Map,I.Cp437=new I(A.Cp437,Int32Array.from([0,2]),"Cp437"),I.ISO8859_1=new I(A.ISO8859_1,Int32Array.from([1,3]),"ISO-8859-1","ISO88591","ISO8859_1"),I.ISO8859_2=new I(A.ISO8859_2,4,"ISO-8859-2","ISO88592","ISO8859_2"),I.ISO8859_3=new I(A.ISO8859_3,5,"ISO-8859-3","ISO88593","ISO8859_3"),I.ISO8859_4=new I(A.ISO8859_4,6,"ISO-8859-4","ISO88594","ISO8859_4"),I.ISO8859_5=new I(A.ISO8859_5,7,"ISO-8859-5","ISO88595","ISO8859_5"),I.ISO8859_6=new I(A.ISO8859_6,8,"ISO-8859-6","ISO88596","ISO8859_6"),I.ISO8859_7=new I(A.ISO8859_7,9,"ISO-8859-7","ISO88597","ISO8859_7"),I.ISO8859_8=new I(A.ISO8859_8,10,"ISO-8859-8","ISO88598","ISO8859_8"),I.ISO8859_9=new I(A.ISO8859_9,11,"ISO-8859-9","ISO88599","ISO8859_9"),I.ISO8859_10=new I(A.ISO8859_10,12,"ISO-8859-10","ISO885910","ISO8859_10"),I.ISO8859_11=new I(A.ISO8859_11,13,"ISO-8859-11","ISO885911","ISO8859_11"),I.ISO8859_13=new I(A.ISO8859_13,15,"ISO-8859-13","ISO885913","ISO8859_13"),I.ISO8859_14=new I(A.ISO8859_14,16,"ISO-8859-14","ISO885914","ISO8859_14"),I.ISO8859_15=new I(A.ISO8859_15,17,"ISO-8859-15","ISO885915","ISO8859_15"),I.ISO8859_16=new I(A.ISO8859_16,18,"ISO-8859-16","ISO885916","ISO8859_16"),I.SJIS=new I(A.SJIS,20,"SJIS","Shift_JIS"),I.Cp1250=new I(A.Cp1250,21,"Cp1250","windows-1250"),I.Cp1251=new I(A.Cp1251,22,"Cp1251","windows-1251"),I.Cp1252=new I(A.Cp1252,23,"Cp1252","windows-1252"),I.Cp1256=new I(A.Cp1256,24,"Cp1256","windows-1256"),I.UnicodeBigUnmarked=new I(A.UnicodeBigUnmarked,25,"UnicodeBigUnmarked","UTF-16BE","UnicodeBig"),I.UTF8=new I(A.UTF8,26,"UTF8","UTF-8"),I.ASCII=new I(A.ASCII,Int32Array.from([27,170]),"ASCII","US-ASCII"),I.Big5=new I(A.Big5,28,"Big5"),I.GB18030=new I(A.GB18030,29,"GB18030","GB2312","EUC_CN","GBK"),I.EUC_KR=new I(A.EUC_KR,30,"EUC_KR","EUC-KR");class _ extends s{}_.kind="UnsupportedOperationException";class S{static decode(t,e){const r=this.encodingName(e);return this.customDecoder?this.customDecoder(t,r):"undefined"==typeof TextDecoder||this.shouldDecodeOnFallback(r)?this.decodeFallback(t,r):new TextDecoder(r).decode(t)}static shouldDecodeOnFallback(t){return!S.isBrowser()&&"ISO-8859-1"===t}static encode(t,e){const r=this.encodingName(e);return this.customEncoder?this.customEncoder(t,r):"undefined"==typeof TextEncoder?this.encodeFallback(t):(new TextEncoder).encode(t)}static isBrowser(){return"undefined"!=typeof window&&"[object Window]"==={}.toString.call(window)}static encodingName(t){return"string"==typeof t?t:t.getName()}static encodingCharacterSet(t){return t instanceof I?t:I.getCharacterSetECIByName(t)}static decodeFallback(t,e){const r=this.encodingCharacterSet(e);if(S.isDecodeFallbackSupported(r)){let e="";for(let r=0,n=t.length;r3&&239===t[0]&&187===t[1]&&191===t[2];for(let e=0;e0?128&r?o--:s=!1:128&r&&(64&r?(o++,32&r?(o++,16&r?(o++,8&r?s=!1:l++):h++):a++):s=!1)),n&&(r>127&&r<160?n=!1:r>159&&(r<192||215===r||247===r)&&C++),i&&(c>0?r<64||127===r||r>252?i=!1:c--:128===r||160===r||r>239?i=!1:r>160&&r<224?(d++,g=0,u++,u>f&&(f=u)):r>127?(c++,u=0,g++,g>w&&(w=g)):(u=0,g=0))}return s&&o>0&&(s=!1),i&&c>0&&(i=!1),s&&(A||a+h+l>0)?p.UTF8:i&&(p.ASSUME_SHIFT_JIS||f>=3||w>=3)?p.SHIFT_JIS:n&&i?2===f&&2===d||10*C>=r?p.SHIFT_JIS:p.ISO88591:n?p.ISO88591:i?p.SHIFT_JIS:s?p.UTF8:p.PLATFORM_DEFAULT_ENCODING}static format(t,...e){let r=-1;return t.replace(/%(-)?(0?[0-9]+)?([.][0-9]+)?([#][0-9]+)?([scfpexd%])/g,(function(t,n,i,s,o,a){if("%%"===t)return"%";if(void 0===e[++r])return;t=s?parseInt(s.substr(1)):void 0;let h,l=o?parseInt(o.substr(1)):void 0;switch(a){case"s":h=e[r];break;case"c":h=e[r][0];break;case"f":h=parseFloat(e[r]).toFixed(t);break;case"p":h=parseFloat(e[r]).toPrecision(t);break;case"e":h=parseFloat(e[r]).toExponential(t);break;case"x":h=parseInt(e[r]).toString(l||16);break;case"d":h=parseFloat(parseInt(e[r],l||10).toPrecision(t)).toFixed(0)}h="object"==typeof h?JSON.stringify(h):(+h).toString(l);let c=parseInt(i),d=i&&i[0]+""=="0"?"0":" ";for(;h.lengths){if(-1===o)o=i-s;else if(i-s!==o)throw new a("row lengths do not match");s=i,h++}l++}else if(t.substring(l,l+e.length)===e)l+=e.length,n[i]=!0,i++;else{if(t.substring(l,l+r.length)!==r)throw new a("illegal character encountered: "+t.substring(l));l+=r.length,n[i]=!1,i++}if(i>s){if(-1===o)o=i-s;else if(i-s!==o)throw new a("row lengths do not match");h++}const c=new R(o,h);for(let t=0;t>>(31&t)&1)}set(t,e){const r=e*this.rowSize+Math.floor(t/32);this.bits[r]|=1<<(31&t)&4294967295}unset(t,e){const r=e*this.rowSize+Math.floor(t/32);this.bits[r]&=~(1<<(31&t)&4294967295)}flip(t,e){const r=e*this.rowSize+Math.floor(t/32);this.bits[r]^=1<<(31&t)&4294967295}xor(t){if(this.width!==t.getWidth()||this.height!==t.getHeight()||this.rowSize!==t.getRowSize())throw new a("input matrix dimensions do not match");const e=new C(Math.floor(this.width/32)+1),r=this.rowSize,n=this.bits;for(let i=0,s=this.height;ithis.height||i>this.width)throw new a("The region must fit inside the matrix");const o=this.rowSize,h=this.bits;for(let r=e;ra&&(a=t),32*eo){let t=31;for(;h>>>t==0;)t--;32*e+t>o&&(o=32*e+t)}}}return o=0&&0===e[r];)r--;if(r<0)return null;const n=Math.floor(r/t);let i=32*Math.floor(r%t);const s=e[r];let o=31;for(;s>>>o==0;)o--;return i+=o,Int32Array.from([i,n])}getWidth(){return this.width}getHeight(){return this.height}getRowSize(){return this.rowSize}equals(t){if(!(t instanceof R))return!1;const e=t;return this.width===e.width&&this.height===e.height&&this.rowSize===e.rowSize&&f.equals(this.bits,e.bits)}hashCode(){let t=this.width;return t=31*t+this.width,t=31*t+this.height,t=31*t+this.rowSize,t=31*t+f.hashCode(this.bits),t}toString(t="X ",e=" ",r="\n"){return this.buildToString(t,e,r)}buildToString(t,e,r){let n=new T;for(let i=0,s=this.height;i>y.LUMINANCE_SHIFT]++;const o=y.estimateBlackPoint(s);if(n<3)for(let t=0;t>y.LUMINANCE_SHIFT]++}}const s=y.estimateBlackPoint(i),o=t.getMatrix();for(let t=0;ti&&(n=s,i=t[s]),t[s]>r&&(r=t[s]);let s=0,o=0;for(let r=0;ro&&(s=r,o=i)}if(n>s){const t=n;n=s,s=t}if(s-n<=e/16)throw new N;let a=s-1,h=-1;for(let e=s-1;e>n;e--){const i=e-n,o=i*i*(s-e)*(r-t[e]);o>h&&(a=e,h=o)}return a<=D.MINIMUM_DIMENSION&&r>=D.MINIMUM_DIMENSION){const n=t.getMatrix();let i=e>>D.BLOCK_SIZE_POWER;e&D.BLOCK_SIZE_MASK&&i++;let s=r>>D.BLOCK_SIZE_POWER;r&D.BLOCK_SIZE_MASK&&s++;const o=D.calculateBlackPoints(n,i,s,e,r),a=new R(e,r);D.calculateThresholdForBlock(n,i,s,e,r,o,a),this.matrix=a}else this.matrix=super.getBlackMatrix();return this.matrix}createBinarizer(t){return new D(t)}static calculateThresholdForBlock(t,e,r,n,i,s,o){const a=i-D.BLOCK_SIZE,h=n-D.BLOCK_SIZE;for(let i=0;ia&&(l=a);const c=D.cap(i,2,r-3);for(let r=0;rh&&(i=h);const a=D.cap(r,2,e-3);let d=0;for(let t=-2;t<=2;t++){const e=s[c+t];d+=e[a-2]+e[a-1]+e[a]+e[a+1]+e[a+2]}const u=d/25;D.thresholdBlock(t,i,l,u,n,o)}}}static cap(t,e,r){return tr?r:t}static thresholdBlock(t,e,r,n,i,s){for(let o=0,a=r*i+e;os&&(r=s);for(let s=0;so&&(e=o);let h=0,l=255,c=0;for(let i=0,s=r*n+e;ic&&(c=r)}if(c-l>D.MIN_DYNAMIC_RANGE)for(i++,s+=n;i>2*D.BLOCK_SIZE_POWER;if(c-l<=D.MIN_DYNAMIC_RANGE&&(d=l/2,i>0&&s>0)){const t=(a[i-1][s]+2*a[i][s-1]+a[i-1][s-1])/4;l>10}i[r]=n}else for(let e=0,r=0,n=t.length;e>10}i[r]=255-n}return i}getRow(t,e){if(t<0||t>=this.getHeight())throw new a("Requested row is outside the image: "+t);const r=this.getWidth(),n=t*r;return null===e?e=this.buffer.slice(n,n+r):(e.lengthnew B(t.deviceId,t.label)))}))}findDeviceById(t){return L(this,void 0,void 0,(function*(){const e=yield this.listVideoInputDevices();return e?e.find((e=>e.deviceId===t)):null}))}decodeFromInputVideoDevice(t,e){return L(this,void 0,void 0,(function*(){return yield this.decodeOnceFromVideoDevice(t,e)}))}decodeOnceFromVideoDevice(t,e){return L(this,void 0,void 0,(function*(){let r;this.reset(),r=t?{deviceId:{exact:t}}:{facingMode:"environment"};const n={video:r};return yield this.decodeOnceFromConstraints(n,e)}))}decodeOnceFromConstraints(t,e){return L(this,void 0,void 0,(function*(){const r=yield navigator.mediaDevices.getUserMedia(t);return yield this.decodeOnceFromStream(r,e)}))}decodeOnceFromStream(t,e){return L(this,void 0,void 0,(function*(){this.reset();const r=yield this.attachStreamToVideo(t,e);return yield this.decodeOnce(r)}))}decodeFromInputVideoDeviceContinuously(t,e,r){return L(this,void 0,void 0,(function*(){return yield this.decodeFromVideoDevice(t,e,r)}))}decodeFromVideoDevice(t,e,r){return L(this,void 0,void 0,(function*(){let n;n=t?{deviceId:{exact:t}}:{facingMode:"environment"};const i={video:n};return yield this.decodeFromConstraints(i,e,r)}))}decodeFromConstraints(t,e,r){return L(this,void 0,void 0,(function*(){const n=yield navigator.mediaDevices.getUserMedia(t);return yield this.decodeFromStream(n,e,r)}))}decodeFromStream(t,e,r){return L(this,void 0,void 0,(function*(){this.reset();const n=yield this.attachStreamToVideo(t,e);return yield this.decodeContinuously(n,r)}))}stopAsyncDecode(){this._stopAsyncDecode=!0}stopContinuousDecode(){this._stopContinuousDecode=!0}attachStreamToVideo(t,e){return L(this,void 0,void 0,(function*(){const r=this.prepareVideoElement(e);return this.addVideoSource(r,t),this.videoElement=r,this.stream=t,yield this.playVideoOnLoadAsync(r),r}))}playVideoOnLoadAsync(t){return new Promise(((e,r)=>this.playVideoOnLoad(t,(()=>e()))))}playVideoOnLoad(t,e){this.videoEndedListener=()=>this.stopStreams(),this.videoCanPlayListener=()=>this.tryPlayVideo(t),t.addEventListener("ended",this.videoEndedListener),t.addEventListener("canplay",this.videoCanPlayListener),t.addEventListener("playing",e),this.tryPlayVideo(t)}isVideoPlaying(t){return t.currentTime>0&&!t.paused&&!t.ended&&t.readyState>2}tryPlayVideo(t){return L(this,void 0,void 0,(function*(){if(this.isVideoPlaying(t))console.warn("Trying to play video that is already playing.");else try{yield t.play()}catch(t){console.warn("It was not possible to play the video.")}}))}getMediaElement(t,e){const r=document.getElementById(t);if(!r)throw new o(`element with id '${t}' not found`);if(r.nodeName.toLowerCase()!==e.toLowerCase())throw new o(`element with id '${t}' must be an ${e} element`);return r}decodeFromImage(t,e){if(!t&&!e)throw new o("either imageElement with a src set or an url must be provided");return e&&!t?this.decodeFromImageUrl(e):this.decodeFromImageElement(t)}decodeFromVideo(t,e){if(!t&&!e)throw new o("Either an element with a src set or an URL must be provided");return e&&!t?this.decodeFromVideoUrl(e):this.decodeFromVideoElement(t)}decodeFromVideoContinuously(t,e,r){if(void 0===t&&void 0===e)throw new o("Either an element with a src set or an URL must be provided");return e&&!t?this.decodeFromVideoUrlContinuously(e,r):this.decodeFromVideoElementContinuously(t,r)}decodeFromImageElement(t){if(!t)throw new o("An image element must be provided.");this.reset();const e=this.prepareImageElement(t);let r;return this.imageElement=e,r=this.isImageLoaded(e)?this.decodeOnce(e,!1,!0):this._decodeOnLoadImage(e),r}decodeFromVideoElement(t){const e=this._decodeFromVideoElementSetup(t);return this._decodeOnLoadVideo(e)}decodeFromVideoElementContinuously(t,e){const r=this._decodeFromVideoElementSetup(t);return this._decodeOnLoadVideoContinuously(r,e)}_decodeFromVideoElementSetup(t){if(!t)throw new o("A video element must be provided.");this.reset();const e=this.prepareVideoElement(t);return this.videoElement=e,e}decodeFromImageUrl(t){if(!t)throw new o("An URL must be provided.");this.reset();const e=this.prepareImageElement();this.imageElement=e;const r=this._decodeOnLoadImage(e);return e.src=t,r}decodeFromVideoUrl(t){if(!t)throw new o("An URL must be provided.");this.reset();const e=this.prepareVideoElement(),r=this.decodeFromVideoElement(e);return e.src=t,r}decodeFromVideoUrlContinuously(t,e){if(!t)throw new o("An URL must be provided.");this.reset();const r=this.prepareVideoElement(),n=this.decodeFromVideoElementContinuously(r,e);return r.src=t,n}_decodeOnLoadImage(t){return new Promise(((e,r)=>{this.imageLoadedListener=()=>this.decodeOnce(t,!1,!0).then(e,r),t.addEventListener("load",this.imageLoadedListener)}))}_decodeOnLoadVideo(t){return L(this,void 0,void 0,(function*(){return yield this.playVideoOnLoadAsync(t),yield this.decodeOnce(t)}))}_decodeOnLoadVideoContinuously(t,e){return L(this,void 0,void 0,(function*(){yield this.playVideoOnLoadAsync(t),this.decodeContinuously(t,e)}))}isImageLoaded(t){return!!t.complete&&0!==t.naturalWidth}prepareImageElement(t){let e;return void 0===t&&(e=document.createElement("img"),e.width=200,e.height=200),"string"==typeof t&&(e=this.getMediaElement(t,"img")),t instanceof HTMLImageElement&&(e=t),e}prepareVideoElement(t){let e;return t||"undefined"==typeof document||(e=document.createElement("video"),e.width=200,e.height=200),"string"==typeof t&&(e=this.getMediaElement(t,"video")),t instanceof HTMLVideoElement&&(e=t),e.setAttribute("autoplay","true"),e.setAttribute("muted","true"),e.setAttribute("playsinline","true"),e}decodeOnce(t,e=!0,r=!0){this._stopAsyncDecode=!1;const n=(i,s)=>{if(this._stopAsyncDecode)return s(new N("Video stream has ended before any code could be detected.")),void(this._stopAsyncDecode=void 0);try{i(this.decode(t))}catch(t){if(e&&t instanceof N||(t instanceof l||t instanceof m)&&r)return setTimeout(n,this._timeBetweenDecodingAttempts,i,s);s(t)}};return new Promise(((t,e)=>n(t,e)))}decodeContinuously(t,e){this._stopContinuousDecode=!1;const r=()=>{if(this._stopContinuousDecode)this._stopContinuousDecode=void 0;else try{const n=this.decode(t);e(n,null),setTimeout(r,this.timeBetweenScansMillis)}catch(t){e(null,t);(t instanceof l||t instanceof m||t instanceof N)&&setTimeout(r,this._timeBetweenDecodingAttempts)}};r()}decode(t){const e=this.createBinaryBitmap(t);return this.decodeBitmap(e)}createBinaryBitmap(t){this.getCaptureCanvasContext(t);let e=!1;t instanceof HTMLVideoElement?(this.drawFrameOnCanvas(t),e=!0):this.drawImageOnCanvas(t);const r=this.getCaptureCanvas(t),n=new b(r,e),i=new D(n);return new h(i)}getCaptureCanvasContext(t){if(!this.captureCanvasContext){const e=this.getCaptureCanvas(t);let r;try{r=e.getContext("2d",{willReadFrequently:!0})}catch(t){r=e.getContext("2d")}this.captureCanvasContext=r}return this.captureCanvasContext}getCaptureCanvas(t){if(!this.captureCanvas){const e=this.createCaptureCanvas(t);this.captureCanvas=e}return this.captureCanvas}drawFrameOnCanvas(t,e={sx:0,sy:0,sWidth:t.videoWidth,sHeight:t.videoHeight,dx:0,dy:0,dWidth:t.videoWidth,dHeight:t.videoHeight},r=this.captureCanvasContext){r.drawImage(t,e.sx,e.sy,e.sWidth,e.sHeight,e.dx,e.dy,e.dWidth,e.dHeight)}drawImageOnCanvas(t,e={sx:0,sy:0,sWidth:t.naturalWidth,sHeight:t.naturalHeight,dx:0,dy:0,dWidth:t.naturalWidth,dHeight:t.naturalHeight},r=this.captureCanvasContext){r.drawImage(t,e.sx,e.sy,e.sWidth,e.sHeight,e.dx,e.dy,e.dWidth,e.dHeight)}decodeBitmap(t){return this.reader.decode(t,this._hints)}createCaptureCanvas(t){if("undefined"==typeof document)return this._destroyCaptureCanvas(),null;const e=document.createElement("canvas");let r,n;return void 0!==t&&(t instanceof HTMLVideoElement?(r=t.videoWidth,n=t.videoHeight):t instanceof HTMLImageElement&&(r=t.naturalWidth||t.width,n=t.naturalHeight||t.height)),e.style.width=r+"px",e.style.height=n+"px",e.width=r,e.height=n,e}stopStreams(){this.stream&&(this.stream.getVideoTracks().forEach((t=>t.stop())),this.stream=void 0),!1===this._stopAsyncDecode&&this.stopAsyncDecode(),!1===this._stopContinuousDecode&&this.stopContinuousDecode()}reset(){this.stopStreams(),this._destroyVideoElement(),this._destroyImageElement(),this._destroyCaptureCanvas()}_destroyVideoElement(){this.videoElement&&(void 0!==this.videoEndedListener&&this.videoElement.removeEventListener("ended",this.videoEndedListener),void 0!==this.videoPlayingEventListener&&this.videoElement.removeEventListener("playing",this.videoPlayingEventListener),void 0!==this.videoCanPlayListener&&this.videoElement.removeEventListener("loadedmetadata",this.videoCanPlayListener),this.cleanVideoSource(this.videoElement),this.videoElement=void 0)}_destroyImageElement(){this.imageElement&&(void 0!==this.imageLoadedListener&&this.imageElement.removeEventListener("load",this.imageLoadedListener),this.imageElement.src=void 0,this.imageElement.removeAttribute("src"),this.imageElement=void 0)}_destroyCaptureCanvas(){this.captureCanvasContext=void 0,this.captureCanvas=void 0}addVideoSource(t,e){try{t.srcObject=e}catch(r){t.src=URL.createObjectURL(e)}}cleanVideoSource(t){try{t.srcObject=null}catch(e){t.src=""}this.videoElement.removeAttribute("src")}}class v{constructor(t,e,r=(null==e?0:8*e.length),n,i,s=d.currentTimeMillis()){this.text=t,this.rawBytes=e,this.numBits=r,this.resultPoints=n,this.format=i,this.timestamp=s,this.text=t,this.rawBytes=e,this.numBits=null==r?null==e?0:8*e.length:r,this.resultPoints=n,this.format=i,this.resultMetadata=null,this.timestamp=null==s?d.currentTimeMillis():s}getText(){return this.text}getRawBytes(){return this.rawBytes}getNumBits(){return this.numBits}getResultPoints(){return this.resultPoints}getBarcodeFormat(){return this.format}getResultMetadata(){return this.resultMetadata}putMetadata(t,e){null===this.resultMetadata&&(this.resultMetadata=new Map),this.resultMetadata.set(t,e)}putAllMetadata(t){null!==t&&(null===this.resultMetadata?this.resultMetadata=t:this.resultMetadata=new Map(t))}addResultPoints(t){const e=this.resultPoints;if(null===e)this.resultPoints=t;else if(null!==t&&t.length>0){const r=new Array(e.length+t.length);d.arraycopy(e,0,r,0,e.length),d.arraycopy(t,0,r,e.length,t.length),this.resultPoints=r}}getTimestamp(){return this.timestamp}toString(){return this.text}}!function(t){t[t.AZTEC=0]="AZTEC",t[t.CODABAR=1]="CODABAR",t[t.CODE_39=2]="CODE_39",t[t.CODE_93=3]="CODE_93",t[t.CODE_128=4]="CODE_128",t[t.DATA_MATRIX=5]="DATA_MATRIX",t[t.EAN_8=6]="EAN_8",t[t.EAN_13=7]="EAN_13",t[t.ITF=8]="ITF",t[t.MAXICODE=9]="MAXICODE",t[t.PDF_417=10]="PDF_417",t[t.QR_CODE=11]="QR_CODE",t[t.RSS_14=12]="RSS_14",t[t.RSS_EXPANDED=13]="RSS_EXPANDED",t[t.UPC_A=14]="UPC_A",t[t.UPC_E=15]="UPC_E",t[t.UPC_EAN_EXTENSION=16]="UPC_EAN_EXTENSION"}(P||(P={}));var k,x=P;!function(t){t[t.OTHER=0]="OTHER",t[t.ORIENTATION=1]="ORIENTATION",t[t.BYTE_SEGMENTS=2]="BYTE_SEGMENTS",t[t.ERROR_CORRECTION_LEVEL=3]="ERROR_CORRECTION_LEVEL",t[t.ISSUE_NUMBER=4]="ISSUE_NUMBER",t[t.SUGGESTED_PRICE=5]="SUGGESTED_PRICE",t[t.POSSIBLE_COUNTRY=6]="POSSIBLE_COUNTRY",t[t.UPC_EAN_EXTENSION=7]="UPC_EAN_EXTENSION",t[t.PDF417_EXTRA_METADATA=8]="PDF417_EXTRA_METADATA",t[t.STRUCTURED_APPEND_SEQUENCE=9]="STRUCTURED_APPEND_SEQUENCE",t[t.STRUCTURED_APPEND_PARITY=10]="STRUCTURED_APPEND_PARITY"}(k||(k={}));var V,H,U,X,G,W,z=k;class Y{constructor(t,e,r,n,i=-1,s=-1){this.rawBytes=t,this.text=e,this.byteSegments=r,this.ecLevel=n,this.structuredAppendSequenceNumber=i,this.structuredAppendParity=s,this.numBits=null==t?0:8*t.length}getRawBytes(){return this.rawBytes}getNumBits(){return this.numBits}setNumBits(t){this.numBits=t}getText(){return this.text}getByteSegments(){return this.byteSegments}getECLevel(){return this.ecLevel}getErrorsCorrected(){return this.errorsCorrected}setErrorsCorrected(t){this.errorsCorrected=t}getErasures(){return this.erasures}setErasures(t){this.erasures=t}getOther(){return this.other}setOther(t){this.other=t}hasStructuredAppend(){return this.structuredAppendParity>=0&&this.structuredAppendSequenceNumber>=0}getStructuredAppendParity(){return this.structuredAppendParity}getStructuredAppendSequenceNumber(){return this.structuredAppendSequenceNumber}}class Z{exp(t){return this.expTable[t]}log(t){if(0===t)throw new a;return this.logTable[t]}static addOrSubtract(t,e){return t^e}}class K{constructor(t,e){if(0===e.length)throw new a;this.field=t;const r=e.length;if(r>1&&0===e[0]){let t=1;for(;tr.length){const t=e;e=r,r=t}let n=new Int32Array(r.length);const i=r.length-e.length;d.arraycopy(r,0,n,0,i);for(let t=i;t=t.getDegree()&&!n.isZero();){const i=n.getDegree()-t.getDegree(),o=e.multiply(n.getCoefficient(n.getDegree()),s),a=t.multiplyByMonomial(i,o),h=e.buildMonomial(i,o);r=r.addOrSubtract(h),n=n.addOrSubtract(a)}return[r,n]}toString(){let t="";for(let e=this.getDegree();e>=0;e--){let r=this.getCoefficient(e);if(0!==r){if(r<0?(t+=" - ",r=-r):t.length>0&&(t+=" + "),0===e||1!==r){const e=this.field.log(r);0===e?t+="1":1===e?t+="a":(t+="a^",t+=e)}0!==e&&(1===e?t+="x":(t+="x^",t+=e))}}return t}}class q extends s{}q.kind="ArithmeticException";class Q extends Z{constructor(t,e,r){super(),this.primitive=t,this.size=e,this.generatorBase=r;const n=new Int32Array(e);let i=1;for(let r=0;r=e&&(i^=t,i&=e-1);this.expTable=n;const s=new Int32Array(e);for(let t=0;t=(r/2|0);){let t=i,e=o;if(i=s,o=a,i.isZero())throw new j("r_{i-1} was zero");s=t;let r=n.getZero();const h=i.getCoefficient(i.getDegree()),l=n.inverse(h);for(;s.getDegree()>=i.getDegree()&&!s.isZero();){const t=s.getDegree()-i.getDegree(),e=n.multiply(s.getCoefficient(s.getDegree()),l);r=r.addOrSubtract(n.buildMonomial(t,e)),s=s.addOrSubtract(i.multiplyByMonomial(t,e))}if(a=r.multiply(o).addOrSubtract(e),s.getDegree()>=i.getDegree())throw new J("Division algorithm failed to reduce polynomial?")}const h=a.getCoefficient(0);if(0===h)throw new j("sigmaTilde(0) was zero");const l=n.inverse(h);return[a.multiplyScalar(l),s.multiplyScalar(l)]}findErrorLocations(t){const e=t.getDegree();if(1===e)return Int32Array.from([t.getCoefficient(1)]);const r=new Int32Array(e);let n=0;const i=this.field;for(let s=1;s1,c,c+r-1),c+=r-1;else for(let t=r-1;t>=0;--t)l[c++]=!!(e&1<=8?tt.readCode(t,e,8):tt.readCode(t,e,r)<<8-r}static convertBoolArrayToByteArray(t){let e=new Uint8Array((t.length+7)/8);for(let r=0;r","?","[","]","{","}","CTRL_UL"],tt.DIGIT_TABLE=["CTRL_PS"," ","0","1","2","3","4","5","6","7","8","9",",",".","CTRL_UL","CTRL_US"];class et{constructor(){}static round(t){return isNaN(t)?0:t<=Number.MIN_SAFE_INTEGER?Number.MIN_SAFE_INTEGER:t>=Number.MAX_SAFE_INTEGER?Number.MAX_SAFE_INTEGER:t+(t<0?-.5:.5)|0}static distance(t,e,r,n){const i=t-r,s=e-n;return Math.sqrt(i*i+s*s)}static sum(t){let e=0;for(let r=0,n=t.length;r!==n;r++){e+=t[r]}return e}}class rt{static floatToIntBits(t){return t}}rt.MAX_VALUE=Number.MAX_SAFE_INTEGER;class nt{constructor(t,e){this.x=t,this.y=e}getX(){return this.x}getY(){return this.y}equals(t){if(t instanceof nt){const e=t;return this.x===e.x&&this.y===e.y}return!1}hashCode(){return 31*rt.floatToIntBits(this.x)+rt.floatToIntBits(this.y)}toString(){return"("+this.x+","+this.y+")"}static orderBestPatterns(t){const e=this.distance(t[0],t[1]),r=this.distance(t[1],t[2]),n=this.distance(t[0],t[2]);let i,s,o;if(r>=e&&r>=n?(s=t[0],i=t[1],o=t[2]):n>=r&&n>=e?(s=t[1],i=t[0],o=t[2]):(s=t[2],i=t[0],o=t[1]),this.crossProductZ(i,s,o)<0){const t=i;i=o,o=t}t[0]=i,t[1]=s,t[2]=o}static distance(t,e){return et.distance(t.x,t.y,e.x,e.y)}static crossProductZ(t,e,r){const n=e.x,i=e.y;return(r.x-n)*(t.y-i)-(r.y-i)*(t.x-n)}}class it{constructor(t,e){this.bits=t,this.points=e}getBits(){return this.bits}getPoints(){return this.points}}class st extends it{constructor(t,e,r,n,i){super(t,e),this.compact=r,this.nbDatablocks=n,this.nbLayers=i}getNbLayers(){return this.nbLayers}getNbDatablocks(){return this.nbDatablocks}isCompact(){return this.compact}}class ot{constructor(t,e,r,n){this.image=t,this.height=t.getHeight(),this.width=t.getWidth(),null==e&&(e=ot.INIT_SIZE),null==r&&(r=t.getWidth()/2|0),null==n&&(n=t.getHeight()/2|0);const i=e/2|0;if(this.leftInit=r-i,this.rightInit=r+i,this.upInit=n-i,this.downInit=n+i,this.upInit<0||this.leftInit<0||this.downInit>=this.height||this.rightInit>=this.width)throw new N}detect(){let t=this.leftInit,e=this.rightInit,r=this.upInit,n=this.downInit,i=!1,s=!0,o=!1,a=!1,h=!1,l=!1,c=!1;const d=this.width,u=this.height;for(;s;){s=!1;let g=!0;for(;(g||!a)&&e=d){i=!0;break}let f=!0;for(;(f||!h)&&n=u){i=!0;break}let w=!0;for(;(w||!l)&&t>=0;)w=this.containsBlackPoint(r,n,t,!1),w?(t--,s=!0,l=!0):l||t--;if(t<0){i=!0;break}let C=!0;for(;(C||!c)&&r>=0;)C=this.containsBlackPoint(t,e,r,!0),C?(r--,s=!0,c=!0):c||r--;if(r<0){i=!0;break}s&&(o=!0)}if(!i&&o){const i=e-t;let s=null;for(let e=1;null===s&&er||o<-1||o>n)throw new N;i=!1,-1===s?(e[t]=0,i=!0):s===r&&(e[t]=r-1,i=!0),-1===o?(e[t+1]=0,i=!0):o===n&&(e[t+1]=n-1,i=!0)}i=!0;for(let t=e.length-2;t>=0&&i;t-=2){const s=Math.floor(e[t]),o=Math.floor(e[t+1]);if(s<-1||s>r||o<-1||o>n)throw new N;i=!1,-1===s?(e[t]=0,i=!0):s===r&&(e[t]=r-1,i=!0),-1===o?(e[t+1]=0,i=!0):o===n&&(e[t+1]=n-1,i=!0)}}}class ht{constructor(t,e,r,n,i,s,o,a,h){this.a11=t,this.a21=e,this.a31=r,this.a12=n,this.a22=i,this.a32=s,this.a13=o,this.a23=a,this.a33=h}static quadrilateralToQuadrilateral(t,e,r,n,i,s,o,a,h,l,c,d,u,g,f,w){const C=ht.quadrilateralToSquare(t,e,r,n,i,s,o,a);return ht.squareToQuadrilateral(h,l,c,d,u,g,f,w).times(C)}transformPoints(t){const e=t.length,r=this.a11,n=this.a12,i=this.a13,s=this.a21,o=this.a22,a=this.a23,h=this.a31,l=this.a32,c=this.a33;for(let d=0;d>1&127):(n<<=10,n+=(e>>2&992)+(e>>1&31))}let i=this.getCorrectedParameterData(n,this.compact);this.compact?(this.nbLayers=1+(i>>6),this.nbDataBlocks=1+(63&i)):(this.nbLayers=1+(i>>11),this.nbDataBlocks=1+(2047&i))}getRotation(t,e){let r=0;t.forEach(((t,n,i)=>{r=(r<<3)+((t>>e-2<<1)+(1&t))})),r=((1&r)<<11)+(r>>1);for(let t=0;t<4;t++)if(w.bitCount(r^this.EXPECTED_CORNER_BITS[t])<=2)return t;throw new N}getCorrectedParameterData(t,e){let r,n;e?(r=7,n=2):(r=10,n=4);let i=r-n,s=new Int32Array(r);for(let e=r-1;e>=0;--e)s[e]=15&t,t>>=4;try{new $(Q.AZTEC_PARAM).decode(s,i)}catch(t){throw new N}let o=0;for(let t=0;t2){let r=this.distancePoint(h,t)*this.nbCenterLayers/(this.distancePoint(i,e)*(this.nbCenterLayers+2));if(r<.75||r>1.25||!this.isWhiteOrBlackRectangle(t,o,a,h))break}e=t,r=o,n=a,i=h,s=!s}if(5!==this.nbCenterLayers&&7!==this.nbCenterLayers)throw new N;this.compact=5===this.nbCenterLayers;let o=new nt(e.getX()+.5,e.getY()-.5),a=new nt(r.getX()+.5,r.getY()+.5),h=new nt(n.getX()-.5,n.getY()+.5),l=new nt(i.getX()-.5,i.getY()-.5);return this.expandSquare([o,a,h,l],2*this.nbCenterLayers-3,2*this.nbCenterLayers)}getMatrixCenter(){let t,e,r,n;try{let i=new ot(this.image).detect();t=i[0],e=i[1],r=i[2],n=i[3]}catch(i){let s=this.image.getWidth()/2,o=this.image.getHeight()/2;t=this.getFirstDifferent(new dt(s+7,o-7),!1,1,-1).toResultPoint(),e=this.getFirstDifferent(new dt(s+7,o+7),!1,1,1).toResultPoint(),r=this.getFirstDifferent(new dt(s-7,o+7),!1,-1,1).toResultPoint(),n=this.getFirstDifferent(new dt(s-7,o-7),!1,-1,-1).toResultPoint()}let i=et.round((t.getX()+n.getX()+e.getX()+r.getX())/4),s=et.round((t.getY()+n.getY()+e.getY()+r.getY())/4);try{let o=new ot(this.image,15,i,s).detect();t=o[0],e=o[1],r=o[2],n=o[3]}catch(o){t=this.getFirstDifferent(new dt(i+7,s-7),!1,1,-1).toResultPoint(),e=this.getFirstDifferent(new dt(i+7,s+7),!1,1,1).toResultPoint(),r=this.getFirstDifferent(new dt(i-7,s+7),!1,-1,1).toResultPoint(),n=this.getFirstDifferent(new dt(i-7,s-7),!1,-1,-1).toResultPoint()}return i=et.round((t.getX()+n.getX()+e.getX()+r.getX())/4),s=et.round((t.getY()+n.getY()+e.getY()+r.getY())/4),new dt(i,s)}getMatrixCornerPoints(t){return this.expandSquare(t,2*this.nbCenterLayers,this.getDimension())}sampleGrid(t,e,r,n,i){let s=ct.getInstance(),o=this.getDimension(),a=o/2-this.nbCenterLayers,h=o/2+this.nbCenterLayers;return s.sampleGrid(t,o,o,a,a,h,a,h,h,a,h,e.getX(),e.getY(),r.getX(),r.getY(),n.getX(),n.getY(),i.getX(),i.getY())}sampleLine(t,e,r){let n=0,i=this.distanceResultPoint(t,e),s=i/r,o=t.getX(),a=t.getY(),h=s*(e.getX()-t.getX())/i,l=s*(e.getY()-t.getY())/i;for(let t=0;t.1&&c<.9?0:c<=.1===h?1:-1}getFirstDifferent(t,e,r,n){let i=t.getX()+r,s=t.getY()+n;for(;this.isValid(i,s)&&this.image.get(i,s)===e;)i+=r,s+=n;for(i-=r,s-=n;this.isValid(i,s)&&this.image.get(i,s)===e;)i+=r;for(i-=r;this.isValid(i,s)&&this.image.get(i,s)===e;)s+=n;return s-=n,new dt(i,s)}expandSquare(t,e,r){let n=r/(2*e),i=t[0].getX()-t[2].getX(),s=t[0].getY()-t[2].getY(),o=(t[0].getX()+t[2].getX())/2,a=(t[0].getY()+t[2].getY())/2,h=new nt(o+n*i,a+n*s),l=new nt(o-n*i,a-n*s);return i=t[1].getX()-t[3].getX(),s=t[1].getY()-t[3].getY(),o=(t[1].getX()+t[3].getX())/2,a=(t[1].getY()+t[3].getY())/2,[h,new nt(o+n*i,a+n*s),l,new nt(o-n*i,a-n*s)]}isValid(t,e){return t>=0&&t0&&e{r.foundPossibleResultPoint(t)}))}}reset(){}}class ft{decode(t,e){try{return this.doDecode(t,e)}catch(r){if(e&&!0===e.get(E.TRY_HARDER)&&t.isRotateSupported()){const r=t.rotateCounterClockwise(),n=this.doDecode(r,e),i=n.getResultMetadata();let s=270;null!==i&&!0===i.get(z.ORIENTATION)&&(s+=i.get(z.ORIENTATION)%360),n.putMetadata(z.ORIENTATION,s);const o=n.getResultPoints();if(null!==o){const t=r.getHeight();for(let e=0;e>(s?8:5));let a;a=s?n:15;const h=Math.trunc(n/2);for(let s=0;s=n)break;try{i=t.getBlackRow(l,i)}catch(t){continue}for(let t=0;t<2;t++){if(1===t&&(i.reverse(),e&&!0===e.get(E.NEED_RESULT_POINT_CALLBACK))){const t=new Map;e.forEach(((e,r)=>t.set(r,e))),t.delete(E.NEED_RESULT_POINT_CALLBACK),e=t}try{const n=this.decodeRow(l,i,e);if(1===t){n.putMetadata(z.ORIENTATION,180);const t=n.getResultPoints();null!==t&&(t[0]=new nt(r-t[0].getX()-1,t[0].getY()),t[1]=new nt(r-t[1].getX()-1,t[1].getY()))}return n}catch(t){}}}throw new N}static recordPattern(t,e,r){const n=r.length;for(let t=0;t=i)throw new N;let s=!t.get(e),o=0,a=e;for(;a0&&n>=0;)t.get(--e)!==i&&(n--,i=!i);if(n>=0)throw new N;ft.recordPattern(t,e+1,r)}static patternMatchVariance(t,e,r){const n=t.length;let i=0,s=0;for(let r=0;rs?n-s:s-n;if(h>r)return Number.POSITIVE_INFINITY;a+=h}return a/i}}class wt extends ft{static findStartPattern(t){const e=t.getSize(),r=t.getNextSet(0);let n=0,i=Int32Array.from([0,0,0,0,0,0]),s=r,o=!1;for(let a=r;a=0&&t.isRange(Math.max(0,s-(a-s)/2),s,!1))return Int32Array.from([s,a,r]);s+=i[0]+i[1],i=i.slice(2,i.length),i[n-1]=0,i[n]=0,n--}else n++;i[n]=1,o=!o}throw new N}static decodeCode(t,e,r){ft.recordPattern(t,r,e);let n=wt.MAX_AVG_VARIANCE,i=-1;for(let t=0;t=0)return i;throw new N}decodeRow(t,e,r){const n=r&&!0===r.get(E.ASSUME_GS1),i=wt.findStartPattern(e),s=i[2];let o=0;const a=new Uint8Array(20);let h;switch(a[o++]=s,s){case wt.CODE_START_A:h=wt.CODE_CODE_A;break;case wt.CODE_START_B:h=wt.CODE_CODE_B;break;case wt.CODE_START_C:h=wt.CODE_CODE_C;break;default:throw new m}let c=!1,d=!1,u="",g=i[0],f=i[1];const w=Int32Array.from([0,0,0,0,0,0]);let C=0,A=0,I=s,_=0,S=!0,p=!1,T=!1;for(;!c;){const t=d;switch(d=!1,C=A,A=wt.decodeCode(e,w,f),a[o++]=A,A!==wt.CODE_STOP&&(S=!0),A!==wt.CODE_STOP&&(_++,I+=_*A),g=f,f+=w.reduce(((t,e)=>t+e),0),A){case wt.CODE_START_A:case wt.CODE_START_B:case wt.CODE_START_C:throw new m}switch(h){case wt.CODE_CODE_A:if(A<64)u+=T===p?String.fromCharCode(" ".charCodeAt(0)+A):String.fromCharCode(" ".charCodeAt(0)+A+128),T=!1;else if(A<96)u+=T===p?String.fromCharCode(A-64):String.fromCharCode(A+64),T=!1;else switch(A!==wt.CODE_STOP&&(S=!1),A){case wt.CODE_FNC_1:n&&(0===u.length?u+="]C1":u+=String.fromCharCode(29));break;case wt.CODE_FNC_2:case wt.CODE_FNC_3:break;case wt.CODE_FNC_4_A:!p&&T?(p=!0,T=!1):p&&T?(p=!1,T=!1):T=!0;break;case wt.CODE_SHIFT:d=!0,h=wt.CODE_CODE_B;break;case wt.CODE_CODE_B:h=wt.CODE_CODE_B;break;case wt.CODE_CODE_C:h=wt.CODE_CODE_C;break;case wt.CODE_STOP:c=!0}break;case wt.CODE_CODE_B:if(A<96)u+=T===p?String.fromCharCode(" ".charCodeAt(0)+A):String.fromCharCode(" ".charCodeAt(0)+A+128),T=!1;else switch(A!==wt.CODE_STOP&&(S=!1),A){case wt.CODE_FNC_1:n&&(0===u.length?u+="]C1":u+=String.fromCharCode(29));break;case wt.CODE_FNC_2:case wt.CODE_FNC_3:break;case wt.CODE_FNC_4_B:!p&&T?(p=!0,T=!1):p&&T?(p=!1,T=!1):T=!0;break;case wt.CODE_SHIFT:d=!0,h=wt.CODE_CODE_A;break;case wt.CODE_CODE_A:h=wt.CODE_CODE_A;break;case wt.CODE_CODE_C:h=wt.CODE_CODE_C;break;case wt.CODE_STOP:c=!0}break;case wt.CODE_CODE_C:if(A<100)A<10&&(u+="0"),u+=A;else switch(A!==wt.CODE_STOP&&(S=!1),A){case wt.CODE_FNC_1:n&&(0===u.length?u+="]C1":u+=String.fromCharCode(29));break;case wt.CODE_CODE_A:h=wt.CODE_CODE_A;break;case wt.CODE_CODE_B:h=wt.CODE_CODE_B;break;case wt.CODE_STOP:c=!0}}t&&(h=h===wt.CODE_CODE_A?wt.CODE_CODE_B:wt.CODE_CODE_A)}const R=f-g;if(f=e.getNextUnset(f),!e.isRange(f,Math.min(e.getSize(),f+(f-g)/2),!1))throw new N;if(I-=_*C,I%103!==C)throw new l;const y=u.length;if(0===y)throw new N;y>0&&S&&(u=h===wt.CODE_CODE_C?u.substring(0,y-2):u.substring(0,y-1));const D=(i[1]+i[0])/2,O=g+R/2,M=a.length,b=new Uint8Array(M);for(let t=0;tn&&(i=e);n=i,e=0;let s=0,o=0;for(let i=0;in&&(o|=1<0;i++){let r=t[i];if(r>n&&(e--,2*r>=s))return-1}return o}}while(e>3);return-1}static patternToChar(t){for(let e=0;e="A"&&i<="Z"))throw new m;s=String.fromCharCode(i.charCodeAt(0)+32);break;case"$":if(!(i>="A"&&i<="Z"))throw new m;s=String.fromCharCode(i.charCodeAt(0)-64);break;case"%":if(i>="A"&&i<="E")s=String.fromCharCode(i.charCodeAt(0)-38);else if(i>="F"&&i<="J")s=String.fromCharCode(i.charCodeAt(0)-11);else if(i>="K"&&i<="O")s=String.fromCharCode(i.charCodeAt(0)+16);else if(i>="P"&&i<="T")s=String.fromCharCode(i.charCodeAt(0)+43);else if("U"===i)s="\0";else if("V"===i)s="@";else if("W"===i)s="`";else{if("X"!==i&&"Y"!==i&&"Z"!==i)throw new m;s=""}break;case"/":if(i>="A"&&i<="O")s=String.fromCharCode(i.charCodeAt(0)-32);else{if("Z"!==i)throw new m;s=":"}}r+=s,n++}else r+=e}return r}}Ct.ALPHABET_STRING="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%",Ct.CHARACTER_ENCODINGS=[52,289,97,352,49,304,112,37,292,100,265,73,328,25,280,88,13,268,76,28,259,67,322,19,274,82,7,262,70,22,385,193,448,145,400,208,133,388,196,168,162,138,42],Ct.ASTERISK_ENCODING=148;class At extends ft{constructor(){super(),this.decodeRowResult="",this.counters=new Int32Array(6)}decodeRow(t,e,r){let n,i,s=this.findAsteriskPattern(e),o=e.getNextSet(s[1]),a=e.getSize(),h=this.counters;h.fill(0),this.decodeRowResult="";do{At.recordPattern(e,o,h);let t=this.toPattern(h);if(t<0)throw new N;n=this.patternToChar(t),this.decodeRowResult+=n,i=o;for(let t of h)o+=t;o=e.getNextSet(o)}while("*"!==n);this.decodeRowResult=this.decodeRowResult.substring(0,this.decodeRowResult.length-1);let l=0;for(let t of h)l+=t;if(o===a||!e.get(o))throw new N;if(this.decodeRowResult.length<2)throw new N;this.checkChecksums(this.decodeRowResult),this.decodeRowResult=this.decodeRowResult.substring(0,this.decodeRowResult.length-2);let c=this.decodeExtended(this.decodeRowResult),d=(s[1]+s[0])/2,u=i+l/2;return new v(c,null,0,[new nt(d,t),new nt(u,t)],x.CODE_93,(new Date).getTime())}findAsteriskPattern(t){let e=t.getSize(),r=t.getNextSet(0);this.counters.fill(0);let n=this.counters,i=r,s=!1,o=n.length,a=0;for(let h=r;h4)return-1;if(1&i)r<<=n;else for(let t=0;t="a"&&i<="d"){if(n>=e-1)throw new m;let s=t.charAt(n+1),o="\0";switch(i){case"d":if(!(s>="A"&&s<="Z"))throw new m;o=String.fromCharCode(s.charCodeAt(0)+32);break;case"a":if(!(s>="A"&&s<="Z"))throw new m;o=String.fromCharCode(s.charCodeAt(0)-64);break;case"b":if(s>="A"&&s<="E")o=String.fromCharCode(s.charCodeAt(0)-38);else if(s>="F"&&s<="J")o=String.fromCharCode(s.charCodeAt(0)-11);else if(s>="K"&&s<="O")o=String.fromCharCode(s.charCodeAt(0)+16);else if(s>="P"&&s<="T")o=String.fromCharCode(s.charCodeAt(0)+43);else if("U"===s)o="\0";else if("V"===s)o="@";else if("W"===s)o="`";else{if(!(s>="X"&&s<="Z"))throw new m;o=String.fromCharCode(127)}break;case"c":if(s>="A"&&s<="O")o=String.fromCharCode(s.charCodeAt(0)-32);else{if("Z"!==s)throw new m;o=":"}}r+=o,n++}else r+=i}return r}checkChecksums(t){let e=t.length;this.checkOneChecksum(t,e-2,20),this.checkOneChecksum(t,e-1,15)}checkOneChecksum(t,e,r){let n=1,i=0;for(let s=e-1;s>=0;s--)i+=n*At.ALPHABET_STRING.indexOf(t.charAt(s)),++n>r&&(n=1);if(t.charAt(e)!==At.ALPHABET_STRING[i%47])throw new l}}At.ALPHABET_STRING="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%abcd*",At.CHARACTER_ENCODINGS=[276,328,324,322,296,292,290,336,274,266,424,420,418,404,402,394,360,356,354,308,282,344,332,326,300,278,436,434,428,422,406,410,364,358,310,314,302,468,466,458,366,374,430,294,474,470,306,350],At.ASTERISK_ENCODING=At.CHARACTER_ENCODINGS[47];class Et extends ft{constructor(){super(...arguments),this.narrowLineWidth=-1}decodeRow(t,e,r){let n=this.decodeStart(e),i=this.decodeEnd(e),s=new T;Et.decodeMiddle(e,n[1],i[0],s);let o=s.toString(),a=null;null!=r&&(a=r.get(E.ALLOWED_LENGTHS)),null==a&&(a=Et.DEFAULT_ALLOWED_LENGTHS);let h=o.length,l=!1,c=0;for(let t of a){if(h===t){l=!0;break}t>c&&(c=t)}if(!l&&h>c&&(l=!0),!l)throw new m;const d=[new nt(n[1],t),new nt(i[0],t)];return new v(o,null,0,d,x.ITF,(new Date).getTime())}static decodeMiddle(t,e,r,n){let i=new Int32Array(10),s=new Int32Array(5),o=new Int32Array(5);for(i.fill(0),s.fill(0),o.fill(0);e0&&n>=0&&!t.get(n);n--)r--;if(0!==r)throw new N}static skipWhiteSpace(t){const e=t.getSize(),r=t.getNextSet(0);if(r===e)throw new N;return r}decodeEnd(t){t.reverse();try{let e,r=Et.skipWhiteSpace(t);try{e=Et.findGuardPattern(t,r,Et.END_PATTERN_REVERSED[0])}catch(n){n instanceof N&&(e=Et.findGuardPattern(t,r,Et.END_PATTERN_REVERSED[1]))}this.validateQuietZone(t,e[0]);let n=e[0];return e[0]=t.getSize()-e[1],e[1]=t.getSize()-n,e}finally{t.reverse()}}static findGuardPattern(t,e,r){let n=r.length,i=new Int32Array(n),s=t.getSize(),o=!1,a=0,h=e;i.fill(0);for(let l=e;l=0)return r%10;throw new N}}Et.PATTERNS=[Int32Array.from([1,1,2,2,1]),Int32Array.from([2,1,1,1,2]),Int32Array.from([1,2,1,1,2]),Int32Array.from([2,2,1,1,1]),Int32Array.from([1,1,2,1,2]),Int32Array.from([2,1,2,1,1]),Int32Array.from([1,2,2,1,1]),Int32Array.from([1,1,1,2,2]),Int32Array.from([2,1,1,2,1]),Int32Array.from([1,2,1,2,1]),Int32Array.from([1,1,3,3,1]),Int32Array.from([3,1,1,1,3]),Int32Array.from([1,3,1,1,3]),Int32Array.from([3,3,1,1,1]),Int32Array.from([1,1,3,1,3]),Int32Array.from([3,1,3,1,1]),Int32Array.from([1,3,3,1,1]),Int32Array.from([1,1,1,3,3]),Int32Array.from([3,1,1,3,1]),Int32Array.from([1,3,1,3,1])],Et.MAX_AVG_VARIANCE=.38,Et.MAX_INDIVIDUAL_VARIANCE=.5,Et.DEFAULT_ALLOWED_LENGTHS=[6,8,10,12,14],Et.START_PATTERN=Int32Array.from([1,1,1,1]),Et.END_PATTERN_REVERSED=[Int32Array.from([1,1,2]),Int32Array.from([1,1,3])];class mt extends ft{constructor(){super(...arguments),this.decodeRowStringBuffer=""}static findStartGuardPattern(t){let e,r=!1,n=0,i=Int32Array.from([0,0,0]);for(;!r;){i=Int32Array.from([0,0,0]),e=mt.findGuardPattern(t,n,!1,this.START_END_PATTERN,i);let s=e[0];n=e[1];let o=s-(n-s);o>=0&&(r=t.isRange(o,s,!1))}return e}static checkChecksum(t){return mt.checkStandardUPCEANChecksum(t)}static checkStandardUPCEANChecksum(t){let e=t.length;if(0===e)return!1;let r=parseInt(t.charAt(e-1),10);return mt.getStandardUPCEANChecksum(t.substring(0,e-1))===r}static getStandardUPCEANChecksum(t){let e=t.length,r=0;for(let n=e-1;n>=0;n-=2){let e=t.charAt(n).charCodeAt(0)-"0".charCodeAt(0);if(e<0||e>9)throw new m;r+=e}r*=3;for(let n=e-2;n>=0;n-=2){let e=t.charAt(n).charCodeAt(0)-"0".charCodeAt(0);if(e<0||e>9)throw new m;r+=e}return(1e3-r)%10}static decodeEnd(t,e){return mt.findGuardPattern(t,e,!1,mt.START_END_PATTERN,new Int32Array(mt.START_END_PATTERN.length).fill(0))}static findGuardPatternWithoutCounters(t,e,r,n){return this.findGuardPattern(t,e,r,n,new Int32Array(n.length))}static findGuardPattern(t,e,r,n,i){let s=t.getSize(),o=0,a=e=r?t.getNextUnset(e):t.getNextSet(e),h=n.length,l=r;for(let r=e;r=0)return s;throw new N}}mt.MAX_AVG_VARIANCE=.48,mt.MAX_INDIVIDUAL_VARIANCE=.7,mt.START_END_PATTERN=Int32Array.from([1,1,1]),mt.MIDDLE_PATTERN=Int32Array.from([1,1,1,1,1]),mt.END_PATTERN=Int32Array.from([1,1,1,1,1,1]),mt.L_PATTERNS=[Int32Array.from([3,2,1,1]),Int32Array.from([2,2,2,1]),Int32Array.from([2,1,2,2]),Int32Array.from([1,4,1,1]),Int32Array.from([1,1,3,2]),Int32Array.from([1,2,3,1]),Int32Array.from([1,1,1,4]),Int32Array.from([1,3,1,2]),Int32Array.from([1,2,1,3]),Int32Array.from([3,1,1,2])];class It{constructor(){this.CHECK_DIGIT_ENCODINGS=[24,20,18,17,12,6,3,10,9,5],this.decodeMiddleCounters=Int32Array.from([0,0,0,0]),this.decodeRowStringBuffer=""}decodeRow(t,e,r){let n=this.decodeRowStringBuffer,i=this.decodeMiddle(e,r,n),s=n.toString(),o=It.parseExtensionString(s),a=[new nt((r[0]+r[1])/2,t),new nt(i,t)],h=new v(s,null,0,a,x.UPC_EAN_EXTENSION,(new Date).getTime());return null!=o&&h.putAllMetadata(o),h}decodeMiddle(t,e,r){let n=this.decodeMiddleCounters;n[0]=0,n[1]=0,n[2]=0,n[3]=0;let i=t.getSize(),s=e[1],o=0;for(let e=0;e<5&&s=10&&(o|=1<<4-e),4!==e&&(s=t.getNextSet(s),s=t.getNextUnset(s))}if(5!==r.length)throw new N;let a=this.determineCheckDigit(o);if(It.extensionChecksum(r.toString())!==a)throw new N;return s}static extensionChecksum(t){let e=t.length,r=0;for(let n=e-2;n>=0;n-=2)r+=t.charAt(n).charCodeAt(0)-"0".charCodeAt(0);r*=3;for(let n=e-1;n>=0;n-=2)r+=t.charAt(n).charCodeAt(0)-"0".charCodeAt(0);return r*=3,r%10}determineCheckDigit(t){for(let e=0;e<10;e++)if(t===this.CHECK_DIGIT_ENCODINGS[e])return e;throw new N}static parseExtensionString(t){if(5!==t.length)return null;let e=It.parseExtension5String(t);return null==e?null:new Map([[z.SUGGESTED_PRICE,e]])}static parseExtension5String(t){let e;switch(t.charAt(0)){case"0":e="£";break;case"5":e="$";break;case"9":switch(t){case"90000":return null;case"99991":return"0.00";case"99990":return"Used"}e="";break;default:e=""}let r=parseInt(t.substring(1)),n=r%100;return e+(r/100).toString()+"."+(n<10?"0"+n:n.toString())}}class _t{constructor(){this.decodeMiddleCounters=Int32Array.from([0,0,0,0]),this.decodeRowStringBuffer=""}decodeRow(t,e,r){let n=this.decodeRowStringBuffer,i=this.decodeMiddle(e,r,n),s=n.toString(),o=_t.parseExtensionString(s),a=[new nt((r[0]+r[1])/2,t),new nt(i,t)],h=new v(s,null,0,a,x.UPC_EAN_EXTENSION,(new Date).getTime());return null!=o&&h.putAllMetadata(o),h}decodeMiddle(t,e,r){let n=this.decodeMiddleCounters;n[0]=0,n[1]=0,n[2]=0,n[3]=0;let i=t.getSize(),s=e[1],o=0;for(let e=0;e<2&&s=10&&(o|=1<<1-e),1!==e&&(s=t.getNextSet(s),s=t.getNextUnset(s))}if(2!==r.length)throw new N;if(parseInt(r.toString())%4!==o)throw new N;return s}static parseExtensionString(t){return 2!==t.length?null:new Map([[z.ISSUE_NUMBER,parseInt(t)]])}}class St{static decodeRow(t,e,r){let n=mt.findGuardPattern(e,r,!1,this.EXTENSION_START_PATTERN,new Int32Array(this.EXTENSION_START_PATTERN.length).fill(0));try{return(new It).decodeRow(t,e,n)}catch(r){return(new _t).decodeRow(t,e,n)}}}St.EXTENSION_START_PATTERN=Int32Array.from([1,1,2]);class pt extends mt{constructor(){super(),this.decodeRowStringBuffer="",pt.L_AND_G_PATTERNS=pt.L_PATTERNS.map((t=>Int32Array.from(t)));for(let t=10;t<20;t++){let e=pt.L_PATTERNS[t-10],r=new Int32Array(e.length);for(let t=0;t=e.getSize()||!e.isRange(c,d,!1))throw new N;let u=a.toString();if(u.length<8)throw new m;if(!pt.checkChecksum(u))throw new l;let g=(n[1]+n[0])/2,f=(h[1]+h[0])/2,w=this.getBarcodeFormat(),C=[new nt(g,t),new nt(f,t)],A=new v(u,null,0,C,w,(new Date).getTime()),I=0;try{let r=St.decodeRow(t,e,h[1]);A.putMetadata(z.UPC_EAN_EXTENSION,r.getText()),A.putAllMetadata(r.getResultMetadata()),A.addResultPoints(r.getResultPoints()),I=r.getText().length}catch(t){}let _=null==r?null:r.get(E.ALLOWED_EAN_EXTENSIONS);if(null!=_){let t=!1;for(let e in _)if(I.toString()===e){t=!0;break}if(!t)throw new N}return w===x.EAN_13||x.UPC_A,A}static checkChecksum(t){return pt.checkStandardUPCEANChecksum(t)}static checkStandardUPCEANChecksum(t){let e=t.length;if(0===e)return!1;let r=parseInt(t.charAt(e-1),10);return pt.getStandardUPCEANChecksum(t.substring(0,e-1))===r}static getStandardUPCEANChecksum(t){let e=t.length,r=0;for(let n=e-1;n>=0;n-=2){let e=t.charAt(n).charCodeAt(0)-"0".charCodeAt(0);if(e<0||e>9)throw new m;r+=e}r*=3;for(let n=e-2;n>=0;n-=2){let e=t.charAt(n).charCodeAt(0)-"0".charCodeAt(0);if(e<0||e>9)throw new m;r+=e}return(1e3-r)%10}static decodeEnd(t,e){return pt.findGuardPattern(t,e,!1,pt.START_END_PATTERN,new Int32Array(pt.START_END_PATTERN.length).fill(0))}}class Tt extends pt{constructor(){super(),this.decodeMiddleCounters=Int32Array.from([0,0,0,0])}decodeMiddle(t,e,r){let n=this.decodeMiddleCounters;n[0]=0,n[1]=0,n[2]=0,n[3]=0;let i=t.getSize(),s=e[1],o=0;for(let e=0;e<6&&s=10&&(o|=1<<5-e)}r=Tt.determineFirstDigit(r,o),s=pt.findGuardPattern(t,s,!0,pt.MIDDLE_PATTERN,new Int32Array(pt.MIDDLE_PATTERN.length).fill(0))[1];for(let e=0;e<6&&st));n[0]=0,n[1]=0,n[2]=0,n[3]=0;const i=t.getSize();let s=e[1],o=0;for(let e=0;e<6&&s=10&&(o|=1<<5-e)}return yt.determineNumSysAndCheckDigit(new T(r),o),s}decodeEnd(t,e){return yt.findGuardPatternWithoutCounters(t,e,!0,yt.MIDDLE_END_PATTERN)}checkChecksum(t){return pt.checkChecksum(yt.convertUPCEtoUPCA(t))}static determineNumSysAndCheckDigit(t,e){for(let r=0;r<=1;r++)for(let n=0;n<10;n++)if(e===this.NUMSYS_AND_CHECK_DIGIT_PATTERNS[r][n])return t.insert(0,"0"+r),void t.append("0"+n);throw N.getNotFoundInstance()}getBarcodeFormat(){return x.UPC_E}static convertUPCEtoUPCA(t){const e=t.slice(1,7).split("").map((t=>t.charCodeAt(0))),r=new T;r.append(t.charAt(0));let n=e[5];switch(n){case 0:case 1:case 2:r.appendChars(e,0,2),r.append(n),r.append("0000"),r.appendChars(e,2,3);break;case 3:r.appendChars(e,0,3),r.append("00000"),r.appendChars(e,3,2);break;case 4:r.appendChars(e,0,4),r.append("00000"),r.append(e[4]);break;default:r.appendChars(e,0,5),r.append("0000"),r.append(n)}return t.length>=8&&r.append(t.charAt(7)),r.toString()}}yt.MIDDLE_END_PATTERN=Int32Array.from([1,1,1,1,1,1]),yt.NUMSYS_AND_CHECK_DIGIT_PATTERNS=[Int32Array.from([56,52,50,49,44,38,35,42,41,37]),Int32Array.from([7,11,13,14,19,25,28,21,22,1])];class Dt extends ft{constructor(t){super();let e=null==t?null:t.get(E.POSSIBLE_FORMATS),r=[];null!=e&&(e.indexOf(x.EAN_13)>-1&&r.push(new Tt),e.indexOf(x.UPC_A)>-1&&r.push(new Nt),e.indexOf(x.EAN_8)>-1&&r.push(new Rt),e.indexOf(x.UPC_E)>-1&&r.push(new yt)),0===r.length&&(r.push(new Tt),r.push(new Nt),r.push(new Rt),r.push(new yt)),this.readers=r}decodeRow(t,e,r){for(let n of this.readers)try{const i=n.decodeRow(t,e,r),s=i.getBarcodeFormat()===x.EAN_13&&"0"===i.getText().charAt(0),o=null==r?null:r.get(E.POSSIBLE_FORMATS),a=null==o||o.includes(x.UPC_A);if(s&&a){const t=i.getRawBytes(),e=new v(i.getText().substring(1),t,t?t.length:null,i.getResultPoints(),x.UPC_A);return e.putAllMetadata(i.getResultMetadata()),e}return i}catch(t){}throw new N}reset(){for(let t of this.readers)t.reset()}}class Ot extends ft{constructor(){super(...arguments),this.CODA_BAR_CHAR_SET={nnnnnww:"0",nnnnwwn:"1",nnnwnnw:"2",wwnnnnn:"3",nnwnnwn:"4",wnnnnwn:"5",nwnnnnw:"6",nwnnwnn:"7",nwwnnnn:"8",wnnwnnn:"9",nnnwwnn:"-",nnwwnnn:"$",wnnnwnw:":",wnwnnnw:"/",wnwnwnn:".",nnwwwww:"+",nnwwnwn:"A",nwnwnnw:"B",nnnwnww:"C",nnnwwwn:"D"}}decodeRow(t,e,r){let n=this.getValidRowData(e);if(!n)throw new N;let i=this.codaBarDecodeRow(n.row);if(!i)throw new N;return new v(i,null,0,[new nt(n.left,t),new nt(n.right,t)],x.CODABAR,(new Date).getTime())}getValidRowData(t){let e=t.toArray(),r=e.indexOf(!0);if(-1===r)return null;let n=e.lastIndexOf(!0);if(n<=r)return null;e=e.slice(r,n+1);let i=[],s=e[0],o=1;for(let t=1;t(t+e)/2),0));for(;t.length>0;){const n=t.splice(0,8).splice(0,7).map((t=>tn&&(n=e[i],r=i);t[r]++}static decrement(t,e){let r=0,n=e[0];for(let i=1;i=Mt.MIN_FINDER_PATTERN_RATIO&&r<=Mt.MAX_FINDER_PATTERN_RATIO){let e=Number.MAX_SAFE_INTEGER,r=Number.MIN_SAFE_INTEGER;for(let n of t)n>r&&(r=n),n=o-a-1&&(t-=Pt.combins(n-h-(o-a),o-a-2)),o-a-1>1){let r=0;for(let t=n-h-(o-a-2);t>e;t--)r+=Pt.combins(n-h-t-1,o-a-3);t-=r*(o-1-a)}else n-h>e&&t--;i+=t}n-=h}return i}static combins(t,e){let r,n;t-e>e?(n=e,r=t-e):(n=t-e,r=e);let i=1,s=1;for(let e=t;e>r;e--)i*=e,s<=n&&(i/=s,s++);for(;s<=n;)i/=s,s++;return i}}class Lt{static buildBitArray(t){let e=2*t.length-1;null==t[t.length-1].getRightChar()&&(e-=1);let r=new C(12*e),n=0,i=t[0].getRightChar().getValue();for(let t=11;t>=0;--t)i&1<=0;--t)s&1<=0;--e)t&1<10||r<0||r>10)throw new m;this.firstDigit=e,this.secondDigit=r}getFirstDigit(){return this.firstDigit}getSecondDigit(){return this.secondDigit}getValue(){return 10*this.firstDigit+this.secondDigit}isFirstDigitFNC1(){return this.firstDigit===Vt.FNC1}isSecondDigitFNC1(){return this.secondDigit===Vt.FNC1}isAnyFNC1(){return this.firstDigit===Vt.FNC1||this.secondDigit===Vt.FNC1}}Vt.FNC1=10;class Ht{constructor(){}static parseFieldsInGeneralPurpose(t){if(!t)return null;if(t.length<2)throw new N;let e=t.substring(0,2);for(let r of Ht.TWO_DIGIT_DATA_LENGTH)if(r[0]===e)return r[1]===Ht.VARIABLE_LENGTH?Ht.processVariableAI(2,r[2],t):Ht.processFixedAI(2,r[1],t);if(t.length<3)throw new N;let r=t.substring(0,3);for(let e of Ht.THREE_DIGIT_DATA_LENGTH)if(e[0]===r)return e[1]===Ht.VARIABLE_LENGTH?Ht.processVariableAI(3,e[2],t):Ht.processFixedAI(3,e[1],t);for(let e of Ht.THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH)if(e[0]===r)return e[1]===Ht.VARIABLE_LENGTH?Ht.processVariableAI(4,e[2],t):Ht.processFixedAI(4,e[1],t);if(t.length<4)throw new N;let n=t.substring(0,4);for(let e of Ht.FOUR_DIGIT_DATA_LENGTH)if(e[0]===n)return e[1]===Ht.VARIABLE_LENGTH?Ht.processVariableAI(4,e[2],t):Ht.processFixedAI(4,e[1],t);throw new N}static processFixedAI(t,e,r){if(r.lengththis.information.getSize())return t+4<=this.information.getSize();for(let e=t;ethis.information.getSize()){let e=this.extractNumericValueFromBitArray(t,4);return new Vt(this.information.getSize(),0===e?Vt.FNC1:e-1,Vt.FNC1)}let e=this.extractNumericValueFromBitArray(t,7);return new Vt(t+7,(e-8)/11,(e-8)%11)}extractNumericValueFromBitArray(t,e){return Ut.extractNumericValueFromBitArray(this.information,t,e)}static extractNumericValueFromBitArray(t,e,r){let n=0;for(let i=0;ithis.information.getSize())return!1;let e=this.extractNumericValueFromBitArray(t,5);if(e>=5&&e<16)return!0;if(t+7>this.information.getSize())return!1;let r=this.extractNumericValueFromBitArray(t,7);if(r>=64&&r<116)return!0;if(t+8>this.information.getSize())return!1;let n=this.extractNumericValueFromBitArray(t,8);return n>=232&&n<253}decodeIsoIec646(t){let e=this.extractNumericValueFromBitArray(t,5);if(15===e)return new kt(t+5,kt.FNC1);if(e>=5&&e<15)return new kt(t+5,"0"+(e-5));let r,n=this.extractNumericValueFromBitArray(t,7);if(n>=64&&n<90)return new kt(t+7,""+(n+1));if(n>=90&&n<116)return new kt(t+7,""+(n+7));switch(this.extractNumericValueFromBitArray(t,8)){case 232:r="!";break;case 233:r='"';break;case 234:r="%";break;case 235:r="&";break;case 236:r="'";break;case 237:r="(";break;case 238:r=")";break;case 239:r="*";break;case 240:r="+";break;case 241:r=",";break;case 242:r="-";break;case 243:r=".";break;case 244:r="/";break;case 245:r=":";break;case 246:r=";";break;case 247:r="<";break;case 248:r="=";break;case 249:r=">";break;case 250:r="?";break;case 251:r="_";break;case 252:r=" ";break;default:throw new m}return new kt(t+8,r)}isStillAlpha(t){if(t+5>this.information.getSize())return!1;let e=this.extractNumericValueFromBitArray(t,5);if(e>=5&&e<16)return!0;if(t+6>this.information.getSize())return!1;let r=this.extractNumericValueFromBitArray(t,6);return r>=16&&r<63}decodeAlphanumeric(t){let e=this.extractNumericValueFromBitArray(t,5);if(15===e)return new kt(t+5,kt.FNC1);if(e>=5&&e<15)return new kt(t+5,"0"+(e-5));let r,n=this.extractNumericValueFromBitArray(t,6);if(n>=32&&n<58)return new kt(t+6,""+(n+33));switch(n){case 58:r="*";break;case 59:r=",";break;case 60:r="-";break;case 61:r=".";break;case 62:r="/";break;default:throw new J("Decoding invalid alphanumeric value: "+n)}return new kt(t+6,r)}isAlphaTo646ToAlphaLatch(t){if(t+1>this.information.getSize())return!1;for(let e=0;e<5&&e+tthis.information.getSize())return!1;for(let e=t;ethis.information.getSize())return!1;for(let e=0;e<4&&e+t{e.forEach((e=>{t.getLeftChar().getValue()===e.getLeftChar().getValue()&&t.getRightChar().getValue()===e.getRightChar().getValue()&&t.getFinderPatter().getValue()===e.getFinderPatter().getValue()&&(r=!0)}))})),r}}class re extends Mt{constructor(){super(...arguments),this.pairs=new Array(re.MAX_PAIRS),this.rows=new Array,this.startEnd=[2]}decodeRow(t,e,r){this.pairs.length=0,this.startFromEven=!1;try{return re.constructResult(this.decodeRow2pairs(t,e))}catch(t){}return this.pairs.length=0,this.startFromEven=!0,re.constructResult(this.decodeRow2pairs(t,e))}reset(){this.pairs.length=0,this.rows.length=0}decodeRow2pairs(t,e){let r,n=!1;for(;!n;)try{this.pairs.push(this.retrieveNextPair(e,this.pairs,t))}catch(t){if(t instanceof N){if(!this.pairs.length)throw new N;n=!0}}if(this.checkChecksum())return this.pairs;if(r=!!this.rows.length,this.storeRow(t,!1),r){let t=this.checkRowsBoolean(!1);if(null!=t)return t;if(t=this.checkRowsBoolean(!0),null!=t)return t}throw new N}checkRowsBoolean(t){if(this.rows.length>25)return this.rows.length=0,null;this.pairs.length=0,t&&(this.rows=this.rows.reverse());let e=null;try{e=this.checkRows(new Array,0)}catch(t){console.log(t)}return t&&(this.rows=this.rows.reverse()),e}checkRows(t,e){for(let r=e;re.length)continue;let r=!0;for(let n=0;nt){i=e.isEquivalent(this.pairs);break}n=e.isEquivalent(this.pairs),r++}i||n||re.isPartialRow(this.pairs,this.rows)||(this.rows.push(r,new ee(this.pairs,t,e)),this.removePartialRows(this.pairs,this.rows))}removePartialRows(t,e){for(let r of e)if(r.getPairs().length!==t.length)for(let e of r.getPairs())for(let r of t)if(te.equals(e,r))break}static isPartialRow(t,e){for(let r of e){let e=!0;for(let n of t){let t=!1;for(let e of r.getPairs())if(n.equals(e)){t=!0;break}if(!t){e=!1;break}}if(e)return!0}return!1}getRows(){return this.rows}static constructResult(t){let e=$t(Lt.buildBitArray(t)).parseInformation(),r=t[0].getFinderPattern().getResultPoints(),n=t[t.length-1].getFinderPattern().getResultPoints(),i=[r[0],r[1],n[0],n[1]];return new v(e,null,null,i,x.RSS_EXPANDED,null)}checkChecksum(){let t=this.pairs.get(0),e=t.getLeftChar(),r=t.getRightChar();if(null===r)return!1;let n=r.getChecksumPortion(),i=2;for(let t=1;t=0)i=r;else if(this.isEmptyPair(e))i=0;else{i=e[e.length-1].getFinderPattern().getStartEnd()[1]}let o=e.length%2!=0;this.startFromEven&&(o=!o);let a=!1;for(;i=0&&!t.get(e);)e--;e++,n=this.startEnd[0]-e,i=e,s=this.startEnd[1]}else i=this.startEnd[0],s=t.getNextUnset(this.startEnd[1]+1),n=s-this.startEnd[1];let o,a=this.getDecodeFinderCounters();d.arraycopy(a,0,a,1,a.length-1),a[0]=n;try{o=this.parseFinderValue(a,re.FINDER_PATTERNS)}catch(t){return null}return new Bt(o,[i,s],i,s,e)}decodeDataCharacter(t,e,r,n){let i=this.getDataCharacterCounters();for(let t=0;t.3)throw new N;let a=this.getOddCounts(),h=this.getEvenCounts(),l=this.getOddRoundingErrors(),c=this.getEvenRoundingErrors();for(let t=0;t8){if(e>8.7)throw new N;r=8}let n=t/2;1&t?(h[n]=r,c[n]=e-r):(a[n]=r,l[n]=e-r)}this.adjustOddEvenCounts(17);let d=4*e.getValue()+(r?0:2)+(n?0:1)-1,u=0,g=0;for(let t=a.length-1;t>=0;t--){if(re.isNotA1left(e,r,n)){let e=re.WEIGHTS[d][2*t];g+=a[t]*e}u+=a[t]}let f=0;for(let t=h.length-1;t>=0;t--)if(re.isNotA1left(e,r,n)){let e=re.WEIGHTS[d][2*t+1];f+=h[t]*e}let w=g+f;if(1&u||u>13||u<4)throw new N;let C=(13-u)/2,A=re.SYMBOL_WIDEST[C],E=9-A,m=Pt.getRSSvalue(a,A,!0),I=Pt.getRSSvalue(h,E,!1),_=re.EVEN_TOTAL_SUBSET[C],S=re.GSUM[C];return new bt(m*_+I+S,w)}static isNotA1left(t,e,r){return!(0===t.getValue()&&e&&r)}adjustOddEvenCounts(t){let e=et.sum(new Int32Array(this.getOddCounts())),r=et.sum(new Int32Array(this.getEvenCounts())),n=!1,i=!1;e>13?i=!0:e<4&&(n=!0);let s=!1,o=!1;r>13?o=!0:r<4&&(s=!0);let a=e+r-t,h=!(1&~e),l=!(1&r);if(1===a)if(h){if(l)throw new N;i=!0}else{if(!l)throw new N;o=!0}else if(-1===a)if(h){if(l)throw new N;n=!0}else{if(!l)throw new N;s=!0}else{if(0!==a)throw new N;if(h){if(!l)throw new N;e1)for(let e of this.possibleRightPairs)if(e.getCount()>1&&ie.checkChecksum(t,e))return ie.constructResult(t,e);throw new N}static addOrTally(t,e){if(null==e)return;let r=!1;for(let n of t)if(n.getValue()===e.getValue()){n.incrementCount(),r=!0;break}r||t.push(e)}reset(){this.possibleLeftPairs.length=0,this.possibleRightPairs.length=0}static constructResult(t,e){let r=4537077*t.getValue()+e.getValue(),n=new String(r).toString(),i=new T;for(let t=13-n.length;t>0;t--)i.append("0");i.append(n);let s=0;for(let t=0;t<13;t++){let e=i.charAt(t).charCodeAt(0)-"0".charCodeAt(0);s+=1&t?e:3*e}s=10-s%10,10===s&&(s=0),i.append(s.toString());let o=t.getFinderPattern().getResultPoints(),a=e.getFinderPattern().getResultPoints();return new v(i.toString(),null,0,[o[0],o[1],a[0],a[1]],x.RSS_14,(new Date).getTime())}static checkChecksum(t,e){let r=(t.getChecksumPortion()+16*e.getChecksumPortion())%79,n=9*t.getFinderPattern().getValue()+e.getFinderPattern().getValue();return n>72&&n--,n>8&&n--,r===n}decodePair(t,e,r,n){try{let i=this.findFinderPattern(t,e),s=this.parseFoundFinderPattern(t,r,e,i),o=null==n?null:n.get(E.NEED_RESULT_POINT_CALLBACK);if(null!=o){let n=(i[0]+i[1])/2;e&&(n=t.getSize()-1-n),o.foundPossibleResultPoint(new nt(n,r))}let a=this.decodeDataCharacter(t,s,!0),h=this.decodeDataCharacter(t,s,!1);return new ne(1597*a.getValue()+h.getValue(),a.getChecksumPortion()+4*h.getChecksumPortion(),s)}catch(t){return null}}decodeDataCharacter(t,e,r){let n=this.getDataCharacterCounters();for(let t=0;t8&&(r=8);let i=Math.floor(t/2);1&t?(a[i]=r,l[i]=e-r):(o[i]=r,h[i]=e-r)}this.adjustOddEvenCounts(r,i);let c=0,d=0;for(let t=o.length-1;t>=0;t--)d*=9,d+=o[t],c+=o[t];let u=0,g=0;for(let t=a.length-1;t>=0;t--)u*=9,u+=a[t],g+=a[t];let f=d+3*u;if(r){if(1&c||c>12||c<4)throw new N;let t=(12-c)/2,e=ie.OUTSIDE_ODD_WIDEST[t],r=9-e,n=Pt.getRSSvalue(o,e,!1),i=Pt.getRSSvalue(a,r,!0),s=ie.OUTSIDE_EVEN_TOTAL_SUBSET[t],h=ie.OUTSIDE_GSUM[t];return new bt(n*s+i+h,f)}{if(1&g||g>10||g<4)throw new N;let t=(10-g)/2,e=ie.INSIDE_ODD_WIDEST[t],r=9-e,n=Pt.getRSSvalue(o,e,!0),i=Pt.getRSSvalue(a,r,!1),s=ie.INSIDE_ODD_TOTAL_SUBSET[t],h=ie.INSIDE_GSUM[t];return new bt(i*s+n+h,f)}}findFinderPattern(t,e){let r=this.getDecodeFinderCounters();r[0]=0,r[1]=0,r[2]=0,r[3]=0;let n=t.getSize(),i=!1,s=0;for(;s=0&&i!==t.get(s);)s--;s++;const o=n[0]-s,a=this.getDecodeFinderCounters(),h=new Int32Array(a.length);d.arraycopy(a,0,h,1,a.length-1),h[0]=o;const l=this.parseFinderValue(h,ie.FINDER_PATTERNS);let c=s,u=n[1];return r&&(c=t.getSize()-1-c,u=t.getSize()-1-u),new Bt(l,[s,n[1]],c,u,e)}adjustOddEvenCounts(t,e){let r=et.sum(new Int32Array(this.getOddCounts())),n=et.sum(new Int32Array(this.getEvenCounts())),i=!1,s=!1,o=!1,a=!1;t?(r>12?s=!0:r<4&&(i=!0),n>12?a=!0:n<4&&(o=!0)):(r>11?s=!0:r<5&&(i=!0),n>10?a=!0:n<4&&(o=!0));let h=r+n-e,l=(1&r)==(t?1:0),c=!(1&~n);if(1===h)if(l){if(c)throw new N;s=!0}else{if(!c)throw new N;a=!0}else if(-1===h)if(l){if(c)throw new N;i=!0}else{if(!c)throw new N;o=!0}else{if(0!==h)throw new N;if(l){if(!c)throw new N;rt.reset()))}}class oe{constructor(t,e,r){this.ecCodewords=t,this.ecBlocks=[e],r&&this.ecBlocks.push(r)}getECCodewords(){return this.ecCodewords}getECBlocks(){return this.ecBlocks}}class ae{constructor(t,e){this.count=t,this.dataCodewords=e}getCount(){return this.count}getDataCodewords(){return this.dataCodewords}}class he{constructor(t,e,r,n,i,s){this.versionNumber=t,this.symbolSizeRows=e,this.symbolSizeColumns=r,this.dataRegionSizeRows=n,this.dataRegionSizeColumns=i,this.ecBlocks=s;let o=0;const a=s.getECCodewords(),h=s.getECBlocks();for(let t of h)o+=t.getCount()*(t.getDataCodewords()+a);this.totalCodewords=o}getVersionNumber(){return this.versionNumber}getSymbolSizeRows(){return this.symbolSizeRows}getSymbolSizeColumns(){return this.symbolSizeColumns}getDataRegionSizeRows(){return this.dataRegionSizeRows}getDataRegionSizeColumns(){return this.dataRegionSizeColumns}getTotalCodewords(){return this.totalCodewords}getECBlocks(){return this.ecBlocks}static getVersionForDimensions(t,e){if(1&t||1&e)throw new m;for(let r of he.VERSIONS)if(r.symbolSizeRows===t&&r.symbolSizeColumns===e)return r;throw new m}toString(){return""+this.versionNumber}static buildVersions(){return[new he(1,10,10,8,8,new oe(5,new ae(1,3))),new he(2,12,12,10,10,new oe(7,new ae(1,5))),new he(3,14,14,12,12,new oe(10,new ae(1,8))),new he(4,16,16,14,14,new oe(12,new ae(1,12))),new he(5,18,18,16,16,new oe(14,new ae(1,18))),new he(6,20,20,18,18,new oe(18,new ae(1,22))),new he(7,22,22,20,20,new oe(20,new ae(1,30))),new he(8,24,24,22,22,new oe(24,new ae(1,36))),new he(9,26,26,24,24,new oe(28,new ae(1,44))),new he(10,32,32,14,14,new oe(36,new ae(1,62))),new he(11,36,36,16,16,new oe(42,new ae(1,86))),new he(12,40,40,18,18,new oe(48,new ae(1,114))),new he(13,44,44,20,20,new oe(56,new ae(1,144))),new he(14,48,48,22,22,new oe(68,new ae(1,174))),new he(15,52,52,24,24,new oe(42,new ae(2,102))),new he(16,64,64,14,14,new oe(56,new ae(2,140))),new he(17,72,72,16,16,new oe(36,new ae(4,92))),new he(18,80,80,18,18,new oe(48,new ae(4,114))),new he(19,88,88,20,20,new oe(56,new ae(4,144))),new he(20,96,96,22,22,new oe(68,new ae(4,174))),new he(21,104,104,24,24,new oe(56,new ae(6,136))),new he(22,120,120,18,18,new oe(68,new ae(6,175))),new he(23,132,132,20,20,new oe(62,new ae(8,163))),new he(24,144,144,22,22,new oe(62,new ae(8,156),new ae(2,155))),new he(25,8,18,6,16,new oe(7,new ae(1,5))),new he(26,8,32,6,14,new oe(11,new ae(1,10))),new he(27,12,26,10,24,new oe(14,new ae(1,16))),new he(28,12,36,10,16,new oe(18,new ae(1,22))),new he(29,16,36,14,16,new oe(24,new ae(1,32))),new he(30,16,48,14,22,new oe(28,new ae(1,49)))]}}he.VERSIONS=he.buildVersions();class le{constructor(t){const e=t.getHeight();if(e<8||e>144||1&e)throw new m;this.version=le.readVersion(t),this.mappingBitMatrix=this.extractDataRegion(t),this.readMappingMatrix=new R(this.mappingBitMatrix.getWidth(),this.mappingBitMatrix.getHeight())}getVersion(){return this.version}static readVersion(t){const e=t.getHeight(),r=t.getWidth();return he.getVersionForDimensions(e,r)}readCodewords(){const t=new Int8Array(this.version.getTotalCodewords());let e=0,r=4,n=0;const i=this.mappingBitMatrix.getHeight(),s=this.mappingBitMatrix.getWidth();let o=!1,a=!1,h=!1,l=!1;do{if(r!==i||0!==n||o)if(r===i-2&&0===n&&3&s&&!a)t[e++]=255&this.readCorner2(i,s),r-=2,n+=2,a=!0;else if(r!==i+4||2!==n||7&s||h)if(r!==i-2||0!==n||4!=(7&s)||l){do{r=0&&!this.readMappingMatrix.get(n,r)&&(t[e++]=255&this.readUtah(r,n,i,s)),r-=2,n+=2}while(r>=0&&n=0&&n=0);r+=3,n+=1}else t[e++]=255&this.readCorner4(i,s),r-=2,n+=2,l=!0;else t[e++]=255&this.readCorner3(i,s),r-=2,n+=2,h=!0;else t[e++]=255&this.readCorner1(i,s),r-=2,n+=2,o=!0}while(r7?e-1:e;s[n].codewords[i]=t[c++]}if(c!==t.length)throw new a;return s}getNumDataCodewords(){return this.numDataCodewords}getCodewords(){return this.codewords}}class de{constructor(t){this.bytes=t,this.byteOffset=0,this.bitOffset=0}getBitOffset(){return this.bitOffset}getByteOffset(){return this.byteOffset}readBits(t){if(t<1||t>32||t>this.available())throw new a(""+t);let e=0,r=this.bitOffset,n=this.byteOffset;const i=this.bytes;if(r>0){const s=8-r,o=t>8-o<>a,t-=o,r+=o,8===r&&(r=0,n++)}if(t>0){for(;t>=8;)e=e<<8|255&i[n],n++,t-=8;if(t>0){const s=8-t,o=255>>s<>s,r+=t}}return this.bitOffset=r,this.byteOffset=n,e}available(){return 8*(this.bytes.length-this.byteOffset)-this.bitOffset}}!function(t){t[t.PAD_ENCODE=0]="PAD_ENCODE",t[t.ASCII_ENCODE=1]="ASCII_ENCODE",t[t.C40_ENCODE=2]="C40_ENCODE",t[t.TEXT_ENCODE=3]="TEXT_ENCODE",t[t.ANSIX12_ENCODE=4]="ANSIX12_ENCODE",t[t.EDIFACT_ENCODE=5]="EDIFACT_ENCODE",t[t.BASE256_ENCODE=6]="BASE256_ENCODE"}(H||(H={}));class ue{static decode(t){const e=new de(t),r=new T,n=new T,i=new Array;let s=H.ASCII_ENCODE;do{if(s===H.ASCII_ENCODE)s=this.decodeAsciiSegment(e,r,n);else{switch(s){case H.C40_ENCODE:this.decodeC40Segment(e,r);break;case H.TEXT_ENCODE:this.decodeTextSegment(e,r);break;case H.ANSIX12_ENCODE:this.decodeAnsiX12Segment(e,r);break;case H.EDIFACT_ENCODE:this.decodeEdifactSegment(e,r);break;case H.BASE256_ENCODE:this.decodeBase256Segment(e,r,i);break;default:throw new m}s=H.ASCII_ENCODE}}while(s!==H.PAD_ENCODE&&e.available()>0);return n.length()>0&&r.append(n.toString()),new Y(t,r.toString(),0===i.length?null:i,null)}static decodeAsciiSegment(t,e,r){let n=!1;do{let i=t.readBits(8);if(0===i)throw new m;if(i<=128)return n&&(i+=128),e.append(String.fromCharCode(i-1)),H.ASCII_ENCODE;if(129===i)return H.PAD_ENCODE;if(i<=229){const t=i-130;t<10&&e.append("0"),e.append(""+t)}else switch(i){case 230:return H.C40_ENCODE;case 231:return H.BASE256_ENCODE;case 232:e.append(String.fromCharCode(29));break;case 233:case 234:case 241:break;case 235:n=!0;break;case 236:e.append("[)>05"),r.insert(0,"");break;case 237:e.append("[)>06"),r.insert(0,"");break;case 238:return H.ANSIX12_ENCODE;case 239:return H.TEXT_ENCODE;case 240:return H.EDIFACT_ENCODE;default:if(254!==i||0!==t.available())throw new m}}while(t.available()>0);return H.ASCII_ENCODE}static decodeC40Segment(t,e){let r=!1;const n=[];let i=0;do{if(8===t.available())return;const s=t.readBits(8);if(254===s)return;this.parseTwoBytes(s,t.readBits(8),n);for(let t=0;t<3;t++){const s=n[t];switch(i){case 0:if(s<3)i=s+1;else{if(!(s0)}static decodeTextSegment(t,e){let r=!1,n=[],i=0;do{if(8===t.available())return;const s=t.readBits(8);if(254===s)return;this.parseTwoBytes(s,t.readBits(8),n);for(let t=0;t<3;t++){const s=n[t];switch(i){case 0:if(s<3)i=s+1;else{if(!(s0)}static decodeAnsiX12Segment(t,e){const r=[];do{if(8===t.available())return;const n=t.readBits(8);if(254===n)return;this.parseTwoBytes(n,t.readBits(8),r);for(let t=0;t<3;t++){const n=r[t];switch(n){case 0:e.append("\r");break;case 1:e.append("*");break;case 2:e.append(">");break;case 3:e.append(" ");break;default:if(n<14)e.append(String.fromCharCode(n+44));else{if(!(n<40))throw new m;e.append(String.fromCharCode(n+51))}}}}while(t.available()>0)}static parseTwoBytes(t,e,r){let n=(t<<8)+e-1,i=Math.floor(n/1600);r[0]=i,n-=1600*i,i=Math.floor(n/40),r[1]=i,r[2]=n-40*i}static decodeEdifactSegment(t,e){do{if(t.available()<=16)return;for(let r=0;r<4;r++){let r=t.readBits(6);if(31===r){const e=8-t.getBitOffset();return void(8!==e&&t.readBits(e))}32&r||(r|=64),e.append(String.fromCharCode(r))}}while(t.available()>0)}static decodeBase256Segment(t,e,r){let n=1+t.getByteOffset();const i=this.unrandomize255State(t.readBits(8),n++);let s;if(s=0===i?t.available()/8|0:i<250?i:250*(i-249)+this.unrandomize255State(t.readBits(8),n++),s<0)throw new m;const o=new Uint8Array(s);for(let e=0;e=0?r:r+256}}ue.C40_BASIC_SET_CHARS=["*","*","*"," ","0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"],ue.C40_SHIFT2_SET_CHARS=["!",'"',"#","$","%","&","'","(",")","*","+",",","-",".","/",":",";","<","=",">","?","@","[","\\","]","^","_"],ue.TEXT_BASIC_SET_CHARS=["*","*","*"," ","0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"],ue.TEXT_SHIFT2_SET_CHARS=ue.C40_SHIFT2_SET_CHARS,ue.TEXT_SHIFT3_SET_CHARS=["`","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","{","|","}","~",String.fromCharCode(127)];class ge{constructor(){this.rsDecoder=new $(Q.DATA_MATRIX_FIELD_256)}decode(t){const e=new le(t),r=e.getVersion(),n=e.readCodewords(),i=ce.getDataBlocks(n,r);let s=0;for(let t of i)s+=t.getNumDataCodewords();const o=new Uint8Array(s),a=i.length;for(let t=0;to&&(l=o,c[0]=e,c[1]=r,c[2]=n,c[3]=i),l>a&&(l=a,c[0]=r,c[1]=n,c[2]=i,c[3]=e),l>h&&(c[0]=n,c[1]=i,c[2]=e,c[3]=r),c}detectSolid2(t){let e=t[0],r=t[1],n=t[2],i=t[3],s=this.transitionsBetween(e,i),o=fe.shiftPoint(r,n,4*(s+1)),a=fe.shiftPoint(n,r,4*(s+1));return this.transitionsBetween(o,e)this.transitionsBetween(a,c)+this.transitionsBetween(h,c)?l:c:l:this.isValid(c)?c:null}shiftToModuleCenter(t){let e=t[0],r=t[1],n=t[2],i=t[3],s=this.transitionsBetween(e,i)+1,o=this.transitionsBetween(n,i)+1,a=fe.shiftPoint(e,r,4*o),h=fe.shiftPoint(n,r,4*s);s=this.transitionsBetween(a,i)+1,o=this.transitionsBetween(h,i)+1,1&~s||(s+=1),1&~o||(o+=1);let l,c,d=(e.getX()+r.getX()+n.getX()+i.getX())/4,u=(e.getY()+r.getY()+n.getY()+i.getY())/4;return e=fe.moveAway(e,d,u),r=fe.moveAway(r,d,u),n=fe.moveAway(n,d,u),i=fe.moveAway(i,d,u),a=fe.shiftPoint(e,r,4*o),a=fe.shiftPoint(a,i,4*s),l=fe.shiftPoint(r,e,4*o),l=fe.shiftPoint(l,n,4*s),h=fe.shiftPoint(n,i,4*o),h=fe.shiftPoint(h,r,4*s),c=fe.shiftPoint(i,n,4*o),c=fe.shiftPoint(c,e,4*s),[a,l,h,c]}isValid(t){return t.getX()>=0&&t.getX()0&&t.getY()Math.abs(i-r);if(o){let t=r;r=n,n=t,t=i,i=s,s=t}let a=Math.abs(i-r),h=Math.abs(s-n),l=-a/2,c=n0){if(e===s)break;e+=c,l-=a}}return u}}class we{constructor(){this.decoder=new ge}decode(t,e=null){let r,n;if(null!=e&&e.has(E.PURE_BARCODE)){const e=we.extractPureBits(t.getBlackMatrix());r=this.decoder.decode(e),n=we.NO_POINTS}else{const e=new fe(t.getBlackMatrix()).detect();r=this.decoder.decode(e.getBits()),n=e.getPoints()}const i=r.getRawBytes(),s=new v(r.getText(),i,8*i.length,n,x.DATA_MATRIX,d.currentTimeMillis()),o=r.getByteSegments();null!=o&&s.putMetadata(z.BYTE_SEGMENTS,o);const a=r.getECLevel();return null!=a&&s.putMetadata(z.ERROR_CORRECTION_LEVEL,a),s}reset(){}static extractPureBits(t){const e=t.getTopLeftOnBit(),r=t.getBottomRightOnBit();if(null==e||null==r)throw new N;const n=this.moduleSize(e,t);let i=e[1];const s=r[1];let o=e[0];const a=(r[0]-o+1)/n,h=(s-i+1)/n;if(a<=0||h<=0)throw new N;const l=n/2;i+=l,o+=l;const c=new R(a,h);for(let e=0;e=Ce.FOR_BITS.size)throw new a;return Ce.FOR_BITS.get(t)}}Ce.FOR_BITS=new Map,Ce.FOR_VALUE=new Map,Ce.L=new Ce(U.L,"L",1),Ce.M=new Ce(U.M,"M",0),Ce.Q=new Ce(U.Q,"Q",3),Ce.H=new Ce(U.H,"H",2);class Ae{constructor(t){this.errorCorrectionLevel=Ce.forBits(t>>3&3),this.dataMask=7&t}static numBitsDiffering(t,e){return w.bitCount(t^e)}static decodeFormatInformation(t,e){const r=Ae.doDecodeFormatInformation(t,e);return null!==r?r:Ae.doDecodeFormatInformation(t^Ae.FORMAT_INFO_MASK_QR,e^Ae.FORMAT_INFO_MASK_QR)}static doDecodeFormatInformation(t,e){let r=Number.MAX_SAFE_INTEGER,n=0;for(const i of Ae.FORMAT_INFO_DECODE_LOOKUP){const s=i[0];if(s===t||s===e)return new Ae(i[1]);let o=Ae.numBitsDiffering(t,s);o40)throw new a;return Ie.VERSIONS[t-1]}static decodeVersionInformation(t){let e=Number.MAX_SAFE_INTEGER,r=0;for(let n=0;n6&&(e.setRegion(t-11,0,3,6),e.setRegion(0,t-11,6,3)),e}toString(){return""+this.versionNumber}}Ie.VERSION_DECODE_INFO=Int32Array.from([31892,34236,39577,42195,48118,51042,55367,58893,63784,68472,70749,76311,79154,84390,87683,92361,96236,102084,102881,110507,110734,117786,119615,126325,127568,133589,136944,141498,145311,150283,152622,158308,161089,167017]),Ie.VERSIONS=[new Ie(1,new Int32Array(0),new Ee(7,new me(1,19)),new Ee(10,new me(1,16)),new Ee(13,new me(1,13)),new Ee(17,new me(1,9))),new Ie(2,Int32Array.from([6,18]),new Ee(10,new me(1,34)),new Ee(16,new me(1,28)),new Ee(22,new me(1,22)),new Ee(28,new me(1,16))),new Ie(3,Int32Array.from([6,22]),new Ee(15,new me(1,55)),new Ee(26,new me(1,44)),new Ee(18,new me(2,17)),new Ee(22,new me(2,13))),new Ie(4,Int32Array.from([6,26]),new Ee(20,new me(1,80)),new Ee(18,new me(2,32)),new Ee(26,new me(2,24)),new Ee(16,new me(4,9))),new Ie(5,Int32Array.from([6,30]),new Ee(26,new me(1,108)),new Ee(24,new me(2,43)),new Ee(18,new me(2,15),new me(2,16)),new Ee(22,new me(2,11),new me(2,12))),new Ie(6,Int32Array.from([6,34]),new Ee(18,new me(2,68)),new Ee(16,new me(4,27)),new Ee(24,new me(4,19)),new Ee(28,new me(4,15))),new Ie(7,Int32Array.from([6,22,38]),new Ee(20,new me(2,78)),new Ee(18,new me(4,31)),new Ee(18,new me(2,14),new me(4,15)),new Ee(26,new me(4,13),new me(1,14))),new Ie(8,Int32Array.from([6,24,42]),new Ee(24,new me(2,97)),new Ee(22,new me(2,38),new me(2,39)),new Ee(22,new me(4,18),new me(2,19)),new Ee(26,new me(4,14),new me(2,15))),new Ie(9,Int32Array.from([6,26,46]),new Ee(30,new me(2,116)),new Ee(22,new me(3,36),new me(2,37)),new Ee(20,new me(4,16),new me(4,17)),new Ee(24,new me(4,12),new me(4,13))),new Ie(10,Int32Array.from([6,28,50]),new Ee(18,new me(2,68),new me(2,69)),new Ee(26,new me(4,43),new me(1,44)),new Ee(24,new me(6,19),new me(2,20)),new Ee(28,new me(6,15),new me(2,16))),new Ie(11,Int32Array.from([6,30,54]),new Ee(20,new me(4,81)),new Ee(30,new me(1,50),new me(4,51)),new Ee(28,new me(4,22),new me(4,23)),new Ee(24,new me(3,12),new me(8,13))),new Ie(12,Int32Array.from([6,32,58]),new Ee(24,new me(2,92),new me(2,93)),new Ee(22,new me(6,36),new me(2,37)),new Ee(26,new me(4,20),new me(6,21)),new Ee(28,new me(7,14),new me(4,15))),new Ie(13,Int32Array.from([6,34,62]),new Ee(26,new me(4,107)),new Ee(22,new me(8,37),new me(1,38)),new Ee(24,new me(8,20),new me(4,21)),new Ee(22,new me(12,11),new me(4,12))),new Ie(14,Int32Array.from([6,26,46,66]),new Ee(30,new me(3,115),new me(1,116)),new Ee(24,new me(4,40),new me(5,41)),new Ee(20,new me(11,16),new me(5,17)),new Ee(24,new me(11,12),new me(5,13))),new Ie(15,Int32Array.from([6,26,48,70]),new Ee(22,new me(5,87),new me(1,88)),new Ee(24,new me(5,41),new me(5,42)),new Ee(30,new me(5,24),new me(7,25)),new Ee(24,new me(11,12),new me(7,13))),new Ie(16,Int32Array.from([6,26,50,74]),new Ee(24,new me(5,98),new me(1,99)),new Ee(28,new me(7,45),new me(3,46)),new Ee(24,new me(15,19),new me(2,20)),new Ee(30,new me(3,15),new me(13,16))),new Ie(17,Int32Array.from([6,30,54,78]),new Ee(28,new me(1,107),new me(5,108)),new Ee(28,new me(10,46),new me(1,47)),new Ee(28,new me(1,22),new me(15,23)),new Ee(28,new me(2,14),new me(17,15))),new Ie(18,Int32Array.from([6,30,56,82]),new Ee(30,new me(5,120),new me(1,121)),new Ee(26,new me(9,43),new me(4,44)),new Ee(28,new me(17,22),new me(1,23)),new Ee(28,new me(2,14),new me(19,15))),new Ie(19,Int32Array.from([6,30,58,86]),new Ee(28,new me(3,113),new me(4,114)),new Ee(26,new me(3,44),new me(11,45)),new Ee(26,new me(17,21),new me(4,22)),new Ee(26,new me(9,13),new me(16,14))),new Ie(20,Int32Array.from([6,34,62,90]),new Ee(28,new me(3,107),new me(5,108)),new Ee(26,new me(3,41),new me(13,42)),new Ee(30,new me(15,24),new me(5,25)),new Ee(28,new me(15,15),new me(10,16))),new Ie(21,Int32Array.from([6,28,50,72,94]),new Ee(28,new me(4,116),new me(4,117)),new Ee(26,new me(17,42)),new Ee(28,new me(17,22),new me(6,23)),new Ee(30,new me(19,16),new me(6,17))),new Ie(22,Int32Array.from([6,26,50,74,98]),new Ee(28,new me(2,111),new me(7,112)),new Ee(28,new me(17,46)),new Ee(30,new me(7,24),new me(16,25)),new Ee(24,new me(34,13))),new Ie(23,Int32Array.from([6,30,54,78,102]),new Ee(30,new me(4,121),new me(5,122)),new Ee(28,new me(4,47),new me(14,48)),new Ee(30,new me(11,24),new me(14,25)),new Ee(30,new me(16,15),new me(14,16))),new Ie(24,Int32Array.from([6,28,54,80,106]),new Ee(30,new me(6,117),new me(4,118)),new Ee(28,new me(6,45),new me(14,46)),new Ee(30,new me(11,24),new me(16,25)),new Ee(30,new me(30,16),new me(2,17))),new Ie(25,Int32Array.from([6,32,58,84,110]),new Ee(26,new me(8,106),new me(4,107)),new Ee(28,new me(8,47),new me(13,48)),new Ee(30,new me(7,24),new me(22,25)),new Ee(30,new me(22,15),new me(13,16))),new Ie(26,Int32Array.from([6,30,58,86,114]),new Ee(28,new me(10,114),new me(2,115)),new Ee(28,new me(19,46),new me(4,47)),new Ee(28,new me(28,22),new me(6,23)),new Ee(30,new me(33,16),new me(4,17))),new Ie(27,Int32Array.from([6,34,62,90,118]),new Ee(30,new me(8,122),new me(4,123)),new Ee(28,new me(22,45),new me(3,46)),new Ee(30,new me(8,23),new me(26,24)),new Ee(30,new me(12,15),new me(28,16))),new Ie(28,Int32Array.from([6,26,50,74,98,122]),new Ee(30,new me(3,117),new me(10,118)),new Ee(28,new me(3,45),new me(23,46)),new Ee(30,new me(4,24),new me(31,25)),new Ee(30,new me(11,15),new me(31,16))),new Ie(29,Int32Array.from([6,30,54,78,102,126]),new Ee(30,new me(7,116),new me(7,117)),new Ee(28,new me(21,45),new me(7,46)),new Ee(30,new me(1,23),new me(37,24)),new Ee(30,new me(19,15),new me(26,16))),new Ie(30,Int32Array.from([6,26,52,78,104,130]),new Ee(30,new me(5,115),new me(10,116)),new Ee(28,new me(19,47),new me(10,48)),new Ee(30,new me(15,24),new me(25,25)),new Ee(30,new me(23,15),new me(25,16))),new Ie(31,Int32Array.from([6,30,56,82,108,134]),new Ee(30,new me(13,115),new me(3,116)),new Ee(28,new me(2,46),new me(29,47)),new Ee(30,new me(42,24),new me(1,25)),new Ee(30,new me(23,15),new me(28,16))),new Ie(32,Int32Array.from([6,34,60,86,112,138]),new Ee(30,new me(17,115)),new Ee(28,new me(10,46),new me(23,47)),new Ee(30,new me(10,24),new me(35,25)),new Ee(30,new me(19,15),new me(35,16))),new Ie(33,Int32Array.from([6,30,58,86,114,142]),new Ee(30,new me(17,115),new me(1,116)),new Ee(28,new me(14,46),new me(21,47)),new Ee(30,new me(29,24),new me(19,25)),new Ee(30,new me(11,15),new me(46,16))),new Ie(34,Int32Array.from([6,34,62,90,118,146]),new Ee(30,new me(13,115),new me(6,116)),new Ee(28,new me(14,46),new me(23,47)),new Ee(30,new me(44,24),new me(7,25)),new Ee(30,new me(59,16),new me(1,17))),new Ie(35,Int32Array.from([6,30,54,78,102,126,150]),new Ee(30,new me(12,121),new me(7,122)),new Ee(28,new me(12,47),new me(26,48)),new Ee(30,new me(39,24),new me(14,25)),new Ee(30,new me(22,15),new me(41,16))),new Ie(36,Int32Array.from([6,24,50,76,102,128,154]),new Ee(30,new me(6,121),new me(14,122)),new Ee(28,new me(6,47),new me(34,48)),new Ee(30,new me(46,24),new me(10,25)),new Ee(30,new me(2,15),new me(64,16))),new Ie(37,Int32Array.from([6,28,54,80,106,132,158]),new Ee(30,new me(17,122),new me(4,123)),new Ee(28,new me(29,46),new me(14,47)),new Ee(30,new me(49,24),new me(10,25)),new Ee(30,new me(24,15),new me(46,16))),new Ie(38,Int32Array.from([6,32,58,84,110,136,162]),new Ee(30,new me(4,122),new me(18,123)),new Ee(28,new me(13,46),new me(32,47)),new Ee(30,new me(48,24),new me(14,25)),new Ee(30,new me(42,15),new me(32,16))),new Ie(39,Int32Array.from([6,26,54,82,110,138,166]),new Ee(30,new me(20,117),new me(4,118)),new Ee(28,new me(40,47),new me(7,48)),new Ee(30,new me(43,24),new me(22,25)),new Ee(30,new me(10,15),new me(67,16))),new Ie(40,Int32Array.from([6,30,58,86,114,142,170]),new Ee(30,new me(19,118),new me(6,119)),new Ee(28,new me(18,47),new me(31,48)),new Ee(30,new me(34,24),new me(34,25)),new Ee(30,new me(20,15),new me(61,16)))],function(t){t[t.DATA_MASK_000=0]="DATA_MASK_000",t[t.DATA_MASK_001=1]="DATA_MASK_001",t[t.DATA_MASK_010=2]="DATA_MASK_010",t[t.DATA_MASK_011=3]="DATA_MASK_011",t[t.DATA_MASK_100=4]="DATA_MASK_100",t[t.DATA_MASK_101=5]="DATA_MASK_101",t[t.DATA_MASK_110=6]="DATA_MASK_110",t[t.DATA_MASK_111=7]="DATA_MASK_111"}(X||(X={}));class _e{constructor(t,e){this.value=t,this.isMasked=e}unmaskBitMatrix(t,e){for(let r=0;r!(t+e&1)))],[X.DATA_MASK_001,new _e(X.DATA_MASK_001,((t,e)=>!(1&t)))],[X.DATA_MASK_010,new _e(X.DATA_MASK_010,((t,e)=>e%3==0))],[X.DATA_MASK_011,new _e(X.DATA_MASK_011,((t,e)=>(t+e)%3==0))],[X.DATA_MASK_100,new _e(X.DATA_MASK_100,((t,e)=>!(Math.floor(t/2)+Math.floor(e/3)&1)))],[X.DATA_MASK_101,new _e(X.DATA_MASK_101,((t,e)=>t*e%6==0))],[X.DATA_MASK_110,new _e(X.DATA_MASK_110,((t,e)=>t*e%6<3))],[X.DATA_MASK_111,new _e(X.DATA_MASK_111,((t,e)=>!(t+e+t*e%3&1)))]]);class Se{constructor(t){const e=t.getHeight();if(e<21||1!=(3&e))throw new m;this.bitMatrix=t}readFormatInformation(){if(null!==this.parsedFormatInfo&&void 0!==this.parsedFormatInfo)return this.parsedFormatInfo;let t=0;for(let e=0;e<6;e++)t=this.copyBit(e,8,t);t=this.copyBit(7,8,t),t=this.copyBit(8,8,t),t=this.copyBit(8,7,t);for(let e=5;e>=0;e--)t=this.copyBit(8,e,t);const e=this.bitMatrix.getHeight();let r=0;const n=e-7;for(let t=e-1;t>=n;t--)r=this.copyBit(8,t,r);for(let t=e-8;t=0;e--)for(let i=t-9;i>=n;i--)r=this.copyBit(i,e,r);let i=Ie.decodeVersionInformation(r);if(null!==i&&i.getDimensionForVersion()===t)return this.parsedVersion=i,i;r=0;for(let e=5;e>=0;e--)for(let i=t-9;i>=n;i--)r=this.copyBit(e,i,r);if(i=Ie.decodeVersionInformation(r),null!==i&&i.getDimensionForVersion()===t)return this.parsedVersion=i,i;throw new m}copyBit(t,e,r){return(this.isMirror?this.bitMatrix.get(e,t):this.bitMatrix.get(t,e))?r<<1|1:r<<1}readCodewords(){const t=this.readFormatInformation(),e=this.readVersion(),r=_e.values.get(t.getDataMask()),n=this.bitMatrix.getHeight();r.unmaskBitMatrix(this.bitMatrix,n);const i=e.buildFunctionPattern();let s=!0;const o=new Uint8Array(e.getTotalCodewords());let a=0,h=0,l=0;for(let t=n-1;t>0;t-=2){6===t&&t--;for(let e=0;e=0;){if(o[c].codewords.length===l)break;c--}c++;const d=l-n.getECCodewordsPerBlock();let u=0;for(let e=0;et.available())throw new m;const n=new Uint8Array(2*r);let i=0;for(;r>0;){const e=t.readBits(13);let s=e/96<<8&4294967295|e%96;s+=s<959?41377:42657,n[i]=s>>8&255,n[i+1]=255&s,i+=2,r--}try{e.append(S.decode(n,p.GB2312))}catch(t){throw new m(t)}}static decodeKanjiSegment(t,e,r){if(13*r>t.available())throw new m;const n=new Uint8Array(2*r);let i=0;for(;r>0;){const e=t.readBits(13);let s=e/192<<8&4294967295|e%192;s+=s<7936?33088:49472,n[i]=s>>8,n[i+1]=s,i+=2,r--}try{e.append(S.decode(n,p.SHIFT_JIS))}catch(t){throw new m(t)}}static decodeByteSegment(t,e,r,n,i,s){if(8*r>t.available())throw new m;const o=new Uint8Array(r);for(let e=0;e=Re.ALPHANUMERIC_CHARS.length)throw new m;return Re.ALPHANUMERIC_CHARS[t]}static decodeAlphanumericSegment(t,e,r,n){const i=e.length();for(;r>1;){if(t.available()<11)throw new m;const n=t.readBits(11);e.append(Re.toAlphaNumericChar(Math.floor(n/45))),e.append(Re.toAlphaNumericChar(n%45)),r-=2}if(1===r){if(t.available()<6)throw new m;e.append(Re.toAlphaNumericChar(t.readBits(6)))}if(n)for(let t=i;t=3;){if(t.available()<10)throw new m;const n=t.readBits(10);if(n>=1e3)throw new m;e.append(Re.toAlphaNumericChar(Math.floor(n/100))),e.append(Re.toAlphaNumericChar(Math.floor(n/10)%10)),e.append(Re.toAlphaNumericChar(n%10)),r-=3}if(2===r){if(t.available()<7)throw new m;const r=t.readBits(7);if(r>=100)throw new m;e.append(Re.toAlphaNumericChar(Math.floor(r/10))),e.append(Re.toAlphaNumericChar(r%10))}else if(1===r){if(t.available()<4)throw new m;const r=t.readBits(4);if(r>=10)throw new m;e.append(Re.toAlphaNumericChar(r))}}static parseECIValue(t){const e=t.readBits(8);if(!(128&e))return 127&e;if(128==(192&e)){return(63&e)<<8&4294967295|t.readBits(8)}if(192==(224&e)){return(31&e)<<16&4294967295|t.readBits(16)}throw new m}}Re.ALPHANUMERIC_CHARS="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:",Re.GB2312_SUBSET=1;class Ne{constructor(t){this.mirrored=t}isMirrored(){return this.mirrored}applyMirroredCorrection(t){if(!this.mirrored||null===t||t.length<3)return;const e=t[0];t[0]=t[2],t[2]=e}}class ye{constructor(){this.rsDecoder=new $(Q.QR_CODE_FIELD_256)}decodeBooleanArray(t,e){return this.decodeBitMatrix(R.parseFromBooleanArray(t),e)}decodeBitMatrix(t,e){const r=new Se(t);let n=null;try{return this.decodeBitMatrixParser(r,e)}catch(t){n=t}try{r.remask(),r.setMirror(!0),r.readVersion(),r.readFormatInformation(),r.mirror();const t=this.decodeBitMatrixParser(r,e);return t.setOther(new Ne(!0)),t}catch(t){if(null!==n)throw n;throw t}}decodeBitMatrixParser(t,e){const r=t.readVersion(),n=t.readFormatInformation().getErrorCorrectionLevel(),i=t.readCodewords(),s=pe.getDataBlocks(i,r,n);let o=0;for(const t of s)o+=t.getNumDataCodewords();const a=new Uint8Array(o);let h=0;for(const t of s){const e=t.getCodewords(),r=t.getNumDataCodewords();this.correctErrors(e,r);for(let t=0;t=r)return!1;return!0}crossCheckVertical(t,e,r,n){const i=this.image,s=i.getHeight(),o=this.crossCheckStateCount;o[0]=0,o[1]=0,o[2]=0;let a=t;for(;a>=0&&i.get(e,a)&&o[1]<=r;)o[1]++,a--;if(a<0||o[1]>r)return NaN;for(;a>=0&&!i.get(e,a)&&o[0]<=r;)o[0]++,a--;if(o[0]>r)return NaN;for(a=t+1;ar)return NaN;for(;ar)return NaN;const h=o[0]+o[1]+o[2];return 5*Math.abs(h-n)>=2*n?NaN:this.foundPatternCross(o)?Oe.centerFromEnd(o,a):NaN}handlePossibleCenter(t,e,r){const n=t[0]+t[1]+t[2],i=Oe.centerFromEnd(t,r),s=this.crossCheckVertical(e,i,2*t[1],n);if(!isNaN(s)){const e=(t[0]+t[1]+t[2])/3;for(const t of this.possibleCenters)if(t.aboutEquals(e,s,i))return t.combineEstimate(s,i,e);const r=new De(i,s,e);this.possibleCenters.push(r),null!==this.resultPointCallback&&void 0!==this.resultPointCallback&&this.resultPointCallback.foundPossibleResultPoint(r)}return null}}class Me extends nt{constructor(t,e,r,n){super(t,e),this.estimatedModuleSize=r,this.count=n,void 0===n&&(this.count=1)}getEstimatedModuleSize(){return this.estimatedModuleSize}getCount(){return this.count}aboutEquals(t,e,r){if(Math.abs(e-this.getY())<=t&&Math.abs(r-this.getX())<=t){const e=Math.abs(t-this.estimatedModuleSize);return e<=1||e<=this.estimatedModuleSize}return!1}combineEstimate(t,e,r){const n=this.count+1,i=(this.count*this.getX()+e)/n,s=(this.count*this.getY()+t)/n,o=(this.count*this.estimatedModuleSize+r)/n;return new Me(i,s,o,n)}}class be{constructor(t){this.bottomLeft=t[0],this.topLeft=t[1],this.topRight=t[2]}getBottomLeft(){return this.bottomLeft}getTopLeft(){return this.topLeft}getTopRight(){return this.topRight}}class Be{constructor(t,e){this.image=t,this.resultPointCallback=e,this.possibleCenters=[],this.crossCheckStateCount=new Int32Array(5),this.resultPointCallback=e}getImage(){return this.image}getPossibleCenters(){return this.possibleCenters}find(t){const e=null!=t&&void 0!==t.get(E.TRY_HARDER),r=null!=t&&void 0!==t.get(E.PURE_BARCODE),n=this.image,i=n.getHeight(),s=n.getWidth();let o=Math.floor(3*i/(4*Be.MAX_MODULES));(oh[2]&&(t+=e-h[2]-o,i=s-1)}e=0,h[0]=0,h[1]=0,h[2]=0,h[3]=0,h[4]=0}else h[0]=h[2],h[1]=h[3],h[2]=h[4],h[3]=1,h[4]=0,e=3;else h[++e]++;if(Be.foundPatternCross(h)){!0===this.handlePossibleCenter(h,t,s,r)&&(o=h[0],this.hasSkipped&&(a=this.haveMultiplyConfirmedCenters()))}}const l=this.selectBestPatterns();return nt.orderBestPatterns(l),new be(l)}static centerFromEnd(t,e){return e-t[4]-t[3]-t[2]/2}static foundPatternCross(t){let e=0;for(let r=0;r<5;r++){const n=t[r];if(0===n)return!1;e+=n}if(e<7)return!1;const r=e/7,n=r/2;return Math.abs(r-t[0])=s&&e>=s&&o.get(e-s,t-s);)i[2]++,s++;if(t=s&&e>=s&&!o.get(e-s,t-s)&&i[1]<=r;)i[1]++,s++;if(tr)return!1;for(;t>=s&&e>=s&&o.get(e-s,t-s)&&i[0]<=r;)i[0]++,s++;if(i[0]>r)return!1;const a=o.getHeight(),h=o.getWidth();for(s=1;t+s=a||e+s>=h)return!1;for(;t+s=a||e+s>=h||i[3]>=r)return!1;for(;t+s=r)return!1;const l=i[0]+i[1]+i[2]+i[3]+i[4];return Math.abs(l-n)<2*n&&Be.foundPatternCross(i)}crossCheckVertical(t,e,r,n){const i=this.image,s=i.getHeight(),o=this.getCrossCheckStateCount();let a=t;for(;a>=0&&i.get(e,a);)o[2]++,a--;if(a<0)return NaN;for(;a>=0&&!i.get(e,a)&&o[1]<=r;)o[1]++,a--;if(a<0||o[1]>r)return NaN;for(;a>=0&&i.get(e,a)&&o[0]<=r;)o[0]++,a--;if(o[0]>r)return NaN;for(a=t+1;a=r)return NaN;for(;a=r)return NaN;const h=o[0]+o[1]+o[2]+o[3]+o[4];return 5*Math.abs(h-n)>=2*n?NaN:Be.foundPatternCross(o)?Be.centerFromEnd(o,a):NaN}crossCheckHorizontal(t,e,r,n){const i=this.image,s=i.getWidth(),o=this.getCrossCheckStateCount();let a=t;for(;a>=0&&i.get(a,e);)o[2]++,a--;if(a<0)return NaN;for(;a>=0&&!i.get(a,e)&&o[1]<=r;)o[1]++,a--;if(a<0||o[1]>r)return NaN;for(;a>=0&&i.get(a,e)&&o[0]<=r;)o[0]++,a--;if(o[0]>r)return NaN;for(a=t+1;a=r)return NaN;for(;a=r)return NaN;const h=o[0]+o[1]+o[2]+o[3]+o[4];return 5*Math.abs(h-n)>=n?NaN:Be.foundPatternCross(o)?Be.centerFromEnd(o,a):NaN}handlePossibleCenter(t,e,r,n){const i=t[0]+t[1]+t[2]+t[3]+t[4];let s=Be.centerFromEnd(t,r),o=this.crossCheckVertical(e,Math.floor(s),t[2],i);if(!isNaN(o)&&(s=this.crossCheckHorizontal(Math.floor(s),Math.floor(o),t[2],i),!isNaN(s)&&(!n||this.crossCheckDiagonal(Math.floor(o),Math.floor(s),t[2],i)))){const t=i/7;let e=!1;const r=this.possibleCenters;for(let n=0,i=r.length;n=Be.CENTER_QUORUM){if(null!=t)return this.hasSkipped=!0,Math.floor((Math.abs(t.getX()-e.getX())-Math.abs(t.getY()-e.getY()))/2);t=e}return 0}haveMultiplyConfirmedCenters(){let t=0,e=0;const r=this.possibleCenters.length;for(const r of this.possibleCenters)r.getCount()>=Be.CENTER_QUORUM&&(t++,e+=r.getEstimatedModuleSize());if(t<3)return!1;const n=e/r;let i=0;for(const t of this.possibleCenters)i+=Math.abs(t.getEstimatedModuleSize()-n);return i<=.05*e}selectBestPatterns(){const t=this.possibleCenters.length;if(t<3)throw new N;const e=this.possibleCenters;let r;if(t>3){let n=0,i=0;for(const t of this.possibleCenters){const e=t.getEstimatedModuleSize();n+=e,i+=e*e}r=n/t;let s=Math.sqrt(i/t-r*r);e.sort(((t,e)=>{const n=Math.abs(e.getEstimatedModuleSize()-r),i=Math.abs(t.getEstimatedModuleSize()-r);return ni?1:0}));const o=Math.max(.2*r,s);for(let t=0;t3;t++){const n=e[t];Math.abs(n.getEstimatedModuleSize()-r)>o&&(e.splice(t,1),t--)}}if(e.length>3){let t=0;for(const r of e)t+=r.getEstimatedModuleSize();r=t/e.length,e.sort(((t,e)=>{if(e.getCount()===t.getCount()){const n=Math.abs(e.getEstimatedModuleSize()-r),i=Math.abs(t.getEstimatedModuleSize()-r);return ni?-1:0}return e.getCount()-t.getCount()})),e.splice(3)}return[e[0],e[1],e[2]]}}Be.CENTER_QUORUM=2,Be.MIN_SKIP=3,Be.MAX_MODULES=57;class Pe{constructor(t){this.image=t}getImage(){return this.image}getResultPointCallback(){return this.resultPointCallback}detect(t){this.resultPointCallback=null==t?null:t.get(E.NEED_RESULT_POINT_CALLBACK);const e=new Be(this.image,this.resultPointCallback).find(t);return this.processFinderPatternInfo(e)}processFinderPatternInfo(t){const e=t.getTopLeft(),r=t.getTopRight(),n=t.getBottomLeft(),i=this.calculateModuleSize(e,r,n);if(i<1)throw new N("No pattern found in proccess finder.");const s=Pe.computeDimension(e,r,n,i),o=Ie.getProvisionalVersionForDimension(s),a=o.getDimensionForVersion()-7;let h=null;if(o.getAlignmentPatternCenters().length>0){const t=r.getX()-e.getX()+n.getX(),s=r.getY()-e.getY()+n.getY(),o=1-3/a,l=Math.floor(e.getX()+o*(t-e.getX())),c=Math.floor(e.getY()+o*(s-e.getY()));for(let t=4;t<=16;t<<=1)try{h=this.findAlignmentInRegion(i,l,c,t);break}catch(t){if(!(t instanceof N))throw t}}const l=Pe.createTransform(e,r,n,h,s),c=Pe.sampleGrid(this.image,l,s);let d;return d=null===h?[n,e,r]:[n,e,r,h],new it(c,d)}static createTransform(t,e,r,n,i){const s=i-3.5;let o,a,h,l;return null!==n?(o=n.getX(),a=n.getY(),h=s-3,l=h):(o=e.getX()-t.getX()+r.getX(),a=e.getY()-t.getY()+r.getY(),h=s,l=s),ht.quadrilateralToQuadrilateral(3.5,3.5,s,3.5,h,l,3.5,s,t.getX(),t.getY(),e.getX(),e.getY(),o,a,r.getX(),r.getY())}static sampleGrid(t,e,r){return ct.getInstance().sampleGridWithTransform(t,r,r,e)}static computeDimension(t,e,r,n){const i=et.round(nt.distance(t,e)/n),s=et.round(nt.distance(t,r)/n);let o=Math.floor((i+s)/2)+7;switch(3&o){case 0:o++;break;case 2:o--;break;case 3:throw new N("Dimensions could be not found.")}return o}calculateModuleSize(t,e,r){return(this.calculateModuleSizeOneWay(t,e)+this.calculateModuleSizeOneWay(t,r))/2}calculateModuleSizeOneWay(t,e){const r=this.sizeOfBlackWhiteBlackRunBothWays(Math.floor(t.getX()),Math.floor(t.getY()),Math.floor(e.getX()),Math.floor(e.getY())),n=this.sizeOfBlackWhiteBlackRunBothWays(Math.floor(e.getX()),Math.floor(e.getY()),Math.floor(t.getX()),Math.floor(t.getY()));return isNaN(r)?n/7:isNaN(n)?r/7:(r+n)/14}sizeOfBlackWhiteBlackRunBothWays(t,e,r,n){let i=this.sizeOfBlackWhiteBlackRun(t,e,r,n),s=1,o=t-(r-t);o<0?(s=t/(t-o),o=0):o>=this.image.getWidth()&&(s=(this.image.getWidth()-1-t)/(o-t),o=this.image.getWidth()-1);let a=Math.floor(e-(n-e)*s);return s=1,a<0?(s=e/(e-a),a=0):a>=this.image.getHeight()&&(s=(this.image.getHeight()-1-e)/(a-e),a=this.image.getHeight()-1),o=Math.floor(t+(o-t)*s),i+=this.sizeOfBlackWhiteBlackRun(t,e,o,a),i-1}sizeOfBlackWhiteBlackRun(t,e,r,n){const i=Math.abs(n-e)>Math.abs(r-t);if(i){let i=t;t=e,e=i,i=r,r=n,n=i}const s=Math.abs(r-t),o=Math.abs(n-e);let a=-s/2;const h=t0){if(u===n)break;u+=l,a-=s}}return 2===c?et.distance(r+h,n,t,e):NaN}findAlignmentInRegion(t,e,r,n){const i=Math.floor(n*t),s=Math.max(0,e-i),o=Math.min(this.image.getWidth()-1,e+i);if(o-s<3*t)throw new N("Alignment top exceeds estimated module size.");const a=Math.max(0,r-i),h=Math.min(this.image.getHeight()-1,r+i);if(h-a<3*t)throw new N("Alignment bottom exceeds estimated module size.");return new Oe(this.image,s,a,o-s,h-a,t,this.resultPointCallback).find()}}class Le{constructor(){this.decoder=new ye}getDecoder(){return this.decoder}decode(t,e){let r,n;if(null!=e&&void 0!==e.get(E.PURE_BARCODE)){const i=Le.extractPureBits(t.getBlackMatrix());r=this.decoder.decodeBitMatrix(i,e),n=Le.NO_POINTS}else{const i=new Pe(t.getBlackMatrix()).detect(e);r=this.decoder.decodeBitMatrix(i.getBits(),e),n=i.getPoints()}r.getOther()instanceof Ne&&r.getOther().applyMirroredCorrection(n);const i=new v(r.getText(),r.getRawBytes(),void 0,n,x.QR_CODE,void 0),s=r.getByteSegments();null!==s&&i.putMetadata(z.BYTE_SEGMENTS,s);const o=r.getECLevel();return null!==o&&i.putMetadata(z.ERROR_CORRECTION_LEVEL,o),r.hasStructuredAppend()&&(i.putMetadata(z.STRUCTURED_APPEND_SEQUENCE,r.getStructuredAppendSequenceNumber()),i.putMetadata(z.STRUCTURED_APPEND_PARITY,r.getStructuredAppendParity())),i}reset(){}static extractPureBits(t){const e=t.getTopLeftOnBit(),r=t.getBottomRightOnBit();if(null===e||null===r)throw new N;const n=this.moduleSize(e,t);let i=e[1],s=r[1],o=e[0],a=r[0];if(o>=a||i>=s)throw new N;if(s-i!=a-o&&(a=o+(s-i),a>=t.getWidth()))throw new N;const h=Math.round((a-o+1)/n),l=Math.round((s-i+1)/n);if(h<=0||l<=0)throw new N;if(l!==h)throw new N;const c=Math.floor(n/2);i+=c,o+=c;const d=o+Math.floor((h-1)*n)-a;if(d>0){if(d>c)throw new N;o-=d}const u=i+Math.floor((l-1)*n)-s;if(u>0){if(u>c)throw new N;i-=u}const g=new R(h,l);for(let e=0;e0;){const o=ke.findGuardPattern(t,i,--n,r,!1,s,h);if(null==o){n++;break}e=o}o[0]=new nt(e[0],n),o[1]=new nt(e[1],n),a=!0;break}}let l=n+1;if(a){let n=0,i=Int32Array.from([Math.trunc(o[0].getX()),Math.trunc(o[1].getX())]);for(;lke.SKIPPED_ROW_COUNT_MAX)break;n++}}l-=n+1,o[2]=new nt(i[0],l),o[3]=new nt(i[1],l)}return l-n0&&h++s?n-s:s-n;if(h>r)return 1/0;a+=h}return a/i}}ke.INDEXES_START_PATTERN=Int32Array.from([0,4,1,5]),ke.INDEXES_STOP_PATTERN=Int32Array.from([6,2,7,3]),ke.MAX_AVG_VARIANCE=.42,ke.MAX_INDIVIDUAL_VARIANCE=.8,ke.START_PATTERN=Int32Array.from([8,1,1,1,1,1,1,3]),ke.STOP_PATTERN=Int32Array.from([7,1,1,3,1,1,1,2,1]),ke.MAX_PIXEL_DRIFT=3,ke.MAX_PATTERN_DRIFT=5,ke.SKIPPED_ROW_COUNT_MAX=25,ke.ROW_STEP=5,ke.BARCODE_MIN_HEIGHT=10;class xe{constructor(t,e){if(0===e.length)throw new a;this.field=t;let r=e.length;if(r>1&&0===e[0]){let t=1;for(;tr.length){let t=e;e=r,r=t}let n=new Int32Array(r.length),i=r.length-e.length;d.arraycopy(r,0,n,0,i);for(let t=i;t=0;e--){let r=this.getCoefficient(e);0!==r&&(r<0?(t.append(" - "),r=-r):t.length()>0&&t.append(" + "),0!==e&&1===r||t.append(r),0!==e&&(1===e?t.append("x"):(t.append("x^"),t.append(e))))}return t.toString()}}class Ve{add(t,e){return(t+e)%this.modulus}subtract(t,e){return(this.modulus+t-e)%this.modulus}exp(t){return this.expTable[t]}log(t){if(0===t)throw new a;return this.logTable[t]}inverse(t){if(0===t)throw new q;return this.expTable[this.modulus-this.logTable[t]-1]}multiply(t,e){return 0===t||0===e?0:this.expTable[(this.logTable[t]+this.logTable[e])%(this.modulus-1)]}getSize(){return this.modulus}equals(t){return t===this}}class He extends Ve{constructor(t,e){super(),this.modulus=t,this.expTable=new Int32Array(t),this.logTable=new Int32Array(t);let r=1;for(let n=0;n0;t--){let r=n.evaluateAt(this.field.exp(t));i[e-t]=r,0!==r&&(s=!0)}if(!s)return 0;let o=this.field.getOne();if(null!=r)for(const e of r){let r=this.field.exp(t.length-1-e),n=new xe(this.field,new Int32Array([this.field.subtract(0,r),1]));o=o.multiply(n)}let a=new xe(this.field,i),h=this.runEuclideanAlgorithm(this.field.buildMonomial(e,1),a,e),c=h[0],d=h[1],u=this.findErrorLocations(c),g=this.findErrorMagnitudes(d,c,u);for(let e=0;e=Math.round(r/2);){let t=n,e=s;if(n=i,s=o,n.isZero())throw l.getChecksumInstance();i=t;let r=this.field.getZero(),a=n.getCoefficient(n.getDegree()),h=this.field.inverse(a);for(;i.getDegree()>=n.getDegree()&&!i.isZero();){let t=i.getDegree()-n.getDegree(),e=this.field.multiply(i.getCoefficient(i.getDegree()),h);r=r.add(this.field.buildMonomial(t,e)),i=i.subtract(n.multiplyByMonomial(t,e))}o=r.multiply(s).subtract(e).negative()}let a=o.getCoefficient(0);if(0===a)throw l.getChecksumInstance();let h=this.field.inverse(a);return[o.multiply(h),i.multiply(h)]}findErrorLocations(t){let e=t.getDegree(),r=new Int32Array(e),n=0;for(let i=1;i0){let e=r?this.topLeft:this.topRight,i=Math.trunc(e.getY()-t);i<0&&(i=0);let o=new nt(e.getX(),i);r?n=o:s=o}if(e>0){let t=r?this.bottomLeft:this.bottomRight,n=Math.trunc(t.getY()+e);n>=this.image.getHeight()&&(n=this.image.getHeight()-1);let s=new nt(t.getX(),n);r?i=s:o=s}return new Xe(this.image,n,i,s,o)}getMinX(){return this.minX}getMaxX(){return this.maxX}getMinY(){return this.minY}getMaxY(){return this.maxY}getTopLeft(){return this.topLeft}getTopRight(){return this.topRight}getBottomLeft(){return this.bottomLeft}getBottomRight(){return this.bottomRight}}class Ge{constructor(t,e,r,n){this.columnCount=t,this.errorCorrectionLevel=n,this.rowCountUpperPart=e,this.rowCountLowerPart=r,this.rowCount=e+r}getColumnCount(){return this.columnCount}getErrorCorrectionLevel(){return this.errorCorrectionLevel}getRowCount(){return this.rowCount}getRowCountUpperPart(){return this.rowCountUpperPart}getRowCountLowerPart(){return this.rowCountLowerPart}}class We{constructor(){this.buffer=""}static form(t,e){let r=-1;return t.replace(/%(-)?(0?[0-9]+)?([.][0-9]+)?([#][0-9]+)?([scfpexd%])/g,(function(t,n,i,s,o,a){if("%%"===t)return"%";if(void 0===e[++r])return;t=s?parseInt(s.substr(1)):void 0;let h,l=o?parseInt(o.substr(1)):void 0;switch(a){case"s":h=e[r];break;case"c":h=e[r][0];break;case"f":h=parseFloat(e[r]).toFixed(t);break;case"p":h=parseFloat(e[r]).toPrecision(t);break;case"e":h=parseFloat(e[r]).toExponential(t);break;case"x":h=parseInt(e[r]).toString(l||16);break;case"d":h=parseFloat(parseInt(e[r],l||10).toPrecision(t)).toFixed(0)}h="object"==typeof h?JSON.stringify(h):(+h).toString(l);let c=parseInt(i),d=i&&i[0]+""=="0"?"0":" ";for(;h.length=0&&(e=this.codewords[n],null!=e))return e;if(n=this.imageRowToCodewordIndex(t)+r,nr,getValue:()=>n};i.getValue()>t?(t=i.getValue(),e=[],e.push(i.getKey())):i.getValue()===t&&e.push(i.getKey())}return Fe.toIntArray(e)}getConfidence(t){return this.values.get(t)}}class Ze extends ze{constructor(t,e){super(t),this._isLeft=e}setRowNumbers(){for(let t of this.getCodewords())null!=t&&t.setRowNumberAsRowIndicatorColumn()}adjustCompleteIndicatorColumnRowNumbers(t){let e=this.getCodewords();this.setRowNumbers(),this.removeIncorrectCodewords(e,t);let r=this.getBoundingBox(),n=this._isLeft?r.getTopLeft():r.getTopRight(),i=this._isLeft?r.getBottomLeft():r.getBottomRight(),s=this.imageRowToCodewordIndex(Math.trunc(n.getY())),o=this.imageRowToCodewordIndex(Math.trunc(i.getY())),a=-1,h=1,l=0;for(let r=s;r=t.getRowCount()||i>r)e[r]=null;else{let t;t=h>2?(h-2)*i:i;let s=t>=r;for(let n=1;n<=t&&!s;n++)s=null!=e[r-n];s?e[r]=null:(a=n.getRowNumber(),l=1)}}}getRowHeights(){let t=this.getBarcodeMetadata();if(null==t)return null;this.adjustIncompleteIndicatorColumnRowNumbers(t);let e=new Int32Array(t.getRowCount());for(let t of this.getCodewords())if(null!=t){let r=t.getRowNumber();if(r>=e.length)continue;e[r]++}return e}adjustIncompleteIndicatorColumnRowNumbers(t){let e=this.getBoundingBox(),r=this._isLeft?e.getTopLeft():e.getTopRight(),n=this._isLeft?e.getBottomLeft():e.getBottomRight(),i=this.imageRowToCodewordIndex(Math.trunc(r.getY())),s=this.imageRowToCodewordIndex(Math.trunc(n.getY())),o=this.getCodewords(),a=-1;for(let e=i;e=t.getRowCount()?o[e]=null:a=r.getRowNumber())}}getBarcodeMetadata(){let t=this.getCodewords(),e=new Ye,r=new Ye,n=new Ye,i=new Ye;for(let s of t){if(null==s)continue;s.setRowNumberAsRowIndicatorColumn();let t=s.getValue()%30,o=s.getRowNumber();switch(this._isLeft||(o+=2),o%3){case 0:r.setValue(3*t+1);break;case 1:i.setValue(t/3),n.setValue(t%3);break;case 2:e.setValue(t+1)}}if(0===e.getValue().length||0===r.getValue().length||0===n.getValue().length||0===i.getValue().length||e.getValue()[0]<1||r.getValue()[0]+n.getValue()[0]Fe.MAX_ROWS_IN_BARCODE)return null;let s=new Ge(e.getValue()[0],r.getValue()[0],n.getValue()[0],i.getValue()[0]);return this.removeIncorrectCodewords(t,s),s}removeIncorrectCodewords(t,e){for(let r=0;re.getRowCount())t[r]=null;else switch(this._isLeft||(s+=2),s%3){case 0:3*i+1!==e.getRowCountUpperPart()&&(t[r]=null);break;case 1:Math.trunc(i/3)===e.getErrorCorrectionLevel()&&i%3===e.getRowCountLowerPart()||(t[r]=null);break;case 2:i+1!==e.getColumnCount()&&(t[r]=null)}}}isLeft(){return this._isLeft}toString(){return"IsLeft: "+this._isLeft+"\n"+super.toString()}}class Ke{constructor(t,e){this.ADJUST_ROW_NUMBER_SKIP=2,this.barcodeMetadata=t,this.barcodeColumnCount=t.getColumnCount(),this.boundingBox=e,this.detectionResultColumns=new Array(this.barcodeColumnCount+2)}getDetectionResultColumns(){this.adjustIndicatorColumnRowNumbers(this.detectionResultColumns[0]),this.adjustIndicatorColumnRowNumbers(this.detectionResultColumns[this.barcodeColumnCount+1]);let t,e=Fe.MAX_CODEWORDS_IN_BARCODE;do{t=e,e=this.adjustRowNumbersAndGetCount()}while(e>0&&e0&&i0&&(o[0]=r[e-1],o[4]=i[e-1],o[5]=s[e-1]),e>1&&(o[8]=r[e-2],o[10]=i[e-2],o[11]=s[e-2]),e>=1;r=1&e,Qe.RATIOS_TABLE[t]||(Qe.RATIOS_TABLE[t]=new Array(Fe.BARS_IN_MODULE)),Qe.RATIOS_TABLE[t][Fe.BARS_IN_MODULE-n-1]=Math.fround(i/Fe.MODULES_IN_CODEWORD)}}this.bSymbolTableReady=!0}static getDecodedValue(t){let e=Qe.getDecodedCodewordValue(Qe.sampleBitCounts(t));return-1!==e?e:Qe.getClosestDecodedValue(t)}static sampleBitCounts(t){let e=et.sum(t),r=new Int32Array(Fe.BARS_IN_MODULE),n=0,i=0;for(let s=0;s1)for(let n=0;n=n)break}enew Array(Fe.BARS_IN_MODULE)));class je{constructor(){this.segmentCount=-1,this.fileSize=-1,this.timestamp=-1,this.checksum=-1}getSegmentIndex(){return this.segmentIndex}setSegmentIndex(t){this.segmentIndex=t}getFileId(){return this.fileId}setFileId(t){this.fileId=t}getOptionalData(){return this.optionalData}setOptionalData(t){this.optionalData=t}isLastSegment(){return this.lastSegment}setLastSegment(t){this.lastSegment=t}getSegmentCount(){return this.segmentCount}setSegmentCount(t){this.segmentCount=t}getSender(){return this.sender||null}setSender(t){this.sender=t}getAddressee(){return this.addressee||null}setAddressee(t){this.addressee=t}getFileName(){return this.fileName}setFileName(t){this.fileName=t}getFileSize(){return this.fileSize}setFileSize(t){this.fileSize=t}getChecksum(){return this.checksum}setChecksum(t){this.checksum=t}getTimestamp(){return this.timestamp}setTimestamp(t){this.timestamp=t}}class Je{static parseLong(t,e=void 0){return parseInt(t,e)}}class $e extends s{}$e.kind="NullPointerException";class tr{writeBytes(t){this.writeBytesOffset(t,0,t.length)}writeBytesOffset(t,e,r){if(null==t)throw new $e;if(e<0||e>t.length||r<0||e+r>t.length||e+r<0)throw new u;if(0!==r)for(let n=0;n0&&this.grow(t)}grow(t){let e=this.buf.length<<1;if(e-t<0&&(e=t),e<0){if(t<0)throw new er;e=w.MAX_VALUE}this.buf=f.copyOfUint8Array(this.buf,e)}write(t){this.ensureCapacity(this.count+1),this.buf[this.count]=t,this.count+=1}writeBytesOffset(t,e,r){if(e<0||e>t.length||r<0||e+r-t.length>0)throw new u;this.ensureCapacity(this.count+r),d.arraycopy(t,e,this.buf,this.count,r),this.count+=r}writeTo(t){t.writeBytesOffset(this.buf,0,this.count)}reset(){this.count=0}toByteArray(){return f.copyOfUint8Array(this.buf,this.count)}size(){return this.count}toString(t){return t?"string"==typeof t?this.toString_string(t):this.toString_number(t):this.toString_void()}toString_void(){return new String(this.buf).toString()}toString_string(t){return new String(this.buf).toString()}toString_number(t){return new String(this.buf).toString()}close(){}}function nr(){if("undefined"!=typeof window)return window.BigInt||null;if("undefined"!=typeof global)return global.BigInt||null;if("undefined"!=typeof self)return self.BigInt||null;throw new Error("Can't search globals for BigInt!")}let ir;function sr(t){if(void 0===ir&&(ir=nr()),null===ir)throw new Error("BigInt is not supported!");return ir(t)}!function(t){t[t.ALPHA=0]="ALPHA",t[t.LOWER=1]="LOWER",t[t.MIXED=2]="MIXED",t[t.PUNCT=3]="PUNCT",t[t.ALPHA_SHIFT=4]="ALPHA_SHIFT",t[t.PUNCT_SHIFT=5]="PUNCT_SHIFT"}(W||(W={}));class or{static decode(t,e){let r=new T(""),n=I.ISO8859_1;r.enableDecoding(n);let i=1,s=t[i++],o=new je;for(;it[0])throw m.getFormatInstance();let n=new Int32Array(or.NUMBER_OF_SEQUENCE_CODEWORDS);for(let r=0;r0){for(let t=0;t<6;++t)s.write(Number(sr(a)>>sr(8*(5-t))));a=0,o=0}}n===e[0]&&r0){for(let t=0;t<6;++t)s.write(Number(sr(a)>>sr(8*(5-t))));a=0,o=0}}}return i.append(S.decode(s.toByteArray(),r)),n}static numericCompaction(t,e,r){let n=0,i=!1,s=new Int32Array(or.MAX_NUMERIC_CODEWORDS);for(;e0&&(r.append(or.decodeBase900toBase10(s,n)),n=0)}return e}static decodeBase900toBase10(t,e){let r=sr(0);for(let n=0;n@[\\]_`~!\r\t,:\n-.$/\"|*()?{}'",or.MIXED_CHARS="0123456789&\r\t,:#-.$/+%*=^",or.EXP900=nr()?function(){let t=[];t[0]=sr(1);let e=sr(900);t[1]=e;for(let r=2;r<16;r++)t[r]=t[r-1]*e;return t}():[],or.NUMBER_OF_SEQUENCE_CODEWORDS=2;class ar{constructor(){}static decode(t,e,r,n,i,s,o){let a,h=new Xe(t,e,r,n,i),l=null,c=null;for(let r=!0;;r=!1){if(null!=e&&(l=ar.getRowIndicatorColumn(t,h,e,!0,s,o)),null!=n&&(c=ar.getRowIndicatorColumn(t,h,n,!1,s,o)),a=ar.merge(l,c),null==a)throw N.getNotFoundInstance();let i=a.getBoundingBox();if(!r||null==i||!(i.getMinY()h.getMaxY()))break;h=i}a.setBoundingBox(h);let d=a.getBarcodeColumnCount()+1;a.setDetectionResultColumn(0,l),a.setDetectionResultColumn(d,c);let u=null!=l;for(let e=1;e<=d;e++){let r,n=u?e:d-e;if(void 0!==a.getDetectionResultColumn(n))continue;r=0===n||n===d?new Ze(h,0===n):new ze(h),a.setDetectionResultColumn(n,r);let i=-1,l=i;for(let e=h.getMinY();e<=h.getMaxY();e++){if(i=ar.getStartColumn(a,n,e,u),i<0||i>h.getMaxX()){if(-1===l)continue;i=l}let c=ar.detectCodeword(t,h.getMinX(),h.getMaxX(),u,i,e,s,o);null!=c&&(r.setCodeword(e,c),l=i,s=Math.min(s,c.getWidth()),o=Math.max(o,c.getWidth()))}}return ar.createDecoderResult(a)}static merge(t,e){if(null==t&&null==e)return null;let r=ar.getBarcodeMetadata(t,e);if(null==r)return null;let n=Xe.merge(ar.adjustBoundingBox(t),ar.adjustBoundingBox(e));return new Ke(r,n)}static adjustBoundingBox(t){if(null==t)return null;let e=t.getRowHeights();if(null==e)return null;let r=ar.getMax(e),n=0;for(let t of e)if(n+=r-t,t>0)break;let i=t.getCodewords();for(let t=0;n>0&&null==i[t];t++)n--;let s=0;for(let t=e.length-1;t>=0&&(s+=r-e[t],!(e[t]>0));t--);for(let t=i.length-1;s>0&&null==i[t];t--)s--;return t.getBoundingBox().addMissingRows(n,s,t.isLeft())}static getMax(t){let e=-1;for(let r of t)e=Math.max(e,r);return e}static getBarcodeMetadata(t,e){let r,n;return null==t||null==(r=t.getBarcodeMetadata())?null==e?null:e.getBarcodeMetadata():null==e||null==(n=e.getBarcodeMetadata())?r:r.getColumnCount()!==n.getColumnCount()&&r.getErrorCorrectionLevel()!==n.getErrorCorrectionLevel()&&r.getRowCount()!==n.getRowCount()?null:r}static getRowIndicatorColumn(t,e,r,n,i,s){let o=new Ze(e,n);for(let a=0;a<2;a++){let h=0===a?1:-1,l=Math.trunc(Math.trunc(r.getX()));for(let a=Math.trunc(Math.trunc(r.getY()));a<=e.getMaxY()&&a>=e.getMinY();a+=h){let e=ar.detectCodeword(t,0,t.getWidth(),n,l,a,i,s);null!=e&&(o.setCodeword(a,e),l=n?e.getStartX():e.getEndX())}}return o}static adjustCodewordCount(t,e){let r=e[0][1],n=r.getValue(),i=t.getBarcodeColumnCount()*t.getBarcodeRowCount()-ar.getNumberOfECCodeWords(t.getBarcodeECLevel());if(0===n.length){if(i<1||i>Fe.MAX_CODEWORDS_IN_BARCODE)throw N.getNotFoundInstance();r.setValue(i)}else n[0]!==i&&r.setValue(i)}static createDecoderResult(t){let e=ar.createBarcodeMatrix(t);ar.adjustCodewordCount(t,e);let r=new Array,n=new Int32Array(t.getBarcodeRowCount()*t.getBarcodeColumnCount()),i=[],s=new Array;for(let o=0;o0;){for(let t=0;tnew Array(t.getBarcodeColumnCount()+2)));for(let t=0;t=0){if(n>=e.length)continue;e[n][r].setValue(t.getValue())}}r++}return e}static isValidBarcodeColumn(t,e){return e>=0&&e<=t.getBarcodeColumnCount()+1}static getStartColumn(t,e,r,n){let i=n?1:-1,s=null;if(ar.isValidBarcodeColumn(t,e-i)&&(s=t.getDetectionResultColumn(e-i).getCodeword(r)),null!=s)return n?s.getEndX():s.getStartX();if(s=t.getDetectionResultColumn(e).getCodewordNearby(r),null!=s)return n?s.getStartX():s.getEndX();if(ar.isValidBarcodeColumn(t,e-i)&&(s=t.getDetectionResultColumn(e-i).getCodewordNearby(r)),null!=s)return n?s.getEndX():s.getStartX();let o=0;for(;ar.isValidBarcodeColumn(t,e-i);){e-=i;for(let r of t.getDetectionResultColumn(e).getCodewords())if(null!=r)return(n?r.getEndX():r.getStartX())+i*o*(r.getEndX()-r.getStartX());o++}return n?t.getBoundingBox().getMinX():t.getBoundingBox().getMaxX()}static detectCodeword(t,e,r,n,i,s,o,a){i=ar.adjustCodewordStartColumn(t,e,r,n,i,s);let h,l=ar.getModuleBitCount(t,e,r,n,i,s);if(null==l)return null;let c=et.sum(l);if(n)h=i+c;else{for(let t=0;t=e)&&h=e:oar.CODEWORD_SKEW_SIZE)return i;o+=a}a=-a,n=!n}return o}static checkCodewordSkew(t,e,r){return e-ar.CODEWORD_SKEW_SIZE<=t&&t<=r+ar.CODEWORD_SKEW_SIZE}static decodeCodewords(t,e,r){if(0===t.length)throw m.getFormatInstance();let n=1<r/2+ar.MAX_ERRORS||r<0||r>ar.MAX_EC_CODEWORDS)throw l.getChecksumInstance();return ar.errorCorrection.decode(t,r,e)}static verifyCodewordCount(t,e){if(t.length<4)throw m.getFormatInstance();let r=t[0];if(r>t.length)throw m.getFormatInstance();if(0===r){if(!(e>=1;return e}static getCodewordBucketNumber(t){return t instanceof Int32Array?this.getCodewordBucketNumber_Int32Array(t):this.getCodewordBucketNumber_number(t)}static getCodewordBucketNumber_number(t){return ar.getCodewordBucketNumber(ar.getBitCountForCodeword(t))}static getCodewordBucketNumber_Int32Array(t){return(t[0]-t[2]+t[4]-t[6]+9)%9}static toString(t){let e=new We;for(let r=0;rt))}static getMaxWidth(t,e){return null==t||null==e?0:Math.trunc(Math.abs(t.getX()-e.getX()))}static getMinWidth(t,e){return null==t||null==e?w.MAX_VALUE:Math.trunc(Math.abs(t.getX()-e.getX()))}static getMaxCodewordWidth(t){return Math.floor(Math.max(Math.max(hr.getMaxWidth(t[0],t[4]),hr.getMaxWidth(t[6],t[2])*Fe.MODULES_IN_CODEWORD/Fe.MODULES_IN_STOP_PATTERN),Math.max(hr.getMaxWidth(t[1],t[5]),hr.getMaxWidth(t[7],t[3])*Fe.MODULES_IN_CODEWORD/Fe.MODULES_IN_STOP_PATTERN)))}static getMinCodewordWidth(t){return Math.floor(Math.min(Math.min(hr.getMinWidth(t[0],t[4]),hr.getMinWidth(t[6],t[2])*Fe.MODULES_IN_CODEWORD/Fe.MODULES_IN_STOP_PATTERN),Math.min(hr.getMinWidth(t[1],t[5]),hr.getMinWidth(t[7],t[3])*Fe.MODULES_IN_CODEWORD/Fe.MODULES_IN_STOP_PATTERN)))}reset(){}}class lr extends s{}lr.kind="ReaderException";class cr{decode(t,e){return this.setHints(e),this.decodeInternal(t)}decodeWithState(t){return null!==this.readers&&void 0!==this.readers||this.setHints(null),this.decodeInternal(t)}setHints(t){this.hints=t;const e=null!=t&&void 0!==t.get(E.TRY_HARDER),r=null==t?null:t.get(E.POSSIBLE_FORMATS),n=new Array;if(null!=r){const i=r.some((t=>t===x.UPC_A||t===x.UPC_E||t===x.EAN_13||t===x.EAN_8||t===x.CODABAR||t===x.CODE_39||t===x.CODE_93||t===x.CODE_128||t===x.ITF||t===x.RSS_14||t===x.RSS_EXPANDED));i&&!e&&n.push(new se(t)),r.includes(x.QR_CODE)&&n.push(new Le),r.includes(x.DATA_MATRIX)&&n.push(new we),r.includes(x.AZTEC)&&n.push(new gt),r.includes(x.PDF_417)&&n.push(new hr),i&&e&&n.push(new se(t))}0===n.length&&(e||n.push(new se(t)),n.push(new Le),n.push(new we),n.push(new gt),n.push(new hr),e&&n.push(new se(t))),this.readers=n}reset(){if(null!==this.readers)for(const t of this.readers)t.reset()}decodeInternal(t){if(null===this.readers)throw new lr("No readers where selected, nothing can be read.");for(const e of this.readers)try{return e.decode(t,this.hints)}catch(t){if(t instanceof lr)continue}throw new N("No MultiFormat Readers were able to detect the code.")}}var dr;!function(t){t[t.ERROR_CORRECTION=0]="ERROR_CORRECTION",t[t.CHARACTER_SET=1]="CHARACTER_SET",t[t.DATA_MATRIX_SHAPE=2]="DATA_MATRIX_SHAPE",t[t.DATA_MATRIX_COMPACT=3]="DATA_MATRIX_COMPACT",t[t.MIN_SIZE=4]="MIN_SIZE",t[t.MAX_SIZE=5]="MAX_SIZE",t[t.MARGIN=6]="MARGIN",t[t.PDF417_COMPACT=7]="PDF417_COMPACT",t[t.PDF417_COMPACTION=8]="PDF417_COMPACTION",t[t.PDF417_DIMENSIONS=9]="PDF417_DIMENSIONS",t[t.AZTEC_LAYERS=10]="AZTEC_LAYERS",t[t.QR_VERSION=11]="QR_VERSION",t[t.GS1_FORMAT=12]="GS1_FORMAT",t[t.FORCE_C40=13]="FORCE_C40"}(dr||(dr={}));var ur=dr;class gr{constructor(t){this.field=t,this.cachedGenerators=[],this.cachedGenerators.push(new K(t,Int32Array.from([1])))}buildGenerator(t){const e=this.cachedGenerators;if(t>=e.length){let r=e[e.length-1];const n=this.field;for(let i=e.length;i<=t;i++){const t=r.multiply(new K(n,Int32Array.from([1,n.exp(i-1+n.getGeneratorBase())])));e.push(t),r=t}}return e[t]}encode(t,e){if(0===e)throw new a("No error correction bytes");const r=t.length-e;if(r<=0)throw new a("No data bytes provided");const n=this.buildGenerator(e),i=new Int32Array(r);d.arraycopy(t,0,i,0,r);let s=new K(this.field,i);s=s.multiplyByMonomial(e,1);const o=s.divide(n)[1].getCoefficients(),h=e-o.length;for(let e=0;e=5&&(r+=fr.N1+(n-5)),n=1,o=i)}n>=5&&(r+=fr.N1+(n-5))}return r}}fr.N1=3,fr.N2=3,fr.N3=40,fr.N4=10;class wr{constructor(t,e){this.width=t,this.height=e;const r=new Array(e);for(let n=0;n!==e;n++)r[n]=new Uint8Array(t);this.bytes=r}getHeight(){return this.height}getWidth(){return this.width}get(t,e){return this.bytes[e][t]}getArray(){return this.bytes}setNumber(t,e,r){this.bytes[e][t]=r}setBoolean(t,e,r){this.bytes[e][t]=r?1:0}clear(t){for(const e of this.bytes)f.fill(e,t)}equals(t){if(!(t instanceof wr))return!1;const e=t;if(this.width!==e.width)return!1;if(this.height!==e.height)return!1;for(let t=0,r=this.height;t>\n"),t.toString()}setMode(t){this.mode=t}setECLevel(t){this.ecLevel=t}setVersion(t){this.version=t}setMaskPattern(t){this.maskPattern=t}setMatrix(t){this.matrix=t}static isValidMaskPattern(t){return t>=0&&t0;){for(6===s&&(s-=1);o>=0&&o=r;)t^=e<=0)for(let t=0;t!==r;t++){const r=n[t];r>=0&&Er.isEmpty(e.get(r,i))&&Er.embedPositionAdjustmentPattern(r-2,i-2,e)}}}}Er.POSITION_DETECTION_PATTERN=Array.from([Int32Array.from([1,1,1,1,1,1,1]),Int32Array.from([1,0,0,0,0,0,1]),Int32Array.from([1,0,1,1,1,0,1]),Int32Array.from([1,0,1,1,1,0,1]),Int32Array.from([1,0,1,1,1,0,1]),Int32Array.from([1,0,0,0,0,0,1]),Int32Array.from([1,1,1,1,1,1,1])]),Er.POSITION_ADJUSTMENT_PATTERN=Array.from([Int32Array.from([1,1,1,1,1]),Int32Array.from([1,0,0,0,1]),Int32Array.from([1,0,1,0,1]),Int32Array.from([1,0,0,0,1]),Int32Array.from([1,1,1,1,1])]),Er.POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE=Array.from([Int32Array.from([-1,-1,-1,-1,-1,-1,-1]),Int32Array.from([6,18,-1,-1,-1,-1,-1]),Int32Array.from([6,22,-1,-1,-1,-1,-1]),Int32Array.from([6,26,-1,-1,-1,-1,-1]),Int32Array.from([6,30,-1,-1,-1,-1,-1]),Int32Array.from([6,34,-1,-1,-1,-1,-1]),Int32Array.from([6,22,38,-1,-1,-1,-1]),Int32Array.from([6,24,42,-1,-1,-1,-1]),Int32Array.from([6,26,46,-1,-1,-1,-1]),Int32Array.from([6,28,50,-1,-1,-1,-1]),Int32Array.from([6,30,54,-1,-1,-1,-1]),Int32Array.from([6,32,58,-1,-1,-1,-1]),Int32Array.from([6,34,62,-1,-1,-1,-1]),Int32Array.from([6,26,46,66,-1,-1,-1]),Int32Array.from([6,26,48,70,-1,-1,-1]),Int32Array.from([6,26,50,74,-1,-1,-1]),Int32Array.from([6,30,54,78,-1,-1,-1]),Int32Array.from([6,30,56,82,-1,-1,-1]),Int32Array.from([6,30,58,86,-1,-1,-1]),Int32Array.from([6,34,62,90,-1,-1,-1]),Int32Array.from([6,28,50,72,94,-1,-1]),Int32Array.from([6,26,50,74,98,-1,-1]),Int32Array.from([6,30,54,78,102,-1,-1]),Int32Array.from([6,28,54,80,106,-1,-1]),Int32Array.from([6,32,58,84,110,-1,-1]),Int32Array.from([6,30,58,86,114,-1,-1]),Int32Array.from([6,34,62,90,118,-1,-1]),Int32Array.from([6,26,50,74,98,122,-1]),Int32Array.from([6,30,54,78,102,126,-1]),Int32Array.from([6,26,52,78,104,130,-1]),Int32Array.from([6,30,56,82,108,134,-1]),Int32Array.from([6,34,60,86,112,138,-1]),Int32Array.from([6,30,58,86,114,142,-1]),Int32Array.from([6,34,62,90,118,146,-1]),Int32Array.from([6,30,54,78,102,126,150]),Int32Array.from([6,24,50,76,102,128,154]),Int32Array.from([6,28,54,80,106,132,158]),Int32Array.from([6,32,58,84,110,136,162]),Int32Array.from([6,26,54,82,110,138,166]),Int32Array.from([6,30,58,86,114,142,170])]),Er.TYPE_INFO_COORDINATES=Array.from([Int32Array.from([8,0]),Int32Array.from([8,1]),Int32Array.from([8,2]),Int32Array.from([8,3]),Int32Array.from([8,4]),Int32Array.from([8,5]),Int32Array.from([8,7]),Int32Array.from([8,8]),Int32Array.from([7,8]),Int32Array.from([5,8]),Int32Array.from([4,8]),Int32Array.from([3,8]),Int32Array.from([2,8]),Int32Array.from([1,8]),Int32Array.from([0,8])]),Er.VERSION_INFO_POLY=7973,Er.TYPE_INFO_POLY=1335,Er.TYPE_INFO_MASK_PATTERN=21522;class mr{constructor(t,e){this.dataBytes=t,this.errorCorrectionBytes=e}getDataBytes(){return this.dataBytes}getErrorCorrectionBytes(){return this.errorCorrectionBytes}}class Ir{constructor(){}static calculateMaskPenalty(t){return fr.applyMaskPenaltyRule1(t)+fr.applyMaskPenaltyRule2(t)+fr.applyMaskPenaltyRule3(t)+fr.applyMaskPenaltyRule4(t)}static encode(t,e,r=null){let n=Ir.DEFAULT_BYTE_MODE_ENCODING;const i=null!==r&&void 0!==r.get(ur.CHARACTER_SET);i&&(n=r.get(ur.CHARACTER_SET).toString());const s=this.chooseMode(t,n),o=new C;if(s===Te.BYTE&&(i||Ir.DEFAULT_BYTE_MODE_ENCODING!==n)){const t=I.getCharacterSetECIByName(n);void 0!==t&&this.appendECI(t,o)}this.appendModeInfo(s,o);const a=new C;let h;if(this.appendBytes(t,s,a,n),null!==r&&void 0!==r.get(ur.QR_VERSION)){const t=Number.parseInt(r.get(ur.QR_VERSION).toString(),10);h=Ie.getVersionForNumber(t);const n=this.calculateBitsNeeded(s,o,a,h);if(!this.willFit(n,h,e))throw new Ar("Data too big for requested version")}else h=this.recommendVersion(e,s,o,a);const l=new C;l.appendBitArray(o);const c=s===Te.BYTE?a.getSizeInBytes():t.length;this.appendLengthInfo(c,h,s,l),l.appendBitArray(a);const d=h.getECBlocksForLevel(e),u=h.getTotalCodewords()-d.getTotalECCodewords();this.terminateBits(u,l);const g=this.interleaveWithECBytes(l,h.getTotalCodewords(),u,d.getNumBlocks()),f=new Cr;f.setECLevel(e),f.setMode(s),f.setVersion(h);const w=h.getDimensionForVersion(),A=new wr(w,w),E=this.chooseMaskPattern(g,e,h,A);return f.setMaskPattern(E),Er.buildMatrix(g,e,h,E,A),f.setMatrix(A),f}static recommendVersion(t,e,r,n){const i=this.calculateBitsNeeded(e,r,n,Ie.getVersionForNumber(1)),s=this.chooseVersion(i,t),o=this.calculateBitsNeeded(e,r,n,s);return this.chooseVersion(o,t)}static calculateBitsNeeded(t,e,r,n){return e.getSize()+t.getCharacterCountBits(n)+r.getSize()}static getAlphanumericCode(t){return t159)&&(r<224||r>235))return!1}return!0}static chooseMaskPattern(t,e,r,n){let i=Number.MAX_SAFE_INTEGER,s=-1;for(let o=0;o=(t+7)/8}static terminateBits(t,e){const r=8*t;if(e.getSize()>r)throw new Ar("data bits cannot fit in the QR Code"+e.getSize()+" > "+r);for(let t=0;t<4&&e.getSize()0)for(let t=n;t<8;t++)e.appendBit(!1);const i=t-e.getSizeInBytes();for(let t=0;t=r)throw new Ar("Block ID too large");const o=t%r,a=r-o,h=Math.floor(t/r),l=h+1,c=Math.floor(e/r),d=c+1,u=h-c,g=l-d;if(u!==g)throw new Ar("EC bytes mismatch");if(r!==a+o)throw new Ar("RS blocks mismatch");if(t!==(c+u)*a+(d+g)*o)throw new Ar("Total bytes mismatch");n=1<=0&&e<=9}static appendNumericBytes(t,e){const r=t.length;let n=0;for(;n=33088&&n<=40956?i=n-33088:n>=57408&&n<=60351&&(i=n-49472),-1===i)throw new Ar("Invalid byte sequence");const s=192*(i>>8)+(255&i);e.appendBits(s,13)}}static appendECI(t,e){e.appendBits(Te.ECI.getBits(),4),e.appendBits(t.getValue(),8)}}Ir.ALPHANUMERIC_TABLE=Int32Array.from([-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,36,-1,-1,-1,37,38,-1,-1,-1,-1,39,40,-1,41,42,43,0,1,2,3,4,5,6,7,8,9,44,-1,-1,-1,-1,-1,-1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1]),Ir.DEFAULT_BYTE_MODE_ENCODING=I.UTF8.getName();class _r{write(t,e,r,n=null){if(0===t.length)throw new a("Found empty contents");if(e<0||r<0)throw new a("Requested dimensions are too small: "+e+"x"+r);let i=Ce.L,s=_r.QUIET_ZONE_SIZE;null!==n&&(void 0!==n.get(ur.ERROR_CORRECTION)&&(i=Ce.fromString(n.get(ur.ERROR_CORRECTION).toString())),void 0!==n.get(ur.MARGIN)&&(s=Number.parseInt(n.get(ur.MARGIN).toString(),10)));const o=Ir.encode(t,i,n);return this.renderResult(o,e,r,s)}writeToDom(t,e,r,n,i=null){"string"==typeof t&&(t=document.querySelector(t));const s=this.write(e,r,n,i);t&&t.appendChild(s)}renderResult(t,e,r,n){const i=t.getMatrix();if(null===i)throw new J;const s=i.getWidth(),o=i.getHeight(),a=s+2*n,h=o+2*n,l=Math.max(e,a),c=Math.max(r,h),d=Math.min(Math.floor(l/a),Math.floor(c/h)),u=Math.floor((l-s*d)/2),g=Math.floor((c-o*d)/2),f=this.createSVGElement(l,c);for(let t=0,e=g;te||i+o>r)throw new a("Crop rectangle does not fit within image data.");h&&this.reverseHorizontal(s,o)}getRow(t,e){if(t<0||t>=this.getHeight())throw new a("Requested row is outside the image: "+t);const r=this.getWidth();(null==e||e.length>16&255,s=r>>7&510,o=255&r;i[e]=(n+s+o)/4&255}this.luminances=i}else this.luminances=t;if(void 0===n&&(this.dataWidth=e),void 0===i&&(this.dataHeight=r),void 0===s&&(this.left=0),void 0===o&&(this.top=0),this.left+e>this.dataWidth||this.top+r>this.dataHeight)throw new a("Crop rectangle does not fit within image data.")}getRow(t,e){if(t<0||t>=this.getHeight())throw new a("Requested row is outside the image: "+t);const r=this.getWidth();(null==e||e.length=0&&this.noBit(r,e)&&this.utah(e,r,t++),e-=2,r+=2}while(e>=0&&r=0&&r=0);e+=3,r++}while(e{let r=1;for(let n=0;n<255;n++)e[n]=r,t[r]=n,r*=2,r>=256&&(r^=301);return{LOG:t,ALOG:e}})([],[]);var Br;t.DataMatrixSymbolShapeHint=void 0,(Br=t.DataMatrixSymbolShapeHint||(t.DataMatrixSymbolShapeHint={}))[Br.FORCE_NONE=0]="FORCE_NONE",Br[Br.FORCE_SQUARE=1]="FORCE_SQUARE",Br[Br.FORCE_RECTANGLE=2]="FORCE_RECTANGLE";const Pr="[)>05",Lr="[)>06",Fr="";class vr{static encodeECC200(t,e){if(t.length!==e.getDataCapacity())throw new Error("The number of codewords does not match the selected symbol");const r=new T;r.append(t);const n=e.getInterleavedBlockCount();if(1===n){const n=this.createECCBlock(t,e.getErrorCodewords());r.append(n)}else{const i=[];for(let t=0;t0;t--)0!==s&&0!==n[t]?i[t]=i[t-1]^br[(Mr[s]+Mr[n[t]])%255]:i[t]=i[t-1];0!==s&&0!==n[0]?i[0]=br[(Mr[s]+Mr[n[0]])%255]:i[0]=0}const s=[];for(let t=0;tString.fromCharCode(t))).join("")}}class kr{getEncodingMode(){return 0}encode(t){if(Yr.determineConsecutiveDigitCount(t.getMessage(),t.pos)>=2)t.writeCodeword(this.encodeASCIIDigits(t.getMessage().charCodeAt(t.pos),t.getMessage().charCodeAt(t.pos+1))),t.pos+=2;else{const e=t.getCurrentChar(),r=Yr.lookAheadTest(t.getMessage(),t.pos,this.getEncodingMode());if(r!==this.getEncodingMode())switch(r){case 5:return t.writeCodeword(231),void t.signalEncoderChange(5);case 1:return t.writeCodeword(230),void t.signalEncoderChange(1);case 3:t.writeCodeword(238),t.signalEncoderChange(3);break;case 2:t.writeCodeword(239),t.signalEncoderChange(2);break;case 4:t.writeCodeword(240),t.signalEncoderChange(4);break;default:throw new Error("Illegal mode: "+r)}else Yr.isExtendedASCII(e)?(t.writeCodeword(235),t.writeCodeword(e-128+1),t.pos++):(t.writeCodeword(e+1),t.pos++)}}encodeASCIIDigits(t,e){if(Yr.isDigit(t)&&Yr.isDigit(e)){return 10*(t-48)+(e-48)+130}throw new Error("not digits: "+t+e)}}class xr{getEncodingMode(){return 5}encode(t){const e=new T;for(e.append(0);t.hasMoreCharacters();){const r=t.getCurrentChar();e.append(r),t.pos++;if(Yr.lookAheadTest(t.getMessage(),t.pos,this.getEncodingMode())!==this.getEncodingMode()){t.signalEncoderChange(0);break}}const r=e.length()-1,n=t.getCodewordCount()+r+1;t.updateSymbolInfo(n);const i=t.getSymbolInfo().getDataCapacity()-n>0;if(t.hasMoreCharacters()||i)if(r<=249)e.setCharAt(0,p.getCharAt(r));else{if(!(r<=1555))throw new Error("Message length not in valid ranges: "+r);e.setCharAt(0,p.getCharAt(Math.floor(r/250)+249)),e.insert(1,p.getCharAt(r%250))}for(let r=0,n=e.length();r3||1!==o))&&(t.pos=n)}e.length()>0&&t.writeCodeword(230),this.handleEOD(t,e)}encode(t){const e=new T;for(;t.hasMoreCharacters();){const r=t.getCurrentChar();t.pos++;let n=this.encodeChar(r,e);const i=2*Math.floor(e.length()/3),s=t.getCodewordCount()+i;t.updateSymbolInfo(s);const o=t.getSymbolInfo().getDataCapacity()-s;if(!t.hasMoreCharacters()){const r=new T;for(e.length()%3==2&&2!==o&&(n=this.backtrackOneCharacter(t,e,r,n));e.length()%3==1&&(n>3||1!==o);)n=this.backtrackOneCharacter(t,e,r,n);break}if(e.length()%3==0){if(Yr.lookAheadTest(t.getMessage(),t.pos,this.getEncodingMode())!==this.getEncodingMode()){t.signalEncoderChange(0);break}}}this.handleEOD(t,e)}backtrackOneCharacter(t,e,r,n){const i=e.length(),s=e.toString().substring(0,i-n);e.setLengthToZero(),e.append(s),t.pos--;const o=t.getCurrentChar();return n=this.encodeChar(o,r),t.resetSymbolInfo(),n}writeNextTriplet(t,e){t.writeCodewords(this.encodeToCodewords(e.toString()));const r=e.toString().substring(3);e.setLengthToZero(),e.append(r)}handleEOD(t,e){const r=Math.floor(e.length()/3*2),n=e.length()%3,i=t.getCodewordCount()+r;t.updateSymbolInfo(i);const s=t.getSymbolInfo().getDataCapacity()-i;if(2===n){for(e.append("\0");e.length()>=3;)this.writeNextTriplet(t,e);t.hasMoreCharacters()&&t.writeCodeword(254)}else if(1===s&&1===n){for(;e.length()>=3;)this.writeNextTriplet(t,e);t.hasMoreCharacters()&&t.writeCodeword(254),t.pos--}else{if(0!==n)throw new Error("Unexpected case. Please report!");for(;e.length()>=3;)this.writeNextTriplet(t,e);(s>0||t.hasMoreCharacters())&&t.writeCodeword(254)}t.signalEncoderChange(0)}encodeChar(t,e){if(t===" ".charCodeAt(0))return e.append(3),1;if(t>="0".charCodeAt(0)&&t<="9".charCodeAt(0))return e.append(t-48+4),1;if(t>="A".charCodeAt(0)&&t<="Z".charCodeAt(0))return e.append(t-65+14),1;if(t<" ".charCodeAt(0))return e.append(0),e.append(t),2;if(t<="/".charCodeAt(0))return e.append(1),e.append(t-33),2;if(t<="@".charCodeAt(0))return e.append(1),e.append(t-58+15),2;if(t<="_".charCodeAt(0))return e.append(1),e.append(t-91+22),2;if(t<=127)return e.append(2),e.append(t-96),2;e.append("1");let r=2;return r+=this.encodeChar(t-128,e),r}encodeToCodewords(t){const e=1600*t.charCodeAt(0)+40*t.charCodeAt(1)+t.charCodeAt(2)+1,r=e/256,n=e%256,i=new T;return i.append(r),i.append(n),i.toString()}}class Hr{getEncodingMode(){return 4}encode(t){const e=new T;for(;t.hasMoreCharacters();){const r=t.getCurrentChar();this.encodeChar(r,e),t.pos++;if(e.length()>=4){t.writeCodewords(this.encodeToCodewords(e.toString()));const r=e.toString().substring(4);e.setLengthToZero(),e.append(r);if(Yr.lookAheadTest(t.getMessage(),t.pos,this.getEncodingMode())!==this.getEncodingMode()){t.signalEncoderChange(0);break}}}e.append(p.getCharAt(31)),this.handleEOD(t,e)}handleEOD(t,e){try{const r=e.length();if(0===r)return;if(1===r){t.updateSymbolInfo();let e=t.getSymbolInfo().getDataCapacity()-t.getCodewordCount();const r=t.getRemainingCharacters();if(r>e&&(t.updateSymbolInfo(t.getCodewordCount()+1),e=t.getSymbolInfo().getDataCapacity()-t.getCodewordCount()),r<=e&&e<=2)return}if(r>4)throw new Error("Count must not exceed 4");const n=r-1,i=this.encodeToCodewords(e.toString());let s=!t.hasMoreCharacters()&&n<=2;if(n<=2){t.updateSymbolInfo(t.getCodewordCount()+n);t.getSymbolInfo().getDataCapacity()-t.getCodewordCount()>=3&&(s=!1,t.updateSymbolInfo(t.getCodewordCount()+i.length))}s?(t.resetSymbolInfo(),t.pos-=n):t.writeCodewords(i)}finally{t.signalEncoderChange(0)}}encodeChar(t,e){t>=" ".charCodeAt(0)&&t<="?".charCodeAt(0)?e.append(t):t>="@".charCodeAt(0)&&t<="^".charCodeAt(0)?e.append(p.getCharAt(t-64)):Yr.illegalCharacter(p.getCharAt(t))}encodeToCodewords(t){const e=t.length;if(0===e)throw new Error("StringBuilder must not be empty");const r=(t.charAt(0).charCodeAt(0)<<18)+((e>=2?t.charAt(1).charCodeAt(0):0)<<12)+((e>=3?t.charAt(2).charCodeAt(0):0)<<6)+(e>=4?t.charAt(3).charCodeAt(0):0),n=r>>16&255,i=r>>8&255,s=255&r,o=new T;return o.append(n),e>=2&&o.append(i),e>=3&&o.append(s),o.toString()}}class Ur{constructor(t,e,r,n,i,s,o=0,a=0){this.rectangular=t,this.dataCapacity=e,this.errorCodewords=r,this.matrixWidth=n,this.matrixHeight=i,this.dataRegions=s,this.rsBlockData=o,this.rsBlockError=a}static lookup(t,e=0,r=null,n=null,i=!0){for(const i of Xr)if((1!==e||!i.rectangular)&&(2!==e||i.rectangular)&&(null==r||!(i.getSymbolWidth()n.getWidth()||i.getSymbolHeight()>n.getHeight()))&&t<=i.dataCapacity)return i;if(i)throw new Error("Can't find a symbol arrangement that matches the message. Data codewords: "+t);return null}getHorizontalDataRegions(){switch(this.dataRegions){case 1:return 1;case 2:case 4:return 2;case 16:return 4;case 36:return 6;default:throw new Error("Cannot handle this number of data regions")}}getVerticalDataRegions(){switch(this.dataRegions){case 1:case 2:return 1;case 4:return 2;case 16:return 4;case 36:return 6;default:throw new Error("Cannot handle this number of data regions")}}getSymbolDataWidth(){return this.getHorizontalDataRegions()*this.matrixWidth}getSymbolDataHeight(){return this.getVerticalDataRegions()*this.matrixHeight}getSymbolWidth(){return this.getSymbolDataWidth()+2*this.getHorizontalDataRegions()}getSymbolHeight(){return this.getSymbolDataHeight()+2*this.getVerticalDataRegions()}getCodewordCount(){return this.dataCapacity+this.errorCodewords}getInterleavedBlockCount(){return this.rsBlockData?this.dataCapacity/this.rsBlockData:1}getDataCapacity(){return this.dataCapacity}getErrorCodewords(){return this.errorCodewords}getDataLengthForInterleavedBlock(t){return this.rsBlockData}getErrorLengthForInterleavedBlock(t){return this.rsBlockError}}const Xr=[new Ur(!1,3,5,8,8,1),new Ur(!1,5,7,10,10,1),new Ur(!0,5,7,16,6,1),new Ur(!1,8,10,12,12,1),new Ur(!0,10,11,14,6,2),new Ur(!1,12,12,14,14,1),new Ur(!0,16,14,24,10,1),new Ur(!1,18,14,16,16,1),new Ur(!1,22,18,18,18,1),new Ur(!0,22,18,16,10,2),new Ur(!1,30,20,20,20,1),new Ur(!0,32,24,16,14,2),new Ur(!1,36,24,22,22,1),new Ur(!1,44,28,24,24,1),new Ur(!0,49,28,22,14,2),new Ur(!1,62,36,14,14,4),new Ur(!1,86,42,16,16,4),new Ur(!1,114,48,18,18,4),new Ur(!1,144,56,20,20,4),new Ur(!1,174,68,22,22,4),new Ur(!1,204,84,24,24,4,102,42),new Ur(!1,280,112,14,14,16,140,56),new Ur(!1,368,144,16,16,16,92,36),new Ur(!1,456,192,18,18,16,114,48),new Ur(!1,576,224,20,20,16,144,56),new Ur(!1,696,272,22,22,16,174,68),new Ur(!1,816,336,24,24,16,136,56),new Ur(!1,1050,408,18,18,36,175,68),new Ur(!1,1304,496,20,20,36,163,62),new class extends Ur{constructor(){super(!1,1558,620,22,22,36,-1,62)}getInterleavedBlockCount(){return 10}getDataLengthForInterleavedBlock(t){return t<=8?156:155}}];class Gr{constructor(t){this.msg=t,this.pos=0,this.skipAtEnd=0;const e=t.split("").map((t=>t.charCodeAt(0))),r=new T;for(let n=0,i=e.length;nthis.symbolInfo.getDataCapacity())&&(this.symbolInfo=Ur.lookup(t,this.shape,this.minSize,this.maxSize,!0))}resetSymbolInfo(){this.symbolInfo=null}}class Wr extends Vr{getEncodingMode(){return 3}encode(t){const e=new T;for(;t.hasMoreCharacters();){const r=t.getCurrentChar();t.pos++,this.encodeChar(r,e);if(e.length()%3==0){this.writeNextTriplet(t,e);if(Yr.lookAheadTest(t.getMessage(),t.pos,this.getEncodingMode())!==this.getEncodingMode()){t.signalEncoderChange(0);break}}}this.handleEOD(t,e)}encodeChar(t,e){switch(t){case 13:e.append(0);break;case"*".charCodeAt(0):e.append(1);break;case">".charCodeAt(0):e.append(2);break;case" ".charCodeAt(0):e.append(3);break;default:t>="0".charCodeAt(0)&&t<="9".charCodeAt(0)?e.append(t-48+4):t>="A".charCodeAt(0)&&t<="Z".charCodeAt(0)?e.append(t-65+14):Yr.illegalCharacter(p.getCharAt(t))}return 1}handleEOD(t,e){t.updateSymbolInfo();const r=t.getSymbolInfo().getDataCapacity()-t.getCodewordCount(),n=e.length();t.pos-=n,(t.getRemainingCharacters()>1||r>1||t.getRemainingCharacters()!==r)&&t.writeCodeword(254),t.getNewEncoding()<0&&t.signalEncoderChange(0)}}class zr extends Vr{getEncodingMode(){return 2}encodeChar(t,e){if(t===" ".charCodeAt(0))return e.append(3),1;if(t>="0".charCodeAt(0)&&t<="9".charCodeAt(0))return e.append(t-48+4),1;if(t>="a".charCodeAt(0)&&t<="z".charCodeAt(0))return e.append(t-97+14),1;if(t<" ".charCodeAt(0))return e.append(0),e.append(t),2;if(t<="/".charCodeAt(0))return e.append(1),e.append(t-33),2;if(t<="@".charCodeAt(0))return e.append(1),e.append(t-58+15),2;if(t>="[".charCodeAt(0)&&t<="_".charCodeAt(0))return e.append(1),e.append(t-91+22),2;if(t==="`".charCodeAt(0))return e.append(2),e.append(0),2;if(t<="Z".charCodeAt(0))return e.append(2),e.append(t-65+1),2;if(t<=127)return e.append(2),e.append(t-123+27),2;e.append("1");let r=2;return r+=this.encodeChar(t-128,e),r}}class Yr{static randomize253State(t){const e=129+(149*t%253+1);return e<=254?e:e-254}static encodeHighLevel(t,e=0,r=null,n=null,i=!1){const s=new Vr,o=[new kr,s,new zr,new Wr,new Hr,new xr],a=new Gr(t);a.setSymbolShape(e),a.setSizeConstraints(r,n),t.startsWith(Pr)&&t.endsWith(Fr)?(a.writeCodeword(236),a.setSkipAtEnd(2),a.pos+=7):t.startsWith(Lr)&&t.endsWith(Fr)&&(a.writeCodeword(237),a.setSkipAtEnd(2),a.pos+=7);let h=0;for(i&&(s.encodeMaximal(a),h=a.getNewEncoding(),a.resetEncoderSignal());a.hasMoreCharacters();)o[h].encode(a),a.getNewEncoding()>=0&&(h=a.getNewEncoding(),a.resetEncoderSignal());const l=a.getCodewordCount();a.updateSymbolInfo();const c=a.getSymbolInfo().getDataCapacity();l=t.length)return r;let n;0===r?n=[0,1,1,1,1,1.25]:(n=[1,2,2,2,2,2.25],n[r]=0);let i=0;const s=new Uint8Array(6),o=[];for(;;){if(e+i===t.length){f.fill(s,0),f.fill(o,0);const t=this.findMinimums(n,o,w.MAX_VALUE,s),e=this.getMinimumCount(s);if(o[0]===t)return 0;if(1===e){if(s[5]>0)return 5;if(s[4]>0)return 4;if(s[2]>0)return 2;if(s[3]>0)return 3}return 1}const r=t.charCodeAt(e+i);if(i++,this.isDigit(r)?n[0]+=.5:this.isExtendedASCII(r)?(n[0]=Math.ceil(n[0]),n[0]+=2):(n[0]=Math.ceil(n[0]),n[0]++),this.isNativeC40(r)?n[1]+=2/3:this.isExtendedASCII(r)?n[1]+=8/3:n[1]+=4/3,this.isNativeText(r)?n[2]+=2/3:this.isExtendedASCII(r)?n[2]+=8/3:n[2]+=4/3,this.isNativeX12(r)?n[3]+=2/3:this.isExtendedASCII(r)?n[3]+=13/3:n[3]+=10/3,this.isNativeEDIFACT(r)?n[4]+=3/4:this.isExtendedASCII(r)?n[4]+=4.25:n[4]+=3.25,this.isSpecialB256(r)?n[5]+=4:n[5]++,i>=4){if(f.fill(s,0),f.fill(o,0),this.findMinimums(n,o,w.MAX_VALUE,s),o[0]s&&(r=s,f.fill(n,0)),r===s&&(n[i]=n[i]+1)}return r}static getMinimumCount(t){let e=0;for(let r=0;r<6;r++)e+=t[r];return e||0}static isDigit(t){return t>="0".charCodeAt(0)&&t<="9".charCodeAt(0)}static isExtendedASCII(t){return t>=128&&t<=255}static isNativeC40(t){return t===" ".charCodeAt(0)||t>="0".charCodeAt(0)&&t<="9".charCodeAt(0)||t>="A".charCodeAt(0)&&t<="Z".charCodeAt(0)}static isNativeText(t){return t===" ".charCodeAt(0)||t>="0".charCodeAt(0)&&t<="9".charCodeAt(0)||t>="a".charCodeAt(0)&&t<="z".charCodeAt(0)}static isNativeX12(t){return this.isX12TermSep(t)||t===" ".charCodeAt(0)||t>="0".charCodeAt(0)&&t<="9".charCodeAt(0)||t>="A".charCodeAt(0)&&t<="Z".charCodeAt(0)}static isX12TermSep(t){return 13===t||t==="*".charCodeAt(0)||t===">".charCodeAt(0)}static isNativeEDIFACT(t){return t>=" ".charCodeAt(0)&&t<="^".charCodeAt(0)}static isSpecialB256(t){return!1}static determineConsecutiveDigitCount(t,e=0){const r=t.length;let n=e;for(;nnew Zr(Rr.forName(t)))),this.encoders=[];const n=[];n.push(new Zr(Nr.ISO_8859_1));let i=null!=e&&e.name.startsWith("UTF");for(let e=0;e=this.bytes.length)return!1;for(let r=0;r=this.length())throw new Error(""+t);if(this.isECI(t))throw new Error("value at "+t+" is not a character but an ECI");return this.isFNC1(t)?this.fnc1:this.bytes[t]}subSequence(t,e){if(t<0||t>e||e>this.length())throw new Error(""+t);const r=new T;for(let n=t;n=this.length())throw new Error(""+t);return this.bytes[t]>255&&this.bytes[t]<=999}isFNC1(t){if(t<0||t>=this.length())throw new Error(""+t);return 1e3===this.bytes[t]}getECIValue(t){if(t<0||t>=this.length())throw new Error(""+t);if(!this.isECI(t))throw new Error("value at "+t+" is not an ECI but a character");return this.bytes[t]-256}addEdge(t,e,r){(null==t[e][r.encoderIndex]||t[e][r.encoderIndex].cachedTotalSize>r.cachedTotalSize)&&(t[e][r.encoderIndex]=r)}addEdges(t,e,r,n,i,s){const o=t.charAt(n).charCodeAt(0);let a=0,h=e.length();e.getPriorityEncoderIndex()>=0&&(o===s||e.canEncode(o,e.getPriorityEncoderIndex()))&&(a=e.getPriorityEncoderIndex(),h=a+1);for(let t=a;t=0;e--)a.unshift(255&t[e])}(null===h.previous?0:h.previous.encoderIndex)!==h.encoderIndex&&a.unshift(256+e.getECIValue(h.encoderIndex)),h=h.previous}const l=[];for(let t=0;t","?","@","[","\\","]","^","_"];class $r{static isExtendedASCII(t,e){return t!==e&&t>=128&&t<=255}static isInC40Shift1Set(t){return t<=31}static isInC40Shift2Set(t,e){for(const e of Jr)if(e.charCodeAt(0)===t)return!0;return t===e}static isInTextShift1Set(t){return this.isInC40Shift1Set(t)}static isInTextShift2Set(t,e){return this.isInC40Shift2Set(t,e)}static encodeHighLevel(t,e=null,r=-1,n=0){let i=0;return t.startsWith(Pr)&&t.endsWith(Fr)?(i=5,t=t.substring(7,t.length-2)):t.startsWith(Lr)&&t.endsWith(Fr)&&(i=6,t=t.substring(7,t.length-2)),decodeURIComponent(escape(String.fromCharCode(...this.encode(t,e,r,n,i))))}static encode(t,e,r,n,i){return this.encodeMinimally(new rn(t,e,r,n,i)).getBytes()}static addEdge(t,e){const r=e.fromPosition+e.characterLength;(null===t[r][e.getEndMode()]||t[r][e.getEndMode()].cachedTotalSize>e.cachedTotalSize)&&(t[r][e.getEndMode()]=e)}static getNumberOfC40Words(t,e,r,n){let i=0;for(let s=e;s=128&&(r&&Yr.isNativeC40(t-128)||!r&&Yr.isNativeText(t-128))?i+=3:i+=4}else i+=2;if(i%3==0||(i-2)%3==0&&s+1===t.length())return n[0]=s-e+1,Math.ceil(i/3)}return n[0]=0,0}static addEdges(t,e,r,n){if(t.isECI(r))return void this.addEdge(e,new en(t,jr.ASCII,r,1,n));const i=t.charAt(r);if(null===n||n.getEndMode()!==jr.EDF){Yr.isDigit(i)&&t.haveNCharacters(r,2)&&Yr.isDigit(t.charAt(r+1))?this.addEdge(e,new en(t,jr.ASCII,r,2,n)):this.addEdge(e,new en(t,jr.ASCII,r,1,n));const s=[jr.C40,jr.TEXT];for(const i of s){const s=[];$r.getNumberOfC40Words(t,r,i===jr.C40,s)>0&&this.addEdge(e,new en(t,i,r,s[0],n))}t.haveNCharacters(r,3)&&Yr.isNativeX12(t.charAt(r))&&Yr.isNativeX12(t.charAt(r+1))&&Yr.isNativeX12(t.charAt(r+2))&&this.addEdge(e,new en(t,jr.X12,r,3,n)),this.addEdge(e,new en(t,jr.B256,r,1,n))}let s;for(s=0;s<3;s++){const i=r+s;if(!t.haveNCharacters(i,1)||!Yr.isNativeEDIFACT(t.charAt(i)))break;this.addEdge(e,new en(t,jr.EDF,r,s+1,n))}3===s&&t.haveNCharacters(r,4)&&Yr.isNativeEDIFACT(t.charAt(r+3))&&this.addEdge(e,new en(t,jr.EDF,r,4,n))}static encodeMinimally(t){const e=t.length(),r=Array(e+1).fill(null).map((()=>Array(6).fill(0)));this.addEdges(t,r,0,null);for(let n=1;n<=e;n++){for(let i=0;i<6;i++)null!==r[n][i]&&n=1&&t<=3?s.cachedTotalSize+1:s.cachedTotalSize;o0&&(r+=this.prepend(en.getBytes(232),n));for(let t=0;t=0;r--)e.unshift(t[r]);return t.length}randomize253State(t){const e=129+(149*t%253+1);return e<=254?e:e-254}applyRandomPattern(t,e,r){for(let n=0;n0&&this.getCodewordsRemaining(this.cachedTotalSize+t)<=2-t)return jr.ASCII}if(this.mode===jr.C40||this.mode===jr.TEXT||this.mode===jr.X12){if(this.fromPosition+this.characterLength>=this.input.length()&&0===this.getCodewordsRemaining(this.cachedTotalSize))return jr.ASCII;if(1===this.getLastASCII()&&0===this.getCodewordsRemaining(this.cachedTotalSize+1))return jr.ASCII}return this.mode}getMode(){return this.mode}getLastASCII(){const t=this.input.length(),e=this.fromPosition+this.characterLength;return t-e>4||e>=t?0:t-e==1?$r.isExtendedASCII(this.input.charAt(e),this.input.getFNC1Character())?0:1:t-e==2?$r.isExtendedASCII(this.input.charAt(e),this.input.getFNC1Character())||$r.isExtendedASCII(this.input.charAt(e+1),this.input.getFNC1Character())?0:Yr.isDigit(this.input.charAt(e))&&Yr.isDigit(this.input.charAt(e+1))?1:2:t-e==3?Yr.isDigit(this.input.charAt(e))&&Yr.isDigit(this.input.charAt(e+1))&&!$r.isExtendedASCII(this.input.charAt(e+2),this.input.getFNC1Character())||Yr.isDigit(this.input.charAt(e+1))&&Yr.isDigit(this.input.charAt(e+2))&&!$r.isExtendedASCII(this.input.charAt(e),this.input.getFNC1Character())?2:0:Yr.isDigit(this.input.charAt(e))&&Yr.isDigit(this.input.charAt(e+1))&&Yr.isDigit(this.input.charAt(e+2))&&Yr.isDigit(this.input.charAt(e+3))?2:0}getMinSymbolSize(t){switch(this.input.getShapeHint()){case 1:for(const e of this.squareCodewordCapacities)if(e>=t)return e;break;case 2:for(const e of this.rectangularCodewordCapacities)if(e>=t)return e}for(const e of this.allCodewordCapacities)if(e>=t)return e;return this.allCodewordCapacities[this.allCodewordCapacities.length-1]}getCodewordsRemaining(t){return this.getMinSymbolSize(t)-t}static getBytes(t,e){const r=new Uint8Array(e?2:1);return r[0]=t,e&&(r[1]=e),r}setC40Word(t,e,r,n,i){const s=1600*(255&r)+40*(255&n)+(255&i)+1;t[e]=s/256,t[e+1]=s%256}getX12Value(t){return 13===t?0:42===t?1:62===t?2:32===t?3:t>=48&&t<=57?t-44:t>=65&&t<=90?t-51:t}getX12Words(){if(this.characterLength%3!=0)throw new Error("X12 words must be a multiple of 3");const t=new Uint8Array(this.characterLength/3*2);for(let e=0;e=33&&r<=47?r-33:r>=48&&r<=57?r-44:r>=58&&r<=64?r-43:r>=65&&r<=90?r-64:r>=91&&r<=95?r-69:96===r?0:r>=97&&r<=122?r-83:r>=123&&r<=127?r-96:r}getC40Words(t,e){const r=[];for(let n=0;n>16&255,e[i+1]=s>>8&255,e[i+2]=255&s}return e}getLatchBytes(){switch(this.getPreviousMode()){case jr.ASCII:case jr.B256:switch(this.mode){case jr.B256:return en.getBytes(231);case jr.C40:return en.getBytes(230);case jr.TEXT:return en.getBytes(239);case jr.X12:return en.getBytes(238);case jr.EDF:return en.getBytes(240)}break;case jr.C40:case jr.TEXT:case jr.X12:if(this.mode!==this.getPreviousMode())switch(this.mode){case jr.ASCII:return en.getBytes(254);case jr.B256:return en.getBytes(254,231);case jr.C40:return en.getBytes(254,230);case jr.TEXT:return en.getBytes(254,239);case jr.X12:return en.getBytes(254,238);case jr.EDF:return en.getBytes(254,240)}break;case jr.EDF:if(this.mode!==jr.EDF)throw new Error("Cannot switch from EDF to "+this.mode)}return new Uint8Array(0)}getDataBytes(){switch(this.mode){case jr.ASCII:return this.input.isECI(this.fromPosition)?en.getBytes(241,this.input.getECIValue(this.fromPosition)+1):$r.isExtendedASCII(this.input.charAt(this.fromPosition),this.input.getFNC1Character())?en.getBytes(235,this.input.charAt(this.fromPosition)-127):2===this.characterLength?en.getBytes(10*this.input.charAt(this.fromPosition)+this.input.charAt(this.fromPosition+1)+130):this.input.isFNC1(this.fromPosition)?en.getBytes(232):en.getBytes(this.input.charAt(this.fromPosition)+1);case jr.B256:return en.getBytes(this.input.charAt(this.fromPosition));case jr.C40:return this.getC40Words(!0,this.input.getFNC1Character());case jr.TEXT:return this.getC40Words(!1,this.input.getFNC1Character());case jr.X12:return this.getX12Words();case jr.EDF:return this.getEDFBytes()}}}class rn extends qr{constructor(t,e,r,n,i){super(t,e,r),this.shape=n,this.macroId=i}getMacroId(){return this.macroId}getShapeHint(){return this.shape}}class nn{isCompact(){return this.compact}setCompact(t){this.compact=t}getSize(){return this.size}setSize(t){this.size=t}getLayers(){return this.layers}setLayers(t){this.layers=t}getCodeWords(){return this.codeWords}setCodeWords(t){this.codeWords=t}getMatrix(){return this.matrix}setMatrix(t){this.matrix=t}}class sn{static singletonList(t){return[t]}static min(t,e){return t.sort(e)[0]}}class on{constructor(t){this.previous=t}getPrevious(){return this.previous}}class an extends on{constructor(t,e,r){super(t),this.value=e,this.bitCount=r}appendTo(t,e){t.appendBits(this.value,this.bitCount)}add(t,e){return new an(this,t,e)}addBinaryShift(t,e){return console.warn("addBinaryShift on SimpleToken, this simply returns a copy of this token"),new an(this,t,e)}toString(){let t=this.value&(1<"}}class hn extends an{constructor(t,e,r){super(t,0,0),this.binaryShiftStart=e,this.binaryShiftByteCount=r}appendTo(t,e){for(let r=0;r62?t.appendBits(this.binaryShiftByteCount-31,16):0===r?t.appendBits(Math.min(this.binaryShiftByteCount,31),5):t.appendBits(this.binaryShiftByteCount-31,5)),t.appendBits(e[this.binaryShiftStart+r],8)}addBinaryShift(t,e){return new hn(this,t,e)}toString(){return"<"+this.binaryShiftStart+"::"+(this.binaryShiftStart+this.binaryShiftByteCount-1)+">"}}function ln(t,e,r){return new an(t,e,r)}const cn=["UPPER","LOWER","DIGIT","MIXED","PUNCT"],dn=new an(null,0,0),un=[Int32Array.from([0,327708,327710,327709,656318]),Int32Array.from([590318,0,327710,327709,656318]),Int32Array.from([262158,590300,0,590301,932798]),Int32Array.from([327709,327708,656318,0,327710]),Int32Array.from([327711,656380,656382,656381,0])];const gn=function(t){for(let e of t)f.fill(e,-1);return t[0][4]=0,t[1][4]=0,t[1][0]=28,t[3][4]=0,t[2][4]=0,t[2][0]=15,t}(f.createInt32Array(6,6));class fn{constructor(t,e,r,n){this.token=t,this.mode=e,this.binaryShiftByteCount=r,this.bitCount=n}getMode(){return this.mode}getToken(){return this.token}getBinaryShiftByteCount(){return this.binaryShiftByteCount}getBitCount(){return this.bitCount}latchAndAppend(t,e){let r=this.bitCount,n=this.token;if(t!==this.mode){let e=un[this.mode][t];n=ln(n,65535&e,e>>16),r+=e>>16}let i=2===t?4:5;return n=ln(n,e,i),new fn(n,t,0,r+i)}shiftAndAppend(t,e){let r=this.token,n=2===this.mode?4:5;return r=ln(r,gn[this.mode][t],n),r=ln(r,e,5),new fn(r,this.mode,0,this.bitCount+n+5)}addBinaryShiftChar(t){let e=this.token,r=this.mode,n=this.bitCount;if(4===this.mode||2===this.mode){let t=un[r][0];e=ln(e,65535&t,t>>16),n+=t>>16,r=0}let i=0===this.binaryShiftByteCount||31===this.binaryShiftByteCount?18:62===this.binaryShiftByteCount?9:8,s=new fn(e,r,this.binaryShiftByteCount+1,n+i);return 2078===s.binaryShiftByteCount&&(s=s.endBinaryShift(t+1)),s}endBinaryShift(t){if(0===this.binaryShiftByteCount)return this;let e=this.token;return e=function(t,e,r){return new hn(t,e,r)}(e,t-this.binaryShiftByteCount,this.binaryShiftByteCount),new fn(e,this.mode,0,this.bitCount)}isBetterThanOrEqualTo(t){let e=this.bitCount+(un[this.mode][t.mode]>>16);return this.binaryShiftByteCountt.binaryShiftByteCount&&t.binaryShiftByteCount>0&&(e+=10),e<=t.bitCount}toBitArray(t){let e=[];for(let r=this.endBinaryShift(t.length).token;null!==r;r=r.getPrevious())e.unshift(r);let r=new C;for(const n of e)n.appendTo(r,t);return r}toString(){return p.format("%s bits=%d bytes=%d",cn[this.mode],this.bitCount,this.binaryShiftByteCount)}static calculateBinaryShiftCost(t){return t.binaryShiftByteCount>62?21:t.binaryShiftByteCount>31?20:t.binaryShiftByteCount>0?10:0}}fn.INITIAL_STATE=new fn(dn,0,0,0);const wn=function(t){const e=p.getCharCode(" "),r=p.getCharCode("."),n=p.getCharCode(",");t[0][e]=1;const i=p.getCharCode("Z"),s=p.getCharCode("A");for(let e=s;e<=i;e++)t[0][e]=e-s+2;t[1][e]=1;const o=p.getCharCode("z"),a=p.getCharCode("a");for(let e=a;e<=o;e++)t[1][e]=e-a+2;t[2][e]=1;const h=p.getCharCode("9"),l=p.getCharCode("0");for(let e=l;e<=h;e++)t[2][e]=e-l+2;t[2][n]=12,t[2][r]=13;const c=["\0"," ","","","","","","","","\b","\t","\n","\v","\f","\r","","","","","","@","\\","^","_","`","|","~",""];for(let e=0;e","?","[","]","{","}"];for(let e=0;e0&&(t[4][p.getCharCode(d[e])]=e);return t}(f.createInt32Array(5,256));class Cn{constructor(t){this.text=t}encode(){const t=p.getCharCode(" "),e=p.getCharCode("\n");let r=sn.singletonList(fn.INITIAL_STATE);for(let n=0;n0?(r=Cn.updateStateListForPair(r,n,i),n++):r=this.updateStateListForChar(r,n)}return sn.min(r,((t,e)=>t.getBitCount()-e.getBitCount())).toBitArray(this.text)}updateStateListForChar(t,e){const r=[];for(let n of t)this.updateStateForChar(n,e,r);return Cn.simplifyStates(r)}updateStateForChar(t,e,r){let n=255&this.text[e],i=wn[t.getMode()][n]>0,s=null;for(let o=0;o<=4;o++){let a=wn[o][n];if(a>0){if(null==s&&(s=t.endBinaryShift(e)),!i||o===t.getMode()||2===o){const t=s.latchAndAppend(o,a);r.push(t)}if(!i&&gn[t.getMode()][o]>=0){const t=s.shiftAndAppend(o,a);r.push(t)}}}if(t.getBinaryShiftByteCount()>0||0===wn[t.getMode()][n]){let n=t.addBinaryShiftChar(e);r.push(n)}}static updateStateListForPair(t,e,r){const n=[];for(let i of t)this.updateStateForPair(i,e,r,n);return this.simplifyStates(n)}static updateStateForPair(t,e,r,n){let i=t.endBinaryShift(e);if(n.push(i.latchAndAppend(4,r)),4!==t.getMode()&&n.push(i.shiftAndAppend(4,r)),3===r||4===r){let t=i.latchAndAppend(2,16-r).latchAndAppend(2,1);n.push(t)}if(t.getBinaryShiftByteCount()>0){let r=t.addBinaryShiftChar(e).addBinaryShiftChar(e+1);n.push(r)}}static simplifyStates(t){let e=[];for(const r of t){let t=!0;for(const n of e){if(n.isBetterThanOrEqualTo(r)){t=!1;break}r.isBetterThanOrEqualTo(n)&&(e=e.filter((t=>t!==n)))}t&&e.push(r)}return e}}class An{constructor(){}static encodeBytes(t){return An.encode(t,An.DEFAULT_EC_PERCENT,An.DEFAULT_AZTEC_LAYERS)}static encode(t,e,r){let n,i,s,o,h,l=new Cn(t).encode(),c=w.truncDivision(l.getSize()*e,100)+11,d=l.getSize()+c;if(r!==An.DEFAULT_AZTEC_LAYERS){if(n=r<0,i=Math.abs(r),i>(n?An.MAX_NB_BITS_COMPACT:An.MAX_NB_BITS))throw new a(p.format("Illegal value %s for layers",r));s=An.totalBitsInLayer(i,n),o=An.WORD_SIZE[i];let t=s-s%o;if(h=An.stuffBits(l,o),h.getSize()+c>t)throw new a("Data to large for user specified layer");if(n&&h.getSize()>64*o)throw new a("Data to large for user specified layer")}else{o=0,h=null;for(let t=0;;t++){if(t>An.MAX_NB_BITS)throw new a("Data too large for an Aztec code");if(n=t<=3,i=n?t+1:t,s=An.totalBitsInLayer(i,n),d>s)continue;null!=h&&o===An.WORD_SIZE[i]||(o=An.WORD_SIZE[i],h=An.stuffBits(l,o));let e=s-s%o;if(!(n&&h.getSize()>64*o)&&h.getSize()+c<=e)break}}let u,g=An.generateCheckWords(h,s,o),f=h.getSize()/o,C=An.generateModeMessage(n,i,f),A=(n?11:14)+4*i,E=new Int32Array(A);if(n){u=A;for(let t=0;t=n||t.get(s+r))&&(o|=1< { try { const d = JSON.parse(fs.readFileSync(planFile(), 'utf8')); return { days: d && d.days && typeof d.days === 'object' ? d.days : {} }; } catch { return { days: {} }; } }; const writePlan = d => atomicWrite(planFile(), JSON.stringify(d), { mode: 0o600 }); const planBetween = (from, to) => { const out = {}; for (const [k, v] of Object.entries(readPlan().days)) if (k >= from && k <= to) out[k] = v; return out; }; -// The pantry: what the family keeps in stock, one shared list. Each item has a name, how many are left (blank when you do not count it) and the level it counts as -// running low at (blank: never). The meal plan points out planned ingredients you have; an item going low can start an automation and goes on the shopping list in a tap. -const pantryFile = () => path.join(process.env.DATA_DIR || path.join(__dirname, 'data'), 'pantry.json'); -const num = v => v === '' || v == null || !isFinite(+v) || +v < 0 ? null : Math.min(100000, Math.round(+v * 100) / 100); -const readPantry = () => { try { const a = JSON.parse(fs.readFileSync(pantryFile(), 'utf8')); return (Array.isArray(a) ? a : []).map(x => typeof x === 'string' ? { id: crypto.randomBytes(4).toString('hex'), name: x, qty: null, low: null } : x).filter(x => x && x.name); } catch { return []; } }; -const writePantry = l => atomicWrite(pantryFile(), JSON.stringify(l), { mode: 0o600 }); -const isLow = x => x.qty != null && x.low != null && x.qty <= x.low; -const pantryView = l => l.map(x => ({ id: x.id, name: x.name, qty: x.qty, low: x.low, isLow: isLow(x) })).sort((a, b) => b.isLow - a.isLow || a.name.localeCompare(b.name)); -const stem = w => w.replace(/(ies)$/, 'y').replace(/(es|s)$/, ''); -const inPantry = (text, items) => { items = items.map(x => typeof x === 'string' ? x : x.name); const words = new Set(String(text).toLowerCase().match(/[a-z]+/g) || []), stems = new Set([...words].map(stem)); return items.filter(it => { const ws = (String(it).toLowerCase().match(/[a-z]+/g) || []).map(stem); return ws.length && ws.every(w => stems.has(w)); }); }; -/** An item has just gone low: tell the automations of everyone who asked to hear about it. */ -function pantryLow(it) { try { require('./automations').fireAll('pantry.low', { title: it.name }); } catch (e) { console.warn('[recipes] pantry rules failed:', e.message); } } +const pantry = require('./pantry'); // what is in stock (the plan checks its ingredients against it) /** A recipe's ingredients onto Mealie's shopping list, `times` over (Mealie adds up what is already there). */ async function addRecipe(slug, times) { const r = await mealie('/api/recipes/' + (slugOk(slug) ? slug : '-')), list = await mainList(), mult = Math.max(0.25, Math.min(20, +times || 1)); @@ -164,22 +153,9 @@ async function handle(req, res) { if (d.days[b.date].length > 12) throw fail(400, 'That day is full'); writePlan(d); return json(res, 200, { ok: true, id }); } if (p === '/plan/remove' && req.method === 'POST') { const b = JSON.parse(await readBody(req, 1e4) || '{}'), d = readPlan(); for (const k of Object.keys(d.days)) { d.days[k] = d.days[k].filter(e => e.id !== b.id); if (!d.days[k].length) delete d.days[k]; } writePlan(d); return json(res, 200, { ok: true }); } - if (p === '/pantry' && req.method === 'GET') return json(res, 200, { items: pantryView(readPantry()) }); - if (p === '/pantry/item' && req.method === 'POST') { // add an item, or change one - const b = JSON.parse(await readBody(req, 2e3) || '{}'), l = readPantry(), name = String(b.name || '').replace(/[\u0000-\u001f]/g, '').trim().slice(0, 60); if (!name) throw fail(400, 'Give the item a name'); - const i = b.id ? l.findIndex(x => x.id === b.id) : l.findIndex(x => x.name.toLowerCase() === name.toLowerCase()); if (b.id && i < 0) throw fail(404, 'That item is gone'); if (i < 0 && l.length >= 400) throw fail(400, 'The pantry is full'); - const before = i >= 0 ? isLow(l[i]) : false, it = { id: i >= 0 ? l[i].id : crypto.randomBytes(4).toString('hex'), name: i >= 0 && !b.id ? l[i].name : name, qty: num(b.qty), low: num(b.low) }; if (i >= 0) l[i] = it; else l.push(it); writePantry(l); - if (isLow(it) && !before) pantryLow(it); - return json(res, 200, { items: pantryView(l) }); - } - if (p === '/pantry/adjust' && req.method === 'POST') { // one more or one less - const b = JSON.parse(await readBody(req, 1e3) || '{}'), l = readPantry(), it = l.find(x => x.id === b.id); if (!it) throw fail(404, 'That item is gone'); - const before = isLow(it); it.qty = Math.max(0, Math.round(((it.qty || 0) + (+b.delta || 0)) * 100) / 100); writePantry(l); if (isLow(it) && !before) pantryLow(it); return json(res, 200, { items: pantryView(l) }); - } - if (p === '/pantry/delete' && req.method === 'POST') { const b = JSON.parse(await readBody(req, 1e3) || '{}'); const l = readPantry().filter(x => x.id !== b.id); writePantry(l); return json(res, 200, { items: pantryView(l) }); } if (p === '/plan/pantry' && req.method === 'GET') { // which planned ingredients the pantry already covers - const from = q.get('from') || '', to = q.get('to') || ''; if (!DAY.test(from) || !DAY.test(to)) throw fail(400, 'Bad dates'); const items = readPantry().filter(x => x.qty !== 0), out = []; if (!items.length) return json(res, 200, { items: [] }); - for (const sl of [...new Set(Object.values(planBetween(from, to)).flat().map(e => e.slug))]) { try { const r = full(await mealie('/api/recipes/' + sl)); for (const i of r.ingredients) { const hit = i.text && inPantry(i.text, items); if (hit && hit.length) out.push({ recipe: r.name, text: i.text, have: hit[0] }); } } catch (e) { if (e.code !== 404 && e.status !== 404) throw e; } } + const from = q.get('from') || '', to = q.get('to') || ''; if (!DAY.test(from) || !DAY.test(to)) throw fail(400, 'Bad dates'); const items = pantry.read().filter(x => x.qty !== 0), out = []; if (!items.length) return json(res, 200, { items: [] }); + for (const sl of [...new Set(Object.values(planBetween(from, to)).flat().map(e => e.slug))]) { try { const r = full(await mealie('/api/recipes/' + sl)); for (const i of r.ingredients) { const hit = i.text && pantry.inPantry(i.text, items); if (hit && hit.length) out.push({ recipe: r.name, text: i.text, have: hit[0] }); } } catch (e) { if (e.code !== 404 && e.status !== 404) throw e; } } return json(res, 200, { items: out }); } if (p === '/plan/shop' && req.method === 'POST') { // every planned meal in the range goes on the shopping list (a recipe planned twice counts twice) diff --git a/server.js b/server.js index 3e42120..ace7c62 100644 --- a/server.js +++ b/server.js @@ -48,6 +48,7 @@ const contacts = require('./contacts'); // each person's address book (mail su const activity = require('./activity'), alertParents = activity.alertParents; const kidlimits = require('./kidlimits'); // child accounts: a daily time limit and bedtime, and asking a parent for more time const screentime = require('./screentime'); // fewer web addresses for iPad Screen Time: a report-only policy, the list of what devices reached, and a picture pass-through +const pantry = require('./pantry'); // the family pantry, with barcode scanning const automations = require('./automations'); // when this happens, do that (per person) const moviefam = require('./moviefam'); // Movies & TV: favorites and the family's movie night list const chores = require('./chores'); // chores for the family, with points @@ -586,6 +587,7 @@ const ACCESS = [ [/^\/api\/bible\//, ['bible']], [/^\/api\/read\//, ['read']], [/^\/api\/radio\//, ['radio']], + [/^\/api\/pantry(\/|$)/, ['recipes']], [/^\/api\/moviefam(\/|$)/, ['video']], [/^\/api\/chores(\/|$)/, ['chores']], [/^\/api\/notes(\/|$)/, ['notes']], @@ -612,7 +614,7 @@ function securityHeaders(res) { res.setHeader('Referrer-Policy', 'same-origin'); res.setHeader('Content-Security-Policy', "frame-ancestors 'self'; base-uri 'self'; object-src 'none'; form-action 'self'"); res.setHeader('Content-Security-Policy-Report-Only', screentime.policy()); // (reports only: nothing is blocked) - res.setHeader('Permissions-Policy', 'camera=(), geolocation=(), payment=()'); + res.setHeader('Permissions-Policy', 'camera=(self), geolocation=(), payment=()'); if (process.env.PUBLIC_URL && process.env.PUBLIC_URL.startsWith('https://')) res.setHeader('Strict-Transport-Security', 'max-age=15552000'); } /** Cross-site request check: a browser request that changes something must come from this same site. */ @@ -716,6 +718,7 @@ async function handleRequest(req, res) { if (pathname === '/api/kid/requests' || pathname.startsWith('/api/kid/requests/')) return require('./requests').handle(req, res, user); if (pathname.startsWith('/api/kid/')) return kidlimits.handle(req, res, user, { askParents: chat.askParents }); if (pathname === '/api/csp-report' || pathname === '/api/img' || pathname === '/api/screentime') return screentime.handle(req, res, user); + if (pathname === '/api/pantry' || pathname.startsWith('/api/pantry/')) return pantry.handle(req, res); if (pathname === '/api/auto' || pathname.startsWith('/api/auto/')) return automations.handle(req, res); if (pathname === '/api/moviefam' || pathname.startsWith('/api/moviefam/')) return moviefam.handle(req, res); if (pathname === '/api/chores' || pathname.startsWith('/api/chores/')) return chores.handle(req, res); diff --git a/tools/frontend-test.js b/tools/frontend-test.js index 904334c..c304026 100644 --- a/tools/frontend-test.js +++ b/tools/frontend-test.js @@ -32,7 +32,7 @@ for (const f of listed) { } assert.deepEqual(failures, [], 'every script loads:\n ' + failures.join('\n ')); // the pieces the app calls by name across files are there -for (const name of ['route', 'viewHome', 'viewSettings', 'viewTasks', 'viewCalendar', 'viewBible', 'viewMail', 'viewRecipes', 'viewVideo', 'themeApply', 'autoSettings', 'bbToday', 'homeListening', 'saveToFiles', 'downloadText']) assert.equal(typeof vm.runInContext(`typeof ${name}`, ctx), 'string') && assert.equal(vm.runInContext(`typeof ${name}`, ctx), 'function', name + ' is defined'); +for (const name of ['route', 'viewHome', 'viewSettings', 'viewTasks', 'viewCalendar', 'viewBible', 'viewMail', 'viewRecipes', 'viewVideo', 'themeApply', 'autoSettings', 'bbToday', 'homeListening', 'saveToFiles', 'downloadText', 'viewPantry', 'pantryScan']) assert.equal(typeof vm.runInContext(`typeof ${name}`, ctx), 'string') && assert.equal(vm.runInContext(`typeof ${name}`, ctx), 'function', name + ' is defined'); // the watch-stats counting (a pure function) { const now = Date.UTC(2026, 5, 15, 12), at = d => Math.floor((now - d * 864e5) / 1000), agg = vm.runInContext('vdAgg', ctx); const a = agg([{ lastViewedAt: at(1), duration: 6e6, Genre: [{ tag: 'Drama' }, { tag: 'Comedy' }] }, { lastViewedAt: at(3), duration: 3e6, Genre: [{ tag: 'Drama' }] }, { lastViewedAt: at(20), duration: 6e6 }, { lastViewedAt: at(200), duration: 6e6, Genre: [{ tag: 'Drama' }] }, { lastViewedAt: at(400), duration: 6e6 }, { duration: 6e6 }], now); diff --git a/tools/pantry-test.js b/tools/pantry-test.js new file mode 100644 index 0000000..b982db6 --- /dev/null +++ b/tools/pantry-test.js @@ -0,0 +1,62 @@ +// The pantry: items with counts and low levels, several barcodes per item (corn from different brands is one item), product lookup (a stand-in for Open Food Facts), and what happens when a count goes low. +const assert = require('assert'), fs = require('fs'), os = require('os'), path = require('path'), http = require('http'); +process.env.DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), 'nehub-pantry-')); +let asked = [], down = false; +const off = http.createServer((req, res) => { const code = /product\/(\d+)\.json/.exec(req.url)[1]; asked.push(code); if (down) { res.destroy(); return; } + const P = { '0016000275287': { product_name: 'Green Giant Sweet Corn 15.25 oz', brands: 'Green Giant', quantity: '15.25 oz' }, '0024000163275': { product_name: "Libby's Whole Kernel Corn 425 g", brands: "Libby's" }, '0070470003344': { product_name: 'Greek Yogurt', brands: 'Chobani' } }; + res.setHeader('content-type', 'application/json'); res.end(JSON.stringify(P[code] ? { status: 1, product: P[code] } : { status: 0 })); }).listen(0, () => { + process.env.OPENFOODFACTS_URL = 'http://127.0.0.1:' + off.address().port; + const users = require('../users'), pantry = require('../pantry'), automations = require('../automations'); + const ann = users.create({ name: 'Ann', role: 'admin', handle: 'YQ' }), bo = users.create({ name: 'Bo', role: 'user', tabs: ['recipes'], handle: 'ZP' }), kid = users.create({ name: 'Kit', role: 'user', tabs: ['recipes'], handle: 'KD' }); kid.kid = { on: true }; + const hub = http.createServer((req, res) => users.runAs(req.headers['x-user'] === 'bo' ? bo : req.headers['x-user'] === 'kid' ? kid : ann, () => pantry.handle(req, res))).listen(0, async () => { + const base = 'http://127.0.0.1:' + hub.address().port + '/api/pantry', j = r => r.json(), get = p => fetch(base + p), post = (p, o, who) => fetch(base + p, { method: 'POST', body: JSON.stringify(o), headers: who ? { 'x-user': who } : {} }); + const fired = []; const realFireAll = automations.fireAll; automations.fireAll = async (t, c) => { fired.push(t + ':' + c.title); }; + try { + // names are cleaned from products + assert.equal(pantry.shortName('Heinz Tomato Ketchup 500 ml', 'Heinz'), 'Tomato Ketchup'); assert.equal(pantry.shortName('Green Giant Sweet Corn 15.25 oz', 'Green Giant'), 'Sweet Corn'); assert.equal(pantry.shortName('', ''), ''); + // items: add, count, change by the same name, adjust, low levels + assert.equal((await post('/item', { name: ' ' })).status, 400); + let r = await j(await post('/item', { name: 'Corn', qty: 2, low: 1 })); assert.deepEqual(r.items.map(x => [x.name, x.qty, x.low, x.isLow, x.codes.length]), [['Corn', 2, 1, false, 0]]); const corn = r.items[0].id; + r = await j(await post('/item', { name: 'corn', qty: 2, low: 1 })); assert.equal(r.items.length, 1, 'the same name updates the item'); assert.equal(r.items[0].name, 'Corn'); + r = await j(await post('/adjust', { id: corn, delta: -1 })); assert.equal(r.items[0].isLow, true); assert.deepEqual(fired, ['pantry.low:Corn'], 'going low starts the rules, once'); await post('/adjust', { id: corn, delta: -1 }); assert.equal(fired.length, 1, 'and not again while it stays low'); + assert.equal((await j(await post('/adjust', { id: corn, delta: -9 }))).items[0].qty, 0, 'never below none'); await post('/adjust', { id: corn, delta: 5 }); + // a barcode we have not seen: the product is looked up, and the items it might be are offered + assert.equal((await get('/lookup?code=abc')).status, 400); + r = await j(await get('/lookup?code=0016000275287')); assert.equal(r.linked, null); assert.equal(r.product.short, 'Sweet Corn'); assert.deepEqual(r.matches.map(m => m.name), ['Corn'], 'Corn is offered, since the product has the word corn'); + assert.equal((await post('/scan', { code: '0016000275287' })).status, 400, 'a new barcode must say which item it is'); + // scanning links it to the chosen item and adds one + r = await j(await post('/scan', { code: '0016000275287', itemId: corn })); assert.equal(r.item.name, 'Corn'); assert.equal(r.item.qty, 6); assert.equal(r.made, false); + asked = []; r = await j(await get('/lookup?code=0016000275287')); assert.deepEqual(r.linked, { id: corn, name: 'Corn' }, 'next time it goes straight to Corn'); assert.deepEqual(asked, [], 'without asking the product database again'); + r = await j(await post('/scan', { code: '0016000275287' })); assert.equal(r.item.qty, 7); + // a second brand is the same item, with one count + r = await j(await post('/scan', { code: '0024000163275', itemId: corn })); assert.equal(r.items.length, 1, 'still one item'); assert.equal(r.items[0].qty, 8); assert.equal(r.items[0].codes.length, 2, 'with two barcodes'); + // use one + r = await j(await post('/scan', { code: '0024000163275', mode: 'use' })); assert.equal(r.item.qty, 7); + // a new item made from a scan; the same name later finds it; products the database does not know are named by hand + r = await j(await post('/scan', { code: '0070470003344', name: 'Yogurt' })); assert.equal(r.made, true); assert.equal(r.item.qty, 1); r = await j(await get('/lookup?code=1234567890128')); assert.equal(r.product, null); assert.equal(r.lookedUp, true); + r = await j(await post('/scan', { code: '1234567890128', name: 'yogurt' })); assert.equal(r.made, false, 'a name that exists links to it'); assert.equal(r.item.qty, 2); + // using one that takes it to its low level fires the rules + fired.length = 0; await post('/item', { id: corn, name: 'Corn', qty: 3, low: 2 }); await post('/scan', { code: '0016000275287', mode: 'use' }); assert.deepEqual(fired, ['pantry.low:Corn']); + // the database being down is not an error for the person: they just name it + down = true; r = await j(await get('/lookup?code=5000112637922')); assert.equal(r.lookedUp, false); assert.equal(r.product, null); down = false; + // moving a barcode to another item takes it off the first; unlinking + const yog = (await j(await get('/'))).items.find(x => x.name === 'Yogurt').id; r = await j(await post('/scan', { code: '0016000275287', itemId: yog })); assert.equal((await j(await get('/lookup?code=0016000275287'))).linked.name, 'Corn', 'a linked barcode stays with its item'); + r = await j(await post('/unlink', { id: corn, code: '0016000275287' })); assert.equal(r.items.find(x => x.id === corn).codes.length, 1); + assert.equal((await post('/delete', { id: yog })).status, 200); assert.ok(!(await j(await get('/'))).items.some(x => x.name === 'Yogurt')); + // the simple way: take one (children too), with undo, and a note of who took what + r = await j(await post('/item', { name: 'Granola bars', qty: 2, low: 1 })); const gb = r.items.find(x => x.name === 'Granola bars').id; fired.length = 0; + r = await j(await post('/use', { id: gb }, 'kid')); assert.equal(r.item.qty, 1); assert.equal(r.item.isLow, true); assert.deepEqual(fired, ['pantry.low:Granola bars'], 'taking the second-to-last one starts the low rule'); assert.equal(r.recent[0].who, 'Kit'); assert.equal(r.recent[0].item, 'Granola bars'); + r = await j(await post('/use', { id: gb, undo: true }, 'kid')); assert.equal(r.item.qty, 2, 'undo puts it back'); await post('/use', { id: gb }, 'kid'); await post('/use', { id: gb }, 'kid'); assert.equal((await post('/use', { id: gb }, 'kid')).status, 409, 'none left to take'); + const note = (await j(await post('/item', { name: 'Napkins' }))).items.find(x => x.name === 'Napkins').id; r = await j(await post('/use', { id: note })); assert.equal(r.item.qty, null, 'an item that is not counted is only noted'); + // a child can look and take, and nothing else + for (const [p, o] of [['/item', { name: 'Candy', qty: 9 }], ['/adjust', { id: gb, delta: 5 }], ['/delete', { id: gb }], ['/unlink', { id: gb, code: '1' }], ['/scan', { code: '0099999999999', mode: 'add', name: 'Candy' }]]) assert.equal((await post(p, o, 'kid')).status, 403, p + ' is for grown-ups'); + assert.equal((await get('/')).status, 200); assert.equal((await j(await fetch(base + '/', { headers: { 'x-user': 'kid' } }))).kid, true); + r = await j(await post('/scan', { code: '0016000275287', itemId: corn })); const before = r.item.qty; r = await j(await post('/scan', { code: '0016000275287', mode: 'use' }, 'kid')); assert.equal(r.item.qty, before - 1, 'a child can scan a known barcode to take one'); assert.equal((await post('/scan', { code: '0555555555555', mode: 'use', name: 'Mystery' }, 'kid')).status, 403, 'but not make new items'); + // the pantry is shared, and old pantry files (a list of names) still load + assert.equal((await j(await get('/', 'bo'))).items.length >= 1, true); fs.writeFileSync(path.join(process.env.DATA_DIR, 'pantry.json'), JSON.stringify(['Flour', 'Salt'])); r = await j(await get('/')); assert.deepEqual(r.items.map(x => x.name), ['Flour', 'Salt']); assert.equal(r.items[0].qty, null); + assert.deepEqual(pantry.inPantry('3 cups all-purpose flour', ['Flour', 'Salt']), ['Flour']); + console.log('pantry test ok'); + } catch (e) { console.error(e); process.exitCode = 1; } + automations.fireAll = realFireAll; hub.close(); off.close(); + }); +}); diff --git a/tools/recipes-test.js b/tools/recipes-test.js index b4c54e1..ec2f91c 100644 --- a/tools/recipes-test.js +++ b/tools/recipes-test.js @@ -62,16 +62,12 @@ const fake = http.createServer((req, res) => { j = await (await post('/plan/shop', { from: '2027-03-02', to: '2027-03-08' })).json(); assert.equal(j.ok, true); assert.equal(j.recipes, 1, 'a recipe planned twice is added once, twice over'); assert.equal((await post('/plan/shop', { from: '2027-04-01', to: '2027-04-07' })).status, 400, 'nothing planned, nothing to add'); await post('/plan/remove', { id: (await (await get('/plan?from=2027-03-02&to=2027-03-02')).json())['2027-03-02'][0].id }); assert.deepEqual(await (await get('/plan?from=2027-03-02&to=2027-03-02')).json(), {}); - // the pantry: items with a count and a low level; the plan flags planned ingredients you have ("3 cups flour" is covered by "flour"; butter is not in the pantry) - await post('/plan/add', { date: '2027-05-03', slug: 'bread', name: 'Bread' }); - assert.equal((await post('/pantry/item', { name: ' ' })).status, 400, 'an item needs a name'); - j = await (await post('/pantry/item', { name: 'Flour', qty: 3, low: 1 })).json(); assert.deepEqual(j.items.map(x => [x.name, x.qty, x.low, x.isLow]), [['Flour', 3, 1, false]]); const fid = j.items[0].id; - j = await (await post('/pantry/item', { name: 'salt', qty: '', low: '' })).json(); assert.equal(j.items.find(x => x.name === 'salt').qty, null, 'an item need not be counted'); assert.equal(j.items.find(x => x.name === 'salt').isLow, false); - j = await (await post('/pantry/item', { name: 'FLOUR', qty: 3, low: 1 })).json(); assert.equal(j.items.filter(x => x.name.toLowerCase() === 'flour').length, 1, 'the same name updates the item'); + // the pantry check: a planned ingredient the pantry has ("3 cups flour" is covered by "flour"; butter is not in the pantry, and an empty one is not "had") + await post('/plan/add', { date: '2027-05-03', slug: 'bread', name: 'Bread' }); const pf = path.join(process.env.DATA_DIR, 'pantry.json'); + fs.writeFileSync(pf, JSON.stringify([{ id: 'a1', name: 'Flour', qty: 3, low: 1, codes: [] }, { id: 'a2', name: 'Salt', qty: null, low: null, codes: [] }])); j = await (await get('/plan/pantry?from=2027-05-03&to=2027-05-09')).json(); assert.deepEqual(j.items.map(i => i.text), ['3 cups flour']); assert.equal(j.items[0].have.toLowerCase(), 'flour'); - j = await (await post('/pantry/adjust', { id: fid, delta: -2 })).json(); assert.equal(j.items[0].qty, 1); assert.equal(j.items[0].isLow, true, 'at the low level counts as running low'); assert.equal(j.items[0].name, 'Flour', 'low ones come first'); - j = await (await post('/pantry/adjust', { id: fid, delta: -5 })).json(); assert.equal(j.items[0].qty, 0, 'never below none'); assert.deepEqual((await (await get('/plan/pantry?from=2027-05-03&to=2027-05-09')).json()).items, [], 'an empty one is not "had"'); - await post('/pantry/delete', { id: fid }); j = await (await get('/pantry')).json(); assert.deepEqual(j.items.map(x => x.name), ['salt']); + fs.writeFileSync(pf, JSON.stringify([{ id: 'a1', name: 'Flour', qty: 0, low: 1, codes: [] }])); assert.deepEqual((await (await get('/plan/pantry?from=2027-05-03&to=2027-05-09')).json()).items, [], 'an empty one is not "had"'); + fs.writeFileSync(pf, '[]'); assert.deepEqual((await (await get('/plan/pantry?from=2027-05-03&to=2027-05-09')).json()).items, [], 'an empty pantry flags nothing'); // a wrong token is explained process.env.MEALIE_TOKEN = 'bad'; r = await get('/'); assert.equal(r.status, 502); assert.match((await r.json()).error, /token/); process.env.MEALIE_TOKEN = ''; assert.equal((await get('/')).status, 503);