diff options
30 files changed, 3730 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c343a4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +database.sqlite +node_modules/ +.npm +config.json + diff --git a/README.md b/README.md new file mode 100644 index 0000000..ae7a0bd --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +# Quadrowple + +Get four in a row to win. Play online with a random person + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..f5eb71f --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1462 @@ +{ + "name": "marksdatabase", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/node": { + "version": "12.7.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.12.tgz", + "integrity": "sha512-KPYGmfD0/b1eXurQ59fXD1GBzhSQfz6/lKBxkaHX9dKTzjXbK68Zt7yGUxUsCS1jeTy/8aL+d9JEr+S54mpkWQ==" + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "requires": { + "mime-types": "~2.1.18", + "negotiator": "0.6.1" + } + }, + "ajv": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz", + "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", + "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bluebird": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.0.tgz", + "integrity": "sha512-aBQ1FxIa7kSWCcmKHlcHFlT2jt6J/l4FzC7KcPELkOJOsPOb/bccdhmIrKDfXhwFrmc7vDoDrrepFvGqjyXGJg==" + }, + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "cls-bluebird": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cls-bluebird/-/cls-bluebird-2.1.0.tgz", + "integrity": "sha1-N+8eCAqP+1XC9BZPU28ZGeeWiu4=", + "requires": { + "is-bluebird": "^1.0.2", + "shimmer": "^1.1.0" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-parser": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.4.tgz", + "integrity": "sha512-lo13tqF3JEtFO7FyA49CqbhaFkskRJ0u/UAiINgrIXeRCY41c88/zxtrECl8AKH3B0hj9q10+h3Kt8I7KlW4tw==", + "requires": { + "cookie": "0.3.1", + "cookie-signature": "1.0.6" + } + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "denque": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.0.tgz", + "integrity": "sha512-gh513ac7aiKrAgjiIBWZG0EASyDF9p4JMWwKA8YU5s9figrL5SRNEMT6FDynsegakuhWd1wVqTvqvqAoDxw7wQ==" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + }, + "dottie": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.1.tgz", + "integrity": "sha512-ch5OQgvGDK2u8pSZeSYAQaV/lczImd7pMJ7BcEPXmnFVjy4yJIzP6CsODJUTH8mg1tyH1Z2abOiuJO3DjZ/GBw==" + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "express": { + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", + "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", + "requires": { + "accepts": "~1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.3", + "content-disposition": "0.5.2", + "content-type": "~1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.1.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.4", + "qs": "6.5.2", + "range-parser": "~1.2.0", + "safe-buffer": "5.1.2", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "~1.4.0", + "type-is": "~1.6.16", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "finalhandler": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.4.0", + "unpipe": "~1.0.0" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "requires": { + "minipass": "^2.6.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "requires": { + "is-property": "^1.0.2" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflection": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", + "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "ipaddr.js": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", + "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=" + }, + "is-bluebird": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-bluebird/-/is-bluebird-1.0.2.tgz", + "integrity": "sha1-CWQ5Bg9KpBGr7hkUOoTWpVNG1uI=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + }, + "mime-db": { + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", + "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==" + }, + "mime-types": { + "version": "2.1.22", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", + "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", + "requires": { + "mime-db": "~1.38.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + }, + "dependencies": { + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + } + } + }, + "minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "requires": { + "minipass": "^2.9.0" + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "moment": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", + "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" + }, + "moment-timezone": { + "version": "0.5.26", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.26.tgz", + "integrity": "sha512-sFP4cgEKTCymBBKgoxZjYzlSovC20Y6J7y3nanDc5RoBIXKlZhoYwBoZGe3flwU6A372AcRwScH8KiwV6zjy1g==", + "requires": { + "moment": ">= 2.9.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "mysql2": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-1.6.5.tgz", + "integrity": "sha512-zedaOOyb3msuuZcJJnxIX/EGOpmljDG7B+UevRH5lqcv+yhy9eCwkArBz8/AO+/rlY3/oCsOdG8R5oD6k0hNfg==", + "requires": { + "denque": "^1.4.0", + "generate-function": "^2.3.1", + "iconv-lite": "^0.4.24", + "long": "^4.0.0", + "lru-cache": "^4.1.3", + "named-placeholders": "^1.1.2", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.1" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "named-placeholders": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.2.tgz", + "integrity": "sha512-wiFWqxoLL3PGVReSZpjLVxyJ1bRqe+KKJVbr4hGs1KWfTZTQyezHFBbuKj9hsizHyGV2ne7EMjHdxEGAybD5SA==", + "requires": { + "lru-cache": "^4.1.3" + } + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==" + }, + "needle": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.3.3.tgz", + "integrity": "sha512-EkY0GeSq87rWp1hoq/sH/wnTWgFVhYlnIkbJ0YJFfRgEFlz2RraCjBpFQ+vrEgEdp0ThfyHADmkChEhcb7PKyw==", + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "node-pre-gyp": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz", + "integrity": "sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q==", + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" + }, + "npm-packlist": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "proxy-addr": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", + "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.8.0" + } + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "psl": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz", + "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==" + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + } + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readline-sync": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz", + "integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==" + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "retry-as-promised": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-3.2.0.tgz", + "integrity": "sha512-CybGs60B7oYU/qSQ6kuaFmRd9sTZ6oXSc0toqePvV74Ac6/IFZSI1ReFQmtCN+uvW1Mtqdwpvt/LGOiCBAY2Mg==", + "requires": { + "any-promise": "^1.3.0" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" + }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" + } + }, + "seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=" + }, + "sequelize": { + "version": "5.19.5", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-5.19.5.tgz", + "integrity": "sha512-NdICIFJ0KEjLGrlbnVC3K74tPursZ9yjY5112uCiAxiXK2LXyXP1ePgATEdMJDdeaR5hmP4//qFInTfrnoGe/w==", + "requires": { + "bluebird": "^3.5.0", + "cls-bluebird": "^2.1.0", + "debug": "^4.1.1", + "dottie": "^2.0.0", + "inflection": "1.12.0", + "lodash": "^4.17.15", + "moment": "^2.24.0", + "moment-timezone": "^0.5.21", + "retry-as-promised": "^3.2.0", + "semver": "^6.3.0", + "sequelize-pool": "^2.3.0", + "toposort-class": "^1.0.1", + "uuid": "^3.3.3", + "validator": "^10.11.0", + "wkx": "^0.4.8" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, + "sequelize-pool": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-2.3.0.tgz", + "integrity": "sha512-Ibz08vnXvkZ8LJTiUOxRcj1Ckdn7qafNZ2t59jYHMX1VIebTAOYefWdRYFt6z6+hy52WGthAHAoLc9hvk3onqA==" + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "shimmer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "sqlite3": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.1.1.tgz", + "integrity": "sha512-CvT5XY+MWnn0HkbwVKJAyWEMfzpAPwnTiB3TobA5Mri44SrTovmmh499NPQP+gatkeOipqPlBLel7rn4E/PCQg==", + "requires": { + "nan": "^2.12.1", + "node-pre-gyp": "^0.11.0", + "request": "^2.87.0" + } + }, + "sqlstring": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", + "integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=" + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + }, + "dependencies": { + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + } + } + }, + "toposort-class": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", + "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.18" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", + "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" + }, + "validator": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz", + "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wkx": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.4.8.tgz", + "integrity": "sha512-ikPXMM9IR/gy/LwiOSqWlSL3X/J5uk9EO2hHNRXS41eTLXaUFEVw9fn/593jW/tE5tedNg8YjT5HkCa4FqQZyQ==", + "requires": { + "@types/node": "*" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..0c45936 --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "marksdatabase", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "run": "nodejs src/" + }, + "author": "", + "license": "ISC", + "dependencies": { + "body-parser": "^1.18.3", + "cookie-parser": "^1.4.4", + "express": "^4.16.4", + "jsonwebtoken": "^8.5.1", + "mysql2": "^1.6.5", + "readline-sync": "^1.4.10", + "sequelize": "^5.19.5", + "sqlite3": "^4.1.1" + } +} diff --git a/src/index.html b/src/index.html new file mode 100644 index 0000000..21b2dd2 --- /dev/null +++ b/src/index.html @@ -0,0 +1,31 @@ +<!doctype html> +<html lang="en"> + +<head> + <title>Games</title> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> + <!-- <link rel="stylesheet" type="text/css" href="/css/styles.css"> --> +</head> + +<body> + <div> + Arcade + <ul> + <li><a href="/pinball">Pinball (demo)</a></li> + <li><a href="/snake">Snake</a></li> + <li><a href="/stacker">Stacker</a></li> + <li><a href="/math">Math mini agmes</a></li> + <li><a href="https://seafarerscafe.itch.io/cosmic-cargo">Cosmic Cargo (itch.io)</a></li> + </ul> + </div> + <div> + Multiplayer + <ul> + <li><a href="/ur">Royal Game of Ur</a></li> + <li><a href="/quadrowple">Quadrowple</a></li> + </ul> + </div> +</body> + +</html>
\ No newline at end of file diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..647bf3e --- /dev/null +++ b/src/index.js @@ -0,0 +1,64 @@ +const server = require('./server'); +const Sequelize = require('sequelize'); +const fs = require('fs'); +const path = require('path'); +const jwt = require('jsonwebtoken'); + + +const config = JSON.parse(fs.readFileSync(path.join(__dirname, 'config.json'))); + +const dbCreds = config.database; +const secret = config.jwt_secret; + +const jwtFunctions = { + sign: function (message) { + return jwt.sign({ value: message }, secret); + }, + verify: function (token) { + return jwt.verify(token, secret).value; + } +} + +const database = new Sequelize(dbCreds.database, undefined, undefined, { + logging(str) { + console.debug(`DB:${str}`); + }, + dialectOptions: { + charset: 'utf8mb4', + multipleStatements: true, + }, + storage: './database.sqlite', + dialect: 'sqlite', + pool: { + max: 5, + min: 0, + idle: 10000, + }, +}); + +database.authenticate().then(() => { + console.debug(`database connection successful: ${dbCreds.database}`); +}, (e) => console.log(e)); + +async function sync(alter, force, callback) { + await database.sync({ alter, force, logging: console.log }); +} + +function setUpModels() { + const models = { + } + return models; +} + +const models = setUpModels(); +sync(); + +server.setUpRoutes(models, jwtFunctions, database); +server.load("./ur/server", models, jwtFunctions, database) +server.load("./quadrowple/server", models, jwtFunctions, database) +server.load("./snake/server", models, jwtFunctions, database) +server.load("./stacker/server", models, jwtFunctions, database) +server.load("./pinball/server", models, jwtFunctions, database) +server.load("./math/server", models, jwtFunctions, database) +server.listen(config.port); + diff --git a/src/math/index.html b/src/math/index.html new file mode 100644 index 0000000..440e7ff --- /dev/null +++ b/src/math/index.html @@ -0,0 +1,29 @@ +<!doctype html> +<html lang="en"> + +<head> + <title>Math Games</title> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> + <style> + canvas { + /* transform-origin: top left; */ + /* transform: scale(4, 4); */ + position: absolute; + left: 0; + top: 0; + } + </style> +</head> + +<body style="padding:0; margin:0; overflow:hidden;"> + <canvas id="canvas"></canvas> + <script src="/math/static/help.js"></script> + <script src="/math/static/nim.js"></script> + <script src="/math/static/solitaire.js"></script> + <script src="/math/static/kings-corner.js"></script> + <script src="/math/static/black-hole.js"></script> + <script src="/math/static/main.js"></script> +</body> + +</html> diff --git a/src/math/server.js b/src/math/server.js new file mode 100644 index 0000000..e68a41b --- /dev/null +++ b/src/math/server.js @@ -0,0 +1,13 @@ +const path = require('path'); +const fs = require('fs'); +const express = require('express'); + +function setUpRoutes(server, models, jwtFunctions, database) { + server.get('/math', (req, res) => res.sendFile(__dirname + "/index.html")) + server.get('/math/styles.css', (req, res) => res.sendFile(__dirname + "/static/styles.css")) + server.use('/math/static', express.static(__dirname + '/static')) +} + +module.exports = { + setUpRoutes +}; diff --git a/src/math/static/black-hole.js b/src/math/static/black-hole.js new file mode 100644 index 0000000..f6b7f8e --- /dev/null +++ b/src/math/static/black-hole.js @@ -0,0 +1,181 @@ +var black_hole = { + status: "", + state: -1, + rowOf: { + 0: 0, + 1: 0, + 2: 0, + 3: 0, + 4: 0, + 5: 0, + 6: 1, + 7: 1, + 8: 1, + 9: 1, + 10: 1, + 11: 2, + 12: 2, + 13: 2, + 14: 2, + 15: 3, + 16: 3, + 17: 3, + 18: 4, + 19: 4, + 20: 5, + }, + colOf: { + 0: 0, + 1: 1, + 2: 2, + 3: 3, + 4: 4, + 5: 5, + 6: 0, + 7: 1, + 8: 2, + 9: 3, + 10: 4, + 11: 0, + 12: 1, + 13: 2, + 14: 3, + 15: 0, + 16: 1, + 17: 2, + 18: 0, + 19: 1, + 20: 0, + }, + canPlay: function (index) { + return this.board[index] == undefined + }, + setup: function () { + this.board = []; + for(var i =0; i < 21; i++){ + this.board.push(undefined); + } + this.turn = 1 + }, + + play: function () { + + }, + other_play: function () { + var madePlay = false + while (!madePlay) { + // guess random + var index = Math.floor(Math.random() * 21) + if(this.canPlay(index)){ + black_hole.board[index] = { + "color": "blue", + "value": Math.ceil(black_hole.turn / 2) + } + black_hole.turn++ + madePlay = true + } + } + + }, +}; +black_hole.updateCallback = function () { + if(black_hole.turn == 21 && black_hole.state < 2) { + black_hole.state = 2 + } + + if (black_hole.state == -1){ // setup + black_hole.setup(); + black_hole.state = 0 + } else if (black_hole.state == 0) { // player turn + // nothing, wait for click + } else if (black_hole.state == 1) { // other turn + black_hole.other_play(); + black_hole.state = 0 + } else if (black_hole.state == 2) { // calculate end + score = {"blue": 0, "red": 0} + black_hole.board.forEach((spot, i) => { + if(spot == undefined){ + var row = black_hole.rowOf[i]; + var col = black_hole.colOf[i]; + black_hole.board.forEach((other_spot, j) => { + var row2 = black_hole.rowOf[j]; + var col2 = black_hole.colOf[j]; + if(other_spot != undefined && + ( + (row == row2-1 && 0 <= (col - col2) && (col - col2) <= 1) || + (row == row2 && Math.abs(col - col2) <= 1) || + (row == row2+1 && 0 <= (col2 - col) && (col2 - col) <= 1) + ) + ){ + score[other_spot.color] += other_spot.value + } + }) + } + }) + black_hole.score = score + if(score.red < score.blue){ + black_hole.winner = "red" + } else { + black_hole.winner = "blue" + } + black_hole.state = -1; + switchState(menu); + } +} +black_hole.drawCallback = function () { + if(black_hole.state < 0){ + return; + } + ctx.fillStyle = "#99b3ff"; + ctx.fillRect(0, 0, width, height); + + + ctx.lineWidth = 2; + black_hole.board.forEach((spot, i) => { + var row = black_hole.rowOf[i]; + var col = black_hole.colOf[i]; + if(spot == undefined){ + ctx.fillStyle = "black"; + ctx.strokeStyle = "black" + } else { + ctx.fillStyle = spot["color"]; + ctx.strokeStyle = spot["color"] + ctx.fillText(spot["value"], 100 + row * 100 + col * 50, 100 + col*88) + } + ctx.beginPath(); + ctx.arc(100 + row * 100 + col * 50, 100 + col*88, 50, 0, 2 * Math.PI); + ctx.stroke(); + }) + + if(black_hole.winner){ + font(32); + ctx.fillStyle = "black"; + ctx.fillText(black_hole.winner + " wins!", 550, 330) + ctx.fillText("red: " + black_hole.score.red, 550, 370) + ctx.fillText("blue: " + black_hole.score.blue, 550, 410) + } +} +black_hole.mouseDownCallback = function (e) { + if(black_hole.state == 3){ + return; + } + + black_hole.board.forEach((spot, i) => { + var row = black_hole.rowOf[i]; + var col = black_hole.colOf[i]; + var x = 100 + row * 100 + col * 50; + var y = 100 + col*88; + if(spot == undefined && Math.sqrt(Math.pow(x - e.x, 2) + Math.pow(y - e.y, 2)) < 50){ + console.log(i); + black_hole.board[i] = { + "color": "red", + "value": Math.ceil(black_hole.turn / 2) + } + black_hole.turn++; + black_hole.state = 1 + } + }) +} +black_hole.mouseUpCallback = function (e) { + +}
\ No newline at end of file diff --git a/src/math/static/card31.js b/src/math/static/card31.js new file mode 100644 index 0000000..c2b6172 --- /dev/null +++ b/src/math/static/card31.js @@ -0,0 +1,8 @@ +var solitaire = {}; +solitaire.updateCallback = function(){ + +} +solitaire.drawCallback = function(){ + ctx.fillStyle = "green"; + ctx.fillRect(0, 0, width, height); +}
\ No newline at end of file diff --git a/src/math/static/help.js b/src/math/static/help.js new file mode 100644 index 0000000..2dfab9f --- /dev/null +++ b/src/math/static/help.js @@ -0,0 +1,21 @@ +var help = { + +}; +help.updateCallback = function(){ + // nothing +} +help.drawCallback = function(){ + ctx.fillStyle = "#99b3ff"; + ctx.fillRect(0, 0, width, height); + + font(26) + ctx.fillStyle = "black" + ctx.fillText("Click on a game to play.", 10, 200) + ctx.fillText("After finishing your game, click to return.", 10, 230) +} +help.mouseDownCallback = function (e) { + switchState(menu); +} +help.mouseUpCallback = function(e){ + +}
\ No newline at end of file diff --git a/src/math/static/kings-corner.js b/src/math/static/kings-corner.js new file mode 100644 index 0000000..c182b56 --- /dev/null +++ b/src/math/static/kings-corner.js @@ -0,0 +1,357 @@ +var kings_corner = { + suit_color: { + "C": "black", + "S": "black", + "H": "red", + "D": "red" + }, + value_to_num: { + "A": 0, + "2": 1, + "3": 2, + "4": 3, + "5": 4, + "6": 5, + "7": 6, + "8": 7, + "9": 8, + "10": 9, + "J": 10, + "Q": 11, + "K": 12 + }, + selected: [], + selected_positions: [], + status: "", + state: -1, + shuffle: function (a) { + var j, x, i; + for (i = a.length - 1; i > 0; i--) { + j = Math.floor(Math.random() * (i + 1)); + x = a[i]; + a[i] = a[j]; + a[j] = x; + } + return a; + }, + canBePlayedOn: function (bottom, top, board_position) { + if (top == undefined) { + return false; + } + if (bottom == undefined) { + return top.value == "K" || board_position < 4; + } + if (this.suit_color[bottom.suit] != this.suit_color[top.suit]) { + return this.value_to_num[bottom.value] - this.value_to_num[top.value] == 1; + } else { + return false; + } + }, + findBoardPosition(cards) { + var board_position; + for (var index = 0; index < this.board.length; index++) { + if (this.board[index] == cards) { + board_position = index; + } + } + return board_position + }, + canPlayBoardHand: function (cards, hand) { + var bottom = cards[cards.length - 1]; + var board_position = this.findBoardPosition(cards); + return this.canBePlayedOn(bottom, hand, board_position) + }, + canPlay: function () { + if (this.selected_positions[0] == "board" + && this.selected_positions[1] == "hand") { + return this.canPlayBoardHand(this.selected[0], this.selected[1]) + } else if (this.selected_positions[1] == "board" + && this.selected_positions[0] == "hand") { + return this.canPlayBoardHand(this.selected[1], this.selected[0]) + } else if (this.selected_positions[0] == "board" + && this.selected_positions[1] == "board") { + + var cards1 = this.selected[1]; + var cards2 = this.selected[0]; + var top = cards1[0] + var bottom = cards2[cards2.length - 1] + var board_position = this.findBoardPosition(cards2); + if (this.canBePlayedOn(bottom, top, board_position)) { + return true; + } + top = cards2[0] + bottom = cards1[cards1.length - 1] + board_position = this.findBoardPosition(cards1); + if (this.canBePlayedOn(bottom, top, board_position)) { + return true; + } + } + return false; + }, + setup: function () { + this.deck = []; + Object.keys(this.value_to_num).forEach((value) => { + Object.keys(this.suit_color).forEach((suit) => { + kings_corner.deck.push({ suit: suit, value: value }); + }) + }) + this.shuffle(this.deck); + this.board = [[this.deck.pop()], [this.deck.pop()], + [this.deck.pop()], [this.deck.pop()], + [], [], [], []] + this.hand = [] + this.other_hand = [] + for (var i = 0; i < 7; i++) { + this.hand.push(this.deck.pop()); + this.other_hand.push(this.deck.pop()); + } + this.hand.push(this.deck.pop()); + }, + removeCard: function (arr, c) { + return arr.filter((card) => { + return !(card.value == c.value && card.suit == c.suit); + }) + }, + play: function () { + if (this.selected.length != 2) { + this.state = 1 + } else if (this.canPlay()) { + if (this.selected_positions[0] == "board" && this.selected_positions[1] == "hand") { + var cards = this.selected[0]; + var top = this.selected[1]; + cards.push(top); + this.hand = this.removeCard(this.hand, top) + } else if (this.selected_positions[1] == "board" && this.selected_positions[0] == "hand") { + var cards = this.selected[1]; + var top = this.selected[0]; + cards.push(top); + this.hand = this.removeCard(this.hand, top) + } else if (this.selected_positions[0] == "board" && this.selected_positions[1] == "board") { + var cards1 = this.selected[1]; + var cards2 = this.selected[0]; + var top = cards1[0] + var bottom = cards2[cards2.length - 1] + var board_position = this.findBoardPosition(cards2); + if (this.canBePlayedOn(bottom, top, board_position)) { + while (this.selected[1].length > 0) { + this.selected[0].push(this.selected[1].shift()); + } + return; + } + top = cards2[0] + bottom = cards1[cards1.length - 1] + board_position = this.findBoardPosition(cards1); + if (this.canBePlayedOn(bottom, top, board_position)) { + while (this.selected[0].length > 0) { + this.selected[1].push(this.selected[0].shift()); + } + return; + } + } + } else { + console.log("no play") + } + }, + other_play: function () { + var madePlay = true + var playedCards = []; + while (madePlay && this.other_hand.length > 0) { + madePlay = false; + for (var i = 0; i < this.other_hand.length; i++) { + let card = this.other_hand[i] + for (var index = 0; index < this.board.length; index++) { + var top = card; + var cards = this.board[index]; + var bottom = cards[cards.length - 1]; + if (this.canBePlayedOn(bottom, top, index)) { + cards.push(card); + this.other_hand = this.removeCard(this.other_hand, card) + playedCards.push(card); + console.log(madePlay) + madePlay = true + break; + } + + } + if (madePlay) { + break; + } + } + for (var index1 = 0; index1 < this.board.length; index1++) { + for (var index2 = 0; index2 < this.board.length; index2++) { + var cards1 = this.board[index1]; + var cards2 = this.board[index2]; + var top = cards1[0] + var bottom = cards2[cards2.length - 1] + var board_position = this.findBoardPosition(cards2); + if (index1 >= 4) { + continue + // dont move a king to the left + } + if (this.canBePlayedOn(bottom, top, board_position)) { + while (cards1.length > 0) { + cards2.push(cards1.shift()); + } + break; + } + } + } + } + + if (playedCards.length == 0) { + this.status = "They played nothing" + } else { + this.status = "They played " + for (var index = 0; index < playedCards.length - 1; index++) { + this.status += `${playedCards[index].value} of ${playedCards[index].suit}, ` + } + this.status += `${playedCards[playedCards.length - 1].value} of ${playedCards[playedCards.length - 1].suit}` + } + }, +}; +kings_corner.updateCallback = function () { + if (kings_corner.state == -1){ // setup + kings_corner.setup(); + kings_corner.state = 0 + } else if (kings_corner.state == 0) { // player turn + if (kings_corner.hand.length == 0) { + kings_corner.status = "You win!" + kings_corner.state = 2 + return; + } + } else if (kings_corner.state == 1) { // other turn + kings_corner.other_hand.push(kings_corner.deck.pop()); + kings_corner.other_play(); + if (kings_corner.other_hand.length == 0) { + kings_corner.status = "You lose!" + kings_corner.state = 3 + return; + } + kings_corner.state = 0 + kings_corner.hand.push(kings_corner.deck.pop()); + } else if (kings_corner.state == 2 || kings_corner.state == 3) { + // nothing + } +} +kings_corner.drawCallback = function () { + if(kings_corner.state < 0){ + return; + } + ctx.fillStyle = "#99b3ff"; + ctx.fillRect(0, 0, width, height); + + font(26) + ctx.fillStyle = "lime"; + ctx.fillRect(5, 5, 90, 40); + ctx.fillStyle = "black" + if (kings_corner.selected.length != 2) { + ctx.fillText("Pass", 10, 30); + } else { + ctx.fillText("Play", 10, 30); + } + + ctx.fillStyle = "black" + ctx.fillText("You", 10, 240) + kings_corner.hand.forEach((card, i) => { + if (kings_corner.selected.includes(card)) { + ctx.fillStyle = "#CCC" + } else { + ctx.fillStyle = "white"; + } + ctx.fillRect(i * 75 + 100, 210, 70, 120); + ctx.fillStyle = kings_corner.suit_color[card.suit] + ctx.fillText(card.suit, i * 75 + 105, 250) + ctx.fillText(card.value, i * 75 + 105, 230) + }) + + ctx.fillStyle = "black" + ctx.fillText("Other", 10, 360) + kings_corner.other_hand.forEach((card, i) => { + ctx.fillStyle = "blue" + ctx.fillRect(i * 75 + 100, 340, 70, 120); + }) + + ctx.fillStyle = "black" + ctx.fillText(kings_corner.status, 100, 500) + + ctx.fillStyle = "black" + ctx.fillText("Board", 10, 120) + kings_corner.board.forEach((cards, i) => { + if (kings_corner.selected.includes(cards)) { + ctx.fillStyle = "#CCC" + } else { + ctx.fillStyle = "white"; + } + ctx.fillRect(i * 75 + 100, 80, 70, 120); + ctx.fillStyle = "black" + // var card = kings_corner.board[i]; + var top = cards[cards.length - 1]; + var bottom = cards[0]; + if (top != undefined) { + ctx.fillStyle = kings_corner.suit_color[top.suit] + ctx.fillText(top.suit, i * 75 + 105, 160) + ctx.fillText(top.value, i * 75 + 105, 180) + + if (top != bottom) { + ctx.fillStyle = kings_corner.suit_color[bottom.suit] + ctx.fillText(bottom.suit, i * 75 + 105, 120) + ctx.fillText(bottom.value, i * 75 + 105, 100) + } + } + }) + if(kings_corner.state >= 2){ + kings_corner.state = -1; + switchState(menu); + } +} +kings_corner.mouseDownCallback = function (e) { + if(kings_corner.state != 0){ + return; + } + + if (5 < e.x && e.x < 95 && 5 < e.y && e.y < 95) { + kings_corner.play(); + return + } + + var new_selected = false + kings_corner.hand.forEach((card, i) => { + if (i * 75 + 100 < e.x && e.x < i * 75 + 170 && + 210 < e.y && e.y < 330) { + + kings_corner.selected.unshift(card); + if (kings_corner.selected.length > 2) { + kings_corner.selected.pop(); + } + kings_corner.selected_positions.unshift("hand"); + if (kings_corner.selected_positions.length > 2) { + kings_corner.selected_positions.pop(); + } + new_selected = true + } + }) + + kings_corner.board.forEach((cards, i) => { + if (i * 75 + 100 < e.x && e.x < i * 75 + 170 && + 80 < e.y && e.y < 200) { + + kings_corner.selected.unshift(cards); + if (kings_corner.selected.length > 2) { + kings_corner.selected.pop(); + } + kings_corner.selected_positions.unshift("board"); + if (kings_corner.selected_positions.length > 2) { + kings_corner.selected_positions.pop(); + } + new_selected = true + } + }) + + if (!new_selected) { + kings_corner.selected = [] + kings_corner.selected_positions = [] + } +} +kings_corner.mouseUpCallback = function (e) { + +}
\ No newline at end of file diff --git a/src/math/static/main.js b/src/math/static/main.js new file mode 100644 index 0000000..d66f48c --- /dev/null +++ b/src/math/static/main.js @@ -0,0 +1,149 @@ +// The callbacks to be called each frame on update, +// and on draw +var updateCallback, drawCallback, mouseDownCallback, mouseUpCallback; +// The interval object +var gameInterval; +let width = 800; +let height = 600; +let fps = 30; + +window.onload = function () { + canvas = document.getElementById("canvas"); + ctx = canvas.getContext("2d"); + canvas.width = width; + canvas.height = height; + document.addEventListener("keydown", keyPush); + document.addEventListener("mousedown", mouseDown); + document.addEventListener("mouseup", mouseUp); + init(); +} + +function switchState(game) { + updateCallback = game.updateCallback; + drawCallback = game.drawCallback; + mouseDownCallback = game.mouseDownCallback; + mouseUpCallback = game.mouseUpCallback; +} + +function game() { + updateCallback(); + drawCallback(); +} + +function init() { + switchState(menu); + gameInterval = setInterval(game, 1000 / fps); + + let buttonX = (width / 5) * 1 // 2/5 the width + let buttonWidth = (width / 5) * 3 + let buttonHeight = 40 + menu.buttons.forEach((gameData, i) => { + gameData.x = buttonX; + gameData.y = (buttonHeight + 10) * i + 200; + gameData.width = buttonWidth; + gameData.height = buttonHeight; + }) + menu.buttons.push({ + x: 680, + y: 530, + width: 100, + height: buttonHeight, + name: "Help", + game: help, + }) +} + +var menu = { + "buttons": [ + { + "name": "Nim", + "game": nim, + }, + // { + // "name": "Solitaire", + // "game": solitaire, + // }, + { + "name": "Kings Corner", + "game": kings_corner, + }, + { + "name": "Black Hole", + "game": black_hole, + }, + ] +}; +menu.updateCallback = function () { + +} +menu.drawCallback = function () { + font(48); + ctx.fillStyle = "#99b3ff"; + ctx.fillRect(0, 0, width, height); + + menu.buttons.forEach((gameData, i) => { + button(gameData.x, gameData.y, gameData.width, gameData.height, gameData.name, gameData.isClicked); + }) +} + +menu.mouseDownCallback = function (e) { + let newGame = buttonAt(e.x, e.y, menu.buttons); + if(newGame){ + newGame.isClicked = true; + } +} + +menu.mouseUpCallback = function (e) { + let newGame = buttonAt(e.x, e.y, menu.buttons); + if(newGame && newGame.isClicked){ + switchState(newGame.game) + } + menu.buttons.forEach((gameData, i) => { + gameData.isClicked = false; + }) +} + +function buttonAt(x, y, buttons) { + return buttons.find((gameData, i) => { + if (gameData.x < x && x < gameData.x + gameData.width + && gameData.y < y && y < gameData.y + gameData.height) { + return true; + } + }) +} + +function font(size) { + ctx.font = size + "px Courier"; +} + +function keyPush(e) { + +} + +function mouseDown(e) { + mouseDownCallback(e); +} + +function mouseUp(e) { + mouseUpCallback(e); +} + +function button(x, y, w, h, text, isClicked){ + if(isClicked){ + ctx.fillStyle = "grey" + } else { + ctx.fillStyle = "darkgrey" + } + ctx.fillRect(x, y, w, h); + ctx.strokeStyle = "black" + ctx.beginPath(); + ctx.moveTo(x, y); + ctx.lineTo(x+w, y); + ctx.lineTo(x+w, y+h); + ctx.lineTo(x, y+h); + ctx.lineTo(x, y); + ctx.stroke(); + font(36); + ctx.fillStyle = "black" + ctx.fillText(text, x+5, y+h-8) +} diff --git a/src/math/static/nim.js b/src/math/static/nim.js new file mode 100644 index 0000000..b8d1665 --- /dev/null +++ b/src/math/static/nim.js @@ -0,0 +1,102 @@ +var nim = { + pieces: 10, + buttons: [ + { + "name": "1", + "x": 50, + "y": 50, + "width": 50, + "height": 50, + "value": 1 + }, + { + "name": "2", + "x": 50, + "y": 125, + "width": 50, + "height": 50, + "value": 2 + } + ], + status: "It is your turn", + gameOver: false, +}; +var nimSetup = false; +nim.updateCallback = function(){ + // Check for who wins/reset/etc +} +nim.drawCallback = function(){ + ctx.fillStyle = "#99b3ff"; + ctx.fillRect(0, 0, width, height); + nim.buttons.forEach((b, i) => { + button(b.x, b.y, 50, 50, b.name, b.isClicked); + }) + + ctx.fillStyle = "green" + for(var i = 0; i < nim.pieces; i++){ + ctx.beginPath(); + ctx.arc(175 + i * 50, 300 + (i%2)*50, 25, 0, 2 * Math.PI); + ctx.fill(); + } + ctx.fillStyle = "grey" + for(var i = nim.pieces; i < 10; i++){ + ctx.beginPath(); + ctx.arc(175 + i * 50, 300 + (i%2)*50, 25, 0, 2 * Math.PI); + ctx.fill(); + } + + font(26) + ctx.fillStyle = "black" + ctx.fillText(nim.status, 175, 75) +} +nim.mouseDownCallback = function (e) { + if(nim.gameOver){ + nim.pieces = 10; + nim.gameOver = false; + nim.status = "It is your turn"; + switchState(menu); + return; + } + let choice = buttonAt(e.x, e.y, nim.buttons); + if(choice){ + choice.isClicked = true; + } +} +nim.mouseUpCallback = function (e) { + let choice = buttonAt(e.x, e.y, nim.buttons); + if(choice && choice.isClicked){ + nim.turn(choice.value); + } + nim.buttons.forEach((gameData, i) => { + gameData.isClicked = false; + }) +} +nim.subtract = function(value){ + nim.pieces -= value; + if(nim.pieces < 0){ + nim.pieces = 0; + } +} +nim.turn = function(value){ + nim.subtract(value); + if(nim.pieces == 0){ + nim.gameOver = true; + nim.status = "You win!" + return; + } + if(nim.pieces % 3 == 0){ + nim.subtract(1); + nim.status = "The other player took 1" + } else if(nim.pieces % 3 == 1){ + nim.subtract(1); + nim.status = "The other player took 1" + } else if(nim.pieces % 3 == 2){ + nim.subtract(2); + nim.status = "The other player took 2" + } + if(nim.pieces == 0){ + this.gameOver = true; + nim.status = "You lose!" + return; + } +}
\ No newline at end of file diff --git a/src/math/static/solitaire.js b/src/math/static/solitaire.js new file mode 100644 index 0000000..c2b6172 --- /dev/null +++ b/src/math/static/solitaire.js @@ -0,0 +1,8 @@ +var solitaire = {}; +solitaire.updateCallback = function(){ + +} +solitaire.drawCallback = function(){ + ctx.fillStyle = "green"; + ctx.fillRect(0, 0, width, height); +}
\ No newline at end of file diff --git a/src/pinball/index.html b/src/pinball/index.html new file mode 100644 index 0000000..b39d48e --- /dev/null +++ b/src/pinball/index.html @@ -0,0 +1,120 @@ +<center> + <canvas id="canvas"></canvas> +</center> +<script> + var WIDTH = 300 + var HEIGHT = 400 + window.onload = function(){ + canvas = document.getElementById("canvas"); + ctx = canvas.getContext("2d"); + canvas.width = WIDTH; + canvas.height = HEIGHT; + document.addEventListener("keydown",keyDown); + document.addEventListener("keyup",keyUp); + setInterval(game, 1000/10); + } + var tileCountWidth = 30; + var tileCountHeight = 40; + var tileWidth = WIDTH/tileCountWidth; + var tileHeight = HEIGHT/tileCountHeight; + var ballX = WIDTH/2; + var ballY = 10; + var leftUp = false; + var rightUp = false; + var vx = randomInt(20)-10; + var vy = 0; + var ay = 2; + var ymax = 20; + var length = 5; + var paddleWidth = 11; + function game(){ + update() + + color("black"); + // BACKGROUND + ctx.fillRect(0,0,WIDTH, HEIGHT); + // SIDES + color("blue"); + ctx.fillRect(0,0,tileWidth, HEIGHT); +// console.log(WIDTH, tileWidth, tileCountWidth) + ctx.fillRect(WIDTH-tileWidth, 0, tileWidth, HEIGHT); + ctx.beginPath(); + // DRAW BALL + color("white"); + ctx.fillRect(ballX, ballY, tileWidth, tileHeight); + // DRAW PADDLES + color("red"); + ctx.lineWidth=10; + + ctx.moveTo(1*tileWidth, 33*tileHeight); + if(leftUp){ + ctx.lineTo((1+paddleWidth)*tileWidth, 33*tileHeight); + } else { + ctx.lineTo((1+paddleWidth)*tileWidth, 35*tileHeight); + } + ctx.stroke(); + var t = tileCountWidth - 1 + ctx.moveTo(t*tileWidth, 33*tileHeight); + if(rightUp){ + ctx.lineTo((t-paddleWidth)*tileWidth, 33*tileHeight); + } else { + ctx.lineTo((t-paddleWidth)*tileWidth, 35*tileHeight); + } + ctx.stroke(); + } + function update(){ + + if(((leftUp && ballX/tileWidth <=8) || (rightUp && ballX/tileWidth >=13)) + && ballY/tileHeight <= 35 && ballY/tileHeight >= 32){ + console.log("Hit!") + vy=-20 + } + vy += ay + vy = Math.min(vy, ymax) + ballY += vy + ballX += vx + if(ballX <= tileWidth){ + ballX = tileWidth + vx = -vx + } + if(ballX >= WIDTH-(2*tileWidth)){ + ballX = WIDTH-(2*tileWidth) + vx = -vx + } + + } + function keyUp(e){ + switch(e.keyCode){ + case 37: + leftUp = false; + break; + case 39: + rightUp = false; + break; + } + } + function keyDown(e){ + switch(e.keyCode){ + case 37: + leftUp = true; + break; + case 39: + rightUp = true; + break; + } + } + function setRandomCoords(item){ + item.x = randomInt(tileWidth); + item.y = randomInt(tileHeight); + } + function randomInt(max){ + return Math.floor(Math.random()*max); + } + function font(size){ + ctx.font=size+"px Courier"; + } + function color(c){ + ctx.strokeStyle=c; + ctx.fillStyle=c; + } +</script> diff --git a/src/pinball/server.js b/src/pinball/server.js new file mode 100644 index 0000000..2bf88d5 --- /dev/null +++ b/src/pinball/server.js @@ -0,0 +1,11 @@ +const path = require('path'); +const fs = require('fs'); + +function setUpRoutes(server, models, jwtFunctions, database) { + server.get('/pinball', (req, res) => res.sendFile(__dirname + "/index.html")) + server.get('/pinball/styles.css', (req, res) => res.sendFile(__dirname + "/static/styles.css")) +} + +module.exports = { + setUpRoutes +}; diff --git a/src/quadrowple/index.html b/src/quadrowple/index.html new file mode 100644 index 0000000..574ffca --- /dev/null +++ b/src/quadrowple/index.html @@ -0,0 +1,27 @@ +<!doctype html> +<html lang="en"> + +<head> + <title>Quad-row-ple</title> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> + <link rel="shortcut icon" href="/favicon.ico"> + <!-- <script src="https://cdn.jsdelivr.net/npm/vue"></script> --> + <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> + <script src="/quadrowple/main.js"></script> + <link rel="stylesheet" type="text/css" href="/quadrowple/styles.css"> +</head> + +<body> + <div id="data"> + <h1 v-if="status">{{status}}</h1> + + <canvas id="canvas" width="351" height="301"></canvas> + + <div> + <button v-on:click="newGame">{{this.playing ? 'Forfeit' : 'New Game'}}</button> + </div> + </div> +</body> + +</html>
\ No newline at end of file diff --git a/src/quadrowple/server.js b/src/quadrowple/server.js new file mode 100644 index 0000000..b44c055 --- /dev/null +++ b/src/quadrowple/server.js @@ -0,0 +1,172 @@ +const path = require('path'); +const fs = require('fs'); + +function setUpRoutes(server, models, jwtFunctions, database) { + + server.get('/quadrowple', (req, res) => res.sendFile(__dirname + "/index.html")) + server.get('/quadrowple/main.js', (req, res) => res.sendFile(__dirname + "/static/main.js")) + server.get('/quadrowple/styles.css', (req, res) => res.sendFile(__dirname + "/static/styles.css")) + // server.use('/static', express.static(path.join(__dirname, '/static'))) + + var games = {} + var gameList = [] + var id = 0 + server.get('/quadrowple/status', (req, res) => { + let cookie = req.cookies.session; + if (!cookie) { + cookie = uuidv4(); + res.cookie('session', cookie, { expires: new Date(Date.now() + (1000 * 60 * 60)) }); + } + currentGames = [] + gameList.forEach( game => { + var diff = new Date() - game.time; + // Keep games that are recently updated + if(diff < 1000 * 10) {// 10 seconds with no update + currentGames.push(game) + } else { // otherwise don't save it and get rid of game + game.players.forEach(c => { + delete games[c] + }); + } + }) + gameList = currentGames + if (!games[cookie]) { + var game = gameList.find((el) => el.waiting) + if (game) { // Start game + game.players.push(cookie) + game.waiting = false + game.board = [[undefined, undefined, undefined, undefined, undefined, undefined], + [undefined, undefined, undefined, undefined, undefined, undefined], + [undefined, undefined, undefined, undefined, undefined, undefined], + [undefined, undefined, undefined, undefined, undefined, undefined], + [undefined, undefined, undefined, undefined, undefined, undefined], + [undefined, undefined, undefined, undefined, undefined, undefined], + [undefined, undefined, undefined, undefined, undefined, undefined]] + game.turn = Math.floor(Math.random() * 2) + games[cookie] = game + } else { // Create new game, and wait + game = { + waiting: true, + players: [cookie], + id: id++, + time: new Date(), + } + gameList.push(game) + games[cookie] = game + } + } else { + games[cookie].time = new Date() + } + res.status(200).send(games[cookie]); + }) + + // returns undefined if game in progress, or index of winner + function gameOver(game) { + for (var player = 0; player < 2; player++) { + // 4 in a row in a column + for (var col = 0; col < 7; col++) { + for (var row = 0; row < 2; row++) { + if (game.board[col][row] == player && + game.board[col][row + 1] == player && + game.board[col][row + 2] == player && + game.board[col][row + 3] == player) { + return player + } + } + } + // 4 in a row in a row + for (var col = 0; col < 3; col++) { + for (var row = 0; row < 6; row++) { + if (game.board[col][row] == player && + game.board[col + 1][row] == player && + game.board[col + 2][row] == player && + game.board[col + 3][row] == player) { + return player + } + } + } + // Check up right diagonal + for (var row = 0; row < 2; row++) { + for (var col = 0; col < 3; col++) { + if (game.board[col][row] == player && + game.board[col + 1][row + 1] == player && + game.board[col + 2][row + 2] == player && + game.board[col + 3][row + 3] == player) { + return player + } + } + } + // Check down right diagonal + for (var row = 3; row < 6; row++) { + for (var col = 0; col < 3; col++) { + if (game.board[col][row] == player && + game.board[col + 1][row - 1] == player && + game.board[col + 2][row - 2] == player && + game.board[col + 3][row - 3] == player) { + return player + } + } + } + } + return undefined + } + + function sendGame(res, game, cookie){ + var winner = gameOver(game) + if (winner != undefined) { + res.status(200).send({ game: game, turn: -1, winner: game.players[winner] == cookie }); + } else { + res.status(200).send({ game: game, turn: game.players[game.turn] == cookie }); + } + } + server.get('/quadrowple/game/:col', (req, res, next) => { + let cookie = req.cookies.session; + if (!cookie || !games[cookie]) { + next() + return + } + var game = games[cookie] + const { col } = req.params; + if (game.players[game.turn] == cookie && gameOver(game) == undefined) { + // Add player's token to column + for (var row = 0; row < 6; row++) { + if (game.board[col][row] == undefined) { + game.board[col][row] = (game.players.indexOf(cookie)) + game.turn = (game.turn + 1) % 2 + break + } + } + } + sendGame(res, game, cookie) + }) + server.get('/quadrowple/game', (req, res, next) => { + let cookie = req.cookies.session; + if (!cookie || !games[cookie]) { + res.status(200).send({restart: true}); + return + } + var game = games[cookie] + if(gameOver(game) != undefined){ + delete games[cookie] + } + sendGame(res, game, cookie) + }) + + server.get('/quadrowple/new', (req, res, next) => { + let cookie = req.cookies.session; + if (!cookie || !games[cookie]) { + next() + return + } + games[cookie].players.forEach( el =>{ + delete games[el] + }) + }) + +} + +module.exports = { + setUpRoutes +}; + + diff --git a/src/quadrowple/static/main.js b/src/quadrowple/static/main.js new file mode 100644 index 0000000..008658c --- /dev/null +++ b/src/quadrowple/static/main.js @@ -0,0 +1,107 @@ +window.onload = function () { + var transactionData = new Vue({ + el: '#data', + data: { + status: "Loading...", + playing: false + }, + methods: { + newGame: function () { + if (this.playing) { + fetch(new Request(`/quadrowple/new`)) + } else { + this.startGame() + } + }, + startGame: function () { + console.log("created") + var mouseDown = function (e) { + col = Math.floor(e.x / 50); + if (0 <= col <= 6) { + fetch(new Request(`/quadrowple/game/${col}`)) + } + } + document.addEventListener("click", mouseDown); + var playInterval; + var playGame = function (t) { + fetch(new Request(`/quadrowple/game`)).then(response => response.json()) + .then(response => { + var c = document.getElementById("canvas"); + var ctx = c.getContext("2d"); + ctx.fillStyle = "#eee" + ctx.fillRect(0, 0, 351, 301) + + if (response.restart) { + t.playing = false + t.status = "The game has been forfeited" + clearInterval(playInterval) + return + } else if (response.winner != undefined) { + clearInterval(playInterval) + if (response.winner) { + t.status = "You won!" + } else { + t.status = "You lose!" + } + } else if (response.turn) { + t.status = "It's your turn!" + } else { + t.status = "Waiting for other player..." + } + + ctx.strokeStyle = "black" + for (var i = 0; i <= 7; i++) { + ctx.moveTo(50 * i, 0); + ctx.lineTo(50 * i, 300); + ctx.stroke(); + } + for (var i = 0; i <= 6; i++) { + ctx.moveTo(0, 50 * i); + ctx.lineTo(350, 50 * i); + ctx.stroke(); + } + + for (var col = 0; col < 7; col++) { + for (var row = 0; row < 6; row++) { + if (response.game.board[col][row] == undefined) { + continue + } else if (response.game.board[col][row] == 0) { + ctx.fillStyle = "#0000FF"; + } else { + ctx.fillStyle = "#FF0000"; + } + ctx.beginPath(); + ctx.arc(25 + 50 * col, 50 * (5 - row) + 25, 23, 0, 2 * Math.PI); + ctx.fill(); + } + } + }); + } + var loadInterval = undefined + var loadStatus = function (recurse, t) { + fetch(new Request(`/quadrowple/status`)).then(response => response.json()) + .then(response => { + if (response.waiting) { + t.status = "Waiting..." + if (recurse) { + loadInterval = window.setInterval(loadStatus, 1000, false, t) + } + } else { + t.status = "Playing..." + t.playing = true + clearInterval(loadInterval) + playInterval = window.setInterval(playGame, 1000, t) + } + }); + } + loadStatus(true, this) + } + }, + created() { + this.startGame(); + }, + computed: { + + } + }); +}
\ No newline at end of file diff --git a/src/quadrowple/static/styles.css b/src/quadrowple/static/styles.css new file mode 100644 index 0000000..4eedd0b --- /dev/null +++ b/src/quadrowple/static/styles.css @@ -0,0 +1,72 @@ +td { + border: 1px solid lightgrey; + min-width: 3em; +} + +table { + max-width: 100%; +} + +li { + cursor: pointer; + text-decoration: underline; +} + +tr:nth-child(2n+1) { + background-color: lightgray; +} +tr { + width: 100%; +} + +.bold { + font-weight: bold; +} + +#data { + width: 100%; +} + +.border { + border: 1px solid lightgrey; +} + +textarea { + border-radius: 4px; + width: 60%; + height: 10em; + display: block; +} + +pre { + white-space: pre-line; +} + +.net-negative { + /* color: red; */ + background-color: lightcoral; +} +.net-positive { + /* color: green; */ + background-color: lightgreen +} +.summary-panel { + float:left; + padding-right: 2em; +} +@media only screen and (max-width: 600px) { + .newItem td { + display:block; + } + .table-index { + display: none; + } + button { + font-size: 32px; + } + input { + font-size: 32px; + display: block; + width: 100%; + } +}
\ No newline at end of file diff --git a/src/server.js b/src/server.js new file mode 100644 index 0000000..ba5cff9 --- /dev/null +++ b/src/server.js @@ -0,0 +1,41 @@ +const express = require('express'); +const bodyParser = require('body-parser'); +const cookieParser = require('cookie-parser'); +//const request = require('request'); +const crypto = require('crypto'); +const uuidv4 = require('uuid/v4'); + +const path = require('path'); +const fs = require('fs'); +const config = JSON.parse(fs.readFileSync(path.join(__dirname, 'config.json'))); + +const server = express(); +server.use(cookieParser()) +server.use(bodyParser.json()); +//server.use(bodyParser.urlencoded({ extended: true })); + +function listen(port) { + server.listen(port, () => console.info(`Listening on port ${port}!`)); +} + +function load(gamePath, models, jwtFunctions, database){ + const game = require(gamePath); + game.setUpRoutes(server, models, jwtFunctions, database); +} + +function setUpRoutes(models, jwtFunctions, database) { + server.use(function (req, res, next) { + console.debug(new Date(), req.method, req.originalUrl); + next() + }) + + server.get('/', (req, res) => res.sendFile(__dirname + "/index.html")) +} + +module.exports = { + listen, + setUpRoutes, + load +}; + + diff --git a/src/snake/index.html b/src/snake/index.html new file mode 100644 index 0000000..eb11f86 --- /dev/null +++ b/src/snake/index.html @@ -0,0 +1,83 @@ +<center> + <canvas width="400" height="400" id="canvas"></canvas> +</center> +<script> + window.onload = function(){ + canvas = document.getElementById("canvas"); + ctx = canvas.getContext("2d"); +// canvas.height = 300; +// canvas.width = 400; + document.addEventListener("keydown",keyPush); + setInterval(game, 1000/10); + } + var tileCountWidth = 40; + var tileCountHeight = 40; + var tileWidth = canvas.width/tileCountWidth; + var tileHeight = canvas.height/tileCountHeight; + var snake = []; + var x = randomInt(tileWidth); + var y = randomInt(tileHeight); + var vx = 1; + var vy = 0; + var apple = {}; + console.log(apple); + setRandomCoords(apple); + console.log(apple); + var length = 5; + function game(){ + color("black"); + ctx.fillRect(0,0,canvas.width, canvas.height); + color("white"); + for(var i = 0; i < snake.length; i++){ + ctx.fillRect(snake[i].x*tileWidth, snake[i].y*tileHeight, tileWidth, tileHeight); + } + color("red"); + ctx.fillRect(apple.x*tileWidth, apple.y*tileHeight, tileWidth, tileHeight); + + x+=vx; + y+=vy; + snake.push({"x": x, "y": y}); + if(x==apple.x && y==apple.y){ + length++; + setRandomCoords(apple); + } + + while(snake.length > length){ + snake.shift(); + } + + } + function keyPush(e){ + switch(e.keyCode){ + case 37: + vx = -1; + vy = 0; + break; + case 38: + vx = 0; + vy = -1; + break; + case 39: + vx = 1; + vy = 0; + break; + case 40: + vx = 0; + vy = 1; + break; + } + } + function setRandomCoords(item){ + item.x = randomInt(tileWidth); + item.y = randomInt(tileHeight); + } + function randomInt(max){ + return Math.floor(Math.random()*max); + } + function font(size){ + ctx.font=size+"px Courier"; + } + function color(c){ + ctx.fillStyle=c; + } +</script> diff --git a/src/snake/server.js b/src/snake/server.js new file mode 100644 index 0000000..c73990b --- /dev/null +++ b/src/snake/server.js @@ -0,0 +1,11 @@ +const path = require('path'); +const fs = require('fs'); + +function setUpRoutes(server, models, jwtFunctions, database) { + server.get('/snake', (req, res) => res.sendFile(__dirname + "/index.html")) + server.get('/snake/styles.css', (req, res) => res.sendFile(__dirname + "/static/styles.css")) +} + +module.exports = { + setUpRoutes +}; diff --git a/src/stacker/index.html b/src/stacker/index.html new file mode 100644 index 0000000..eb256a6 --- /dev/null +++ b/src/stacker/index.html @@ -0,0 +1,215 @@ +<!doctype html> +<html lang="en"> + +<head> + <title>Stacker</title> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> + <!-- <link rel="stylesheet" type="text/css" href="/css/styles.css"> --> +</head> + +<body style="padding:0; margin:0; overflow:hidden;"> + <canvas id="canvas"></canvas> + <script> + var gameInterval, canvas, ctx; + var score, t, isGameOver, mouseX, mouseY, scaleX, scaleY, selected, stack, next, v, perfect; + let VELOCITY = 15; + + function init() { + next = {left: 0, width:200}; + v = VELOCITY; + stack = [{left: 100, width:200}]; + + score = 0; + isGameOver = false; + mouseX = 0; + mouseY = 0; + t = 0; + selected = -1; + perfect = 0; + gameInterval = setInterval(game, 1000 / 10); + } + + window.onload = function () { + canvas = document.getElementById("canvas"); + ctx = canvas.getContext("2d"); + + document.addEventListener("keydown", keyPush); + document.addEventListener("mousedown", mousePush); + + window.addEventListener('resize', resizeCanvas, false); + window.addEventListener('orientationchange', resizeCanvas, false); + resizeCanvas(); + + init(); + } + + function resizeCanvas() { + canvas.width = window.innerWidth; + canvas.height = window.innerHeight; + scaleX = window.innerWidth/400; + scaleY = window.innerHeight/600; + + if(scaleX/scaleY > 1.3){ + scaleX = scaleY = 1; + } + ctx.scale(scaleX, scaleY); + } + function game() { + update(); + draw(); + } + function draw() { + color("white"); + ctx.fillRect(0, 0, canvas.width,canvas.height); + color("black"); + ctx.fillRect(0, 0, 400,400); + + // Draw moving block + if(stack.length % 2 == 0){ + color("white"); + } else { + color("red") + } + var y; + if(stack.length < 10){ + y = 380-stack.length*20; + } else { + y = 380-10*20; + } + ctx.fillRect(next.left, y, next.width, 20) + + + // Draw stack + var index = max(stack.length-10, 0); + stack.slice(-10).forEach((element, i) => { + if(index % 2 == 0){ + color("white"); + } else { + color("red") + } + + let y = 380-i*20 + ctx.fillRect(element.left, y, element.width, 20) + index++; + }); + + // Draw "perfect" marker + if(perfect > 0 ){ + font(20); + color("red"); + let last = stack[stack.length - 1] + ctx.fillText("Perfect!", 170, 60); + perfect--; + } + + // Draw score + font(20); + color("red"); + ctx.fillText("Score: " + score, 170, 30); + + // Draw touch controls + color("#ff9900"); + if(selected) { + color("#cc9900") + } + ctx.beginPath(); + ctx.moveTo(200, 500); + ctx.arc(200, 500, 100, 0, 2*Math.PI); + ctx.fill(); + selected = 0; + + if (isGameOver) { + color("blue"); + font(32); + ctx.fillText("Game over!", 160, 200); + font(24); + } + } + + function update() { + t++; + next.left += v; + if(next.left + next.width >= 400) { + let diff = next.left + next.width - 400; + next.left -= diff; + v = -1 * VELOCITY; + } else if(next.left <= 0) { + let diff = 0 - next.left; + next.left += diff; + v = VELOCITY; + } + if (next.width <= 0) { + gameOver(); + } + } + function max(a, b) { + return a > b ? a : b; + } + function min(a, b) { + return a < b ? a : b; + } + function keyPush(e) { + if(isGameOver){ + init(); + return; + } + if(e.keyCode == 32){ + let last = stack[stack.length -1]; + var left = max(next.left, last.left); + let right = min(next.left + next.width, last.left+last.width); + var width = right-left; + + if(stack[stack.length -1 ].width - width < 10){ + width = stack[stack.length -1 ].width + left = stack[stack.length -1 ].left + perfect = 5; + } + + if(width > 0){ + stack.push({left: left, width: width}) + score += 1; + } + + if(v < 0) { + next = {left: 0, width: width} + v = VELOCITY + } else { + next = {left: 400-width, width: width} + v = -1 * VELOCITY + } + } + } + function mousePush(e) { + mouseX = e.clientX/scaleX - 200; + mouseY = e.clientY/scaleY - 500; + if (Math.sqrt(mouseX * mouseX + mouseY * mouseY) > 100) { + return; + } + selected = 1; + keyPush({keyCode: 32}) + } + function randomInt(max) { + return Math.floor(Math.random() * max); + } + function font(size) { + ctx.font = size + "px sans serif"; + } + function color(c) { + ctx.fillStyle = c; + } + function gameOver() { + isGameOver = true; + clearInterval(gameInterval); + + const urlParams = new URLSearchParams(window.location.search); + const uid = urlParams.get('uid'); + const mid = urlParams.get('mid'); + + const request = new Request(`/setScore?uid=${uid}&mid=${mid}&score=${score}`); + fetch(request).then(response => console.log("response")); + } + </script> +</body> + +</html>
\ No newline at end of file diff --git a/src/stacker/server.js b/src/stacker/server.js new file mode 100644 index 0000000..ee2fca6 --- /dev/null +++ b/src/stacker/server.js @@ -0,0 +1,11 @@ +const path = require('path'); +const fs = require('fs'); + +function setUpRoutes(server, models, jwtFunctions, database) { + server.get('/stacker', (req, res) => res.sendFile(__dirname + "/index.html")) + server.get('/stacker/styles.css', (req, res) => res.sendFile(__dirname + "/static/styles.css")) +} + +module.exports = { + setUpRoutes +}; diff --git a/src/ur/index.html b/src/ur/index.html new file mode 100644 index 0000000..809ed3d --- /dev/null +++ b/src/ur/index.html @@ -0,0 +1,27 @@ +<!doctype html> +<html lang="en"> + +<head> + <title>Royal Game of Ur</title> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> + <link rel="shortcut icon" href="/favicon.ico"> + <!-- <script src="https://cdn.jsdelivr.net/npm/vue"></script> --> + <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> + <script src="/ur/main.js"></script> + <link rel="stylesheet" type="text/css" href="/ur/styles.css"> +</head> + +<body> + <div id="data"> + <h1 v-if="status">{{status}}</h1> + + <canvas id="canvas" width="401" height="301"></canvas> + + <div> + <button v-on:click="newGame">{{this.playing ? 'Forfeit' : 'New Game'}}</button> + </div> + </div> +</body> + +</html>
\ No newline at end of file diff --git a/src/ur/server.js b/src/ur/server.js new file mode 100644 index 0000000..81437ee --- /dev/null +++ b/src/ur/server.js @@ -0,0 +1,175 @@ +const path = require('path'); +const fs = require('fs'); + +function setUpRoutes(server, models, jwtFunctions, database) { + + server.get('/ur', (req, res) => res.sendFile(__dirname + "/index.html")) + server.get('/ur/main.js', (req, res) => res.sendFile(__dirname + "/static/main.js")) + server.get('/ur/styles.css', (req, res) => res.sendFile(__dirname + "/static/styles.css")) + // server.use('/static', express.static(path.join(__dirname, '/static'))) + + var games = {} + var gameList = [] + var id = 0 + server.get('/ur/status', (req, res) => { + let cookie = req.cookies.session; + if (!cookie) { + cookie = uuidv4(); + res.cookie('session', cookie, { expires: new Date(Date.now() + (1000 * 60 * 60)) }); + } + currentGames = [] + gameList.forEach( game => { + var diff = new Date() - game.time; + // Keep games that are recently updated + if(diff < 1000 * 10) {// 10 seconds with no update + currentGames.push(game) + } else { // otherwise don't save it and get rid of game + game.players.forEach(c => { + delete games[c] + }); + } + }) + gameList = currentGames + if (!games[cookie]) { + var game = gameList.find((el) => el.waiting) + if (game) { // Start game + game.players.push(cookie) + game.waiting = false + game.board = [[undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined], + [undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined], + [undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined]] + game.turn = Math.floor(Math.random() * 2) + games[cookie] = game + } else { // Create new game, and wait + game = { + waiting: true, + players: [cookie], + id: id++, + time: new Date(), + } + gameList.push(game) + games[cookie] = game + } + } else { + games[cookie].time = new Date() + } + res.status(200).send(games[cookie]); + }) + + // returns undefined if game in progress, or index of winner + function gameOver(game) { + // TODO + return false; + + for (var player = 0; player < 2; player++) { + // 4 in a row in a column + for (var col = 0; col < 7; col++) { + for (var row = 0; row < 2; row++) { + if (game.board[row][col] == player){ + return player + } + } + } + // 4 in a row in a row + for (var col = 0; col < 3; col++) { + for (var row = 0; row < 6; row++) { + if (game.board[col][row] == player && + game.board[col + 1][row] == player && + game.board[col + 2][row] == player && + game.board[col + 3][row] == player) { + return player + } + } + } + // Check up right diagonal + for (var row = 0; row < 2; row++) { + for (var col = 0; col < 3; col++) { + if (game.board[col][row] == player && + game.board[col + 1][row + 1] == player && + game.board[col + 2][row + 2] == player && + game.board[col + 3][row + 3] == player) { + return player + } + } + } + // Check down right diagonal + for (var row = 3; row < 6; row++) { + for (var col = 0; col < 3; col++) { + if (game.board[col][row] == player && + game.board[col + 1][row - 1] == player && + game.board[col + 2][row - 2] == player && + game.board[col + 3][row - 3] == player) { + return player + } + } + } + } + return undefined + } + + function sendGame(res, game, cookie){ + var winner = gameOver(game) + if (winner != undefined) { + res.status(200).send({ game: game, turn: -1, winner: game.players[winner] == cookie }); + } else { + res.status(200).send({ game: game, turn: game.players[game.turn] == cookie }); + } + } + server.get('/ur/game/:col/:row', (req, res, next) => { + let cookie = req.cookies.session; + if (!cookie || !games[cookie]) { + next() + return + } + var game = games[cookie] + const { col } = req.params; + if (game.players[game.turn] == cookie && gameOver(game) == undefined) { + // Add player's token to column + + // do nothing + if(game.board == undefined){ + + } else { + // move piece at col, row + game.board[col, row] + } + + for (var row = 0; row < 6; row++) { + if (game.board[col][row] == undefined) { + game.board[col][row] = (game.players.indexOf(cookie)) + game.turn = (game.turn + 1) % 2 + break + } + } + } + sendGame(res, game, cookie) + }) + server.get('/ur/game', (req, res, next) => { + let cookie = req.cookies.session; + if (!cookie || !games[cookie]) { + res.status(200).send({restart: true}); + return + } + var game = games[cookie] + if(gameOver(game) != undefined){ + delete games[cookie] + } + sendGame(res, game, cookie) + }) + + server.get('/ur/new', (req, res, next) => { + let cookie = req.cookies.session; + if (!cookie || !games[cookie]) { + next() + return + } + games[cookie].players.forEach( el =>{ + delete games[el] + }) + }) + +} + +module.exports = { + setUpRoutes +}; diff --git a/src/ur/static/main.js b/src/ur/static/main.js new file mode 100644 index 0000000..8f29c6c --- /dev/null +++ b/src/ur/static/main.js @@ -0,0 +1,130 @@ +window.onload = function () { + var transactionData = new Vue({ + el: '#data', + data: { + status: "Loading...", + playing: false + }, + methods: { + newGame: function () { + if (this.playing) { + fetch(new Request(`/ur/new`)) + } else { + this.startGame() + } + }, + startGame: function () { + console.log("created") + var mouseDown = function (e) { + var canvas = document.getElementById('canvas') + col = Math.floor((e.x - canvas.offsetLeft) / 50); + row = Math.floor((e.y - canvas.offsetTop) / 50); + console.log(row, col) + if (0 <= col && col <= 7 && 0 <= row && row <= 2) { + console.log("clicked board") + fetch(new Request(`/ur/game/${col}/${row}`)) + } else if( 0 == col && 4 == row){ + console.log("roll") + } + } + document.addEventListener("click", mouseDown); + var playInterval; + var playGame = function (t) { + fetch(new Request(`/ur/game`)).then(response => response.json()) + .then(response => { + var c = document.getElementById("canvas"); + var ctx = c.getContext("2d"); + ctx.fillStyle = "#eee" + ctx.fillRect(0, 0, 401, 301) + + if (response.restart) { + t.playing = false + t.status = "The game has been forfeited" + clearInterval(playInterval) + return + } else if (response.winner != undefined) { + clearInterval(playInterval) + if (response.winner) { + t.status = "You won!" + } else { + t.status = "You lose!" + } + } else if (response.turn) { + t.status = "It's your turn!" + } else { + t.status = "Waiting for other player..." + } + + ctx.strokeStyle = "black" + for (var i = 0; i <= 4; i++) { + ctx.moveTo(50 * i, 0); + ctx.lineTo(50 * i, 150); + ctx.stroke(); + } + for (var i = 6; i <= 8; i++) { + ctx.moveTo(50 * i, 0); + ctx.lineTo(50 * i, 150); + ctx.stroke(); + } + ctx.moveTo(250, 50); + ctx.lineTo(250, 100); + ctx.moveTo(0, 0); + ctx.lineTo(200, 0); + ctx.moveTo(300, 0); + ctx.lineTo(400, 0); + ctx.moveTo(0, 50); + ctx.lineTo(400, 50); + ctx.moveTo(0, 100); + ctx.lineTo(400, 100); + ctx.moveTo(0, 150); + ctx.lineTo(200, 150); + ctx.moveTo(300, 150); + ctx.lineTo(400, 150); + ctx.stroke(); + + for (var col = 0; col < 7; col++) { + for (var row = 0; row < 6; row++) { + if (response.game.board[col][row] == undefined) { + continue + } else if (response.game.board[col][row] == 0) { + ctx.fillStyle = "#0000FF"; + } else { + ctx.fillStyle = "#FF0000"; + } + ctx.beginPath(); + ctx.arc(25 + 50 * col, 50 * (5 - row) + 25, 23, 0, 2 * Math.PI); + ctx.fill(); + } + } + ctx.fillStyle = "black" + ctx.fillRect(0, 200, 50, 50); + }); + } + var loadInterval = undefined + var loadStatus = function (recurse, t) { + fetch(new Request(`/ur/status`)).then(response => response.json()) + .then(response => { + if (response.waiting) { + t.status = "Waiting..." + if (recurse) { + loadInterval = window.setInterval(loadStatus, 1000, false, t) + } + } else { + t.status = "Playing..." + t.playing = true + clearInterval(loadInterval) + playInterval = window.setInterval(playGame, 1000, t) + } + }); + } + loadStatus(true, this) + } + }, + created() { + this.startGame(); + }, + computed: { + + } + }); +}
\ No newline at end of file diff --git a/src/ur/static/styles.css b/src/ur/static/styles.css new file mode 100644 index 0000000..4eedd0b --- /dev/null +++ b/src/ur/static/styles.css @@ -0,0 +1,72 @@ +td { + border: 1px solid lightgrey; + min-width: 3em; +} + +table { + max-width: 100%; +} + +li { + cursor: pointer; + text-decoration: underline; +} + +tr:nth-child(2n+1) { + background-color: lightgray; +} +tr { + width: 100%; +} + +.bold { + font-weight: bold; +} + +#data { + width: 100%; +} + +.border { + border: 1px solid lightgrey; +} + +textarea { + border-radius: 4px; + width: 60%; + height: 10em; + display: block; +} + +pre { + white-space: pre-line; +} + +.net-negative { + /* color: red; */ + background-color: lightcoral; +} +.net-positive { + /* color: green; */ + background-color: lightgreen +} +.summary-panel { + float:left; + padding-right: 2em; +} +@media only screen and (max-width: 600px) { + .newItem td { + display:block; + } + .table-index { + display: none; + } + button { + font-size: 32px; + } + input { + font-size: 32px; + display: block; + width: 100%; + } +}
\ No newline at end of file |