From dcc9cd2383a2bad74eb3b1a219556cae14919b44 Mon Sep 17 00:00:00 2001 From: Vick Scarlet Date: Sun, 15 Aug 2021 22:05:43 +0800 Subject: [PATCH] add Event --- .vscode/launch.json | 2 +- package.json | 2 +- src/condition.js | 8 +++- src/event.js | 95 ++++++++++++++++++++++++++++++++++++++++++ src/prop.js | 90 ++++++++++++++++++++++----------------- src/util.js | 12 ++++++ test.js | 74 +++++++++++++++++++------------- utils/xlsxTransform.js | 24 +++++++---- 8 files changed, 227 insertions(+), 80 deletions(-) create mode 100644 src/event.js create mode 100644 src/util.js diff --git a/.vscode/launch.json b/.vscode/launch.json index 713b86d..8868d4d 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,7 +8,7 @@ "type": "node", "request": "launch", "name": "test", - "program": "${workspaceFolder}/app.js", + "program": "${workspaceFolder}/test.js", "skipFiles": [ "/**" ] diff --git a/package.json b/package.json index 257ea15..8c613c5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "xlsx_transform", - "module": "true", + "type": "module", "bin": "convert.js", "dependencies": { "xlsx": "^0.17.0" diff --git a/src/condition.js b/src/condition.js index bcf11bf..63c523f 100644 --- a/src/condition.js +++ b/src/condition.js @@ -1,6 +1,10 @@ class Condition { - constructor(prop) { - this._prop = prop; + constructor(initialData={}) { + this.initial(initialData); + } + + initial({prop}) { + if(prop) this.prop = prop; } parse(condition) { diff --git a/src/event.js b/src/event.js new file mode 100644 index 0000000..684b596 --- /dev/null +++ b/src/event.js @@ -0,0 +1,95 @@ +import {clone} from './util.js'; + +class Event { + constructor(initialData={}) { + this.initial(initialData); + } + + initial({prop, condition, events, pools}) { + if(prop) this.prop = prop; + if(condition) this.condition = condition; + if(events) this.events = events; + if(pools) this.pools = pools; + } + + random() { + const age = this.getProp(this.prop.TYPES.AGE); + const pool = this.filterPool( + this.getPool(age) + ); + + let totalWeights = 0; + for(const [,weight] of pool) + totalWeights += weight; + + let random = Math.random() * totalWeights; + for(const [event,weight] of pool) + if((random-=weight)<0) + return event; + } + + check(eventId) { + const { Include, Exclude } = this.get(eventId); + if(Exclude && this.checkCondition(Exclude)) return false; + if(Include) return this.checkCondition(Include); + return true; + } + + checkCondition(condition) { + return this.condition.check(condition); + } + + filterPool(pool) { + return pool.filter(([event])=>this.check(event)); + } + + get(eventId) { + const event = this.events[eventId]; + if(!event) console.error(`[ERROR] No Event[${eventId}]`); + return clone(event); + } + + getPool(age) { + return clone(this.pools[age].Pool) || []; + } + + getProp(prop) { + return this.prop.get(prop); + } + + get prop() {return this._prop;} + set prop(p) {this._prop = p;} + + get condition() {return this._condition;} + set condition(c) {this._condition = c;} + + get pools() {return this._pools;} + set pools(p) { + this._pools = p; + + for(const age in p) + p[age].Pool = p[age].Pool?.map(v=>{ + const value = v.split('*').map(n=>Number(n)); + if(value.length==1) value.push(1); + return value; + }); + + } + + get events() {return this._events;} + set events(e) { + this._events = e; + for(const id in e) { + const event = e[id]; + if(!event.branch) continue; + event.branch = event.branch.map(b=>{ + b = b.split(':'); + b[1] = Number(b[1]); + return b; + }); + } + } + +} + +export default Event; \ No newline at end of file diff --git a/src/prop.js b/src/prop.js index 815dad7..b09e740 100644 --- a/src/prop.js +++ b/src/prop.js @@ -1,20 +1,29 @@ +import {clone} from './util.js'; + class Prop { - constructor(initialData) { - this._data = {}; - for(const key in initialData) - this.set(key, initialData[key]); + constructor(initialData={}) { + this.initial(initialData); + } + + initial(data) { + this._data = { + AGE: 0 + }; + for(const key in data) + this.set(key, data[key]); } get(prop) { switch(prop) { - case 'CHR': - case 'INT': - case 'STR': - case 'MNY': - case 'SPR': - case 'LIF': - case 'TLT': - case 'EVT': + case this.TYPES.AGE: + case this.TYPES.CHR: + case this.TYPES.INT: + case this.TYPES.STR: + case this.TYPES.MNY: + case this.TYPES.SPR: + case this.TYPES.LIF: + case this.TYPES.TLT: + case this.TYPES.EVT: return this._data[prop]; default: return 0; } @@ -22,15 +31,16 @@ class Prop { set(prop, value) { switch(prop) { - case 'CHR': - case 'INT': - case 'STR': - case 'MNY': - case 'SPR': - case 'LIF': - case 'TLT': - case 'EVT': - this._data[prop] = this.clone(value); + case this.TYPES.AGE: + case this.TYPES.CHR: + case this.TYPES.INT: + case this.TYPES.STR: + case this.TYPES.MNY: + case this.TYPES.SPR: + case this.TYPES.LIF: + case this.TYPES.TLT: + case this.TYPES.EVT: + this._data[prop] = clone(value); break; default: return 0; } @@ -38,16 +48,17 @@ class Prop { change(prop, value) { switch(prop) { - case 'CHR': - case 'INT': - case 'STR': - case 'MNY': - case 'SPR': - case 'LIF': + case this.TYPES.AGE: + case this.TYPES.CHR: + case this.TYPES.INT: + case this.TYPES.STR: + case this.TYPES.MNY: + case this.TYPES.SPR: + case this.TYPES.LIF: this._data[prop] += value; break; - case 'TLT': - case 'EVT': + case this.TYPES.TLT: + case this.TYPES.EVT: const v = this._data[prop]; if(value<0) { const index = v.indexOf(value); @@ -59,15 +70,18 @@ class Prop { } } - clone(value) { - switch(typeof value) { - case 'object': - if(Array.isArray(value)) return value.map(v=>this.clone(v)); - const newObj = {}; - for(const key in value) newObj[key] = this.clone(value[key]); - return newObj; - default: return value; - } + get TYPES() { + return { + AGE: "AGE", + CHR: "CHR", + INT: "INT", + STR: "STR", + MNY: "MNY", + SPR: "SPR", + LIF: "LIF", + TLT: "TLT", + EVT: "EVT", + }; } } diff --git a/src/util.js b/src/util.js new file mode 100644 index 0000000..bfbb061 --- /dev/null +++ b/src/util.js @@ -0,0 +1,12 @@ +function clone(value) { + switch(typeof value) { + case 'object': + if(Array.isArray(value)) return value.map(v=>clone(v)); + const newObj = {}; + for(const key in value) newObj[key] = clone(value[key]); + return newObj; + default: return value; + } +} + +export { clone }; \ No newline at end of file diff --git a/test.js b/test.js index 7d0abb2..022807a 100644 --- a/test.js +++ b/test.js @@ -152,39 +152,55 @@ // } +import {readFile} from 'fs/promises'; import Prop from './src/prop.js'; import Condition from './src/condition.js'; +import Event from './src/event.js'; -const prop = new Prop({ - CHR: 5, // 颜值 charm CHR - INT: 5, // 智力 intelligence INT - STR: 5, // 体质 strength STR - MNY: 5, // 家境 money MNY - SPR: 5, // 快乐 spirit SPR - LIF: 5, // 生命 life LIF - TLT: [5], // 天赋 talent TLT - EVT: [5], // 事件 event EVT -}); -const condition = new Condition(prop); +// function debug(...conditions) { +// for(const cond of conditions) +// console.debug(condition.check(cond), '\t', cond); +// } -function debug(...conditions) { - for(const cond of conditions) - console.debug(condition.check(cond), '\t', cond); +// debug( +// '(STR<2&MNY>3)|(MNY<2&CHR<2)', +// '(STR<2&MNY>3)', +// '(STR>2&MNY>3)', +// '((((STR>2&MNY>2))))', +// '((((STR>2&MNY>2)|(MNY<2&CHR<2))))', +// '((((STR>2&MNY>2)|(MNY<2&CHR<2)&(STR>2&MNY>3))))', +// '((((STR>2&MNY>2)|(MNY<2&CHR<2))&(STR>2&MNY>3)))', +// 'EVT![1,2,3]', +// 'EVT![1,2]', +// 'EVT?[1,2,3]', +// 'EVT?[1,2]', +// ); + +// const events = await axios('excel/events.json'); +// const pools = await axios('excel/pools.json'); +async function debug() { + + const events = JSON.parse(await readFile('excel/events.json')); + const pools = JSON.parse(await readFile('excel/pools.json')); + + const prop = new Prop(); + const condition = new Condition(); + const event = new Event(); + + prop.initial({ + CHR: 5, // 颜值 charm CHR + INT: 5, // 智力 intelligence INT + STR: 5, // 体质 strength STR + MNY: 5, // 家境 money MNY + SPR: 5, // 快乐 spirit SPR + LIF: 5, // 生命 life LIF + TLT: [5], // 天赋 talent TLT + EVT: [5], // 事件 event EVT + }); + condition.initial({prop}); + event.initial({events, pools, prop, condition}); + console.debug(event.random()); } -debug( - '(STR<2&MNY>3)|(MNY<2&CHR<2)', - '(STR<2&MNY>3)', - '(STR>2&MNY>3)', - '((((STR>2&MNY>2))))', - '((((STR>2&MNY>2)|(MNY<2&CHR<2))))', - '((((STR>2&MNY>2)|(MNY<2&CHR<2)&(STR>2&MNY>3))))', - '((((STR>2&MNY>2)|(MNY<2&CHR<2))&(STR>2&MNY>3)))', - 'EVT![1,2,3]', - 'EVT![1,2]', - 'EVT?[1,2,3]', - 'EVT?[1,2]', -); - - +debug(); \ No newline at end of file diff --git a/utils/xlsxTransform.js b/utils/xlsxTransform.js index 1db188f..65bdf3a 100644 --- a/utils/xlsxTransform.js +++ b/utils/xlsxTransform.js @@ -1,10 +1,10 @@ -import { readFile, writeFile, stat, readdir } from 'fs/promises'; -import * as XLSX from 'xlsx'; -import { join, extname, dirname } from 'path'; +// import { readFile, writeFile, stat, readdir } from 'fs/promises'; +// import * as XLSX from 'xlsx'; +// import { join, extname, dirname } from 'path'; -// const { readFile, writeFile, stat, readdir } = require('fs/promises'); -// const XLSX = require('xlsx'); -// const { join, extname, dirname } = require('path'); +const { readFile, writeFile, stat, readdir } = require('fs/promises'); +const XLSX = require('xlsx'); +const { join, extname, dirname } = require('path'); async function transform(filePath) { const xlsxFileBuffer = await readFile(filePath); @@ -16,14 +16,18 @@ async function transform(filePath) { const sheetRawData = sheets[sheetName]; if(!sheetRawData['!ref']) break; const rawData = XLSX.utils.sheet_to_json(sheetRawData); - const newData = []; + const newData = {}; data[sheetName] = newData; rawData.shift(); for(const row of rawData) { const rowData = {}; - newData.push(rowData) - for(const key in row) { + let mainKey; + for(let key in row) { const cell = row[key]; + if(key[0] == "$") { + key = key.substr(1); + mainKey = cell; + } if(key.includes(':')) { const keys = key.split(':'); const lastKey = keys.pop(); @@ -39,6 +43,8 @@ async function transform(filePath) { rowData[key] = cell; } } + if(mainKey===undefined) return console.error('No Main Key', rowData); + newData[mainKey] = rowData; } } return data;