Honestly way too much went into this single commit. I am so sorry future me
This commit is contained in:
parent
cd3f653f3f
commit
42c0004150
33
.vscode/settings.json
vendored
33
.vscode/settings.json
vendored
@ -1,25 +1,26 @@
|
||||
{
|
||||
"workbench.colorCustomizations": {
|
||||
"activityBar.activeBackground": "#d2d1f5",
|
||||
"activityBar.background": "#d2d1f5",
|
||||
"activityBar.activeBackground": "#83a0ea",
|
||||
"activityBar.background": "#83a0ea",
|
||||
"activityBar.foreground": "#15202b",
|
||||
"activityBar.inactiveForeground": "#15202b99",
|
||||
"activityBarBadge.background": "#dd6562",
|
||||
"activityBarBadge.background": "#fae4ea",
|
||||
"activityBarBadge.foreground": "#15202b",
|
||||
"commandCenter.border": "#15202b99",
|
||||
"sash.hoverBorder": "#d2d1f5",
|
||||
"statusBar.background": "#a9a7ec",
|
||||
"statusBar.foreground": "#15202b",
|
||||
"statusBarItem.hoverBackground": "#807de3",
|
||||
"statusBarItem.remoteBackground": "#a9a7ec",
|
||||
"statusBarItem.remoteForeground": "#15202b",
|
||||
"titleBar.activeBackground": "#a9a7ec",
|
||||
"titleBar.activeForeground": "#15202b",
|
||||
"titleBar.inactiveBackground": "#a9a7ec99",
|
||||
"titleBar.inactiveForeground": "#15202b99"
|
||||
"commandCenter.border": "#e7e7e799",
|
||||
"sash.hoverBorder": "#83a0ea",
|
||||
"statusBar.background": "#577ee3",
|
||||
"statusBar.foreground": "#e7e7e7",
|
||||
"statusBarItem.hoverBackground": "#83a0ea",
|
||||
"statusBarItem.remoteBackground": "#577ee3",
|
||||
"statusBarItem.remoteForeground": "#e7e7e7",
|
||||
"titleBar.activeBackground": "#577ee3",
|
||||
"titleBar.activeForeground": "#e7e7e7",
|
||||
"titleBar.inactiveBackground": "#577ee399",
|
||||
"titleBar.inactiveForeground": "#e7e7e799"
|
||||
},
|
||||
"peacock.remoteColor": "#a9a7ec",
|
||||
"peacock.remoteColor": "#577ee3",
|
||||
"deno.enable": true,
|
||||
"deno.unstable": true,
|
||||
"deno.config": "./deno.jsonc"
|
||||
"deno.config": "./deno.jsonc",
|
||||
"svg.preview.background": "black"
|
||||
}
|
0
40kParsing/index.ts
Normal file
0
40kParsing/index.ts
Normal file
24
40kParsing/pdfParsing.ts
Normal file
24
40kParsing/pdfParsing.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { PDFDocumentProxy, PDFPageProxy, getDocument } from 'npm:pdfjs-dist';
|
||||
|
||||
export async function parsePDF(pdfPath: string): Promise<string> {
|
||||
// Load the PDF file
|
||||
const loadingTask = getDocument(pdfPath);
|
||||
const pdf: PDFDocumentProxy = await loadingTask.promise;
|
||||
|
||||
const numPages = pdf.numPages;
|
||||
const textContent: string[] = [];
|
||||
|
||||
// Iterate over each page and extract text content
|
||||
for (let i = 1; i <= numPages; i++) {
|
||||
const page: PDFPageProxy = await pdf.getPage(i);
|
||||
const pageContent = await page.getTextContent();
|
||||
|
||||
// Extract text from the content items
|
||||
const pageText = pageContent.items.map(item => item.str).join(' ');
|
||||
textContent.push(pageText);
|
||||
}
|
||||
|
||||
// Combine the text content from all pages
|
||||
return textContent.join('\n');
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
import {parse, stringify} from 'yaml';
|
||||
|
||||
for await (const service of Deno.readDir('.')) {
|
||||
if (service.isFile || !service.name.includes('-service')) continue;
|
||||
|
||||
@ -11,7 +13,7 @@ ${port ? 'EXPOSE ' + port : ''}
|
||||
|
||||
WORKDIR /${serviceName}
|
||||
|
||||
ADD ./user-service .
|
||||
ADD ${serviceFile} .
|
||||
COPY ./deno.jsonc .
|
||||
COPY ./secrets.json .
|
||||
COPY ./key.txt .
|
||||
@ -19,6 +21,16 @@ ADD ./common ./common
|
||||
ADD ./lib ./lib
|
||||
ADD ./middleware ./middleware
|
||||
|
||||
CMD ["run", "${perms.join('", "')}", main.ts${port ? `, "${port}"` : ''}]
|
||||
CMD ["run", "${perms.join('", "')}", "main.ts"${port ? `, "${port}"` : ''}]
|
||||
`);
|
||||
|
||||
const dockerCompose: any = parse(await Deno.readTextFile('./docker-compose.yml'));
|
||||
dockerCompose['services'][serviceName] = {
|
||||
build: {
|
||||
context: "./",
|
||||
dockerfile: serviceFile + 'Dockerfile'
|
||||
}
|
||||
}
|
||||
|
||||
await Deno.writeTextFile('./docker-compose.yml', stringify(dockerCompose))
|
||||
}
|
@ -85,10 +85,12 @@ import { Router } from 'oak';
|
||||
|
||||
const app = new CGGService({ prefix: '/${serviceName}' });
|
||||
|
||||
app.route(new Router());
|
||||
app.route(new Router()
|
||||
.get('/', ctx => ctx.response.body = '${serviceName} service')
|
||||
);
|
||||
|
||||
app.start();
|
||||
console.log('User service running on ' + Deno.args.at(0));
|
||||
console.log('${serviceName} service running on ' + Deno.args.at(0));
|
||||
`);
|
||||
await Deno.writeTextFile(serviceFile + 'perms', perms.map(p => p.denoPerm).join('\n'));
|
||||
await Deno.writeTextFile(serviceFile + 'prefix', serviceName);
|
||||
@ -100,16 +102,26 @@ ${port ? 'EXPOSE ' + port : ''}
|
||||
|
||||
WORKDIR /${serviceName}
|
||||
|
||||
ADD ./user-service .
|
||||
COPY ./deno.jsonc .
|
||||
COPY ./secrets.json .
|
||||
COPY ./key.txt .
|
||||
ADD ${serviceFile} .
|
||||
ADD ./deno.jsonc .
|
||||
ADD ./secrets.json .
|
||||
ADD ./key.txt .
|
||||
ADD ./common ./common
|
||||
ADD ./lib ./lib
|
||||
ADD ./middleware ./middleware
|
||||
|
||||
CMD ["run", "${perms.join('", "')}", main.ts${port ? `, "${port}"` : ''}]
|
||||
`);
|
||||
|
||||
const dockerCompose: any = parse(await Deno.readTextFile('./docker-compose.yml'));
|
||||
dockerCompose['services'][serviceName] = {
|
||||
build: {
|
||||
context: "./",
|
||||
dockerfile: serviceFile + 'Dockerfile'
|
||||
}
|
||||
}
|
||||
|
||||
await Deno.writeTextFile('./docker-compose.yml', stringify(dockerCompose))
|
||||
}
|
||||
|
||||
if (confirm('Does this service need DB access?'))
|
||||
|
@ -2,7 +2,7 @@
|
||||
"imports": {
|
||||
"oak": "https://deno.land/x/oak@v12.2.0/mod.ts",
|
||||
"mongoose": "npm:mongoose",
|
||||
"yaml": "npm:yaml",
|
||||
"yaml": "https://deno.land/std@0.186.0/yaml/mod.ts",
|
||||
"/": "./",
|
||||
"./": "./",
|
||||
"common/": "./common/",
|
||||
|
52
deno.lock
generated
52
deno.lock
generated
@ -348,6 +348,46 @@
|
||||
"https://deno.land/std@0.183.0/streams/writer_from_stream_writer.ts": "07c7ee025151a190f37fc42cbb01ff93afc949119ebddc6e0d0df14df1bf6950",
|
||||
"https://deno.land/std@0.183.0/streams/zip_readable_streams.ts": "a9d81aa451240f79230add674809dbee038d93aabe286e2d9671e66591fc86ca",
|
||||
"https://deno.land/std@0.183.0/types.d.ts": "dbaeb2c4d7c526db9828fc8df89d8aecf53b9ced72e0c4568f97ddd8cda616a4",
|
||||
"https://deno.land/std@0.186.0/_util/asserts.ts": "178dfc49a464aee693a7e285567b3d0b555dc805ff490505a8aae34f9cfb1462",
|
||||
"https://deno.land/std@0.186.0/bytes/copy.ts": "939d89e302a9761dcf1d9c937c7711174ed74c59eef40a1e4569a05c9de88219",
|
||||
"https://deno.land/std@0.186.0/io/buffer.ts": "17f4410eaaa60a8a85733e8891349a619eadfbbe42e2f319283ce2b8f29723ab",
|
||||
"https://deno.land/std@0.186.0/types.d.ts": "dbaeb2c4d7c526db9828fc8df89d8aecf53b9ced72e0c4568f97ddd8cda616a4",
|
||||
"https://deno.land/std@0.186.0/yaml/_dumper/dumper.ts": "a2c937a53a2b0473125a31a330334cc3f30e98fd82f8143bc225583d1260890b",
|
||||
"https://deno.land/std@0.186.0/yaml/_dumper/dumper_state.ts": "f0d0673ceea288334061ca34b63954c2bb5feb5bf6de5e4cfe9a942cdf6e5efe",
|
||||
"https://deno.land/std@0.186.0/yaml/_error.ts": "b59e2c76ce5a47b1b9fa0ff9f96c1dd92ea1e1b17ce4347ece5944a95c3c1a84",
|
||||
"https://deno.land/std@0.186.0/yaml/_loader/loader.ts": "04cf748a736a9b3a29bd3d4b3c77d81489f82cfe8391627fd6ba8327e1e8cec2",
|
||||
"https://deno.land/std@0.186.0/yaml/_loader/loader_state.ts": "0841870b467169269d7c2dfa75cd288c319bc06f65edd9e42c29e5fced91c7a4",
|
||||
"https://deno.land/std@0.186.0/yaml/_mark.ts": "dcd8585dee585e024475e9f3fe27d29740670fb64ebb970388094cad0fc11d5d",
|
||||
"https://deno.land/std@0.186.0/yaml/_state.ts": "ef03d55ec235d48dcfbecc0ab3ade90bfae69a61094846e08003421c2cf5cfc6",
|
||||
"https://deno.land/std@0.186.0/yaml/_type/binary.ts": "d34d8c8d8ed521e270cfede3401c425b971af4f6c69da1e2cb32b172d42c7da7",
|
||||
"https://deno.land/std@0.186.0/yaml/_type/bool.ts": "5bfa75da84343d45347b521ba4e5aeace9fe6f53447405290d53315a3fc20e66",
|
||||
"https://deno.land/std@0.186.0/yaml/_type/float.ts": "056bd3cb9c5586238b20517511014fb24b0e36f98f9f6073e12da308b6b9808a",
|
||||
"https://deno.land/std@0.186.0/yaml/_type/function.ts": "ff574fe84a750695302864e1c31b93f12d14ada4bde79a5f93197fc33ad17471",
|
||||
"https://deno.land/std@0.186.0/yaml/_type/int.ts": "563ad074f0fa7aecf6b6c3d84135bcc95a8269dcc15de878de20ce868fd773fa",
|
||||
"https://deno.land/std@0.186.0/yaml/_type/map.ts": "7b105e4ab03a361c61e7e335a0baf4d40f06460b13920e5af3fb2783a1464000",
|
||||
"https://deno.land/std@0.186.0/yaml/_type/merge.ts": "8192bf3e4d637f32567917f48bb276043da9cf729cf594e5ec191f7cd229337e",
|
||||
"https://deno.land/std@0.186.0/yaml/_type/mod.ts": "060e2b3d38725094b77ea3a3f05fc7e671fced8e67ca18e525be98c4aa8f4bbb",
|
||||
"https://deno.land/std@0.186.0/yaml/_type/nil.ts": "606e8f0c44d73117c81abec822f89ef81e40f712258c74f186baa1af659b8887",
|
||||
"https://deno.land/std@0.186.0/yaml/_type/omap.ts": "cfe59a294726f5cea705c39a61fd2b08199cf48f4ccd6b040cb550ec0f38d0a1",
|
||||
"https://deno.land/std@0.186.0/yaml/_type/pairs.ts": "0032fdfe57558d21696a4f8cf5b5cfd1f698743177080affc18629685c905666",
|
||||
"https://deno.land/std@0.186.0/yaml/_type/regexp.ts": "1ce118de15b2da43b4bd8e4395f42d448b731acf3bdaf7c888f40789f9a95f8b",
|
||||
"https://deno.land/std@0.186.0/yaml/_type/seq.ts": "95333abeec8a7e4d967b8c8328b269e342a4bbdd2585395549b9c4f58c8533a2",
|
||||
"https://deno.land/std@0.186.0/yaml/_type/set.ts": "f28ba44e632ef2a6eb580486fd47a460445eeddbdf1dbc739c3e62486f566092",
|
||||
"https://deno.land/std@0.186.0/yaml/_type/str.ts": "a67a3c6e429d95041399e964015511779b1130ea5889fa257c48457bd3446e31",
|
||||
"https://deno.land/std@0.186.0/yaml/_type/timestamp.ts": "706ea80a76a73e48efaeb400ace087da1f927647b53ad6f754f4e06d51af087f",
|
||||
"https://deno.land/std@0.186.0/yaml/_type/undefined.ts": "94a316ca450597ccbc6750cbd79097ad0d5f3a019797eed3c841a040c29540ba",
|
||||
"https://deno.land/std@0.186.0/yaml/_utils.ts": "26b311f0d42a7ce025060bd6320a68b50e52fd24a839581eb31734cd48e20393",
|
||||
"https://deno.land/std@0.186.0/yaml/mod.ts": "28ecda6652f3e7a7735ee29c247bfbd32a2e2fc5724068e9fd173ec4e59f66f7",
|
||||
"https://deno.land/std@0.186.0/yaml/parse.ts": "1fbbda572bf3fff578b6482c0d8b85097a38de3176bf3ab2ca70c25fb0c960ef",
|
||||
"https://deno.land/std@0.186.0/yaml/schema.ts": "96908b78dc50c340074b93fc1598d5e7e2fe59103f89ff81e5a49b2dedf77a67",
|
||||
"https://deno.land/std@0.186.0/yaml/schema/core.ts": "fa406f18ceedc87a50e28bb90ec7a4c09eebb337f94ef17468349794fa828639",
|
||||
"https://deno.land/std@0.186.0/yaml/schema/default.ts": "0047e80ae8a4a93293bc4c557ae8a546aabd46bb7165b9d9b940d57b4d88bde9",
|
||||
"https://deno.land/std@0.186.0/yaml/schema/extended.ts": "0784416bf062d20a1626b53c03380e265b3e39b9409afb9f4cb7d659fd71e60d",
|
||||
"https://deno.land/std@0.186.0/yaml/schema/failsafe.ts": "d219ab5febc43f770917d8ec37735a4b1ad671149846cbdcade767832b42b92b",
|
||||
"https://deno.land/std@0.186.0/yaml/schema/json.ts": "5f41dd7c2f1ad545ef6238633ce9ee3d444dfc5a18101e1768bd5504bf90e5e5",
|
||||
"https://deno.land/std@0.186.0/yaml/schema/mod.ts": "4472e827bab5025e92bc2eb2eeefa70ecbefc64b2799b765c69af84822efef32",
|
||||
"https://deno.land/std@0.186.0/yaml/stringify.ts": "fffc09c65c68d3d63f8159e8cbaa3f489bc20a8e55b4fbb61a8c2e9f914d1d02",
|
||||
"https://deno.land/std@0.186.0/yaml/type.ts": "1aabb8e0a3f4229ce0a3526256f68826d9bdf65a36c8a3890ead8011fcba7670",
|
||||
"https://deno.land/std@0.61.0/encoding/utf8.ts": "8654fa820aa69a37ec5eb11908e20b39d056c9bf1c23ab294303ff467f3d50a1",
|
||||
"https://deno.land/std@0.93.0/_util/assert.ts": "2f868145a042a11d5ad0a3c748dcf580add8a0dbc0e876eaa0026303a5488f58",
|
||||
"https://deno.land/std@0.93.0/_util/os.ts": "e282950a0eaa96760c0cf11e7463e66babd15ec9157d4c9ed49cc0925686f6a7",
|
||||
@ -440,6 +480,18 @@
|
||||
"https://deno.land/x/crypt@v0.1.0/src/base64.ts": "a9df3135c7b3ddedb4a839715f69b029dd322b342589df079e0c660e39bb3088",
|
||||
"https://deno.land/x/crypt@v0.1.0/src/bcrypt/bcrypt.ts": "ba4c04eefba74415d094d57f08694fdc71b552956241d5a442cd167fd828a1af",
|
||||
"https://deno.land/x/crypt@v0.1.0/src/bcrypt/mod.ts": "8ed6d792a8fa46568933a09339ea6e322aad12ac2a961caf1365c95333ad68da",
|
||||
"https://deno.land/x/crypto@v0.10.0/aes.ts": "0f4e5af07514a07d56ec01b2186c0153f13d6e00c26fc4e70692996af6280e48",
|
||||
"https://deno.land/x/crypto@v0.10.0/block-modes.ts": "a7ef359649a2cf235451e80aed7a5fda612d92ca2b158bf2a724b32899f8e455",
|
||||
"https://deno.land/x/crypto@v0.10.0/src/aes/consts.ts": "582aeed7afda2fe3deac4a60c4a9f29c60a7fb66f56645f95fa0ddab49bde994",
|
||||
"https://deno.land/x/crypto@v0.10.0/src/aes/mod.ts": "afa8c53d140a4f5c12d17ed03aef7f7d3186b3848f7ff4c73e9e758bba47b101",
|
||||
"https://deno.land/x/crypto@v0.10.0/src/block-modes/base.ts": "ed96f69c0855ffc2d34ffbab293ac131dd4fd3d24e6d8ccd86e2a2f9f898c9b5",
|
||||
"https://deno.land/x/crypto@v0.10.0/src/block-modes/cbc.ts": "ce1ae944dd1912febd1d69c26c3a4ba18caeac9544ac3c62abd8b2429842de19",
|
||||
"https://deno.land/x/crypto@v0.10.0/src/block-modes/cfb.ts": "95b937293e9daebd336370fd954a3c53e47853fc81e1574db1ea4f31c6eb4663",
|
||||
"https://deno.land/x/crypto@v0.10.0/src/block-modes/ctr.ts": "06fd8e338dbda0a6a7fa49718a0fd247830759820e61646a6cf611ad69a9d464",
|
||||
"https://deno.land/x/crypto@v0.10.0/src/block-modes/ecb.ts": "c346d692f16f8efbcc041c25dd761ca223ef92e03bb05457908953bf261ba325",
|
||||
"https://deno.land/x/crypto@v0.10.0/src/block-modes/mod.ts": "bb7e3ddafa15b1ca024b4b5013b23d134410d01e90ce3d5be5489eb9d5f601c5",
|
||||
"https://deno.land/x/crypto@v0.10.0/src/block-modes/ofb.ts": "0f77075505853b4ba1a55b4edecb17323f8a1489456a3d3b74717565cccbf2ef",
|
||||
"https://deno.land/x/crypto@v0.10.0/src/utils/padding.ts": "db60b542bf7629fada4a9b92dbae7fcfc7d074a325f3b4e6d5a269b16546aa9b",
|
||||
"https://deno.land/x/djwt@v2.8/algorithm.ts": "fa4c7354ab9f4808d38104fdc6f21c8270f65f109ed84136d4fe31a4504426d4",
|
||||
"https://deno.land/x/djwt@v2.8/deps.ts": "261b7b6bfe2602329d8f9de2938c2a898cd6dfa746b3454ae415df2c53e6ae4d",
|
||||
"https://deno.land/x/djwt@v2.8/mod.ts": "7abba8518688e88648882a95161b42391ac6043c142b1ab491b36f712189e1e1",
|
||||
|
@ -1,6 +1,6 @@
|
||||
version: '3.9'
|
||||
services:
|
||||
nginx:
|
||||
nginx:
|
||||
image: 'jc21/nginx-proxy-manager:latest'
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
@ -8,10 +8,17 @@ services:
|
||||
- '81:81'
|
||||
- '443:443'
|
||||
volumes:
|
||||
- ./data:/data
|
||||
- ./letsencrypt:/etc/letsencrypt
|
||||
- './data:/data'
|
||||
- './letsencrypt:/etc/letsencrypt'
|
||||
user:
|
||||
build:
|
||||
build:
|
||||
context: ./
|
||||
dockerfile: ./user-service/Dockerfile
|
||||
|
||||
rules:
|
||||
build:
|
||||
context: ./
|
||||
dockerfile: ./rules-service/Dockerfile
|
||||
game-systems:
|
||||
build:
|
||||
context: ./
|
||||
dockerfile: ./game-systems-service/Dockerfile
|
||||
|
@ -4,7 +4,7 @@ EXPOSE 6903
|
||||
|
||||
WORKDIR /game-systems
|
||||
|
||||
ADD ./user-service .
|
||||
ADD ./game-systems-service/ .
|
||||
COPY ./deno.jsonc .
|
||||
COPY ./secrets.json .
|
||||
COPY ./key.txt .
|
||||
@ -12,4 +12,4 @@ ADD ./common ./common
|
||||
ADD ./lib ./lib
|
||||
ADD ./middleware ./middleware
|
||||
|
||||
CMD ["run", "--allow-net", "--allow-read", "--allow-write", main.ts, "6903"]
|
||||
CMD ["run", "--allow-net", "--allow-read", "--allow-write", "--allow-env", "main.ts", "6903"]
|
||||
|
1
game-systems-service/key.txt
Normal file
1
game-systems-service/key.txt
Normal file
@ -0,0 +1 @@
|
||||
{"kty":"oct","k":"8Wrvb6Sb0XTbL-qklscCDurI-yynKakHa6rGISTEgM77Za1cSvcWuOkWPNoaf395sEo1_uxe071IR2v6K4nfr5jbXQL20aGIcvhZeuBm-ATTZNvNuUqHTuRNJyFyw9hqUEQ62W-WvX78L15HCVFSuGd21WCHxtsJ9oUofPXto34","alg":"HS512","key_ops":["sign","verify"],"ext":true}
|
@ -4,7 +4,9 @@ import { Router } from 'oak';
|
||||
|
||||
const app = new CGGService({ prefix: '/game-systems' });
|
||||
|
||||
app.route(new Router());
|
||||
app.route(new Router()
|
||||
.get('/', ctx => ctx.response.body = 'game-systems service')
|
||||
);
|
||||
|
||||
app.start();
|
||||
console.log('User service running on ' + Deno.args.at(0));
|
||||
console.log('game-systems service running on ' + Deno.args.at(0));
|
||||
|
@ -1,3 +1,4 @@
|
||||
--allow-net
|
||||
--allow-read
|
||||
--allow-write
|
||||
--allow-write
|
||||
--allow-env
|
55
game-systems-service/types/schema.ts
Normal file
55
game-systems-service/types/schema.ts
Normal file
@ -0,0 +1,55 @@
|
||||
import { JSONArray, JSONObject, searchJSON } from "../../lib/JSONSearch/jsonSearch.ts";
|
||||
|
||||
export interface ISchema {
|
||||
name: string;
|
||||
accolades: any; // TODO - populate with accolades schema type
|
||||
publicationRules: {
|
||||
name: string;
|
||||
isExtensible: boolean;
|
||||
// overwrites: boolean;
|
||||
canExtend: boolean;
|
||||
reviewRequired: boolean;
|
||||
corrections: {
|
||||
reviewRequired: boolean;
|
||||
preserveHistory: boolean;
|
||||
}
|
||||
}[]
|
||||
allowsListBuilding: boolean;
|
||||
listBuildingRules: any; // TODO - populate with list building rules schema type
|
||||
schemaProperties: Record<string, any>;
|
||||
}
|
||||
|
||||
// export type searchString = `${/[a-z]/i}`
|
||||
|
||||
export class GameSystemSchema<T extends JSONObject | JSONArray> implements ISchema {
|
||||
name: string;
|
||||
accolades: any;
|
||||
publicationRules: {
|
||||
name: string;
|
||||
isExtensible: boolean;
|
||||
// overwrites: boolean;
|
||||
canExtend: boolean;
|
||||
reviewRequired: boolean;
|
||||
corrections: {
|
||||
reviewRequired: boolean;
|
||||
preserveHistory: boolean;
|
||||
};
|
||||
}[];
|
||||
allowsListBuilding: boolean;
|
||||
listBuildingRules: any;
|
||||
|
||||
schemaProperties: Record<string, any>;
|
||||
|
||||
constructor(schemaJson: ISchema) {
|
||||
this.name = schemaJson.name;
|
||||
this.accolades = schemaJson.accolades;
|
||||
this.publicationRules = schemaJson.publicationRules;
|
||||
this.allowsListBuilding = schemaJson.allowsListBuilding;
|
||||
this.listBuildingRules = schemaJson.listBuildingRules;
|
||||
this.schemaProperties = schemaJson.schemaProperties;
|
||||
}
|
||||
|
||||
search(search: string, values: T) {
|
||||
return searchJSON(values, search);
|
||||
}
|
||||
}
|
292
game-systems-service/types/schemaTest.ts
Normal file
292
game-systems-service/types/schemaTest.ts
Normal file
@ -0,0 +1,292 @@
|
||||
import { GameSystemSchema } from "./schema.ts";
|
||||
|
||||
const schemaJson = [
|
||||
{
|
||||
"_id": "6454820f30920b2262cd6640",
|
||||
"index": 0,
|
||||
"guid": "52724d58-ce75-4743-b6a9-8ae02b4a7450",
|
||||
"isActive": false,
|
||||
"balance": "$1,008.96",
|
||||
"picture": "http://placehold.it/32x32",
|
||||
"age": 27,
|
||||
"eyeColor": "brown",
|
||||
"name": "Taylor Bell",
|
||||
"gender": "female",
|
||||
"company": "FROSNEX",
|
||||
"email": "taylorbell@frosnex.com",
|
||||
"phone": "+1 (857) 459-2766",
|
||||
"address": "787 Brooklyn Avenue, Hiko, Florida, 6808",
|
||||
"about": "Ad ad cupidatat ea irure Lorem fugiat laboris exercitation consectetur in ea et. Quis do enim labore velit tempor voluptate ipsum proident aliqua ex excepteur exercitation. Pariatur aute nisi commodo eiusmod velit. Sit eu proident do minim culpa nulla veniam. Ipsum proident tempor nostrud exercitation occaecat sit est laborum officia do.\r\n",
|
||||
"registered": "2020-11-14T02:52:36 +07:00",
|
||||
"latitude": -42.333547,
|
||||
"longitude": -158.109059,
|
||||
"tags": [
|
||||
"proident",
|
||||
"officia",
|
||||
"cillum",
|
||||
"proident",
|
||||
"tempor",
|
||||
"exercitation",
|
||||
"Lorem"
|
||||
],
|
||||
"friends": [
|
||||
{
|
||||
"id": 0,
|
||||
"name": "Fulton Greer"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Hubbard Glass"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Burt Carr"
|
||||
}
|
||||
],
|
||||
"greeting": "Hello, Taylor Bell! You have 1 unread messages.",
|
||||
"favoriteFruit": "banana"
|
||||
},
|
||||
{
|
||||
"_id": "6454820fc0e3a34b70195552",
|
||||
"index": 1,
|
||||
"guid": "8e71b785-ad4d-4e12-a513-7385a9ba8286",
|
||||
"isActive": true,
|
||||
"balance": "$1,911.49",
|
||||
"picture": "http://placehold.it/32x32",
|
||||
"age": 27,
|
||||
"eyeColor": "green",
|
||||
"name": "Dianna Howard",
|
||||
"gender": "female",
|
||||
"company": "ZILLANET",
|
||||
"email": "diannahoward@zillanet.com",
|
||||
"phone": "+1 (962) 507-2555",
|
||||
"address": "348 Woods Place, Floris, Oklahoma, 3814",
|
||||
"about": "Officia enim aute proident tempor culpa mollit exercitation nulla. Commodo culpa ipsum ex laboris. Consequat nisi est incididunt sunt occaecat qui exercitation deserunt non et tempor. Ipsum voluptate anim veniam irure ad aute id magna sit anim non consectetur ipsum proident. Magna officia exercitation exercitation pariatur laborum proident.\r\n",
|
||||
"registered": "2019-01-03T10:15:04 +07:00",
|
||||
"latitude": -22.630118,
|
||||
"longitude": 33.280088,
|
||||
"tags": [
|
||||
"aute",
|
||||
"nisi",
|
||||
"labore",
|
||||
"deserunt",
|
||||
"nisi",
|
||||
"dolore",
|
||||
"excepteur"
|
||||
],
|
||||
"friends": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Whitney Hanson"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Brewer Ball"
|
||||
}
|
||||
],
|
||||
"greeting": "Hello, Dianna Howard! You have 1 unread messages.",
|
||||
"favoriteFruit": "banana"
|
||||
},
|
||||
{
|
||||
"_id": "6454820f92d45ff55d79f55f",
|
||||
"index": 2,
|
||||
"guid": "bd42ca2d-3a82-4b80-82e6-43346611ba25",
|
||||
"isActive": false,
|
||||
"balance": "$2,100.03",
|
||||
"picture": "http://placehold.it/32x32",
|
||||
"age": 40,
|
||||
"eyeColor": "green",
|
||||
"name": "Montoya Sharp",
|
||||
"gender": "male",
|
||||
"company": "SENTIA",
|
||||
"email": "montoyasharp@sentia.com",
|
||||
"phone": "+1 (909) 447-3348",
|
||||
"address": "773 Homecrest Avenue, Brambleton, Maine, 4567",
|
||||
"about": "Mollit duis commodo reprehenderit commodo exercitation occaecat veniam in. Excepteur quis deserunt aliqua sit Lorem. Fugiat dolore nulla sint proident commodo ullamco consectetur. Fugiat do eiusmod adipisicing tempor cupidatat. Consectetur tempor magna ex officia aute eiusmod. Sunt ut laboris magna eiusmod commodo voluptate cupidatat in. Eiusmod aliqua proident aliquip ex tempor duis excepteur irure dolor cillum do.\r\n",
|
||||
"registered": "2014-09-21T03:51:32 +06:00",
|
||||
"latitude": 44.616264,
|
||||
"longitude": 12.645741,
|
||||
"tags": [
|
||||
"fugiat",
|
||||
"nulla",
|
||||
"nulla",
|
||||
"commodo",
|
||||
"amet",
|
||||
"enim",
|
||||
"anim"
|
||||
],
|
||||
"friends": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Wynn Mathews"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Love Cook"
|
||||
}
|
||||
],
|
||||
"greeting": "Hello, Montoya Sharp! You have 8 unread messages.",
|
||||
"favoriteFruit": "apple"
|
||||
},
|
||||
{
|
||||
"_id": "6454820f75a0b1fd48ee40d1",
|
||||
"index": 3,
|
||||
"guid": "385bb445-c07f-40d6-b7ab-42c9b4c88903",
|
||||
"isActive": false,
|
||||
"balance": "$1,883.35",
|
||||
"picture": "http://placehold.it/32x32",
|
||||
"age": 40,
|
||||
"eyeColor": "brown",
|
||||
"name": "Marsh Parrish",
|
||||
"gender": "male",
|
||||
"company": "SEALOUD",
|
||||
"email": "marshparrish@sealoud.com",
|
||||
"phone": "+1 (954) 529-2585",
|
||||
"address": "138 Ebony Court, Leeper, Federated States Of Micronesia, 9374",
|
||||
"about": "Tempor esse et officia velit do in minim est eu enim. Ut irure Lorem cillum Lorem consequat proident in deserunt. Duis deserunt sit culpa ad aliqua quis. Incididunt amet dolore nostrud minim.\r\n",
|
||||
"registered": "2020-12-30T01:05:12 +07:00",
|
||||
"latitude": 65.637405,
|
||||
"longitude": 24.894416,
|
||||
"tags": [
|
||||
"quis",
|
||||
"qui",
|
||||
"consequat",
|
||||
"esse",
|
||||
"incididunt",
|
||||
"aliquip",
|
||||
"commodo"
|
||||
],
|
||||
"friends": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Gayle Mccarty"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Janet Mcleod"
|
||||
}
|
||||
],
|
||||
"greeting": "Hello, Marsh Parrish! You have 1 unread messages.",
|
||||
"favoriteFruit": "apple"
|
||||
},
|
||||
{
|
||||
"_id": "6454820f750a53838f37a442",
|
||||
"index": 4,
|
||||
"guid": "e5f25407-cc91-4976-87c2-f222af9e4817",
|
||||
"isActive": false,
|
||||
"balance": "$1,749.38",
|
||||
"picture": "http://placehold.it/32x32",
|
||||
"age": 33,
|
||||
"eyeColor": "green",
|
||||
"name": "Elvira Salinas",
|
||||
"gender": "female",
|
||||
"company": "ENTHAZE",
|
||||
"email": "elvirasalinas@enthaze.com",
|
||||
"phone": "+1 (957) 446-2769",
|
||||
"address": "292 Dwight Street, Shrewsbury, Wyoming, 6008",
|
||||
"about": "Aute nostrud labore id dolor amet deserunt. Lorem Lorem aliquip Lorem laborum ad ad officia adipisicing magna amet ipsum est aliquip. Sunt excepteur nulla nisi in magna ut minim enim ipsum nisi magna exercitation pariatur. Eu in et do ad quis ex excepteur do occaecat labore. Labore nulla occaecat consequat aliquip fugiat culpa labore magna aliqua. Aliqua cillum in et aliquip cupidatat Lorem eu pariatur dolore velit. Sint minim irure nostrud qui laborum fugiat sunt ex.\r\n",
|
||||
"registered": "2018-07-31T10:42:54 +06:00",
|
||||
"latitude": -22.4115,
|
||||
"longitude": 3.726494,
|
||||
"tags": [
|
||||
"cupidatat",
|
||||
"duis",
|
||||
"laborum",
|
||||
"incididunt",
|
||||
"et",
|
||||
"in",
|
||||
"sit"
|
||||
],
|
||||
"friends": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Alta Romero"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Christian Carrillo"
|
||||
}
|
||||
],
|
||||
"greeting": "Hello, Elvira Salinas! You have 6 unread messages.",
|
||||
"favoriteFruit": "banana"
|
||||
},
|
||||
{
|
||||
"_id": "6454820f0aa22ca7285106c8",
|
||||
"index": 5,
|
||||
"guid": "9856b273-6ade-4847-8d8e-13b27b8ddb8b",
|
||||
"isActive": false,
|
||||
"balance": "$3,662.75",
|
||||
"picture": "http://placehold.it/32x32",
|
||||
"age": 23,
|
||||
"eyeColor": "blue",
|
||||
"name": "Pearlie Sims",
|
||||
"gender": "female",
|
||||
"company": "HONOTRON",
|
||||
"email": "pearliesims@honotron.com",
|
||||
"phone": "+1 (810) 452-2724",
|
||||
"address": "435 Cadman Plaza, Mooresburg, Kentucky, 4520",
|
||||
"about": "Consequat et quis laborum laborum enim cillum do quis officia pariatur. Pariatur consectetur cillum commodo cillum non tempor incididunt consectetur Lorem laborum nostrud. Ullamco non sunt fugiat eiusmod ea voluptate duis irure proident.\r\n",
|
||||
"registered": "2020-03-24T07:59:59 +06:00",
|
||||
"latitude": -58.432669,
|
||||
"longitude": -6.30611,
|
||||
"tags": [
|
||||
"sit",
|
||||
"minim",
|
||||
"ea",
|
||||
"anim",
|
||||
"sint",
|
||||
"culpa",
|
||||
"ea"
|
||||
],
|
||||
"friends": [
|
||||
{
|
||||
"id": 0,
|
||||
"name": "Goodman Holmes"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Francesca Bowers"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Mona Chapman"
|
||||
}
|
||||
],
|
||||
"greeting": "Hello, Pearlie Sims! You have 2 unread messages.",
|
||||
"favoriteFruit": "apple"
|
||||
}
|
||||
];
|
||||
|
||||
const SchemaSearch = new GameSystemSchema({
|
||||
name: 'Test Schema',
|
||||
accolades: '',
|
||||
allowsListBuilding: true,
|
||||
listBuildingRules: '',
|
||||
publicationRules: [],
|
||||
schemaProperties: {
|
||||
"_id": "id",
|
||||
"index": "number",
|
||||
"guid": "guid",
|
||||
"isActive": "boolean",
|
||||
"balance": "money",
|
||||
"picture": "string",
|
||||
"age": "number",
|
||||
"eyeColor": "string",
|
||||
"name": "string",
|
||||
"gender": "string",
|
||||
"company": "string",
|
||||
"email": "email",
|
||||
"phone": "phone",
|
||||
"address": "string",
|
||||
"about": "string",
|
||||
"registered": "date",
|
||||
"latitude": "number",
|
||||
"longitude": "number",
|
||||
"tags": ["string"],
|
||||
"friends": ['.'],
|
||||
"greeting": "string",
|
||||
"favoriteFruit": "string"
|
||||
}
|
||||
})
|
||||
|
||||
console.log(SchemaSearch.search('friends[id=0]', schemaJson));
|
@ -1,15 +0,0 @@
|
||||
|
||||
FROM denoland/deno:1.33.2
|
||||
EXPOSE 6902
|
||||
|
||||
WORKDIR /honors
|
||||
|
||||
ADD ./user-service .
|
||||
COPY ./deno.jsonc .
|
||||
COPY ./secrets.json .
|
||||
COPY ./key.txt .
|
||||
ADD ./common ./common
|
||||
ADD ./lib ./lib
|
||||
ADD ./middleware ./middleware
|
||||
|
||||
CMD ["run", "--allow-net", main.ts, "6902"]
|
@ -1,5 +0,0 @@
|
||||
|
||||
import mongoose from 'mongoose';
|
||||
import { configDatabase } from 'lib/data.ts';
|
||||
|
||||
configDatabase(mongoose);
|
@ -1,10 +0,0 @@
|
||||
|
||||
import { CGGService } from 'cgg/Application.ts';
|
||||
import { Router } from 'oak';
|
||||
|
||||
const app = new CGGService({ prefix: '/honors' });
|
||||
|
||||
app.route(new Router());
|
||||
|
||||
app.start();
|
||||
console.log('User service running on ' + Deno.args.at(0));
|
@ -1 +0,0 @@
|
||||
--allow-net
|
@ -1 +0,0 @@
|
||||
6902
|
@ -1 +0,0 @@
|
||||
honors
|
182
lib/JSONSearch/jsonSearch.ts
Normal file
182
lib/JSONSearch/jsonSearch.ts
Normal file
@ -0,0 +1,182 @@
|
||||
export type JSONObject = { [key: string]: any };
|
||||
export type JSONArray = JSONObject[];
|
||||
|
||||
export function searchJSON(json: string | JSONObject | JSONArray, query: string): string | JSONArray | JSONObject | string[] | undefined {
|
||||
if (typeof json === 'string') {
|
||||
json = JSON.parse(json);
|
||||
}
|
||||
|
||||
const props = query.split('.');
|
||||
const currentArray: JSONArray = Array.isArray(json) ? json : [json];
|
||||
|
||||
for (let i = 0; i < currentArray.length; i++) {
|
||||
let current = currentArray[i];
|
||||
|
||||
for (let j = 0; j < props.length; j++) {
|
||||
const prop = props[j];
|
||||
// let isArrayQuery = false;
|
||||
let arrayProp: string, arrayQuery: string | string[], arrayIndex: number;
|
||||
|
||||
if (prop.includes('[') && prop.includes(']')) {
|
||||
// isArrayQuery = true;
|
||||
[arrayProp, arrayQuery] = prop.split(/[\[\]]/g).filter(Boolean);
|
||||
|
||||
if (arrayQuery.includes('/')) {
|
||||
arrayQuery = arrayQuery.split('/');
|
||||
} else {
|
||||
arrayQuery = [arrayQuery];
|
||||
}
|
||||
|
||||
arrayIndex = 0;
|
||||
current = current[arrayProp][arrayIndex];
|
||||
while (current) {
|
||||
if (checkArrayQuery(current, arrayQuery)) {
|
||||
break;
|
||||
}
|
||||
current = current[arrayProp][++arrayIndex];
|
||||
}
|
||||
} else {
|
||||
current = current[prop];
|
||||
}
|
||||
|
||||
if (current === undefined) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (current !== undefined) {
|
||||
return current;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function checkArrayQuery(obj: JSONObject, queryArr: string[]): boolean {
|
||||
return queryArr.every((query) => {
|
||||
let [prop, operator, valueStr] = query.split(/([=!><]+)/);
|
||||
prop = obj[prop];
|
||||
const values = valueStr.split('/');
|
||||
|
||||
if (values.length > 1) {
|
||||
return values.includes(prop);
|
||||
}
|
||||
|
||||
switch (operator) {
|
||||
case'=':
|
||||
return areSimilar(prop, valueStr);
|
||||
case '==':
|
||||
return prop == valueStr;
|
||||
case '!=':
|
||||
return prop != valueStr;
|
||||
case '>':
|
||||
return prop > valueStr;
|
||||
case '>=':
|
||||
return prop >= valueStr;
|
||||
case '<':
|
||||
return prop < valueStr;
|
||||
case '<=':
|
||||
return prop <= valueStr;
|
||||
case '><':
|
||||
return includes(prop, valueStr);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function areSimilar<T extends string | number>(val1: T, val2: T, tolerance = .05, useRatio?: boolean): boolean {
|
||||
if ((typeof val1 === 'number' || isNaN(Number(val1))) && (typeof val2 === 'number' || isNaN(Number(val2)))) {
|
||||
switch (!useRatio || val2 == 0) {
|
||||
case true: {
|
||||
return Math.abs(Number(val1) - Number(val2)) < tolerance;
|
||||
}
|
||||
case false: {
|
||||
const ratio = Number(val1) / (Number(val2))
|
||||
return ratio >= 1 - tolerance && ratio <= 1 + tolerance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const v1 = val1.toString();
|
||||
const v2 = val2.toString();
|
||||
|
||||
const dist = levenshtein(v1, v2);
|
||||
const diff = dist / ((v1.length + v2.length) / 2);
|
||||
return useRatio ? diff <= 1 + tolerance && diff >= 1 - tolerance : diff <= Math.round(tolerance);
|
||||
}
|
||||
|
||||
function levenshtein(str1: string, str2: string): number {
|
||||
const cost: number[][] = [];
|
||||
const n = str1.length;
|
||||
const m = str2.length;
|
||||
let i, j;
|
||||
|
||||
const minimum = (a: number, b: number, c: number) => {
|
||||
let min = a;
|
||||
if (b < min) {
|
||||
min = b;
|
||||
}
|
||||
if (c < min) {
|
||||
min = c;
|
||||
}
|
||||
return min;
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
return Infinity;
|
||||
}
|
||||
if (m == 0) {
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
for (let i = 0; i <= n; i++) {
|
||||
cost[i] = [];
|
||||
}
|
||||
|
||||
for (i = 0; i <= n; i++) {
|
||||
cost[i][0] = i;
|
||||
}
|
||||
|
||||
for (j = 0; j <= m; j++) {
|
||||
cost[0][j] = j;
|
||||
}
|
||||
|
||||
for (i = 1; i <= n; i++) {
|
||||
|
||||
const x = str1.charAt(i - 1);
|
||||
|
||||
for (j = 1; j <= m; j++) {
|
||||
|
||||
const y = str2.charAt(j - 1);
|
||||
|
||||
if (x == y) {
|
||||
|
||||
cost[i][j] = cost[i - 1][j - 1];
|
||||
|
||||
} else {
|
||||
|
||||
cost[i][j] = 1 + minimum(cost[i - 1][j - 1], cost[i][j - 1], cost[i - 1][j]);
|
||||
}
|
||||
|
||||
}//endfor
|
||||
|
||||
}//endfor
|
||||
|
||||
return cost[n][m];
|
||||
}
|
||||
|
||||
function includes<T extends string | number>(val1: T | T[], val2: T) {
|
||||
if (Array.isArray(val1)) return val1.includes(val2);
|
||||
else {
|
||||
const v1 = val1.toString();
|
||||
const v2 = val2.toString();
|
||||
|
||||
return v1.includes(v2);
|
||||
}
|
||||
}
|
||||
|
||||
function normalize(val: any) {
|
||||
if (typeof val === 'string') return val.normalize();
|
||||
return val;
|
||||
}
|
23
lib/gsEncryption/index.ts
Normal file
23
lib/gsEncryption/index.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import {Aes} from "https://deno.land/x/crypto@v0.10.0/aes.ts";
|
||||
import {Cbc, Padding} from "https://deno.land/x/crypto@v0.10.0/block-modes.ts";
|
||||
|
||||
const te = new TextEncoder();
|
||||
|
||||
const key = te.encode("EmmaHasHugeTitts");
|
||||
const data = te.encode("DataToBeEncrypted");
|
||||
const iv = new Uint8Array(16);
|
||||
|
||||
const cipher = new Cbc(Aes, key, iv, Padding.PKCS7)
|
||||
const decipher = new Cbc(Aes, key, iv, Padding.PKCS7)
|
||||
|
||||
const encrypted = cipher.encrypt(data);
|
||||
const decrypted = decipher.decrypt(encrypted);
|
||||
|
||||
console.decode = function (encoded: Uint8Array) {
|
||||
const td = new TextDecoder();
|
||||
this.log(td.decode(encoded));
|
||||
}
|
||||
|
||||
console.decode(data);
|
||||
console.decode(encrypted);
|
||||
console.decode(decrypted);
|
@ -4,7 +4,7 @@ let key: CryptoKey;
|
||||
try {
|
||||
const storedKey = Deno.readTextFileSync('./key.txt');
|
||||
key = await crypto.subtle.importKey('jwk', JSON.parse(storedKey), {name: 'HMAC', hash: 'SHA-512'}, true, ['sign', 'verify']);
|
||||
} catch (error) {
|
||||
} catch (_) {
|
||||
key = await crypto.subtle.generateKey(
|
||||
{ name: "HMAC", hash: {name: 'SHA-512'} },
|
||||
true,
|
||||
|
14
project-warstone/.eslintrc.cjs
Normal file
14
project-warstone/.eslintrc.cjs
Normal file
@ -0,0 +1,14 @@
|
||||
module.exports = {
|
||||
env: { browser: true, es2020: true },
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:react-hooks/recommended',
|
||||
],
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
|
||||
plugins: ['react-refresh'],
|
||||
rules: {
|
||||
'react-refresh/only-export-components': 'warn',
|
||||
},
|
||||
}
|
24
project-warstone/.gitignore
vendored
Normal file
24
project-warstone/.gitignore
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
13
project-warstone/index.html
Normal file
13
project-warstone/index.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/battlelog icon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>BattleLog</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
34
project-warstone/package.json
Normal file
34
project-warstone/package.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "project-warstone",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build",
|
||||
"lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/react-router-dom": "^5.3.3",
|
||||
"autoprefixer": "^10.4.14",
|
||||
"postcss": "^8.4.24",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-router-dom": "^6.12.0",
|
||||
"recoil": "^0.7.7",
|
||||
"tailwindcss": "^3.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.0.37",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"@typescript-eslint/eslint-plugin": "^5.59.0",
|
||||
"@typescript-eslint/parser": "^5.59.0",
|
||||
"@vitejs/plugin-react-swc": "^3.0.0",
|
||||
"eslint": "^8.38.0",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-react-refresh": "^0.3.4",
|
||||
"typescript": "^5.0.2",
|
||||
"vite": "^4.3.9"
|
||||
}
|
||||
}
|
6
project-warstone/postcss.config.js
Normal file
6
project-warstone/postcss.config.js
Normal file
@ -0,0 +1,6 @@
|
||||
export default {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
394
project-warstone/public/battlelog icon.svg
Normal file
394
project-warstone/public/battlelog icon.svg
Normal file
@ -0,0 +1,394 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="36.50486mm"
|
||||
height="36.50486mm"
|
||||
viewBox="0 0 36.50486 36.50486"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
sodipodi:docname="battlelog icon.svg"
|
||||
inkscape:export-filename="C:\Users\ironi\Pictures\battlelog.png"
|
||||
inkscape:export-xdpi="138.39"
|
||||
inkscape:export-ydpi="138.39"
|
||||
inkscape:version="1.0 (4035a4fb49, 2020-05-01)">
|
||||
<defs
|
||||
id="defs2">
|
||||
<marker
|
||||
inkscape:isstock="true"
|
||||
style="overflow:visible"
|
||||
id="Arrow1Sstart"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow1Sstart">
|
||||
<path
|
||||
transform="matrix(0.2,0,0,0.2,1.2,0)"
|
||||
style="fill:#35185a;fill-opacity:1;fill-rule:evenodd;stroke:#35185a;stroke-width:1pt;stroke-opacity:1"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
id="path993" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:isstock="true"
|
||||
style="overflow:visible"
|
||||
id="marker1259"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow1Lstart">
|
||||
<path
|
||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
||||
style="fill:#35185a;fill-opacity:1;fill-rule:evenodd;stroke:#35185a;stroke-width:1pt;stroke-opacity:1"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
id="path1257" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:isstock="true"
|
||||
style="overflow:visible"
|
||||
id="Arrow1Lstart"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow1Lstart">
|
||||
<path
|
||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
||||
style="fill:#35185a;fill-opacity:1;fill-rule:evenodd;stroke:#35185a;stroke-width:1pt;stroke-opacity:1"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 Z"
|
||||
id="path981" />
|
||||
</marker>
|
||||
<inkscape:path-effect
|
||||
effect="mirror_symmetry"
|
||||
start_point="24.197977,13.799948"
|
||||
end_point="24.197977,15.24464"
|
||||
center_point="24.197977,14.522294"
|
||||
id="path-effect933"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
mode="free"
|
||||
discard_orig_path="false"
|
||||
fuse_paths="false"
|
||||
oposite_fuse="false"
|
||||
split_items="false" />
|
||||
<inkscape:path-effect
|
||||
split_items="false"
|
||||
oposite_fuse="false"
|
||||
fuse_paths="false"
|
||||
discard_orig_path="false"
|
||||
mode="free"
|
||||
lpeversion="1"
|
||||
is_visible="true"
|
||||
id="path-effect898"
|
||||
center_point="24.087931,14.05635"
|
||||
end_point="24.087931,17.323464"
|
||||
start_point="24.087931,10.789236"
|
||||
effect="mirror_symmetry" />
|
||||
<inkscape:path-effect
|
||||
hide_knots="false"
|
||||
only_selected="false"
|
||||
apply_with_radius="true"
|
||||
apply_no_radius="true"
|
||||
use_knot_distance="true"
|
||||
flexible="false"
|
||||
chamfer_steps="1"
|
||||
radius="0"
|
||||
mode="F"
|
||||
method="auto"
|
||||
unit="px"
|
||||
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.9337788,0,1 @ F,0,0,1,0,0.70814436,0,1 @ F,0,0,1,0,0,0,1"
|
||||
lpeversion="1"
|
||||
is_visible="true"
|
||||
id="path-effect896"
|
||||
effect="fillet_chamfer" />
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect875"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.9337788,0,1 @ F,0,0,1,0,0.70814436,0,1 @ F,0,0,1,0,0,0,1"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
radius="0"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
effect="mirror_symmetry"
|
||||
start_point="24.087931,10.789236"
|
||||
end_point="24.087931,17.323464"
|
||||
center_point="24.087931,14.05635"
|
||||
id="path-effect873"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
mode="free"
|
||||
discard_orig_path="false"
|
||||
fuse_paths="false"
|
||||
oposite_fuse="false"
|
||||
split_items="false" />
|
||||
<inkscape:path-effect
|
||||
effect="mirror_symmetry"
|
||||
start_point="15.2,12.19"
|
||||
end_point="0,18.82"
|
||||
center_point="7.6,15.505"
|
||||
id="path-effect869"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
mode="free"
|
||||
discard_orig_path="false"
|
||||
fuse_paths="false"
|
||||
oposite_fuse="false"
|
||||
split_items="false" />
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : -108.11874 : 1"
|
||||
inkscape:vp_y="0 : 999.99993 : 0"
|
||||
inkscape:vp_z="210 : -108.11874 : 1"
|
||||
inkscape:persp3d-origin="105 : -157.61873 : 1"
|
||||
id="perspective841" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="8"
|
||||
inkscape:cx="74.035737"
|
||||
inkscape:cy="76.334249"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:document-rotation="0"
|
||||
showgrid="false"
|
||||
inkscape:window-width="3440"
|
||||
inkscape:window-height="1369"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="1432"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-10.381405,6.5569707)">
|
||||
<path
|
||||
sodipodi:open="true"
|
||||
d="M 45.469057,11.723468 A 16.835245,16.835245 0 0 1 28.637202,28.530704 16.835245,16.835245 0 0 1 11.798626,11.730202 16.835245,16.835245 0 0 1 28.567716,-5.1396559 16.835245,16.835245 0 0 1 45.468798,11.597965"
|
||||
sodipodi:arc-type="arc"
|
||||
sodipodi:end="6.2773942"
|
||||
sodipodi:start="0.0016637066"
|
||||
sodipodi:ry="16.835245"
|
||||
sodipodi:rx="16.835245"
|
||||
sodipodi:cy="11.695459"
|
||||
sodipodi:cx="28.633835"
|
||||
sodipodi:type="arc"
|
||||
id="path979"
|
||||
style="font-variation-settings:'wght' 700;mix-blend-mode:normal;fill:#688e26;fill-opacity:1;stroke:#35185a;stroke-width:2.834;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;paint-order:stroke fill markers" />
|
||||
<path
|
||||
style="fill:#35185a;fill-opacity:0;stroke:#35185a;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 24.087931,10.789236 h -10.41137 c -0.859457,0 -1.396618,0.93039 -0.966889,1.674701 l 2.451577,4.246256 c 0.2191,0.379493 0.624015,0.613271 1.062216,0.613271 h 7.864466 m 0,-6.534228 h 10.41137 c 0.859457,0 1.396618,0.93039 0.966889,1.674701 l -2.451577,4.246256 c -0.2191,0.379493 -0.624015,0.613271 -1.062216,0.613271 h -7.864466"
|
||||
id="path863"
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:original-d="M 24.087931,10.789236 H 11.742782 l 3.772539,6.534228 h 8.57261"
|
||||
inkscape:path-effect="#path-effect875;#path-effect873"
|
||||
transform="matrix(1,0,0,0.68612415,0,3.7150793)"
|
||||
inkscape:export-xdpi="73.4646"
|
||||
inkscape:export-ydpi="73.4646" />
|
||||
<path
|
||||
inkscape:path-effect="#path-effect896;#path-effect898"
|
||||
inkscape:original-d="M 24.087931,10.789236 H 11.742782 l 3.772539,6.534228 h 8.57261"
|
||||
sodipodi:nodetypes="cccc"
|
||||
id="path863-8"
|
||||
d="m 24.087931,10.789236 h -10.41137 c -0.859457,0 -1.396618,0.93039 -0.966889,1.674701 l 2.451577,4.246256 c 0.2191,0.379493 0.624015,0.613271 1.062216,0.613271 h 7.864466 m 0,-6.534228 h 10.41137 c 0.859457,0 1.396618,0.93039 0.966889,1.674701 l -2.451577,4.246256 c -0.2191,0.379493 -0.624015,0.613271 -1.062216,0.613271 h -7.864466"
|
||||
style="fill:none;fill-opacity:1;stroke:#35185a;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
transform="matrix(-0.67499607,0,0,-0.40562746,40.347189,15.060924)"
|
||||
inkscape:export-xdpi="73.4646"
|
||||
inkscape:export-ydpi="73.4646" />
|
||||
<g
|
||||
id="g931"
|
||||
inkscape:path-effect="#path-effect933"
|
||||
transform="matrix(0.98544691,0,0,0.98544691,0.21734233,0.22302668)"
|
||||
inkscape:export-xdpi="73.4646"
|
||||
inkscape:export-ydpi="73.4646">
|
||||
<path
|
||||
d="m 17.89465,13.809577 c 0,0.516139 -0.275356,0.99307 -0.722345,1.25114 -0.44699,0.258069 -0.997703,0.258069 -1.444692,0 -0.446989,-0.25807 -0.722346,-0.735001 -0.722346,-1.25114 h 1.444692 z m 12.606654,0 c 0,0.516139 0.275356,0.99307 0.722345,1.25114 0.44699,0.258069 0.997703,0.258069 1.444692,0 0.446989,-0.25807 0.722346,-0.735001 0.722346,-1.25114 h -1.444692 z"
|
||||
sodipodi:arc-type="slice"
|
||||
sodipodi:end="3.1415927"
|
||||
sodipodi:start="0"
|
||||
sodipodi:ry="1.4446917"
|
||||
sodipodi:rx="1.4446917"
|
||||
sodipodi:cy="13.809577"
|
||||
sodipodi:cx="16.449959"
|
||||
sodipodi:type="arc"
|
||||
id="path906"
|
||||
style="fill:none;fill-opacity:1;stroke:#35185a;stroke-width:0.141635;stroke-linecap:round;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;stroke:#35185a;stroke-width:0.141635;stroke-linecap:round;stroke-opacity:1"
|
||||
id="path908"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="19.547373"
|
||||
sodipodi:cy="13.809577"
|
||||
sodipodi:rx="1.4446917"
|
||||
sodipodi:ry="1.4446917"
|
||||
sodipodi:start="0"
|
||||
sodipodi:end="3.1415927"
|
||||
sodipodi:arc-type="slice"
|
||||
d="m 20.992064,13.809577 c 0,0.516139 -0.275356,0.99307 -0.722345,1.25114 -0.44699,0.258069 -0.997703,0.258069 -1.444692,0 -0.446989,-0.25807 -0.722346,-0.735001 -0.722346,-1.25114 h 1.444692 z m 6.411826,0 c 0,0.516139 0.275356,0.99307 0.722345,1.25114 0.44699,0.258069 0.997703,0.258069 1.444692,0 0.446989,-0.25807 0.722346,-0.735001 0.722346,-1.25114 h -1.444692 z" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;stroke:#35185a;stroke-width:0.141635;stroke-linecap:round;stroke-opacity:1"
|
||||
id="path906-6"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="22.64736"
|
||||
sodipodi:cy="13.809577"
|
||||
sodipodi:rx="1.4446917"
|
||||
sodipodi:ry="1.4446917"
|
||||
sodipodi:start="0"
|
||||
sodipodi:end="3.1415927"
|
||||
sodipodi:arc-type="slice"
|
||||
d="m 24.092052,13.809577 c 0,0.516139 -0.275357,0.99307 -0.722346,1.25114 -0.44699,0.258069 -0.997703,0.258069 -1.444692,0 -0.446989,-0.25807 -0.722346,-0.735001 -0.722346,-1.25114 h 1.444692 z m 0.21185,0 c 0,0.516139 0.275357,0.99307 0.722346,1.25114 0.44699,0.258069 0.997703,0.258069 1.444692,0 0.446989,-0.25807 0.722346,-0.735001 0.722346,-1.25114 h -1.444692 z" />
|
||||
</g>
|
||||
<path
|
||||
style="fill:#35185a;fill-opacity:0;stroke:none;stroke-width:0.0194533;stroke-linecap:round;stroke-opacity:1"
|
||||
d="m 60.839149,58.589236 c -1.142597,-0.09331 -2.207846,-0.524549 -2.865794,-1.160143 -0.164868,-0.159266 -9.292094,-10.983964 -9.574525,-11.355184 -0.303686,-0.399159 -0.429649,-0.784273 -0.407842,-1.24693 0.02282,-0.484087 0.202576,-0.868101 0.604522,-1.291417 0.519984,-0.547631 1.227896,-0.90187 2.168345,-1.085038 l 0.295953,-0.05764 39.786475,-0.0083 c 28.413597,-0.0059 39.871077,-3.06e-4 40.082427,0.0196 1.59021,0.149734 2.88448,1.030138 3.1288,2.128311 0.064,0.287534 0.041,0.70402 -0.053,0.959883 -0.0807,0.21978 -0.20788,0.448223 -0.34436,0.618695 -0.37269,0.465523 -9.39015,11.162257 -9.51235,11.283792 -0.59012,0.586881 -1.43643,0.971191 -2.5609,1.162906 -0.25853,0.04408 -1.57262,0.04621 -30.380295,0.04927 -16.560541,0.0018 -30.225883,-0.0063 -30.367426,-0.01782 z m 1.892205,-0.693177 c 1.008145,-0.122025 1.965943,-0.505487 2.769287,-1.108705 1.398597,-1.050184 2.247639,-2.766897 2.248296,-4.545924 l 8.8e-5,-0.23805 h -5.66568 -5.665681 l 0.01764,0.391024 c 0.05254,1.164265 0.348408,2.10567 0.943301,3.001412 0.450649,0.678551 0.957482,1.181334 1.641025,1.627914 0.656227,0.428733 1.524566,0.751701 2.307597,0.858282 0.312297,0.04251 1.103588,0.05042 1.404122,0.01405 z m 11.631318,-0.01425 c 2.380346,-0.308828 4.328704,-2.122817 4.797814,-4.466928 0.08253,-0.412383 0.117867,-0.746555 0.117867,-1.114535 V 52.00338 h -5.652464 -5.652464 l 0.01436,0.482533 c 0.0252,0.846558 0.204316,1.562125 0.577733,2.308009 0.733555,1.465242 2.038375,2.529854 3.609942,2.945379 0.269923,0.07137 0.646012,0.142633 0.874994,0.165803 0.26769,0.02709 1.027925,0.01359 1.312215,-0.02329 z m 11.453072,0.01425 c 0.815059,-0.09865 1.673408,-0.397143 2.328353,-0.809679 0.936578,-0.58993 1.627766,-1.35301 2.09824,-2.316476 0.372578,-0.762994 0.545448,-1.465359 0.582666,-2.36737 l 0.01647,-0.399154 H 85.171691 79.50191 l 0.01647,0.399154 c 0.03559,0.862436 0.206056,1.581879 0.542645,2.290165 0.453782,0.954897 1.113697,1.712994 2.008267,2.307058 0.697991,0.46352 1.575372,0.787429 2.420418,0.893562 0.256726,0.03224 1.068429,0.03392 1.326032,0.0027 z m 11.555063,-5.61e-4 c 2.146627,-0.265348 3.915343,-1.660422 4.664213,-3.678899 0.19636,-0.529259 0.31295,-1.1475 0.34336,-1.820758 l 0.0177,-0.392461 h -5.66946 -5.669465 l 0.01568,0.431063 c 0.05273,1.449779 0.594152,2.738041 1.584253,3.769587 0.876777,0.913477 2.040853,1.501682 3.323321,1.679267 0.300867,0.04166 1.095621,0.04864 1.39037,0.0122 z m 11.623843,-0.0124 c 1.01975,-0.132136 1.99984,-0.549097 2.81288,-1.196683 0.27722,-0.220806 0.76521,-0.721231 0.96908,-0.993779 0.71924,-0.961501 1.09835,-2.041839 1.13433,-3.232462 l 0.0138,-0.456798 h -5.65597 -5.65597 l 0.0144,0.469666 c 0.008,0.258316 0.0329,0.573893 0.0556,0.701281 0.22055,1.240496 0.75206,2.267533 1.61433,3.119355 0.47106,0.465362 0.90861,0.775375 1.50126,1.063687 0.56005,0.27245 1.12606,0.445669 1.71139,0.523747 0.37176,0.04959 1.10988,0.05058 1.48488,0.002 z m 11.78156,-0.03469 c 0.61118,-0.116373 1.06271,-0.268848 1.5953,-0.538703 1.30497,-0.661211 2.30356,-1.808851 2.77725,-3.191771 0.19454,-0.567968 0.28436,-1.08441 0.30844,-1.773565 l 0.0119,-0.34099 h -5.66362 -5.66362 l 0.0153,0.431063 c 0.0315,0.887454 0.20855,1.597065 0.58916,2.361018 0.84016,1.686402 2.41501,2.813001 4.3185,3.089342 0.37416,0.05432 1.34319,0.03371 1.71138,-0.03639 z"
|
||||
id="path969"
|
||||
inkscape:export-xdpi="73.4646"
|
||||
inkscape:export-ydpi="73.4646"
|
||||
transform="scale(0.26458333)" />
|
||||
<path
|
||||
style="fill:#35185a;fill-opacity:1;stroke:#35185a;stroke-width:0.0334066;stroke-linecap:round;stroke-opacity:1"
|
||||
d="m 100.5298,41.981141 c -15.624906,0.01072 -31.249865,-0.0041 -46.87473,0.03578 -1.039624,0.02394 -2.085658,-0.02858 -3.121051,0.07082 -1.128071,0.253419 -2.271734,0.891143 -2.765762,1.983041 -0.350827,0.789345 -0.149624,1.741198 0.426068,2.370074 3.094249,3.685534 6.1823,7.376726 9.294838,11.046656 1.013733,1.089552 2.555503,1.567043 4.016404,1.485543 18.562036,0.0075 37.124099,0.01 55.686123,-0.01317 1.57941,-0.0197 3.16164,0.02202 4.73914,-0.06135 0.77035,-0.173856 1.56199,-0.439035 2.16646,-0.965367 1.1499,-1.142589 2.14504,-2.429187 3.20549,-3.653012 2.27089,-2.708381 4.56936,-5.394841 6.80216,-8.134489 0.47225,-0.673634 0.53862,-1.616338 0.0802,-2.315101 -0.45116,-0.73531 -1.17253,-1.285495 -1.99473,-1.544267 -1.06727,-0.405663 -2.22377,-0.248963 -3.33774,-0.288028 -9.44091,-0.02587 -18.88192,-0.01553 -28.32286,-0.01713 z M 62.094507,52.408549 c 1.752373,0 3.504747,0 5.257121,0 -0.05169,1.287348 -0.547297,2.55812 -1.456941,3.486161 -0.945084,1.003235 -2.336883,1.658468 -3.74105,1.616894 -2.346997,0.118464 -4.598872,-1.63866 -5.146726,-3.908776 -0.09935,-0.390635 -0.15444,-0.791875 -0.173669,-1.194279 1.753755,0 3.50751,0 5.261265,0 z m 11.533298,0 c 1.753053,0.0063 3.531929,-0.01256 5.268861,0.0094 -0.07169,1.339475 -0.605662,2.683303 -1.604948,3.600743 -0.768085,0.80005 -1.827263,1.310518 -2.921807,1.458995 -0.919685,0.0846 -1.87546,0.05785 -2.729118,-0.334846 -1.530359,-0.617907 -2.751312,-2.008172 -3.113531,-3.609593 -0.08871,-0.367145 -0.13874,-0.754103 -0.154076,-1.124708 1.75154,0 3.503079,0 5.254619,0 z m 11.550648,0 c 1.751942,0 3.503884,0 5.255826,0 -0.05498,1.880385 -1.165573,3.705954 -2.861963,4.545159 -0.768407,0.399974 -1.634067,0.597168 -2.500464,0.559873 -1.256844,0.02309 -2.49985,-0.501542 -3.429106,-1.334716 -0.788675,-0.748594 -1.401404,-1.708488 -1.605405,-2.797094 -0.06751,-0.319956 -0.113137,-0.645786 -0.115406,-0.973222 1.752173,0 3.504345,0 5.256518,0 z m 11.534162,0 c 1.750876,0 3.501755,0 5.252635,0 -6.7e-4,1.940214 -1.21507,3.791409 -2.967571,4.607675 -0.941185,0.48259 -2.026519,0.564517 -3.063642,0.463952 -1.847899,-0.284921 -3.516587,-1.59356 -4.136978,-3.371687 -0.199979,-0.544441 -0.306335,-1.121052 -0.331295,-1.69994 1.748949,0 3.497902,0 5.246851,0 z m 11.552715,0 c 1.75353,0 3.50706,0 5.26058,0 -0.0483,1.339478 -0.57179,2.630046 -1.5304,3.568162 -0.9346,0.944584 -2.2401,1.549748 -3.57986,1.53086 -0.84134,0.08077 -1.67576,-0.162821 -2.44134,-0.492728 -1.03601,-0.51283 -1.89442,-1.383754 -2.42386,-2.409705 -0.34363,-0.687548 -0.49716,-1.446492 -0.54224,-2.196589 1.75238,0 3.50475,0 5.25712,0 z m 11.54081,0 c 1.75278,0 3.50556,0 5.25833,0 -0.0488,1.261424 -0.51726,2.518415 -1.40834,3.427293 -0.92781,1.019206 -2.27089,1.683834 -3.66164,1.66997 -0.82227,0.08494 -1.63768,-0.139202 -2.39253,-0.448502 -1.02375,-0.469995 -1.84373,-1.289497 -2.40833,-2.252781 -0.41537,-0.738415 -0.60178,-1.559916 -0.64703,-2.39598 1.75318,0 3.50636,0 5.25954,0 z"
|
||||
id="path975"
|
||||
inkscape:export-xdpi="73.4646"
|
||||
inkscape:export-ydpi="73.4646"
|
||||
transform="scale(0.26458333)" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#35185a;stroke-width:0.05;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
id="rect977"
|
||||
width="2.5958393"
|
||||
height="0.17676066"
|
||||
x="21.741636"
|
||||
y="8.6375818"
|
||||
rx="0.1586249"
|
||||
ry="0.074778207"
|
||||
inkscape:export-xdpi="73.4646"
|
||||
inkscape:export-ydpi="73.4646" />
|
||||
<rect
|
||||
ry="0.074778207"
|
||||
rx="0.1586249"
|
||||
y="8.9901352"
|
||||
x="22.051559"
|
||||
height="0.17676066"
|
||||
width="2.5958395"
|
||||
id="rect977-5"
|
||||
style="fill:none;fill-opacity:1;stroke:#35185a;stroke-width:0.0499999;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
inkscape:export-xdpi="73.4646"
|
||||
inkscape:export-ydpi="73.4646" />
|
||||
<rect
|
||||
ry="0.074778207"
|
||||
rx="0.1586249"
|
||||
y="9.3622065"
|
||||
x="22.423628"
|
||||
height="0.17676066"
|
||||
width="2.5958395"
|
||||
id="rect977-2"
|
||||
style="fill:none;fill-opacity:1;stroke:#35185a;stroke-width:0.0499999;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
inkscape:export-xdpi="73.4646"
|
||||
inkscape:export-ydpi="73.4646" />
|
||||
<path
|
||||
style="fill:#35185a;fill-opacity:1;stroke:#35185a;stroke-width:0.00590551;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
d="m 84.501308,30.491633 c -4.578124,0.0075 -9.156441,-0.01371 -13.734429,0.02525 -0.693567,-0.01774 -1.390723,0.195106 -1.967292,0.578202 -1.340862,1.306989 -2.618146,2.678056 -3.921631,4.022187 -0.928179,0.979151 -1.884243,1.932938 -2.787903,2.934783 -0.296924,0.387827 -0.253972,0.964169 0.073,1.321595 0.453039,0.536154 1.165881,0.790805 1.846924,0.862427 9.088796,0.02919 18.177699,0.01801 27.266541,0.02098 8.971612,-0.0035 17.943722,9.79e-4 26.915032,-0.0075 0.67701,-0.159585 1.4309,-0.390888 1.83118,-1.006164 0.27401,-0.42712 0.20268,-1.042849 -0.1938,-1.371596 -2.08805,-2.215504 -4.20148,-4.40741 -6.33794,-6.57628 -0.41935,-0.445875 -1.03719,-0.630893 -1.61981,-0.752075 -1.12915,-0.06287 -2.26223,-0.02992 -3.39294,-0.0446 -7.9923,-0.01217 -15.984625,-0.0056 -23.97693,-0.0072 z m 0.931336,2.152832 c 1.991263,0.01019 3.993432,-0.0229 5.978121,0.02435 0.20274,0.01796 0.49119,-0.01541 0.573759,0.224553 0.06009,0.217689 -0.148816,0.405783 -0.358582,0.38678 -1.989608,0.04777 -3.991315,0.02099 -5.985535,0.03298 -1.043119,-0.01138 -2.088546,0.0277 -3.130249,-0.03035 -0.205687,-0.01898 -0.475698,-0.243439 -0.294983,-0.450256 0.130309,-0.212203 0.428219,-0.133687 0.627544,-0.167934 0.862957,-0.02591 1.726689,-0.01689 2.589925,-0.02012 z m 4.653564,1.317505 c 0.887729,0.01056 1.777847,-0.01728 2.664124,0.03168 0.208257,0.02208 0.514584,0.173208 0.392761,0.426697 -0.08105,0.133587 -0.264999,0.197053 -0.405884,0.227421 -3.009715,-0.0043 -6.019854,0.02491 -9.029297,-0.01581 -0.190892,-0.02956 -0.429268,-0.16786 -0.359863,-0.396119 0.06704,-0.205168 0.332926,-0.248012 0.524142,-0.24539 2.070841,-0.03742 4.142853,-0.02119 6.214017,-0.02847 z m 1.40625,1.40625 c 0.887729,0.01056 1.777848,-0.01728 2.664123,0.03168 0.208257,0.02208 0.514585,0.173208 0.392763,0.426697 -0.08105,0.133587 -0.265,0.197053 -0.405885,0.227421 -3.009715,-0.0043 -6.019854,0.02491 -9.029297,-0.01581 -0.190892,-0.02956 -0.429268,-0.16786 -0.359863,-0.396119 0.06704,-0.205168 0.332926,-0.248012 0.524142,-0.24539 2.070841,-0.03742 4.142853,-0.02119 6.214017,-0.02847 z"
|
||||
id="path1004"
|
||||
inkscape:export-xdpi="73.4646"
|
||||
inkscape:export-ydpi="73.4646"
|
||||
transform="scale(0.26458333)" />
|
||||
<rect
|
||||
style="fill:#35185a;fill-opacity:1;stroke:#35185a;stroke-width:0.044635;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
id="rect1014"
|
||||
width="14.53014"
|
||||
height="0.8528896"
|
||||
x="30.362129"
|
||||
y="8.6211557"
|
||||
rx="0.14023046"
|
||||
ry="0.14540984"
|
||||
inkscape:export-xdpi="73.4646"
|
||||
inkscape:export-ydpi="73.4646" />
|
||||
<rect
|
||||
style="fill:#35185a;fill-opacity:1;stroke:#35185a;stroke-width:0.0506043;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
id="rect1016"
|
||||
width="2.0594873"
|
||||
height="1.0700072"
|
||||
x="42.406349"
|
||||
y="8.506938"
|
||||
rx="0.15056987"
|
||||
ry="0.12785782"
|
||||
inkscape:export-xdpi="73.4646"
|
||||
inkscape:export-ydpi="73.4646" />
|
||||
<rect
|
||||
style="fill:#35185a;fill-opacity:1;stroke:#35185a;stroke-width:0.0396433;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
id="rect1018"
|
||||
width="2.9120724"
|
||||
height="1.4533808"
|
||||
x="29.59572"
|
||||
y="8.3237476"
|
||||
rx="0.13227929"
|
||||
ry="0.12945224"
|
||||
inkscape:export-xdpi="73.4646"
|
||||
inkscape:export-ydpi="73.4646" />
|
||||
<path
|
||||
style="font-variation-settings:'wght' 700;fill:#35185a;fill-opacity:1;stroke:#35185a;stroke-width:0.057007;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
id="path1028"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="-21.117058"
|
||||
sodipodi:cy="-8.0305481"
|
||||
sodipodi:rx="2.0635529"
|
||||
sodipodi:ry="0.47371906"
|
||||
sodipodi:start="0"
|
||||
sodipodi:end="3.1415927"
|
||||
sodipodi:arc-type="slice"
|
||||
d="m -19.053505,-8.0305481 a 2.0635529,0.47371906 0 0 1 -1.031776,0.4102527 2.0635529,0.47371906 0 0 1 -2.063553,0 2.0635529,0.47371906 0 0 1 -1.031777,-0.4102527 h 2.063553 z"
|
||||
transform="scale(-1)"
|
||||
inkscape:export-xdpi="73.4646"
|
||||
inkscape:export-ydpi="73.4646" />
|
||||
<path
|
||||
transform="scale(-1)"
|
||||
d="m -23.800879,-8.067503 a 2.0635529,0.47371906 0 0 1 -1.031776,0.4102528 2.0635529,0.47371906 0 0 1 -2.063553,0 2.0635529,0.47371906 0 0 1 -1.031776,-0.4102528 h 2.063553 z"
|
||||
sodipodi:arc-type="slice"
|
||||
sodipodi:end="3.1415927"
|
||||
sodipodi:start="0"
|
||||
sodipodi:ry="0.47371906"
|
||||
sodipodi:rx="2.0635529"
|
||||
sodipodi:cy="-8.067503"
|
||||
sodipodi:cx="-25.864431"
|
||||
sodipodi:type="arc"
|
||||
id="path1030"
|
||||
style="font-variation-settings:'wght' 700;fill:#35185a;fill-opacity:1;stroke:#35185a;stroke-width:0.057007;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
inkscape:export-xdpi="73.4646"
|
||||
inkscape:export-ydpi="73.4646" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 24 KiB |
14
project-warstone/src/App.tsx
Normal file
14
project-warstone/src/App.tsx
Normal file
@ -0,0 +1,14 @@
|
||||
import { RecoilRoot } from 'recoil'
|
||||
import { TextMapper } from './components/Importer/text-mapper'
|
||||
import { SchemaBuilder } from './components/SchemaBuilder'
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<RecoilRoot>
|
||||
{/* <TextMapper /> */}
|
||||
<SchemaBuilder />
|
||||
</RecoilRoot>
|
||||
)
|
||||
}
|
||||
|
||||
export default App
|
1
project-warstone/src/assets/react.svg
Normal file
1
project-warstone/src/assets/react.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>
|
After Width: | Height: | Size: 4.0 KiB |
@ -0,0 +1,32 @@
|
||||
import React, { useState, useEffect, ReactNode, useRef, useLayoutEffect, useCallback } from 'react';
|
||||
import { FCC } from '../../types';
|
||||
|
||||
interface IProps {
|
||||
currentPage: number;
|
||||
}
|
||||
|
||||
const AnimatedPageContainer: FCC<IProps> = ({ children, currentPage }) => {
|
||||
const [uuid] = useState(crypto.randomUUID());
|
||||
|
||||
const renderChild = (child: ReactNode, index: number) => {
|
||||
const isActive = index === currentPage;
|
||||
|
||||
return (
|
||||
<div
|
||||
key={`page container ${uuid}: ${index}`}
|
||||
data-active={isActive}
|
||||
className="data-[active=true]:opacity-100 data-[active=true]:static opacity-0 top-0 left-0 absolute transition-opacity duration-300 data-[active=false]:-z-10"
|
||||
>
|
||||
{child}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
{React.Children.map(children, renderChild)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AnimatedPageContainer;
|
1066
project-warstone/src/components/Importer/text-mapper.tsx
Normal file
1066
project-warstone/src/components/Importer/text-mapper.tsx
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,53 @@
|
||||
import { FC, useCallback, useEffect } from 'react'
|
||||
import { FieldType, FieldTypes, fieldTypeOptions, fieldTypesWithValues } from '../../types/schema'
|
||||
import { useObjectStateWrapper } from '../../hooks/useObjectState';
|
||||
import { FieldTypeInput } from './field-type-input';
|
||||
import { InputBinder } from '../../types/inputBinder';
|
||||
import { ValueField } from './value-field';
|
||||
|
||||
interface IProps {
|
||||
update: (arg: FieldType) => void;
|
||||
field: FieldType;
|
||||
fieldName: string;
|
||||
}
|
||||
|
||||
export const FieldEditor: FC<IProps> = ({ update, field, fieldName }) => {
|
||||
const { update: updateField, bindProperty, bindPropertyCheck } = useObjectStateWrapper(field, (e) => update(typeof e === 'function' ? e(field) : e))
|
||||
|
||||
const shouldShowValueField = useCallback(() => fieldTypesWithValues.includes(field.type) || field.isConstant, [field.isConstant, field.type]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log(field.value);
|
||||
}, [field])
|
||||
|
||||
return (
|
||||
<li className="odd:bg-black/50 flex gap-4 items-center p-2">
|
||||
<p>{fieldName}</p>
|
||||
<select className="capitalize" {...bindProperty('type')}>
|
||||
{fieldTypeOptions.map(o => (
|
||||
<option className="capitalize" value={FieldTypes[o]}>{o}</option>
|
||||
))}
|
||||
</select>
|
||||
{shouldShowValueField() && (
|
||||
// <>
|
||||
// {field.type === FieldTypes.dice && (
|
||||
// <label>
|
||||
// Sides:
|
||||
// <select {...bindProperty('value')}>
|
||||
// {diceSides.map(d => (
|
||||
// <option value={'d' + d}>{d}</option>
|
||||
// ))}
|
||||
// </select>
|
||||
// </label>
|
||||
// )}
|
||||
// {field.type === FieldTypes.type && (
|
||||
// <FieldTypeInput bind={bindProperty('value')} />
|
||||
|
||||
// )}
|
||||
// </>
|
||||
<ValueField type={field.type} bind={bindProperty('value')} />
|
||||
)}
|
||||
<label><input type="checkbox" {...bindPropertyCheck('isConstant')} /> Is constant</label>
|
||||
</li>
|
||||
)
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { SchemaEditAtom } from '../../recoil/atoms/schema';
|
||||
import { FCC } from '../../types'
|
||||
import { InputBinder } from '../../types/inputBinder'
|
||||
|
||||
interface IProps {
|
||||
bind: InputBinder
|
||||
}
|
||||
|
||||
export const FieldTypeInput: FCC<IProps> = ({ bind }) => {
|
||||
const Schema = useRecoilValue(SchemaEditAtom);
|
||||
|
||||
return (
|
||||
<>
|
||||
<input type="text" {...bind} list="type-editor-type-list" />
|
||||
<optgroup id="type-editor-type-list">
|
||||
{Object.keys(Schema.types).map(k => (
|
||||
<option className="capitalize" value={k}>{k}</option>
|
||||
))}
|
||||
</optgroup>
|
||||
</>
|
||||
)
|
||||
}
|
45
project-warstone/src/components/SchemaBuilder/index.tsx
Normal file
45
project-warstone/src/components/SchemaBuilder/index.tsx
Normal file
@ -0,0 +1,45 @@
|
||||
import { FC, useCallback, useState } from 'react'
|
||||
import AnimatedPageContainer from '../AnimatedPageContainer';
|
||||
import { TypeEditor } from './type-editor';
|
||||
import { useObjectState, useObjectStateWrapper } from '../../hooks/useObjectState';
|
||||
import { Schema, TypeType } from '../../types/schema';
|
||||
import { useInput } from '../../hooks/useInput';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import { SchemaEditAtom } from '../../recoil/atoms/schema';
|
||||
|
||||
|
||||
export const SchemaBuilder: FC = () => {
|
||||
const [schema, setSchema] = useRecoilState(SchemaEditAtom);
|
||||
const {update: updateSchema} = useObjectStateWrapper<Schema>(schema, setSchema);
|
||||
|
||||
const {value: typeName, bind: bindTypeName, reset: resetTypeName} = useInput('');
|
||||
|
||||
const [pageNumber, setPageNumber] = useState(1);
|
||||
|
||||
const saveType = useCallback((name: string, type: TypeType) => {
|
||||
updateSchema(e => ({
|
||||
types: {
|
||||
...e.types,
|
||||
}
|
||||
}));
|
||||
resetTypeName();
|
||||
}, [resetTypeName, updateSchema]);
|
||||
|
||||
return (
|
||||
<div className="container flex gap-4 p-8">
|
||||
<div className="panel w-2/3 h-full">
|
||||
<AnimatedPageContainer currentPage={pageNumber}>
|
||||
<div>
|
||||
<p className="subheader">Add A Type</p>
|
||||
<input type="text" {...bindTypeName} />
|
||||
<button className="interactive" disabled={!typeName} onClick={() => setPageNumber(1)}>Configure</button>
|
||||
</div>
|
||||
<TypeEditor name={typeName} saveType={saveType} />
|
||||
</AnimatedPageContainer>
|
||||
</div>
|
||||
<div className="panel w-1/3 whitespace-pre-wrap">
|
||||
{JSON.stringify(schema, null, 2)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
import { FC, useCallback } from 'react'
|
||||
import { FCC } from '../../types'
|
||||
import { FieldType, FieldTypes, TypeType } from '../../types/schema'
|
||||
import { useObjectState } from '../../hooks/useObjectState';
|
||||
import { useInput } from '../../hooks/useInput';
|
||||
import { FieldEditor } from './field-editor';
|
||||
|
||||
interface IProps {
|
||||
name: string;
|
||||
saveType: (arg0: string, arg1: TypeType) => void;
|
||||
}
|
||||
|
||||
const constantProperties = ['metadata'];
|
||||
|
||||
export const TypeEditor: FCC<IProps> = ({ saveType, name }) => {
|
||||
const { update: updateType, reset: resetType, state: type } = useObjectState<TypeType>({});
|
||||
|
||||
const { value: propertyName, setValue: setPropertyName, bind: bindPropertyName, reset: resetPropertyName } = useInput('');
|
||||
|
||||
const save = () => {
|
||||
saveType(name, type);
|
||||
resetType();
|
||||
}
|
||||
|
||||
const addField = useCallback(() => {
|
||||
updateType({
|
||||
[propertyName]: {
|
||||
type: FieldTypes.number,
|
||||
value: '',
|
||||
isConstant: false,
|
||||
limit: 1,
|
||||
}
|
||||
})
|
||||
}, [propertyName, updateType])
|
||||
|
||||
const updateField = useCallback((k: keyof typeof type) => (field: FieldType) => {
|
||||
updateType({ [k]: field })
|
||||
}, [updateType])
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p className="subheader">Creating type "{name}"</p>
|
||||
<input type="text" {...bindPropertyName} />
|
||||
<button disabled={!propertyName} onClick={addField}>Add Field</button>
|
||||
<ul>
|
||||
{Object.entries(type).filter(([k]) => !constantProperties.includes(k)).map(([key, value]) => (
|
||||
<FieldEditor field={value} update={updateField(key)} fieldName={key} />
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
import { FC } from 'react';
|
||||
import { FieldTypes } from '../../types/schema';
|
||||
import { InputBinder } from '../../types/inputBinder';
|
||||
import { FieldTypeInput } from './field-type-input';
|
||||
|
||||
interface IValueProps {
|
||||
type: FieldTypes;
|
||||
bind: InputBinder;
|
||||
}
|
||||
|
||||
const diceSides = [3, 4, 6, 8, 10, 12, 20, 100];
|
||||
|
||||
export const ValueField: FC<IValueProps> = ({type, bind}) => {
|
||||
switch (type) {
|
||||
case FieldTypes.dice:
|
||||
return (
|
||||
<label>
|
||||
Sides:
|
||||
<select {...bind}>
|
||||
{diceSides.map(d => (
|
||||
<option value={'d' + d}>{d}</option>
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
);
|
||||
case FieldTypes.type:
|
||||
return (
|
||||
<FieldTypeInput bind={bind} />
|
||||
)
|
||||
case FieldTypes.number:
|
||||
return (
|
||||
<input type="number" {...bind} />
|
||||
)
|
||||
default:
|
||||
return <></>;
|
||||
}
|
||||
}
|
35
project-warstone/src/hooks/useInput.ts
Normal file
35
project-warstone/src/hooks/useInput.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { useState, ChangeEvent } from 'react';
|
||||
|
||||
export const useInput = <T extends string | number>(initialValue: T) => {
|
||||
const [value, setValue] = useState<T>(initialValue);
|
||||
|
||||
return {
|
||||
value,
|
||||
setValue,
|
||||
reset: () => setValue(initialValue),
|
||||
bind: {
|
||||
value: value,
|
||||
onChange: (event: ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) => {
|
||||
const changed: string | number = typeof initialValue === 'number' ? parseInt(event.target.value) : event.target.value;
|
||||
setValue(changed as T);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export const useCheckbox = (initial: boolean) => {
|
||||
const [value, setValue] = useState(initial);
|
||||
|
||||
return {
|
||||
value,
|
||||
setValue,
|
||||
reset: () => setValue(initial),
|
||||
bind: {
|
||||
checked: value,
|
||||
onClick: () => {
|
||||
setValue(v => !v);
|
||||
},
|
||||
readOnly: true
|
||||
}
|
||||
};
|
||||
};
|
84
project-warstone/src/hooks/useObjectState.ts
Normal file
84
project-warstone/src/hooks/useObjectState.ts
Normal file
@ -0,0 +1,84 @@
|
||||
import React, { ChangeEvent, useCallback, useState } from 'react';
|
||||
import { InputBinder } from '../types/inputBinder';
|
||||
|
||||
export const useObjectState = <T extends object>(initial: T) => {
|
||||
const [state, setState] = useState<T>(initial || {} as T);
|
||||
|
||||
const bindProperty = useCallback(<K extends keyof T>(property: K) => ({
|
||||
value: state[property] ?? '',
|
||||
name: property,
|
||||
onChange: (event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) =>
|
||||
setState(value => (
|
||||
{
|
||||
...value,
|
||||
[event.target.name]: (
|
||||
(typeof value[property] === 'number') ?
|
||||
Number(event.target.value) || 0 :
|
||||
event.target.value)
|
||||
}
|
||||
))
|
||||
}), [state])
|
||||
|
||||
const bindPropertyCheck = useCallback(<K extends keyof T>(property: K) => ({
|
||||
checked: !!state[property],
|
||||
name: property,
|
||||
onChange: (event: ChangeEvent<HTMLInputElement>) => setState(value => ({
|
||||
...value, [event.target.name]: (event.target.checked)
|
||||
})),
|
||||
readOnly: true
|
||||
}), [state])
|
||||
|
||||
const update = useCallback((updates: Partial<T>) => setState(s => ({ ...s, ...updates })), [])
|
||||
|
||||
const reset = useCallback(() => {
|
||||
setState(initial);
|
||||
}, [initial])
|
||||
|
||||
return {
|
||||
bindProperty,
|
||||
bindPropertyCheck,
|
||||
update,
|
||||
state,
|
||||
setState,
|
||||
reset
|
||||
}
|
||||
}
|
||||
|
||||
export const useObjectStateWrapper = <T extends object>(state: T, setState: React.Dispatch<React.SetStateAction<T>>) => {
|
||||
|
||||
const bindProperty = useCallback(<K extends keyof T>(property: K): InputBinder => ({
|
||||
value: state[property] ?? '',
|
||||
name: property.toString(),
|
||||
onChange: (event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) =>
|
||||
setState(value => (
|
||||
{
|
||||
...value,
|
||||
[event.target.name]: (
|
||||
(typeof value[property] === 'number') ?
|
||||
Number(event.target.value) || 0 :
|
||||
event.target.value)
|
||||
}
|
||||
))
|
||||
}), [setState, state])
|
||||
|
||||
const bindPropertyCheck = useCallback(<K extends keyof T>(property: K) => ({
|
||||
checked: !!state[property],
|
||||
name: property,
|
||||
onChange: (event: ChangeEvent<HTMLInputElement>) => setState(value => ({
|
||||
...value, [event.target.name]: (event.target.checked)
|
||||
})),
|
||||
readOnly: true
|
||||
}), [setState, state])
|
||||
|
||||
const update = useCallback((updates: Partial<T> | ((arg: T) => Partial<T>)) =>
|
||||
setState(s => ({ ...s, ...(typeof updates === 'function' ? updates(s) : updates) }
|
||||
)), [setState])
|
||||
|
||||
return {
|
||||
bindProperty,
|
||||
bindPropertyCheck,
|
||||
update,
|
||||
state,
|
||||
setState
|
||||
}
|
||||
}
|
10
project-warstone/src/hooks/useQueryParams.ts
Normal file
10
project-warstone/src/hooks/useQueryParams.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { useEffect, useRef } from 'react'
|
||||
import { QueryParams } from '../utils/queryParams'
|
||||
|
||||
export const useQueryParams = (options?: {clean: boolean}) => {
|
||||
const queryParams = useRef(new QueryParams(options))
|
||||
|
||||
useEffect(() => {
|
||||
console.log(queryParams.current.get('test'))
|
||||
}, [queryParams.current])
|
||||
}
|
19
project-warstone/src/hooks/useRefCallback.ts
Normal file
19
project-warstone/src/hooks/useRefCallback.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { ReactNode, useCallback, useRef } from 'react'
|
||||
|
||||
export const useRefCallback = <T = ReactNode>() : [T | null, (arg: T) => void] => {
|
||||
const ref = useRef<T | null>(null);
|
||||
const setRef = useCallback((val: T) => {
|
||||
console.log(val);
|
||||
if (ref.current) {
|
||||
// does something?
|
||||
}
|
||||
|
||||
if (val) {
|
||||
// also does something?
|
||||
}
|
||||
|
||||
ref.current = val
|
||||
}, [])
|
||||
|
||||
return [ref.current, setRef]
|
||||
}
|
39
project-warstone/src/index.css
Normal file
39
project-warstone/src/index.css
Normal file
@ -0,0 +1,39 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
body {
|
||||
@apply bg-bastille text-white
|
||||
}
|
||||
input, select {
|
||||
@apply p-1 rounded-lg text-cinder-500
|
||||
}
|
||||
}
|
||||
|
||||
@layer components {
|
||||
.panel {
|
||||
@apply bg-cinder shadow-xl p-8 rounded-xl
|
||||
}
|
||||
.header {
|
||||
@apply text-2xl font-bold
|
||||
}
|
||||
.subheader {
|
||||
@apply text-xl font-bold
|
||||
}
|
||||
button {
|
||||
@apply interactive bg-olive-drab p-1
|
||||
}
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
.interactive {
|
||||
@apply border-2 rounded-lg border-falcon cursor-pointer
|
||||
}
|
||||
.interactive svg {
|
||||
@apply fill-falcon
|
||||
}
|
||||
.interactive:disabled {
|
||||
@apply border-falcon-300 brightness-50 cursor-default
|
||||
}
|
||||
}
|
10
project-warstone/src/main.tsx
Normal file
10
project-warstone/src/main.tsx
Normal file
@ -0,0 +1,10 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import App from './App.tsx'
|
||||
import './index.css'
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
)
|
7
project-warstone/src/recoil/atoms/schema.ts
Normal file
7
project-warstone/src/recoil/atoms/schema.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { atom } from 'recoil';
|
||||
import { Schema, TypeType } from '../../types/schema';
|
||||
|
||||
export const SchemaEditAtom = atom<Schema>({
|
||||
key: 'schema-edit',
|
||||
default: {name: '', types: {}}
|
||||
});
|
24
project-warstone/src/services/game-systems.ts
Normal file
24
project-warstone/src/services/game-systems.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { Schema } from '../types/schema';
|
||||
|
||||
export const GameSystemsService = {
|
||||
// todo - connect to service to save schema for game
|
||||
saveSchema: async (schema: Schema) => {
|
||||
localStorage.setItem('schema', JSON.stringify(schema));
|
||||
|
||||
return { status: 200 }
|
||||
},
|
||||
// todo - connect to service to fetch schema for game
|
||||
getSchema: async (id: string) => {
|
||||
const schema = localStorage.getItem('schema');
|
||||
|
||||
if (schema)
|
||||
return {
|
||||
status: 200,
|
||||
json: async () => JSON.parse(schema)
|
||||
}
|
||||
|
||||
return {
|
||||
status: 404
|
||||
}
|
||||
}
|
||||
}
|
3
project-warstone/src/types.ts
Normal file
3
project-warstone/src/types.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import { FC, PropsWithChildren } from "react";
|
||||
|
||||
export type FCC<P=Record<string, never>> = FC<PropsWithChildren<P>>
|
7
project-warstone/src/types/inputBinder.ts
Normal file
7
project-warstone/src/types/inputBinder.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { ChangeEvent } from 'react'
|
||||
|
||||
export type InputBinder = {
|
||||
name: string,
|
||||
value: string | number,
|
||||
onChange: (e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => void
|
||||
}
|
28
project-warstone/src/types/schema.ts
Normal file
28
project-warstone/src/types/schema.ts
Normal file
@ -0,0 +1,28 @@
|
||||
export type MetadataType = {
|
||||
[key: string]: string
|
||||
}
|
||||
|
||||
export type FieldType = {
|
||||
type: FieldTypes;
|
||||
value: string;
|
||||
isConstant: boolean;
|
||||
limit: number;
|
||||
};
|
||||
|
||||
export type TypeType = Record<string, FieldType>;
|
||||
|
||||
export type Schema = {
|
||||
name: string;
|
||||
types: Record<string, TypeType>
|
||||
}
|
||||
|
||||
export enum FieldTypes {
|
||||
number = 'number',
|
||||
text = 'text',
|
||||
checkbox = 'checkbox',
|
||||
type = '@type',
|
||||
dice = 'dice'
|
||||
}
|
||||
|
||||
export const fieldTypeOptions: (keyof typeof FieldTypes)[] = ['number', 'text', 'checkbox', 'type', 'dice']
|
||||
export const fieldTypesWithValues = [FieldTypes.dice, FieldTypes.type];
|
20
project-warstone/src/utils/queryParams.ts
Normal file
20
project-warstone/src/utils/queryParams.ts
Normal file
@ -0,0 +1,20 @@
|
||||
export class QueryParams {
|
||||
private params = new Map<string, string>()
|
||||
constructor(options?: {clean: boolean}) {
|
||||
if (!options?.clean) {
|
||||
const {search} = location;
|
||||
for (const [key, value] of search.replace('?', '').split('&').map(e => e.split('='))) {
|
||||
this.params.set(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get = this.params.get
|
||||
set = this.params.set
|
||||
delete = this.params.delete
|
||||
clear = this.params.clear
|
||||
|
||||
apply() {
|
||||
location.search = '?' + encodeURIComponent(Array.from(this.params.entries()).map(e => e.join('=')).join('&'))
|
||||
}
|
||||
}
|
1
project-warstone/src/vite-env.d.ts
vendored
Normal file
1
project-warstone/src/vite-env.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
54
project-warstone/tailwind.config.js
Normal file
54
project-warstone/tailwind.config.js
Normal file
@ -0,0 +1,54 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
content: [
|
||||
"./index.html",
|
||||
"./src/**/*.{js,ts,jsx,tsx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
'cinder': {
|
||||
DEFAULT: '#120F16',
|
||||
50: '#6B5983',
|
||||
100: '#615177',
|
||||
200: '#4E415F',
|
||||
300: '#3A3047',
|
||||
400: '#26202E',
|
||||
500: '#120F16',
|
||||
},
|
||||
'falcon': {
|
||||
DEFAULT: '#785474',
|
||||
50: '#9A6F95',
|
||||
100: '#90658B',
|
||||
200: '#785474',
|
||||
300: '#573D54',
|
||||
400: '#362634',
|
||||
500: '#150F14',
|
||||
},
|
||||
'bastille': {
|
||||
DEFAULT: '#1A1420',
|
||||
50: '#765B91',
|
||||
100: '#6C5384',
|
||||
200: '#57436B',
|
||||
300: '#433352',
|
||||
400: '#2E2439',
|
||||
500: '#1A1420',
|
||||
},
|
||||
'olive-drab': {
|
||||
DEFAULT: '#688E26',
|
||||
50: '#8BBE33',
|
||||
100: '#80AE2F',
|
||||
200: '#688E26',
|
||||
300: '#48621A',
|
||||
400: '#27350E',
|
||||
500: '#070902',
|
||||
},
|
||||
},
|
||||
container: {
|
||||
center: true
|
||||
}
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
|
25
project-warstone/tsconfig.json
Normal file
25
project-warstone/tsconfig.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"include": ["src"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
10
project-warstone/tsconfig.node.json
Normal file
10
project-warstone/tsconfig.node.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"skipLibCheck": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
11
project-warstone/vite.config.ts
Normal file
11
project-warstone/vite.config.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react-swc'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
appType: 'spa',
|
||||
preview: {
|
||||
port: 6969
|
||||
}
|
||||
})
|
1684
project-warstone/yarn.lock
Normal file
1684
project-warstone/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
@ -4,7 +4,7 @@ EXPOSE 6901
|
||||
|
||||
WORKDIR /rules
|
||||
|
||||
ADD ./user-service .
|
||||
ADD ./rules-service/ .
|
||||
COPY ./deno.jsonc .
|
||||
COPY ./secrets.json .
|
||||
COPY ./key.txt .
|
||||
@ -12,4 +12,4 @@ ADD ./common ./common
|
||||
ADD ./lib ./lib
|
||||
ADD ./middleware ./middleware
|
||||
|
||||
CMD ["run", "--allow-net", main.ts, "6901"]
|
||||
CMD ["run", "--allow-write", "--allow-read", "--allow-net", "--allow-env", "main.ts", "6901"]
|
||||
|
1
rules-service/key.txt
Normal file
1
rules-service/key.txt
Normal file
@ -0,0 +1 @@
|
||||
{"kty":"oct","k":"ydUZuTH_gj0WAPHiVAF3ATiHuMoVr85jobnNN_iRHpf-OPQd984g_4hY7zikrmjTXRJARwHv6Rr24E7UoHogvvfGeKF8NkO7yhJ2thF5auv2fyScIMbFMW3tv0AA0YioB0-QUZLBjd1SF9HYK6s5Rqt0-fJaNSKnthzEsKD8wak","alg":"HS512","key_ops":["sign","verify"],"ext":true}
|
@ -4,7 +4,9 @@ import { Router } from 'oak';
|
||||
|
||||
const app = new CGGService({ prefix: '/rules' });
|
||||
|
||||
app.route(new Router());
|
||||
app.route(new Router()
|
||||
.get('/', ctx => ctx.response.body = 'rules service')
|
||||
);
|
||||
|
||||
app.start();
|
||||
console.log('User service running on ' + Deno.args.at(0));
|
||||
console.log('rules service running on ' + Deno.args.at(0));
|
||||
|
@ -1 +1,4 @@
|
||||
--allow-net
|
||||
--allow-write
|
||||
--allow-read
|
||||
--allow-net
|
||||
--allow-env
|
30
startDev.ts
30
startDev.ts
@ -1,38 +1,38 @@
|
||||
import { copy } from "https://deno.land/std@0.104.0/io/util.ts";
|
||||
import { proxy } from "https://deno.land/x/oak_http_proxy@2.1.0/mod.ts";
|
||||
import { fileExists } from "./lib/fileExists.ts";
|
||||
import { Application, Context, Router } from "oak";
|
||||
import { path } from "https://deno.land/x/compress@v0.4.1/deps.ts";
|
||||
const app = new Application();
|
||||
|
||||
|
||||
let port = 3001;
|
||||
for await (const dirEntry of Deno.readDir(Deno.cwd())) {
|
||||
if (!(dirEntry.isDirectory && dirEntry.name.includes('-service'))) continue;
|
||||
const filename = dirEntry.name + '/index.ts';
|
||||
const filename = dirEntry.name + '/main.ts';
|
||||
const permfile = dirEntry.name + '/perms';
|
||||
const prefixfile = dirEntry.name + '/prefix';
|
||||
const portfile = dirEntry.name + '/port';
|
||||
if (!(await fileExists(filename))) continue;
|
||||
if (!(await fileExists(prefixfile))) continue;
|
||||
|
||||
const perms = (await fileExists(permfile)) ? await Deno.readTextFileSync(permfile).split('\n') : []
|
||||
// successful, file or directory must exist
|
||||
const p = Deno.run({
|
||||
cmd: ['deno', 'run', ...perms, '--watch', filename, port.toString()],
|
||||
stdout: "piped",
|
||||
stderr: "piped",
|
||||
})
|
||||
const port = await Deno.readTextFile(portfile);
|
||||
const p = new Deno.Command(Deno.execPath(), {
|
||||
args: [
|
||||
'run',
|
||||
...perms,
|
||||
filename,
|
||||
port
|
||||
]
|
||||
}).spawn()
|
||||
|
||||
const prefix = Deno.readTextFileSync(prefixfile);
|
||||
const fixedPort = port;
|
||||
const routes = new Router()
|
||||
.all(`/${prefix}/(.*)`, proxy((ctx: Context) => `http://localhost:${fixedPort}${ctx.request.url.pathname}`, {}))
|
||||
app.use(routes.routes());
|
||||
.all(`/${prefix}/(.*)`, proxy((ctx: Context) => `http://localhost:${port}${ctx.request.url.pathname}`, {}))
|
||||
|
||||
app.use(routes.allowedMethods());
|
||||
app.use(routes.routes());
|
||||
|
||||
port++;
|
||||
|
||||
copy(p.stdout, Deno.stdout);
|
||||
copy(p.stderr, Deno.stderr);
|
||||
}
|
||||
|
||||
app.listen({
|
||||
|
8
test.json
Normal file
8
test.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"\ufeff\nRIPPER SWARMS\nM\nT\nSV\nW\nLD\nOC\nA\nBS\nS\nAP\nD\nABILITIES\n6\"\n2\n6+\n4\n8+\n0\n\n\n\n\n\n\nRANGED WEAPONS\nRANGE\n\n\n\n\n\n\nSpinemaws [PISTOL]\n6\"\n4\n5+\n3\n0\n1\nCORE: Deep Strike\nMELEE WEAPONS\nRANGE\nA\nWS\nS\nAP\nD\nFACTION: Synapse\nXenos claws and teeth [SUSTAINED HITS 1]\nMelee\n6\n5+\n2\n0\n1\nChitinous Horrors (Aura): While an enemy unit is within\nKEYWORDS: Swarm, Great Devourer, Ripper Swarms\n\n\n\n\n\nEngagement Range of this unit, halve the Objective Control\n\n\n\n\n\n\ncharacteristic of models in that enemy unit.\n\n\n\n\n\n\nFACTION KEYWORDS:\n\n\n\n\n\n\nTyranids\n\n\nRIPPER SWARMS\nLiving carpets of Rippers squirm across the ground wherever the \nTyranid swarms advance. Little more than simple eating machines, \nthese chitinous horrors swarm over the wounded and dead alike, and \ncan even drag down trained warriors in sufficient numbers. Once a \nRipper\u2019s fangs sink home, it will not let go\u2026\nWARGEAR OPTIONS \tUNIT COMPOSITION\n\u25a0 All models in this unit can each be equipped with 1 spinemaws.\t\u25a0 3-6 Ripper Swarms\nEvery model is equipped with: xenos claws and teeth.\nKEYWORDS: Swarm, Great Devourer, Ripper Swarms \tFACTION KEYWORDS: \tTyranids\n\nSCREAMER-KILLER\nM\nT\nSV\nW\nLD\nOC\nBS\nS\nAP\nD\nABILITIES\n8\"\n9\n2+\n10\n8+\n3\n\n\n\n\n\nRANGED WEAPONS\nRANGE\nA\n\n\n\n\n\nBio-plasmic scream [ASSAULT, BLAST]\n18\"\nD6+3\n4+\n8\n-2\n1\nCORE: Deadly Demise 1\nMELEE WEAPONS\nRANGE\nA\nWS\nS\nAP\nD\nFACTION: Synapse\nScreamer-killer talons\nMelee\n10\n3+\n10\n-2\n3\nDeath Scream: In your Shooting phase, after this model has\nKEYWORDS: Monster, Great Devourer, Screamer-Killer\n\n\n\n\nshot, select one unit hit by one or more of those attacks.\n\n\n\n\n\nThat unit must take a Battle-shock test, subtracting 1 from\n\n\n\n\n\nthat test.\n\n\n\n\n\nFACTION KEYWORDS:\n\n\n\n\n\nTyranids\n\n\nSCREAMER-KILLER\nAn older adaptation of the basic Carnifex strain, the Screamer-Killer \nwas christened by terrified Imperial troops for the distinctive howl \nit emits as it generates then unleashes its bio-plasmic blasts. \nScreamer-Killers are often seen at the forefront of a Tyranid assault, \nwhere they can inflict the most damage quickly.\nWARGEAR OPTIONS \tUNIT COMPOSITION\n\u25a0 None\t\u25a0 1 Screamer-Killer\nThis model is equipped with: bio-plasmic scream": null,
|
||||
" \nScreamer-Killer talons.\nKEYWORDS: Monster, Great Devourer, Screamer-Killer\nFACTION KEYWORDS: \nTyranids\n\nPSYCHOPHAGE\nM\nT\nSV\nW\nLD\nOC\nA\nBS\nS\nAP\nD\nABILITIES\n8\"\n9\n3+\n10\n8+\n3\n\n\n\n\n\n\nRANGED WEAPONS\nRANGE\n\n\n\n\n\n\nPsychoclastic torrent [IGNORES COVER, TORRENT]\n12\"\nD6\nN/A\n6\n-1\n1\nCORE: Deadly Demise 1, Feel No Pain 5+\nMELEE WEAPONS\nRANGE\nA\nWS\nS\nAP\nD\nFACTION: Synapse\nTalons and betentacled maw\nMelee\nD6+1\n3+\n6\n-1\n2\nBio-stimulus (Aura): While a friendly Tyranids unit\n[ANTI-PSYKER 2+, DEVASTATING WOUNDS]\n\n\n\n\n\n\nis within 6\" of this model, models in that unit have the\n\n\n\n\n\n\n\nFeel No Pain 6+ ability.\nFeeding Frenzy: Each time this model makes a melee attack \nthat targets a unit that is below its Starting Strength, add 1 to \nthe Hit roll. If that target is also Below Half-strength, add 1 to \nthe Wound roll as well.\nKEYWORDS: Monster, Great Devourer, Psychophage \tFACTION KEYWORDS: \tTyranids\n\nPSYCHOPHAGE\nThese monsters stampede into battle with frightening speed. They \ndevour any prey organism in their paths, but especially favour those \nvictims with psychic abilities. How they metabolise such esoteric \npowers is unclear, but doing so allows them to project surges of \npsychocorrosive ash that deflagrate their victims\u2019 minds and souls.\nWARGEAR OPTIONS \tUNIT COMPOSITION\n\u25a0 None\t\u25a0 1 Psychophage\nThis model is equipped with: psychoclastic torrent": null,
|
||||
" talons \nand betentacled maw.\nKEYWORDS: Monster, Great Devourer, Psychophage \tFACTION KEYWORDS: \tTyranids\n\nBARBGAUNTS\nM\nT\nSV\nW\nLD\nOC\nA\nBS\nS\nAP\nD\nABILITIES\n6\"\n4\n4+\n2\n8+\n1\n\n\n\n\n\n\nRANGED WEAPONS\nRANGE\n\n\n\n\n\n\nBio-cannon [BLAST, HEAVY]\n24\"\nD6\n4+\n5\n0\n1\nFACTION: Synapse\nMELEE WEAPONS\nRANGE\nA\nWS\nS\nAP\nD\nDisruption Bombardment: In your Shooting phase, after\n\n\n\n\n\n\n\nthis unit has shot, if an enemy Infantry unit was hit by one\nXenos claws and teeth\nMelee\n1\n4+\n4\n0\n1\n\n\n\n\n\n\n\n\nor more of those attacks made by this unit\u2019s bio-cannons,\nKEYWORDS: Infantry, Great Devourer, Barbgaunts\n\n\n\n\n\nuntil the end of your opponent\u2019s next turn, that enemy unit is\n\n\n\n\n\n\ndisrupted. While a unit is disrupted, subtract 2 from its Move\n\n\n\n\n\n\ncharacteristic, and subtract 2 from Advance and Charge rolls\n\n\n\n\n\n\nmade for it.\n\n\n\n\n\n\nFACTION KEYWORDS:\n\n\n\n\n\n\nTyranids\n\n\nBARBGAUNTS\nBarbgaunts are little more than living weapons, their bodies and \nbio-cannons slaved to the will of a pulsating ganglio-parasite that \npiggybacks them into battle. There, they unleash volleys of chitinous \nbarbs that detonate with the fury of violent muscle-spasms and \ntransfix nearby victims with hails of jagged projectiles.\nWARGEAR OPTIONS \tUNIT COMPOSITION\n\u25a0 None\t\u25a0 5-10 Barbgaunts\nEvery model is equipped with: bio-cannon": null,
|
||||
" xenos claws \nand teeth.\nKEYWORDS: Infantry, Great Devourer, Barbgaunts \tFACTION KEYWORDS: \tTyranids\n\nTERMAGANTS\nM\nT\nSV\nW\nLD\nOC\nA\nBS\nS\nAP\nD\nABILITIES\n6\"\n3\n5+\n1\n8+\n2\n\n\n\n\n\n\nRANGED WEAPONS\nRANGE\n\n\n\n\n\n\nFleshborer [ASSAULT]\n18\"\n1\n4+\n5\n0\n1\nFACTION: Synapse\nTermagant spinefists [ASSAULT, PISTOL, TWIN-LINKED]\n12\"\n2\n4+\n3\n0\n1\nSkulking Horrors: Once per turn, when an enemy unit ends a\nTermagant devourer\n18\"\n2\n4+\n4\n0\n1\n\n\n\n\n\n\n\n\nNormal, Advance or Fall Back move within 9\" of this unit, if this\nMELEE WEAPONS\nRANGE\nA\nWS\nS\nAP\nD\nunit is not within Engagement Range of one or more enemy\n\n\n\n\n\n\n\nunits, it can make a Normal move of up to D6\".\nXenos claws and teeth\nMelee\n1\n4+\n3\n0\n1\n\n\nKEYWORDS: Infantry, Great Devourer, Endless Multitude, Termagants\nFACTION KEYWORDS: \nTyranids\n\nTERMAGANTS\nScuttling predators that attack in huge swarms, Termagants were \noriginally spawned to roam the tight arterial passages of hive ships \nand hunt intruders. They harry their prey with a hail of firepower, \nseeking always to outflank and envelop their victims as they erode \ntheir numbers.\nWARGEAR OPTIONS \tUNIT COMPOSITION\n\u25a0 All models in this unit can each have their fleshborer replaced with 1 Termagant devourer.\t\u25a0 10-20 Termagants\n\u25a0 All models in this unit can each have their fleshborer replaced with 1 Termagant spinefists.\nKEYWORDS: Infantry, Great Devourer, Endless Multitude, Termagants\nEvery model is equipped with: fleshborer": null,
|
||||
" xenos claws and teeth.\nFACTION KEYWORDS: \nTyranids\n\nNEUROTYRANT\nM\nT\nSV\nW\nLD\nOC\nA\nBS\nS\nAP\nD\nABILITIES\n6\"\n8\n4+\n9\n7+\n3\n\n\n\n\n\n\nRANGED WEAPONS\nRANGE\n\n\n\n\n\n\nPsychic scream [IGNORES COVER, PSYCHIC, TORRENT]\n18\"\n2D6\nN/A\n5\n-1\n2\nCORE: Leader\nMELEE WEAPONS\nRANGE\nA\nWS\nS\nAP\nD\nFACTION: Synapse, Shadow in the Warp\nNeurotyrant claws and lashes\nMelee\n6\n3+\n5\n0\n1\nNode Lash (Psychic): While this model is leading a unit, each\n\n\n\n\n\n\n\ntime a model in that unit makes an attack, add 1 to the Hit roll.\n\n\n\n\n\n\n\nIf the target is Battle-shocked, add 1 to the Wound roll as well.\nPsychic Terror (Psychic): If one or more Neurotyrants \nfrom your army are on the battlefield when you unleash the \nShadow in the Warp, subtract 1 from the Battle-shock test \neach enemy unit on the battlefield must take as a result.\nSynaptic Relays: In your Command phase, you can select \nup to two friendly Tyranids units within 12\" of this model\u2019s \nunit. Until the start of your next Command phase, the selected \nunits are always considered to be within Synapse Range of \nyour army.\nDesigner\u2019s Note: Place a Synaptic Relay token next to each selected unit to \nremind you. \nINVULNERABLE SAVE \t4+\nKEYWORDS: Monster, Character, Fly, Psyker, Great Devourer, Synapse, \tNeurotyrant\nFACTION KEYWORDS: \nTyranids\n\nNEUROTYRANT\nThe Shadow in the Warp radiating from this immensely powerful \npsyker-analogue creeps in all directions, driving even non-psychic \nprey organisms to screaming madness. As its foes writhe in agony, \nthe Neurotyrant guides the swarms around it to slaughter with \nbrutal efficiency.\nWARGEAR OPTIONS \tUNIT COMPOSITION\n\u25a0 None\t\u25a0 1 Neurotyrant\nThis model is equipped with: psychic scream": null,
|
||||
" Neurotyrant \nclaws and lashes.\nLEADER\nThis model can be attached to the following units:\n\u25a0 Neurogaunts\n\u25a0 Tyrant Guard\nKEYWORDS: Monster, Character, Fly, Psyker, Great Devourer, Synapse, \tNeurotyrant\nFACTION KEYWORDS: \nTyranids\n\nVON RYAN\u2019S LEAPERS\nM\nT\nSV\nW\nLD\nOC\nA\nWS\nS\nAP\nD\nABILITIES\n10\"\n5\n4+\n3\n8+\n1\n\n\n\n\n\n\nMELEE WEAPONS\n\n\nRANGE\n\n\n\n\n\n\nLeaper\u2019s talons\n\n\nMelee\n6\n3+\n5\n-1\n1\nCORE: Fights First, Infiltrators, Stealth\nFACTION: Synapse\nPouncing Leap: You can target this unit with the Heroic \nIntervention Stratagem for 0CP, and can do so even if \nyou have already used that Stratagem on a different unit \nthis phase.\nKEYWORDS: Infantry, Great Devourer, Von Ryan\u2019s Leapers\nINVULNERABLE SAVE\n6+\n\nFACTION KEYWORDS:\n\n\nTyranids\n\n\n\nVON RYAN\u2019S LEAPERS\nStealthy hunters and expert ambushers, Von Ryan\u2019s Leapers are swift, \nagile and especially lethal when fighting in dense terrain. Akin to \nliving mines, they lie still at the optimum locations to cause as much \ndamage as possible. When they sense the perfect time to strike, they \nbutcher all around in a murderous frenzy.\nWARGEAR OPTIONS \tUNIT COMPOSITION\n\u25a0 None\t\u25a0 3-6 Von Ryan\u2019s Leapers\nEvery model is equipped with: Leaper\u2019s talons.\nKEYWORDS: Infantry, Great Devourer, Von Ryan\u2019s Leapers\nFACTION KEYWORDS: \nTyranids\n\nNEUROGAUNTS\nM\nT\nSV\nW\nLD\nOC\nA\nWS\nS\nAP\nD\nABILITIES\n6\"\n3\n6+\n1\n8+\n1\n\n\n\n\n\n\nMELEE WEAPONS\n\n\nRANGE\n\n\n\n\n\n\nXenos claws and teeth\n\n\nMelee\n1\n4+\n3\n0\n1\nFACTION: Synapse\nNeurocytes: While this unit is within Synapse Range of your \narmy, it has the Synapse keyword.\nKEYWORDS: Infantry, Great Devourer, Endless Multitude, Neurogaunts\nFACTION KEYWORDS: \nTyranids\n\nNEUROGAUNTS\nNeurogaunts scuttle forward in seething masses, driven on by the \nparasitic neurocytes that cling to their backs. Their primary purpose is \nto protect the synaptic node beasts coordinating invasion swarms. It \nis a task they go about with single-minded savagery, slashing, biting \nand giving their lives without an instant\u2019s hesitation.\nWARGEAR OPTIONS\n\u25a0 None\nUNIT COMPOSITION\n\u25a0 1-2 Neurogaunt Nodebeasts*\n\u25a0 10-20 Neurogaunts\nEvery model is equipped with: xenos claws and teeth.\n* This unit can only contain 2 Neurogaunt Nodebeasts if it contains \n20 Neurogaunts.\nKEYWORDS: Infantry, Great Devourer, Endless Multitude, Neurogaunts\nFACTION KEYWORDS: \nTyranids\n\nWINGED TYRANID PRIME\nM\nT\nSV\nW\nLD\nOC\nA\nWS\nS\nAP\nD\nABILITIES\n12\"\n5\n4+\n6\n7+\n1\n\n\n\n\n\n\nMELEE WEAPONS\n\n\nRANGE\n\n\n\n\n\n\nPrime talons\n\n\nMelee\n6\n2+\n6\n-1\n2\nCORE: Deep Strike, Leader\nFACTION: Shadow in the Warp, Synapse\nAlpha Warrior: While this model is leading a unit, \nweapons equipped by models in that unit have the \n[SUSTAINED HITS 1] ability.\nDeath Blow: If this model is destroyed by a melee attack, if it \nhas not fought this phase, roll one D6: on a 4+, do not remove \nit from play. The destroyed model can fight after the attacking \nmodel\u2019s unit has finished making its attacks, and is then \nremoved from play.\nKEYWORDS: Infantry, Character, Fly, Great Devourer, Synapse, \tWinged Tyranid Prime\nFACTION KEYWORDS: \nTyranids\n\n\nWINGED TYRANID PRIME\nTyranid Primes adapted for flight possess all the physical and synaptic \nmight of an alpha war-beast, while also boasting the frightening speed \nand manoeuvrability imparted by huge leathery wings. Swooping \ndown into the midst of the foe, they rend and tear until nought remains \nbut corpses and fleeing prey.\nWARGEAR OPTIONS \tUNIT COMPOSITION\n\u25a0 None\t\u25a0 1 Winged Tyranid Prime\nThis model is equipped with: Prime talons.\nLEADER\nThis model can be attached to the following units:\n\u25a0 Gargoyles\n\u25a0 Tyranid Warriors with melee Bio-weapons\n\u25a0 Tyranid Warriors with Ranged Bio-weapons\nKEYWORDS: Infantry, Character, Fly, Great Devourer, Synapse, \tWinged Tyranid Prime\nFACTION KEYWORDS: \nTyranids": null
|
||||
}
|
@ -4,7 +4,7 @@ EXPOSE 6900
|
||||
|
||||
WORKDIR /user
|
||||
|
||||
ADD ./user-service .
|
||||
ADD ./user-service/ .
|
||||
COPY ./deno.jsonc .
|
||||
COPY ./secrets.json .
|
||||
COPY ./key.txt .
|
||||
@ -12,4 +12,4 @@ ADD ./common ./common
|
||||
ADD ./lib ./lib
|
||||
ADD ./middleware ./middleware
|
||||
|
||||
CMD ["run", "--allow-read", "--allow-write", "--allow-net", "--allow-sys", "--allow-env", main.ts, "6900"]
|
||||
CMD ["run", "--allow-read", "--allow-write", "--allow-net", "--allow-sys", "--allow-env", "main.ts", "6900"]
|
||||
|
1
user-service/key.txt
Normal file
1
user-service/key.txt
Normal file
@ -0,0 +1 @@
|
||||
{"kty":"oct","k":"7t_uWZkFrXoHs2QT9KwIPPqeoZ4YBVLIMg_YbiubAFyhiSCMjZ_k6gEeQHHjdXa2E02dB5SrpWaYN4FtwWyEPYfRcdO19eCN3nDM1dcLQZ9aaOMC-6DFBN7g9LKkm6sEFf48kyvOB_Kmm0m7XWAIhd0rdq_lv5KKtzdaBaxyd6g","alg":"HS512","key_ops":["sign","verify"],"ext":true}
|
@ -46,4 +46,4 @@ app.route(new Router()
|
||||
// app.use(routes.allowedMethods());
|
||||
|
||||
app.start();
|
||||
console.log('User service running on ' + Deno.args.at(0));
|
||||
console.log('user service running on ' + Deno.args.at(0));
|
||||
|
Loading…
x
Reference in New Issue
Block a user