From 9b89d76e6b779fc529b9f3fa9084a2c4d3804453 Mon Sep 17 00:00:00 2001 From: AlecM33 Date: Sun, 19 Jun 2022 18:59:08 -0400 Subject: [PATCH] qr code --- .eslintrc.json | 2 +- client/src/modules/GameStateRenderer.js | 10 +++++++--- client/src/modules/HTMLFragments.js | 1 + client/src/modules/third_party/qrcode.js | 1 + client/src/styles/game.css | 24 +++++++++++++++++++----- karma.conf.js | 1 + 6 files changed, 30 insertions(+), 9 deletions(-) create mode 100644 client/src/modules/third_party/qrcode.js diff --git a/.eslintrc.json b/.eslintrc.json index f238ba3..1de264a 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -7,7 +7,7 @@ "extends": [ "standard" ], - "ignorePatterns": ["/client/dist/*", "client/certs/*", "client/favicon_package/*", "client/webpack/*", "node_modules/*"], + "ignorePatterns": ["/client/dist/*", "client/certs/*", "client/favicon_package/*", "client/webpack/*", "node_modules/*", "client/src/modules/third_party/*"], "parser": "@babel/eslint-parser", "parserOptions": { "requireConfigFile": false, diff --git a/client/src/modules/GameStateRenderer.js b/client/src/modules/GameStateRenderer.js index 97b560d..cac34d7 100644 --- a/client/src/modules/GameStateRenderer.js +++ b/client/src/modules/GameStateRenderer.js @@ -4,6 +4,8 @@ import { HTMLFragments } from './HTMLFragments.js'; import { ModalManager } from './ModalManager.js'; import { XHRUtility } from './XHRUtility.js'; import { UserUtility } from './UserUtility.js'; +// QRCode module via: https://github.com/soldair/node-qrcode +import { QRCode } from './third_party/qrcode.js'; export class GameStateRenderer { constructor (stateBucket, socket) { @@ -69,9 +71,6 @@ export class GameStateRenderer { renderLobbyHeader () { removeExistingTitle(); - const title = document.createElement('h1'); - title.innerText = 'Lobby'; - document.getElementById('game-title').appendChild(title); const gameLinkContainer = document.getElementById('game-link'); const copyImg = document.createElement('img'); @@ -109,6 +108,11 @@ export class GameStateRenderer { '?playerCount=' + getGameSize(this.stateBucket.currentGameState.deck) + '&timer=' + encodeURIComponent(timeString); + QRCode.toCanvas(document.getElementById('canvas'), link, { scale: 3 }, function (error) { + if (error) console.error(error); + console.log('success!'); + }); + const linkCopyHandler = (e) => { if (e.type === 'click' || e.code === 'Enter') { navigator.clipboard.writeText(link) diff --git a/client/src/modules/HTMLFragments.js b/client/src/modules/HTMLFragments.js index d2517be..db86009 100644 --- a/client/src/modules/HTMLFragments.js +++ b/client/src/modules/HTMLFragments.js @@ -6,6 +6,7 @@ export const HTMLFragments = {
+
clock diff --git a/client/src/modules/third_party/qrcode.js b/client/src/modules/third_party/qrcode.js new file mode 100644 index 0000000..8cc258c --- /dev/null +++ b/client/src/modules/third_party/qrcode.js @@ -0,0 +1 @@ +export var QRCode = (function (t) { 'use strict'; let r; const e = function () { return typeof Promise === 'function' && Promise.prototype && Promise.prototype.then; }; const n = [0, 26, 44, 70, 100, 134, 172, 196, 242, 292, 346, 404, 466, 532, 581, 655, 733, 815, 901, 991, 1085, 1156, 1258, 1364, 1474, 1588, 1706, 1828, 1921, 2051, 2185, 2323, 2465, 2611, 2761, 2876, 3034, 3196, 3362, 3532, 3706]; const o = function (t) { if (!t) throw new Error('"version" cannot be null or undefined'); if (t < 1 || t > 40) throw new Error('"version" should be in range from 1 to 40'); return 4 * t + 17; }; const a = function (t) { return n[t]; }; const i = function (t) { for (var r = 0; t !== 0;)r ++, t >>>= 1; return r; }; const u = function (t) { if (typeof t !== 'function') throw new Error('"toSJISFunc" is not a valid function.'); r = t; }; const s = function () { return void 0 !== r; }; const f = function (t) { return r(t); }; function h (t, r) { return t(r = { exports: {} }, r.exports), r.exports; } const c = h(function (t, r) { r.L = { bit: 1 }, r.M = { bit: 0 }, r.Q = { bit: 3 }, r.H = { bit: 2 }, r.isValid = function (t) { return t && void 0 !== t.bit && t.bit >= 0 && t.bit < 4; }, r.from = function (t, e) { if (r.isValid(t)) return t; try { return (function (t) { if (typeof t !== 'string') throw new Error('Param is not a string'); switch (t.toLowerCase()) { case 'l':case 'low':return r.L; case 'm':case 'medium':return r.M; case 'q':case 'quartile':return r.Q; case 'h':case 'high':return r.H; default:throw new Error('Unknown EC Level: ' + t); } }(t)); } catch (t) { return e; } }; }); function g () { this.buffer = [], this.length = 0; }c.L, c.M, c.Q, c.H, c.isValid, g.prototype = { get: function (t) { const r = Math.floor(t / 8); return (this.buffer[r] >>> 7 - t % 8 & 1) == 1; }, put: function (t, r) { for (let e = 0; e < r; e ++) this.putBit((t >>> r - e - 1 & 1) == 1); }, getLengthInBits: function () { return this.length; }, putBit: function (t) { const r = Math.floor(this.length / 8); this.buffer.length <= r && this.buffer.push(0), t && (this.buffer[r] |= 128 >>> this.length % 8), this.length ++; } }; const d = g; function l (t) { if (!t || t < 1) throw new Error('BitMatrix size must be defined and greater than 0'); this.size = t, this.data = new Uint8Array(t * t), this.reservedBit = new Uint8Array(t * t); }l.prototype.set = function (t, r, e, n) { const o = t * this.size + r; this.data[o] = e, n && (this.reservedBit[o] = !0); }, l.prototype.get = function (t, r) { return this.data[t * this.size + r]; }, l.prototype.xor = function (t, r, e) { this.data[t * this.size + r] ^= e; }, l.prototype.isReserved = function (t, r) { return this.reservedBit[t * this.size + r]; }; const v = l; const p = h(function (t, r) { const e = o; r.getRowColCoords = function (t) { if (t === 1) return []; for (var r = Math.floor(t / 7) + 2, n = e(t), o = n === 145 ? 26 : 2 * Math.ceil((n - 13) / (2 * r - 2)), a = [n - 7], i = 1; i < r - 1; i ++)a[i] = a[i - 1] - o; return a.push(6), a.reverse(); }, r.getPositions = function (t) { for (var e = [], n = r.getRowColCoords(t), o = n.length, a = 0; a < o; a ++) for (let i = 0; i < o; i ++)a === 0 && i === 0 || a === 0 && i === o - 1 || a === o - 1 && i === 0 || e.push([n[a], n[i]]); return e; }; }); p.getRowColCoords, p.getPositions; const w = o; const m = function (t) { const r = w(t); return [[0, 0], [r - 7, 0], [0, r - 7]]; }; const E = h(function (t, r) { r.Patterns = { PATTERN000: 0, PATTERN001: 1, PATTERN010: 2, PATTERN011: 3, PATTERN100: 4, PATTERN101: 5, PATTERN110: 6, PATTERN111: 7 }; const e = 3; const n = 3; const o = 40; const a = 10; function i (t, e, n) { switch (t) { case r.Patterns.PATTERN000:return (e + n) % 2 == 0; case r.Patterns.PATTERN001:return e % 2 == 0; case r.Patterns.PATTERN010:return n % 3 == 0; case r.Patterns.PATTERN011:return (e + n) % 3 == 0; case r.Patterns.PATTERN100:return (Math.floor(e / 2) + Math.floor(n / 3)) % 2 == 0; case r.Patterns.PATTERN101:return e * n % 2 + e * n % 3 == 0; case r.Patterns.PATTERN110:return (e * n % 2 + e * n % 3) % 2 == 0; case r.Patterns.PATTERN111:return (e * n % 3 + (e + n) % 2) % 2 == 0; default:throw new Error('bad maskPattern:' + t); } }r.isValid = function (t) { return t != null && t !== '' && !isNaN(t) && t >= 0 && t <= 7; }, r.from = function (t) { return r.isValid(t) ? parseInt(t, 10) : void 0; }, r.getPenaltyN1 = function (t) { for (var r = t.size, n = 0, o = 0, a = 0, i = null, u = null, s = 0; s < r; s ++) { o = a = 0, i = u = null; for (let f = 0; f < r; f ++) { let h = t.get(s, f); h === i ? o ++ : (o >= 5 && (n += e + (o - 5)), i = h, o = 1), (h = t.get(f, s)) === u ? a ++ : (a >= 5 && (n += e + (a - 5)), u = h, a = 1); }o >= 5 && (n += e + (o - 5)), a >= 5 && (n += e + (a - 5)); } return n; }, r.getPenaltyN2 = function (t) { for (var r = t.size, e = 0, o = 0; o < r - 1; o ++) for (let a = 0; a < r - 1; a ++) { const i = t.get(o, a) + t.get(o, a + 1) + t.get(o + 1, a) + t.get(o + 1, a + 1); i !== 4 && i !== 0 || e ++; } return e * n; }, r.getPenaltyN3 = function (t) { for (var r = t.size, e = 0, n = 0, a = 0, i = 0; i < r; i ++) { n = a = 0; for (let u = 0; u < r; u ++)n = n << 1 & 2047 | t.get(i, u), u >= 10 && (n === 1488 || n === 93) && e ++, a = a << 1 & 2047 | t.get(u, i), u >= 10 && (a === 1488 || a === 93) && e ++; } return e * o; }, r.getPenaltyN4 = function (t) { for (var r = 0, e = t.data.length, n = 0; n < e; n ++)r += t.data[n]; return Math.abs(Math.ceil(100 * r / e / 5) - 10) * a; }, r.applyMask = function (t, r) { for (let e = r.size, n = 0; n < e; n ++) for (let o = 0; o < e; o ++)r.isReserved(o, n) || r.xor(o, n, i(t, o, n)); }, r.getBestMask = function (t, e) { for (var n = Object.keys(r.Patterns).length, o = 0, a = 1 / 0, i = 0; i < n; i ++) { e(i), r.applyMask(i, t); const u = r.getPenaltyN1(t) + r.getPenaltyN2(t) + r.getPenaltyN3(t) + r.getPenaltyN4(t); r.applyMask(i, t), u < a && (a = u, o = i); } return o; }; }); E.Patterns, E.isValid, E.getPenaltyN1, E.getPenaltyN2, E.getPenaltyN3, E.getPenaltyN4, E.applyMask, E.getBestMask; const y = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 2, 2, 4, 1, 2, 4, 4, 2, 4, 4, 4, 2, 4, 6, 5, 2, 4, 6, 6, 2, 5, 8, 8, 4, 5, 8, 8, 4, 5, 8, 11, 4, 8, 10, 11, 4, 9, 12, 16, 4, 9, 16, 16, 6, 10, 12, 18, 6, 10, 17, 16, 6, 11, 16, 19, 6, 13, 18, 21, 7, 14, 21, 25, 8, 16, 20, 25, 8, 17, 23, 25, 9, 17, 23, 34, 9, 18, 25, 30, 10, 20, 27, 32, 12, 21, 29, 35, 12, 23, 34, 37, 12, 25, 34, 40, 13, 26, 35, 42, 14, 28, 38, 45, 15, 29, 40, 48, 16, 31, 43, 51, 17, 33, 45, 54, 18, 35, 48, 57, 19, 37, 51, 60, 19, 38, 53, 63, 20, 40, 56, 66, 21, 43, 59, 70, 22, 45, 62, 74, 24, 47, 65, 77, 25, 49, 68, 81]; const A = [7, 10, 13, 17, 10, 16, 22, 28, 15, 26, 36, 44, 20, 36, 52, 64, 26, 48, 72, 88, 36, 64, 96, 112, 40, 72, 108, 130, 48, 88, 132, 156, 60, 110, 160, 192, 72, 130, 192, 224, 80, 150, 224, 264, 96, 176, 260, 308, 104, 198, 288, 352, 120, 216, 320, 384, 132, 240, 360, 432, 144, 280, 408, 480, 168, 308, 448, 532, 180, 338, 504, 588, 196, 364, 546, 650, 224, 416, 600, 700, 224, 442, 644, 750, 252, 476, 690, 816, 270, 504, 750, 900, 300, 560, 810, 960, 312, 588, 870, 1050, 336, 644, 952, 1110, 360, 700, 1020, 1200, 390, 728, 1050, 1260, 420, 784, 1140, 1350, 450, 812, 1200, 1440, 480, 868, 1290, 1530, 510, 924, 1350, 1620, 540, 980, 1440, 1710, 570, 1036, 1530, 1800, 570, 1064, 1590, 1890, 600, 1120, 1680, 1980, 630, 1204, 1770, 2100, 660, 1260, 1860, 2220, 720, 1316, 1950, 2310, 750, 1372, 2040, 2430]; const I = function (t, r) { switch (r) { case c.L:return y[4 * (t - 1) + 0]; case c.M:return y[4 * (t - 1) + 1]; case c.Q:return y[4 * (t - 1) + 2]; case c.H:return y[4 * (t - 1) + 3]; default: } }; const M = function (t, r) { switch (r) { case c.L:return A[4 * (t - 1) + 0]; case c.M:return A[4 * (t - 1) + 1]; case c.Q:return A[4 * (t - 1) + 2]; case c.H:return A[4 * (t - 1) + 3]; default: } }; const N = new Uint8Array(512); const B = new Uint8Array(256); !(function () { for (let t = 1, r = 0; r < 255; r ++)N[r] = t, B[t] = r, 256 & (t <<= 1) && (t ^= 285); for (let e = 255; e < 512; e ++)N[e] = N[e - 255]; }()); const C = function (t) { return N[t]; }; const P = function (t, r) { return t === 0 || r === 0 ? 0 : N[B[t] + B[r]]; }; const R = h(function (t, r) { r.mul = function (t, r) { for (var e = new Uint8Array(t.length + r.length - 1), n = 0; n < t.length; n ++) for (let o = 0; o < r.length; o ++)e[n + o] ^= P(t[n], r[o]); return e; }, r.mod = function (t, r) { for (var e = new Uint8Array(t); e.length - r.length >= 0;) { for (let n = e[0], o = 0; o < r.length; o ++)e[o] ^= P(r[o], n); for (var a = 0; a < e.length && e[a] === 0;)a ++; e = e.slice(a); } return e; }, r.generateECPolynomial = function (t) { for (var e = new Uint8Array([1]), n = 0; n < t; n ++)e = r.mul(e, new Uint8Array([1, C(n)])); return e; }; }); function T (t) { this.genPoly = void 0, this.degree = t, this.degree && this.initialize(this.degree); }R.mul, R.mod, R.generateECPolynomial, T.prototype.initialize = function (t) { this.degree = t, this.genPoly = R.generateECPolynomial(this.degree); }, T.prototype.encode = function (t) { if (!this.genPoly) throw new Error('Encoder not initialized'); const r = new Uint8Array(t.length + this.degree); r.set(t); const e = R.mod(r, this.genPoly); const n = this.degree - e.length; if (n > 0) { const o = new Uint8Array(this.degree); return o.set(e, n), o; } return e; }; const L = T; const b = function (t) { return !isNaN(t) && t >= 1 && t <= 40; }; let U = '(?:[u3000-u303F]|[u3040-u309F]|[u30A0-u30FF]|[uFF00-uFFEF]|[u4E00-u9FAF]|[u2605-u2606]|[u2190-u2195]|u203B|[u2010u2015u2018u2019u2025u2026u201Cu201Du2225u2260]|[u0391-u0451]|[u00A7u00A8u00B1u00B4u00D7u00F7])+'; const x = '(?:(?![A-Z0-9 $%*+\\-./:]|' + (U = U.replace(/u/g, '\\u')) + ')(?:.|[\r\n]))+'; const k = new RegExp(U, 'g'); const F = new RegExp('[^A-Z0-9 $%*+\\-./:]+', 'g'); const S = new RegExp(x, 'g'); const D = new RegExp('[0-9]+', 'g'); const Y = new RegExp('[A-Z $%*+\\-./:]+', 'g'); const _ = new RegExp('^' + U + '$'); const z = new RegExp('^[0-9]+$'); const H = new RegExp('^[A-Z0-9 $%*+\\-./:]+$'); const J = { KANJI: k, BYTE_KANJI: F, BYTE: S, NUMERIC: D, ALPHANUMERIC: Y, testKanji: function (t) { return _.test(t); }, testNumeric: function (t) { return z.test(t); }, testAlphanumeric: function (t) { return H.test(t); } }; const K = h(function (t, r) { r.NUMERIC = { id: 'Numeric', bit: 1, ccBits: [10, 12, 14] }, r.ALPHANUMERIC = { id: 'Alphanumeric', bit: 2, ccBits: [9, 11, 13] }, r.BYTE = { id: 'Byte', bit: 4, ccBits: [8, 16, 16] }, r.KANJI = { id: 'Kanji', bit: 8, ccBits: [8, 10, 12] }, r.MIXED = { bit: -1 }, r.getCharCountIndicator = function (t, r) { if (!t.ccBits) throw new Error('Invalid mode: ' + t); if (!b(r)) throw new Error('Invalid version: ' + r); return r >= 1 && r < 10 ? t.ccBits[0] : r < 27 ? t.ccBits[1] : t.ccBits[2]; }, r.getBestModeForData = function (t) { return J.testNumeric(t) ? r.NUMERIC : J.testAlphanumeric(t) ? r.ALPHANUMERIC : J.testKanji(t) ? r.KANJI : r.BYTE; }, r.toString = function (t) { if (t && t.id) return t.id; throw new Error('Invalid mode'); }, r.isValid = function (t) { return t && t.bit && t.ccBits; }, r.from = function (t, e) { if (r.isValid(t)) return t; try { return (function (t) { if (typeof t !== 'string') throw new Error('Param is not a string'); switch (t.toLowerCase()) { case 'numeric':return r.NUMERIC; case 'alphanumeric':return r.ALPHANUMERIC; case 'kanji':return r.KANJI; case 'byte':return r.BYTE; default:throw new Error('Unknown mode: ' + t); } }(t)); } catch (t) { return e; } }; }); K.NUMERIC, K.ALPHANUMERIC, K.BYTE, K.KANJI, K.MIXED, K.getCharCountIndicator, K.getBestModeForData, K.isValid; const O = h(function (t, r) { const e = i(7973); function n (t, r) { return K.getCharCountIndicator(t, r) + 4; } function o (t, r) { let e = 0; return t.forEach(function (t) { const o = n(t.mode, r); e += o + t.getBitsLength(); }), e; }r.from = function (t, r) { return b(t) ? parseInt(t, 10) : r; }, r.getCapacity = function (t, r, e) { if (!b(t)) throw new Error('Invalid QR Code version'); void 0 === e && (e = K.BYTE); const o = 8 * (a(t) - M(t, r)); if (e === K.MIXED) return o; const i = o - n(e, t); switch (e) { case K.NUMERIC:return Math.floor(i / 10 * 3); case K.ALPHANUMERIC:return Math.floor(i / 11 * 2); case K.KANJI:return Math.floor(i / 13); case K.BYTE:default:return Math.floor(i / 8); } }, r.getBestVersionForData = function (t, e) { let n; const a = c.from(e, c.M); if (Array.isArray(t)) { if (t.length > 1) return (function (t, e) { for (let n = 1; n <= 40; n ++) { if (o(t, n) <= r.getCapacity(n, e, K.MIXED)) return n; } }(t, a)); if (t.length === 0) return 1; n = t[0]; } else n = t; return (function (t, e, n) { for (let o = 1; o <= 40; o ++) if (e <= r.getCapacity(o, n, t)) return o; }(n.mode, n.getLength(), a)); }, r.getEncodedBits = function (t) { if (!b(t) || t < 7) throw new Error('Invalid QR Code version'); for (var r = t << 12; i(r) - e >= 0;)r ^= 7973 << i(r) - e; return t << 12 | r; }; }); O.getCapacity, O.getBestVersionForData, O.getEncodedBits; const Q = i(1335); const V = function (t, r) { for (var e = t.bit << 3 | r, n = e << 10; i(n) - Q >= 0;)n ^= 1335 << i(n) - Q; return 21522 ^ (e << 10 | n); }; function q (t) { this.mode = K.NUMERIC, this.data = t.toString(); }q.getBitsLength = function (t) { return 10 * Math.floor(t / 3) + (t % 3 ? t % 3 * 3 + 1 : 0); }, q.prototype.getLength = function () { return this.data.length; }, q.prototype.getBitsLength = function () { return q.getBitsLength(this.data.length); }, q.prototype.write = function (t) { let r, e, n; for (r = 0; r + 3 <= this.data.length; r += 3)e = this.data.substr(r, 3), n = parseInt(e, 10), t.put(n, 10); const o = this.data.length - r; o > 0 && (e = this.data.substr(r), n = parseInt(e, 10), t.put(n, 3 * o + 1)); }; const j = q; const $ = ['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', ' ', '$', '%', '*', '+', '-', '.', '/', ':']; function X (t) { this.mode = K.ALPHANUMERIC, this.data = t; }X.getBitsLength = function (t) { return 11 * Math.floor(t / 2) + t % 2 * 6; }, X.prototype.getLength = function () { return this.data.length; }, X.prototype.getBitsLength = function () { return X.getBitsLength(this.data.length); }, X.prototype.write = function (t) { let r; for (r = 0; r + 2 <= this.data.length; r += 2) { let e = 45 * $.indexOf(this.data[r]); e += $.indexOf(this.data[r + 1]), t.put(e, 11); } this.data.length % 2 && t.put($.indexOf(this.data[r]), 6); }; const Z = X; function W (t) { this.mode = K.BYTE, this.data = new Uint8Array(function (t) { for (var r = [], e = t.length, n = 0; n < e; n ++) { let o = t.charCodeAt(n); if (o >= 55296 && o <= 56319 && e > n + 1) { const a = t.charCodeAt(n + 1); a >= 56320 && a <= 57343 && (o = 1024 * (o - 55296) + a - 56320 + 65536, n += 1); }o < 128 ? r.push(o) : o < 2048 ? (r.push(o >> 6 | 192), r.push(63 & o | 128)) : o < 55296 || o >= 57344 && o < 65536 ? (r.push(o >> 12 | 224), r.push(o >> 6 & 63 | 128), r.push(63 & o | 128)) : o >= 65536 && o <= 1114111 ? (r.push(o >> 18 | 240), r.push(o >> 12 & 63 | 128), r.push(o >> 6 & 63 | 128), r.push(63 & o | 128)) : r.push(239, 191, 189); } return new Uint8Array(r).buffer; }(t)); }W.getBitsLength = function (t) { return 8 * t; }, W.prototype.getLength = function () { return this.data.length; }, W.prototype.getBitsLength = function () { return W.getBitsLength(this.data.length); }, W.prototype.write = function (t) { for (let r = 0, e = this.data.length; r < e; r ++)t.put(this.data[r], 8); }; const G = W; function tt (t) { this.mode = K.KANJI, this.data = t; }tt.getBitsLength = function (t) { return 13 * t; }, tt.prototype.getLength = function () { return this.data.length; }, tt.prototype.getBitsLength = function () { return tt.getBitsLength(this.data.length); }, tt.prototype.write = function (t) { let r; for (r = 0; r < this.data.length; r ++) { let e = f(this.data[r]); if (e >= 33088 && e <= 40956)e -= 33088; else { if (!(e >= 57408 && e <= 60351)) throw new Error('Invalid SJIS character: ' + this.data[r] + '\nMake sure your charset is UTF-8'); e -= 49472; }e = 192 * (e >>> 8 & 255) + (255 & e), t.put(e, 13); } }; const rt = tt; const et = h(function (t) { var r = { single_source_shortest_paths: function (t, e, n) { const o = {}; const a = {}; a[e] = 0; let i; let u; let s; let f; let h; let c; let g; const d = r.PriorityQueue.make(); for (d.push(e, 0); !d.empty();) for (s in u = (i = d.pop()).value, f = i.cost, h = t[u] || {})h.hasOwnProperty(s) && (c = f + h[s], g = a[s], (void 0 === a[s] || g > c) && (a[s] = c, d.push(s, c), o[s] = u)); if (void 0 !== n && void 0 === a[n]) { const l = ['Could not find a path from ', e, ' to ', n, '.'].join(''); throw new Error(l); } return o; }, extract_shortest_path_from_predecessor_list: function (t, r) { for (var e = [], n = r; n;)e.push(n), n = t[n]; return e.reverse(), e; }, find_path: function (t, e, n) { const o = r.single_source_shortest_paths(t, e, n); return r.extract_shortest_path_from_predecessor_list(o, n); }, PriorityQueue: { make: function (t) { let e; const n = r.PriorityQueue; const o = {}; for (e in t = t || {}, n)n.hasOwnProperty(e) && (o[e] = n[e]); return o.queue = [], o.sorter = t.sorter || n.default_sorter, o; }, default_sorter: function (t, r) { return t.cost - r.cost; }, push: function (t, r) { const e = { value: t, cost: r }; this.queue.push(e), this.queue.sort(this.sorter); }, pop: function () { return this.queue.shift(); }, empty: function () { return this.queue.length === 0; } } }; t.exports = r; }); const nt = h(function (t, r) { function e (t) { return unescape(encodeURIComponent(t)).length; } function n (t, r, e) { for (var n, o = []; (n = t.exec(e)) !== null;)o.push({ data: n[0], index: n.index, mode: r, length: n[0].length }); return o; } function o (t) { let r; let e; const o = n(J.NUMERIC, K.NUMERIC, t); const a = n(J.ALPHANUMERIC, K.ALPHANUMERIC, t); return s() ? (r = n(J.BYTE, K.BYTE, t), e = n(J.KANJI, K.KANJI, t)) : (r = n(J.BYTE_KANJI, K.BYTE, t), e = []), o.concat(a, r, e).sort(function (t, r) { return t.index - r.index; }).map(function (t) { return { data: t.data, mode: t.mode, length: t.length }; }); } function a (t, r) { switch (r) { case K.NUMERIC:return j.getBitsLength(t); case K.ALPHANUMERIC:return Z.getBitsLength(t); case K.KANJI:return rt.getBitsLength(t); case K.BYTE:return G.getBitsLength(t); } } function i (t, r) { let e; const n = K.getBestModeForData(t); if ((e = K.from(r, n)) !== K.BYTE && e.bit < n.bit) throw new Error('"' + t + '" cannot be encoded with mode ' + K.toString(e) + '.\n Suggested mode is: ' + K.toString(n)); switch (e !== K.KANJI || s() || (e = K.BYTE), e) { case K.NUMERIC:return new j(t); case K.ALPHANUMERIC:return new Z(t); case K.KANJI:return new rt(t); case K.BYTE:return new G(t); } }r.fromArray = function (t) { return t.reduce(function (t, r) { return typeof r === 'string' ? t.push(i(r, null)) : r.data && t.push(i(r.data, r.mode)), t; }, []); }, r.fromString = function (t, n) { for (var i = (function (t, r) { for (var e = {}, n = { start: {} }, o = ['start'], i = 0; i < t.length; i ++) { for (var u = t[i], s = [], f = 0; f < u.length; f ++) { const h = u[f]; const c = '' + i + f; s.push(c), e[c] = { node: h, lastCount: 0 }, n[c] = {}; for (let g = 0; g < o.length; g ++) { const d = o[g]; e[d] && e[d].node.mode === h.mode ? (n[d][c] = a(e[d].lastCount + h.length, h.mode) - a(e[d].lastCount, h.mode), e[d].lastCount += h.length) : (e[d] && (e[d].lastCount = h.length), n[d][c] = a(h.length, h.mode) + 4 + K.getCharCountIndicator(h.mode, r)); } }o = s; } for (let l = 0; l < o.length; l ++)n[o[l]].end = 0; return { map: n, table: e }; }((function (t) { for (var r = [], n = 0; n < t.length; n ++) { const o = t[n]; switch (o.mode) { case K.NUMERIC:r.push([o, { data: o.data, mode: K.ALPHANUMERIC, length: o.length }, { data: o.data, mode: K.BYTE, length: o.length }]); break; case K.ALPHANUMERIC:r.push([o, { data: o.data, mode: K.BYTE, length: o.length }]); break; case K.KANJI:r.push([o, { data: o.data, mode: K.BYTE, length: e(o.data) }]); break; case K.BYTE:r.push([{ data: o.data, mode: K.BYTE, length: e(o.data) }]); } } return r; }(o(t))), n)), u = et.find_path(i.map, 'start', 'end'), s = [], f = 1; f < u.length - 1; f ++)s.push(i.table[u[f]].node); return r.fromArray(function (t) { return t.reduce(function (t, r) { const e = t.length - 1 >= 0 ? t[t.length - 1] : null; return e && e.mode === r.mode ? (t[t.length - 1].data += r.data, t) : (t.push(r), t); }, []); }(s)); }, r.rawSplit = function (t) { return r.fromArray(o(t)); }; }); function ot (t, r, e) { let n; let o; const a = t.size; const i = V(r, e); for (n = 0; n < 15; n ++)o = (i >> n & 1) == 1, n < 6 ? t.set(n, 8, o, !0) : n < 8 ? t.set(n + 1, 8, o, !0) : t.set(a - 15 + n, 8, o, !0), n < 8 ? t.set(8, a - n - 1, o, !0) : n < 9 ? t.set(8, 15 - n - 1 + 1, o, !0) : t.set(8, 15 - n - 1, o, !0); t.set(a - 8, 8, 1, !0); } function at (t, r, e) { const n = new d(); e.forEach(function (r) { n.put(r.mode.bit, 4), n.put(r.getLength(), K.getCharCountIndicator(r.mode, t)), r.write(n); }); const o = 8 * (a(t) - M(t, r)); for (n.getLengthInBits() + 4 <= o && n.put(0, 4); n.getLengthInBits() % 8 != 0;)n.putBit(0); for (let i = (o - n.getLengthInBits()) / 8, u = 0; u < i; u ++)n.put(u % 2 ? 17 : 236, 8); return (function (t, r, e) { for (var n = a(r), o = M(r, e), i = n - o, u = I(r, e), s = u - n % u, f = Math.floor(n / u), h = Math.floor(i / u), c = h + 1, g = f - h, d = new L(g), l = 0, v = new Array(u), p = new Array(u), w = 0, m = new Uint8Array(t.buffer), E = 0; E < u; E ++) { const y = E < s ? h : c; v[E] = m.slice(l, l + y), p[E] = d.encode(v[E]), l += y, w = Math.max(w, y); } let A; let N; const B = new Uint8Array(n); let C = 0; for (A = 0; A < w; A ++) for (N = 0; N < u; N ++)A < v[N].length && (B[C ++] = v[N][A]); for (A = 0; A < g; A ++) for (N = 0; N < u; N ++)B[C ++] = p[N][A]; return B; }(n, t, r)); } function it (t, r, e, n) { let a; if (Array.isArray(t))a = nt.fromArray(t); else { if (typeof t !== 'string') throw new Error('Invalid data'); let i = r; if (!i) { const u = nt.rawSplit(t); i = O.getBestVersionForData(u, e); }a = nt.fromString(t, i || 40); } const s = O.getBestVersionForData(a, e); if (!s) throw new Error('The amount of data is too big to be stored in a QR Code'); if (r) { if (r < s) throw new Error('\nThe chosen QR Code version cannot contain this amount of data.\nMinimum version required to store current data is: ' + s + '.\n'); } else r = s; const f = at(r, e, a); const h = o(r); const c = new v(h); return (function (t, r) { for (let e = t.size, n = m(r), o = 0; o < n.length; o ++) for (let a = n[o][0], i = n[o][1], u = -1; u <= 7; u ++) if (!(a + u <= -1 || e <= a + u)) for (let s = -1; s <= 7; s ++)i + s <= -1 || e <= i + s || (u >= 0 && u <= 6 && (s === 0 || s === 6) || s >= 0 && s <= 6 && (u === 0 || u === 6) || u >= 2 && u <= 4 && s >= 2 && s <= 4 ? t.set(a + u, i + s, !0, !0) : t.set(a + u, i + s, !1, !0)); }(c, r)), (function (t) { for (let r = t.size, e = 8; e < r - 8; e ++) { const n = e % 2 == 0; t.set(e, 6, n, !0), t.set(6, e, n, !0); } }(c)), (function (t, r) { for (let e = p.getPositions(r), n = 0; n < e.length; n ++) for (let o = e[n][0], a = e[n][1], i = -2; i <= 2; i ++) for (let u = -2; u <= 2; u ++)i === -2 || i === 2 || u === -2 || u === 2 || i === 0 && u === 0 ? t.set(o + i, a + u, !0, !0) : t.set(o + i, a + u, !1, !0); }(c, r)), ot(c, e, 0), r >= 7 && (function (t, r) { for (var e, n, o, a = t.size, i = O.getEncodedBits(r), u = 0; u < 18; u ++)e = Math.floor(u / 3), n = u % 3 + a - 8 - 3, o = (i >> u & 1) == 1, t.set(e, n, o, !0), t.set(n, e, o, !0); }(c, r)), (function (t, r) { for (let e = t.size, n = -1, o = e - 1, a = 7, i = 0, u = e - 1; u > 0; u -= 2) for (u === 6 && u --; ;) { for (let s = 0; s < 2; s ++) if (!t.isReserved(o, u - s)) { let f = !1; i < r.length && (f = (r[i] >>> a & 1) == 1), t.set(o, u - s, f), -- a === -1 && (i ++, a = 7); } if ((o += n) < 0 || e <= o) { o -= n, n = -n; break; } } }(c, f)), isNaN(n) && (n = E.getBestMask(c, ot.bind(null, c, e))), E.applyMask(n, c), ot(c, e, n), { modules: c, version: r, errorCorrectionLevel: e, maskPattern: n, segments: a }; }nt.fromArray, nt.fromString, nt.rawSplit; const ut = function (t, r) { if (void 0 === t || t === '') throw new Error('No input text'); let e; let n; let o = c.M; return void 0 !== r && (o = c.from(r.errorCorrectionLevel, c.M), e = O.from(r.version), n = E.from(r.maskPattern), r.toSJISFunc && u(r.toSJISFunc)), it(t, e, o, n); }; const st = h(function (t, r) { function e (t) { if (typeof t === 'number' && (t = t.toString()), typeof t !== 'string') throw new Error('Color should be defined as hex string'); let r = t.slice().replace('#', '').split(''); if (r.length < 3 || r.length === 5 || r.length > 8) throw new Error('Invalid hex color: ' + t); r.length !== 3 && r.length !== 4 || (r = Array.prototype.concat.apply([], r.map(function (t) { return [t, t]; }))), r.length === 6 && r.push('F', 'F'); const e = parseInt(r.join(''), 16); return { r: e >> 24 & 255, g: e >> 16 & 255, b: e >> 8 & 255, a: 255 & e, hex: '#' + r.slice(0, 6).join('') }; }r.getOptions = function (t) { t || (t = {}), t.color || (t.color = {}); const r = void 0 === t.margin || t.margin === null || t.margin < 0 ? 4 : t.margin; const n = t.width && t.width >= 21 ? t.width : void 0; const o = t.scale || 4; return { width: n, scale: n ? 4 : o, margin: r, color: { dark: e(t.color.dark || '#000000ff'), light: e(t.color.light || '#ffffffff') }, type: t.type, rendererOpts: t.rendererOpts || {} }; }, r.getScale = function (t, r) { return r.width && r.width >= t + 2 * r.margin ? r.width / (t + 2 * r.margin) : r.scale; }, r.getImageWidth = function (t, e) { const n = r.getScale(t, e); return Math.floor((t + 2 * e.margin) * n); }, r.qrToImageData = function (t, e, n) { for (let o = e.modules.size, a = e.modules.data, i = r.getScale(o, n), u = Math.floor((o + 2 * n.margin) * i), s = n.margin * i, f = [n.color.light, n.color.dark], h = 0; h < u; h ++) for (let c = 0; c < u; c ++) { let g = 4 * (h * u + c); let d = n.color.light; if (h >= s && c >= s && h < u - s && c < u - s)d = f[a[Math.floor((h - s) / i) * o + Math.floor((c - s) / i)] ? 1 : 0]; t[g ++] = d.r, t[g ++] = d.g, t[g ++] = d.b, t[g] = d.a; } }; }); st.getOptions, st.getScale, st.getImageWidth, st.qrToImageData; const ft = h(function (t, r) { r.render = function (t, r, e) { let n = e; let o = r; void 0 !== n || r && r.getContext || (n = r, r = void 0), r || (o = (function () { try { return document.createElement('canvas'); } catch (t) { throw new Error('You need to specify a canvas element'); } }())), n = st.getOptions(n); const a = st.getImageWidth(t.modules.size, n); const i = o.getContext('2d'); const u = i.createImageData(a, a); return st.qrToImageData(u.data, t, n), (function (t, r, e) { t.clearRect(0, 0, r.width, r.height), r.style || (r.style = {}), r.height = e, r.width = e, r.style.height = e + 'px', r.style.width = e + 'px'; }(i, o, a)), i.putImageData(u, 0, 0), o; }, r.renderToDataURL = function (t, e, n) { let o = n; void 0 !== o || e && e.getContext || (o = e, e = void 0), o || (o = {}); const a = r.render(t, e, o); const i = o.type || 'image/png'; const u = o.rendererOpts || {}; return a.toDataURL(i, u.quality); }; }); function ht (t, r) { const e = t.a / 255; const n = r + '="' + t.hex + '"'; return e < 1 ? n + ' ' + r + '-opacity="' + e.toFixed(2).slice(1) + '"' : n; } function ct (t, r, e) { let n = t + r; return void 0 !== e && (n += ' ' + e), n; }ft.render, ft.renderToDataURL; const gt = function (t, r, e) { const n = st.getOptions(r); const o = t.modules.size; const a = t.modules.data; const i = o + 2 * n.margin; const u = n.color.light.a ? '' : ''; const s = ''; const f = 'viewBox="0 0 ' + i + ' ' + i + '"'; const h = '' + u + s + '\n'; return typeof e === 'function' && e(null, h), h; }; function dt (t, r, n, o, a) { const i = [].slice.call(arguments, 1); const u = i.length; const s = typeof i[u - 1] === 'function'; if (!s && !e()) throw new Error('Callback required as last argument'); if (!s) { if (u < 1) throw new Error('Too few arguments provided'); return u === 1 ? (n = r, r = o = void 0) : u !== 2 || r.getContext || (o = n, n = r, r = void 0), new Promise(function (e, a) { try { const i = ut(n, o); e(t(i, r, o)); } catch (t) { a(t); } }); } if (u < 2) throw new Error('Too few arguments provided'); u === 2 ? (a = n, n = r, r = o = void 0) : u === 3 && (r.getContext && void 0 === a ? (a = o, o = void 0) : (a = o, o = n, n = r, r = void 0)); try { const f = ut(n, o); a(null, t(f, r, o)); } catch (t) { a(t); } } const lt = ut; const vt = dt.bind(null, ft.render); const pt = dt.bind(null, ft.renderToDataURL); const wt = dt.bind(null, function (t, r, e) { return gt(t, e); }); const mt = { create: lt, toCanvas: vt, toDataURL: pt, toString: wt }; return t.create = lt, t.default = mt, t.toCanvas = vt, t.toDataURL = pt, t.toString = wt, Object.defineProperty(t, '__esModule', { value: !0 }), t; }({})); diff --git a/client/src/styles/game.css b/client/src/styles/game.css index 140f950..e783b1a 100644 --- a/client/src/styles/game.css +++ b/client/src/styles/game.css @@ -70,8 +70,15 @@ } #lobby-header { - margin-bottom: 1em; + display: flex; + flex-direction: column; + align-items: center; max-width: 95%; + margin: 1em 1em 0 1em; +} + +#lobby-header > div:nth-child(1) { + width: 100%; } h1 { @@ -79,10 +86,6 @@ h1 { margin: 0.5em auto; } -#game-state-container > div:not(#transfer-mod-modal-background):not(#transfer-mod-modal):not(#game-people-container) { - margin: 1em; -} - #game-content .placeholder-row:nth-child(1) { margin-top: 2em; } @@ -534,6 +537,11 @@ label[for='moderator'] { background-color: #333243; } +canvas { + border-radius: 3px; + margin: 1em; +} + .game-player { border-left: 3px solid #21ba45; display: flex; @@ -655,6 +663,12 @@ label[for='moderator'] { flex-wrap: wrap; } +#game-parameters { + background-color: #333243; + border-radius: 3px; + padding: 5px 20px; +} + #game-player-list { overflow-y: auto; overflow-x: hidden; diff --git a/karma.conf.js b/karma.conf.js index 2fb85b6..ecc80dd 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -5,6 +5,7 @@ module.exports = function(config) { files: [ { pattern: 'spec/e2e/*.js', type: 'module' }, { pattern: 'client/src/modules/*.js', type: 'module', included: true, served: true }, + { pattern: 'client/src/modules/third_party/*.js', type: 'module', included: true, served: true }, { pattern: 'client/src/config/*.js', type: 'module', included: true, served: true }, { pattern: 'client/src/model/*.js', type: 'module', included: true, served: true }, { pattern: 'client/src/view_templates/*.js', type: 'module', included: true, served: true }