.
This commit is contained in:
parent
33afc8084e
commit
00c8a6c97f
20 changed files with 5527 additions and 1 deletions
41
wahapedia_import/exportion/app.js
Normal file
41
wahapedia_import/exportion/app.js
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
var createError = require('http-errors');
|
||||
var express = require('express');
|
||||
var path = require('path');
|
||||
const pino = require('express-pino-logger')();
|
||||
var cookieParser = require('cookie-parser');
|
||||
var logger = require('morgan');
|
||||
|
||||
// var indexRouter = require('./routes/index');
|
||||
|
||||
var app = express();
|
||||
|
||||
// view engine setup
|
||||
app.set('views', path.join(__dirname, 'views'));
|
||||
app.set('view engine', 'jade');
|
||||
|
||||
app.use(logger('dev'));
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: false }));
|
||||
app.use(cookieParser());
|
||||
app.use(express.static(path.join(__dirname, 'public')));
|
||||
app.use(pino);
|
||||
|
||||
app.use('/', require('./routes/index'));
|
||||
|
||||
// catch 404 and forward to error handler
|
||||
app.use(function(req, res, next) {
|
||||
next(createError(404));
|
||||
});
|
||||
|
||||
// error handler
|
||||
app.use(function(err, req, res, next) {
|
||||
// set locals, only providing error in development
|
||||
res.locals.message = err.message;
|
||||
res.locals.error = req.app.get('env') === 'development' ? err : {};
|
||||
|
||||
// render the error page
|
||||
res.status(err.status || 500);
|
||||
res.render('error');
|
||||
});
|
||||
|
||||
module.exports = app;
|
||||
90
wahapedia_import/exportion/bin/www
Executable file
90
wahapedia_import/exportion/bin/www
Executable file
|
|
@ -0,0 +1,90 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var app = require('../app');
|
||||
var debug = require('debug')('exportion:server');
|
||||
var http = require('http');
|
||||
|
||||
/**
|
||||
* Get port from environment and store in Express.
|
||||
*/
|
||||
|
||||
var port = normalizePort(process.env.PORT || '3000');
|
||||
app.set('port', port);
|
||||
|
||||
/**
|
||||
* Create HTTP server.
|
||||
*/
|
||||
|
||||
var server = http.createServer(app);
|
||||
|
||||
/**
|
||||
* Listen on provided port, on all network interfaces.
|
||||
*/
|
||||
|
||||
server.listen(port);
|
||||
server.on('error', onError);
|
||||
server.on('listening', onListening);
|
||||
|
||||
/**
|
||||
* Normalize a port into a number, string, or false.
|
||||
*/
|
||||
|
||||
function normalizePort(val) {
|
||||
var port = parseInt(val, 10);
|
||||
|
||||
if (isNaN(port)) {
|
||||
// named pipe
|
||||
return val;
|
||||
}
|
||||
|
||||
if (port >= 0) {
|
||||
// port number
|
||||
return port;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener for HTTP server "error" event.
|
||||
*/
|
||||
|
||||
function onError(error) {
|
||||
if (error.syscall !== 'listen') {
|
||||
throw error;
|
||||
}
|
||||
|
||||
var bind = typeof port === 'string'
|
||||
? 'Pipe ' + port
|
||||
: 'Port ' + port;
|
||||
|
||||
// handle specific listen errors with friendly messages
|
||||
switch (error.code) {
|
||||
case 'EACCES':
|
||||
console.error(bind + ' requires elevated privileges');
|
||||
process.exit(1);
|
||||
break;
|
||||
case 'EADDRINUSE':
|
||||
console.error(bind + ' is already in use');
|
||||
process.exit(1);
|
||||
break;
|
||||
default:
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener for HTTP server "listening" event.
|
||||
*/
|
||||
|
||||
function onListening() {
|
||||
var addr = server.address();
|
||||
var bind = typeof addr === 'string'
|
||||
? 'pipe ' + addr
|
||||
: 'port ' + addr.port;
|
||||
debug('Listening on ' + bind);
|
||||
}
|
||||
13
wahapedia_import/exportion/config/data.js
Normal file
13
wahapedia_import/exportion/config/data.js
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
const mysql = require("mysql");
|
||||
|
||||
//Database connection
|
||||
const pool = mysql.createPool({
|
||||
connectionLimit : 7,
|
||||
host : 'localhost',
|
||||
user : 'root',
|
||||
password : 'root',
|
||||
database : 'wahapedia',
|
||||
charset : "utf8mb4_unicode_ci"
|
||||
});
|
||||
|
||||
module.exports = pool;
|
||||
2823
wahapedia_import/exportion/package-lock.json
generated
Normal file
2823
wahapedia_import/exportion/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
23
wahapedia_import/exportion/package.json
Normal file
23
wahapedia_import/exportion/package.json
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"name": "exportion",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "nodemon ./bin/www"
|
||||
},
|
||||
"dependencies": {
|
||||
"body-parser": "^1.19.0",
|
||||
"cookie-parser": "~1.4.4",
|
||||
"debug": "~2.6.9",
|
||||
"express": "~4.16.1",
|
||||
"express-pino-logger": "^4.0.0",
|
||||
"http-errors": "~1.6.3",
|
||||
"jade": "~1.11.0",
|
||||
"morgan": "~1.9.1",
|
||||
"mysql": "^2.18.1",
|
||||
"nodemon": "^1.19.4",
|
||||
"pino-colada": "^1.6.0",
|
||||
"sqlstring": "^2.3.1",
|
||||
"string-similarity": "^4.0.4"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,794 @@
|
|||
// TODO: Error reporting
|
||||
// TODO: Fix incrementation guess
|
||||
|
||||
const subFacNames = {
|
||||
AS: 'Order',
|
||||
AdM: 'Forge World',
|
||||
AE: 'Craftworld',
|
||||
AM: 'Regiment',
|
||||
CD: 'Allegiance',
|
||||
QT: 'Dread Household', // Questor Traitoris
|
||||
CSM: 'Legion',
|
||||
DG: 'Plague Company',
|
||||
DRU: 'Kabal', // Wych Cult, Haemunculous Coven
|
||||
GC: 'Cult',
|
||||
GK: 'Brotherhood',
|
||||
QI: 'Noble Household', // Questor Allegiance
|
||||
NEC: 'Dynasty',
|
||||
ORK: 'Clan',
|
||||
SM: 'Chapter',
|
||||
TAU: 'Sept',
|
||||
TS: 'Great Cult',
|
||||
TYR: 'Hive Fleet',
|
||||
}
|
||||
processInfo = (data,factionKey) => {
|
||||
let factionName = data.factions.find(faction => faction.faction_id == factionKey).name
|
||||
let info = {
|
||||
name: factionName,
|
||||
game: 'Warhammer 40,000',
|
||||
genre: 'sci-fi',
|
||||
publisher: 'GW',
|
||||
url: 'https://warhammer40000.com/',
|
||||
notes: 'This manifest is provided for the purposes of testing the features of *Rosterizer* and is not intended for distribution.',
|
||||
revision: '0.0.1',
|
||||
dependencies: [
|
||||
{
|
||||
slug: "123456",
|
||||
name: "40k9e",
|
||||
game: "Warhammer 40,000"
|
||||
}
|
||||
],
|
||||
manifest: {},
|
||||
}
|
||||
return info
|
||||
}
|
||||
processItems = (data) => {
|
||||
let assetCatalog = {'Roster§Army': {}};
|
||||
processModels(data,assetCatalog);
|
||||
processAbilities(data,assetCatalog);
|
||||
processWargear(data,assetCatalog);
|
||||
processPsychicPowers(data,assetCatalog);
|
||||
processWarlordTraits(data,assetCatalog);
|
||||
processUnits(data,assetCatalog);
|
||||
return assetCatalog
|
||||
}
|
||||
processClasses = data => {
|
||||
let assetTaxonomy = {};
|
||||
processFactions(data,assetTaxonomy);
|
||||
processPsychicClasses(data,assetTaxonomy);
|
||||
return assetTaxonomy
|
||||
}
|
||||
processModels = (data,assetCatalog) => {
|
||||
data.models.forEach((model,i,a) => {
|
||||
a[i].duplicated = data.models.filter(dataModel => dataModel.name === a[i].name).length - 1
|
||||
a[i].itemKey = 'Model§' + a[i].name;
|
||||
if(a[i].duplicated){
|
||||
let unitName = data.datasheets.filter(datasheet => datasheet.datasheet_id == model.datasheet_id)[0].name;
|
||||
a[i].itemKey += ` (${unitName})`;
|
||||
}
|
||||
});
|
||||
let modelList = Array.from(new Set(data.models.map(model => model.itemKey)));
|
||||
modelList.forEach(modelItemKey => {
|
||||
let dupModels = data.models.filter(model => model.itemKey === modelItemKey);
|
||||
let tempItem = dedupModels(dupModels);
|
||||
if(dupModels[0].duplicated){
|
||||
tempItem.rules = {
|
||||
'rename me': {
|
||||
evals:[],
|
||||
failState: 'pass',
|
||||
evaluate: 'AND',
|
||||
actions: [
|
||||
{
|
||||
paths: [
|
||||
[
|
||||
'{self}',
|
||||
'designation'
|
||||
]
|
||||
],
|
||||
actionType: 'set',
|
||||
value: dupModels[0].name,
|
||||
iterations: 1
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
assetCatalog[modelItemKey] = tempItem;
|
||||
// console.log(modelItemKey)
|
||||
let tempStatline = JSON.parse(JSON.stringify(tempItem));
|
||||
delete tempStatline.stats.Points;
|
||||
assetCatalog[modelItemKey.replace('Model§','Statline§')] = tempStatline;
|
||||
});
|
||||
}
|
||||
dedupModels = (dupModels) => {
|
||||
let deduped = dupModels[0];
|
||||
let props = ['attacks','ballistic_skill','base_size','cost','leadership','movement','save','strength','toughness','weapon_skill','wounds'];
|
||||
props.forEach(prop => {
|
||||
let arr = dupModels.map(model => model[prop]);
|
||||
deduped[prop] = findMode(arr);
|
||||
});
|
||||
return {
|
||||
stats: {
|
||||
Points: {value: deduped.cost},
|
||||
M: {value: deduped.movement},
|
||||
WS: {value: deduped.weapon_skill},
|
||||
BS: {value: deduped.ballistic_skill},
|
||||
S: {value: deduped.strength},
|
||||
T: {value: deduped.toughness},
|
||||
W: {value: deduped.wounds},
|
||||
A: {value: deduped.attacks},
|
||||
Ld: {value: deduped.leadership},
|
||||
Sv: {value: deduped.save},
|
||||
Base: {value: deduped.base_size},
|
||||
}
|
||||
}
|
||||
}
|
||||
findMode = (arr) => {
|
||||
if (arr.length == 0) return null;
|
||||
|
||||
var modeMap = {},
|
||||
maxEl = [arr[0]],
|
||||
maxCount = 1;
|
||||
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
var el = arr[i];
|
||||
|
||||
if (modeMap[el] == null) modeMap[el] = 1;
|
||||
else modeMap[el]++;
|
||||
|
||||
if (modeMap[el] > maxCount) {
|
||||
maxEl = [el];
|
||||
maxCount = modeMap[el];
|
||||
} else if (modeMap[el] == maxCount) {
|
||||
maxEl.push(el);
|
||||
maxCount = modeMap[el];
|
||||
}
|
||||
}
|
||||
// console.log(maxEl)
|
||||
let val = maxEl.sort((a,b) => {
|
||||
if(typeof a === 'string' && typeof b === 'string') return b.localeCompare(a);
|
||||
else if(typeof a === 'number' && typeof b === 'number') return a-b
|
||||
})[0];
|
||||
return val
|
||||
}
|
||||
ordinalize = (n,keepNumber = true) => {
|
||||
const ordinals = ['th','st','nd','rd'];
|
||||
let v = n % 100;
|
||||
return (keepNumber?n:'') + (ordinals[(v-20)%10]||ordinals[v]||ordinals[0]);
|
||||
}
|
||||
processAbilities = (data,assetCatalog) => {
|
||||
data.abilities.abilities.forEach((ability,i,a) => {
|
||||
// console.log(ability.name)
|
||||
// console.log(formatText(ability.description))
|
||||
let shouldLog = false;// = ability.name === 'Tactical Precision (Aura)';
|
||||
let tempAbility = {text: formatText(ability.description,shouldLog)};
|
||||
let itemKey;
|
||||
if(!ability.is_other_wargear){
|
||||
itemKey = 'Ability§' + ability.name;
|
||||
if(!assetCatalog[itemKey]) assetCatalog[itemKey] = tempAbility;
|
||||
else assetCatalog[itemKey].text += '\n\nERROR: The following text was found on another ability with the same name.\n\n' + formatText(ability.description,shouldLog);
|
||||
}else{
|
||||
itemKey = 'Wargear§' + ability.name;
|
||||
let abilityCostArr = data.abilities.datasheets_abilities.filter(datasheets_ability => datasheets_ability.ability_id === ability.ability_id).map(datasheets_ability => datasheets_ability.cost);
|
||||
let costMode = findMode(abilityCostArr);
|
||||
if(costMode) tempAbility.stats = {Points: {value: costMode}};
|
||||
if(!assetCatalog[itemKey]) assetCatalog[itemKey] = tempAbility;
|
||||
else assetCatalog[itemKey].text += '\n\nERROR: The following text was found on another wargear with the same name.\n\n' + formatText(ability.description,shouldLog);
|
||||
}
|
||||
let subFactTest = new RegExp(`<${data.factCurrent}>`, 'gi');
|
||||
if(subFactTest.test(assetCatalog[itemKey].text)){
|
||||
let ruleText = assetCatalog[itemKey].text.replace(subFactTest,'{v}')
|
||||
assetCatalog[itemKey].text = '';
|
||||
// console.log(ruleText)
|
||||
assetCatalog[itemKey].stats = assetCatalog[itemKey].stats || {};
|
||||
assetCatalog[itemKey].stats[data.factCurrent] = {
|
||||
statType: 'term',
|
||||
value: `<${data.factCurrent.toUpperCase()}>`,
|
||||
text: ruleText,
|
||||
visibility: 'hidden',
|
||||
dynamic: true
|
||||
}
|
||||
}
|
||||
a[i].itemKey = itemKey;
|
||||
data.text = data.text || '';
|
||||
data.text += assetCatalog[itemKey].text;
|
||||
});
|
||||
data.abilities.composed = [];
|
||||
data.abilities.datasheets_abilities.forEach((element) => {
|
||||
data.abilities.composed.push({
|
||||
...element,
|
||||
...data.abilities.abilities.find(e=>e.ability_id===element.ability_id)
|
||||
});
|
||||
});
|
||||
}
|
||||
processWargear = (data,assetCatalog) => {
|
||||
data.wargear.wargear_list.forEach(wargear => {
|
||||
let weapName = wargear.name.replace(/(1: |2: |3: )/,'').replace(/в/g,'d');
|
||||
let tempWeapon = {stats:{
|
||||
AP: {value: wargear.armor_piercing},
|
||||
D: {value: wargear.damage},
|
||||
S: {value: wargear.strength},
|
||||
Type: {value: wargear.type},
|
||||
Range: {value: wargear.weapon_range},
|
||||
}};
|
||||
if(wargear.abilities) tempWeapon.text = formatText(wargear.abilities);
|
||||
let wargearArr = data.wargear.wargear_list.filter(wargear_list => wargear_list.wargear_id == wargear.wargear_id).map(wargear => 'Weapon§' + wargear.name);
|
||||
let costArr = data.wargear.datasheets_wargear.filter(datasheets_wargear => datasheets_wargear.wargear_id == wargear.wargear_id).map(wargear => wargear.cost);
|
||||
let cost = findMode(costArr);
|
||||
// console.log(wargear.wargear_id,cost,costArr)
|
||||
if(wargearArr.length == 1 && cost){
|
||||
tempWeapon.stats.Points = {value: cost};
|
||||
}
|
||||
assetCatalog['Weapon§' + weapName] = tempWeapon;
|
||||
if(wargearArr.length > 1){
|
||||
// console.log(wargearArr,weapName)
|
||||
let itemKey = 'Wargear§' + data.wargear.wargear.filter(gear => gear.wargear_id == wargear.wargear_id)[0].name;
|
||||
assetCatalog[itemKey] = assetCatalog[itemKey] || {};
|
||||
assetCatalog[itemKey].assets = assetCatalog[itemKey].assets || {};
|
||||
assetCatalog[itemKey].assets.traits = assetCatalog[itemKey].assets.traits || [];
|
||||
assetCatalog[itemKey].assets.traits.push('Weapon§' + weapName);
|
||||
if(cost){
|
||||
assetCatalog[itemKey].stats = {Points: {value: cost}};
|
||||
}
|
||||
}
|
||||
});
|
||||
let shootingMelee = data.wargear.wargear_list.filter(wargear => wargear.name.includes('(shooting)') || wargear.name.includes('(melee)'));
|
||||
let shooting = shootingMelee.filter(wargear => wargear.name.includes('(shooting)'));
|
||||
let melee = shootingMelee.filter(wargear => wargear.name.includes('(melee)'));
|
||||
shooting.forEach(shooter => {
|
||||
let bareName = shooter.name.replace(' (shooting)','');
|
||||
if(melee.filter(meleer => meleer.name.includes(bareName))){
|
||||
assetCatalog['Wargear§'+bareName] = {
|
||||
assets: {traits:[
|
||||
'Weapon§'+bareName+' (melee)',
|
||||
'Weapon§'+bareName+' (shooting)',
|
||||
]}
|
||||
}
|
||||
if(assetCatalog['Weapon§'+shooter.name].stats?.Points?.value){
|
||||
assetCatalog['Wargear§'+bareName].stats = assetCatalog['Wargear§'+bareName].stats || {};
|
||||
assetCatalog['Wargear§'+bareName].stats.Points = assetCatalog['Wargear§'+bareName].stats.Points || {};
|
||||
assetCatalog['Wargear§'+bareName].stats.Points.value = assetCatalog['Weapon§'+shooter.name].stats.Points.value;
|
||||
delete assetCatalog['Weapon§'+shooter.name].stats;
|
||||
delete assetCatalog['Weapon§'+bareName+' (melee)'].stats;
|
||||
}
|
||||
}
|
||||
})
|
||||
data.wargear.composed = [];
|
||||
data.wargear.datasheets_wargear.forEach((wargear) => {
|
||||
let wargearArr = data.wargear.wargear_list.filter(wargear_list => wargear_list.wargear_id == wargear.wargear_id);
|
||||
let thisWargear = data.wargear.wargear.find(e=>e.wargear_id===wargear.wargear_id);
|
||||
data.wargear.composed.push({
|
||||
...wargear,
|
||||
...thisWargear,
|
||||
itemKey: (wargearArr.length == 1 ? 'Weapon§' : 'Wargear§') + thisWargear.name
|
||||
});
|
||||
});
|
||||
}
|
||||
createWargearStat = (i,wargearArr,modelLoadout,assetCatalog) => {
|
||||
var stringSimilarity = require('string-similarity');
|
||||
let bestMatchIndex = stringSimilarity.findBestMatch(modelLoadout[i]?.toLowerCase() || '',wargearArr.map(gear => gear.itemKey.toLowerCase())).bestMatchIndex;
|
||||
let current = i < modelLoadout.length ? wargearArr[bestMatchIndex].itemKey.split('§')[1] : '-';
|
||||
let tempStat = {
|
||||
value: current,
|
||||
label: 'Loadout',
|
||||
statType: 'rank',
|
||||
statOrder: i+1,
|
||||
group: 'Loadout',
|
||||
groupOrder: 2,
|
||||
ranks: {
|
||||
'-': {order: 0},
|
||||
},
|
||||
visibility: 'active',
|
||||
dynamic: true
|
||||
}
|
||||
wargearArr.forEach((wargear,i) => {
|
||||
let wargearName = wargear.itemKey.split('§')[1];
|
||||
let actualTrait = assetCatalog[wargear.itemKey];
|
||||
let assignedTrait = (actualTrait.stats?.Points?.value === undefined && !wargear.cost) || actualTrait.stats?.Points?.value == wargear.cost ? wargear.itemKey : {
|
||||
item: wargear.itemKey,
|
||||
stats: {Points: {value: Number(wargear.cost)}}
|
||||
}
|
||||
tempStat.ranks[wargearName] = {
|
||||
order: i+1,
|
||||
traits: [{trait: assignedTrait}],
|
||||
}
|
||||
});
|
||||
return tempStat
|
||||
}
|
||||
processPsychicPowers = (data,assetCatalog) => {
|
||||
data.psychicPowers.forEach(power => {
|
||||
if(power.type){
|
||||
let powerName = power.type + '§' + power.name.toLowerCase().split(' ').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');
|
||||
let tempPower = {
|
||||
text: formatText(power.description)
|
||||
};
|
||||
if(power.roll) tempPower.stats = {Roll:{value: power.roll}};
|
||||
assetCatalog[powerName] = tempPower;
|
||||
}else{
|
||||
let powerName = 'Psychic Power§' + power.name.toLowerCase().split(' ').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');
|
||||
let tempPower = {
|
||||
text: formatText(power.description),
|
||||
stats:{Roll:{
|
||||
value: power.type + (power.roll ? (' ' + power.roll) : '')
|
||||
}}
|
||||
};
|
||||
assetCatalog[powerName] = tempPower;
|
||||
}
|
||||
});
|
||||
}
|
||||
processWarlordTraits = (data,assetCatalog) => {
|
||||
data.warlordTraits.forEach(trait => {
|
||||
let traitName = 'Warlord Trait§' + trait.name.toLowerCase().split(' ').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');
|
||||
let tempTrait = {
|
||||
text: formatText(trait.description),
|
||||
stats:{Discipline:{
|
||||
value: trait.type + (trait.roll ? (' ' + trait.roll) : '')
|
||||
}}
|
||||
};
|
||||
assetCatalog[traitName] = tempTrait;
|
||||
});
|
||||
}
|
||||
formatText = (text,log = false) => {
|
||||
let newText = text
|
||||
let replacePatterns1 = {
|
||||
pPattern: [/<p[^>]+>((?:.(?!\<\/p\>))*.)<\/p>/g,'$1'],
|
||||
divPattern: [/<div[^>]+>((?:.(?!\<\/div\>))*.)<\/div>/g,'$1'],
|
||||
anchorPattern: [/<a[\s]+href="([^>]+)">((?:.(?!\<\/a\>))*.)<\/a>/g,'[$2](https://wahapedia.ru$1)'],
|
||||
tooltipPattern: [/<span[\s]+class="tooltip([^>]+)>((?:.(?!\<\/span\>))*.)<\/span>/g,'$2'],
|
||||
kwb3Pattern: [/<span[\s]+class="kwb3">((?:.(?!\<\/span\>))*.)<\/span>/g,'$1'],
|
||||
boldunderPattern: [/<span[\s]+class="kwb kwbu">((?:.(?!\<\/span\>))*.)<\/span>/g,'<b><i>$1</i></b>'],
|
||||
boldPattern: [/<span[\s]+class="kwb">((?:.(?!\<\/span\>))*.)<\/span>/g,'<b>$1</b>'],
|
||||
underPattern: [/<span[\s]+class="kwbu">((?:.(?!\<\/span\>))*.)<\/span>/g,'<i>$1<i>'],
|
||||
ttPattern: [/<span[\s]+class="tt">((?:.(?!\<\/span\>))*.)<\/span>/g,'<b>$1</b>'],
|
||||
boldunderPattern2: [/<span[\s]+class="kwb kwbu">((?:.(?!\<\/span\>))*.)<\/span>/g,'<b><i>$1</i></b>'],
|
||||
boldPattern2: [/<span[\s]+class="kwb">((?:.(?!\<\/span\>))*.)<\/span>/g,'<b>$1</b>'],
|
||||
underPattern2: [/<span[\s]+class="kwbu">((?:.(?!\<\/span\>))*.)<\/span>/g,'<i>$1<i>'],
|
||||
ttPattern2: [/<span[\s]+class="tt">((?:.(?!\<\/span\>))*.)<\/span>/g,'<b>$1</b>'],
|
||||
h_customPattern: [/<span[\s]+class="h_custom">((?:.(?!\<\/span\>))*.)<\/span>/g,'<b>$1</b>'],
|
||||
redfontPattern: [/<span[\s]+class="redfont">((?:.(?!\<\/span\>))*.)<\/span>/g,'<b>$1</b>'],
|
||||
}
|
||||
let replacePatterns2 = {
|
||||
doubleBoldEndPattern: [/<\/b><\/b>/g,'</b>'],
|
||||
doubleItalicsEndPattern: [/<\/i>((?:.(?!\<i\>))*)<\/i>/g,'$1<i>'],
|
||||
whitespacePattern1: [/\<\/b\>[\s]\<b\>/g,' '],
|
||||
whitespacePattern2: [/\<\/i\>[\s]\<i\>/g,' '],
|
||||
boldTranslationPattern: [/<\/?b>/g,'**'],
|
||||
doubleBoldPattern: [/\*\*\*\*/g,''],
|
||||
doubleBoldPattern2: [/\*\*\s\*\*/g,' '],
|
||||
italicsTranslationPattern: [/<\/?i>/g,'*']
|
||||
}
|
||||
newText = text.replace(/kwb2/g,'kwb');
|
||||
if(log) console.log(newText)
|
||||
Object.entries(replacePatterns1).forEach(([name,pattern]) => {
|
||||
newText = newText.replace(pattern[0],pattern[1]);
|
||||
if(log) console.log(name,newText)
|
||||
});
|
||||
if(log) console.log(newText)
|
||||
let newTextArr = newText.split('<b>');
|
||||
if(log) console.log(newTextArr)
|
||||
newTextArr.forEach((sliver,i,a) => {
|
||||
if(i > 0 && a[i+1]?.includes('</b>')){
|
||||
a[i+1] = a[i] + a[i+1];
|
||||
delete a[i];
|
||||
}
|
||||
});
|
||||
newText = Object.values(newTextArr).join('<b>');
|
||||
newTextArr = newText.split('<i>');
|
||||
newTextArr.forEach((sliver,i,a) => {
|
||||
if(i > 0 && a[i+1]?.includes('</i>')){
|
||||
a[i+1] = a[i] + a[i+1];
|
||||
delete a[i];
|
||||
}
|
||||
});
|
||||
newText = Object.values(newTextArr).join('<i>');
|
||||
Object.entries(replacePatterns2).forEach(([name,pattern]) => {
|
||||
newText = newText.replace(pattern[0],pattern[1]);
|
||||
if(log) console.log(name,newText)
|
||||
});
|
||||
// newText = newText.replace(/"/g,'″'); // too many html structures get screwed by this
|
||||
newText = newText.replace(/<ul[^>]+><li>/g,'* ');
|
||||
if(log) console.log(newText)
|
||||
newText = newText.replace(/<\/li><li>/g,'\n* ');
|
||||
if(log) console.log(newText)
|
||||
newText = newText.replace(/<\/li><\/ul>/g,'');
|
||||
if(log) console.log(newText)
|
||||
newText = newText.replace(/<br>/g,'\n\n');
|
||||
if(log) console.log(newText)
|
||||
return newText
|
||||
}
|
||||
processUnits = (data,assetCatalog) => {
|
||||
var stringSimilarity = require('string-similarity');
|
||||
data.datasheets.forEach(datasheet => {
|
||||
let unitId = datasheet.datasheet_id;
|
||||
let tempItem = {stats:{
|
||||
'Power Level': {
|
||||
value: Number(datasheet.power_points)
|
||||
}
|
||||
},keywords:{},assets:{}};
|
||||
|
||||
let models = data.models.filter(model => model.datasheet_id === unitId);
|
||||
// console.log(unitId,models)
|
||||
if(models[0]?.line === 1 && models[0]?.models_per_unit.includes('-')){
|
||||
tempItem.stats.model = {
|
||||
value: 'Model§' + data.models.filter(model => model.datasheet_id === unitId && model.line === 1)[0].name
|
||||
}
|
||||
}
|
||||
|
||||
let keywords = data.keywords.filter(keyword => keyword.datasheet_id === unitId && !keyword.is_faction_keyword);
|
||||
if(keywords.length) tempItem.keywords.Keywords = keywords.map(keyword => keyword.keyword);
|
||||
let factionKeywords = data.keywords.filter(keyword => keyword.datasheet_id === unitId && keyword.is_faction_keyword);
|
||||
if(factionKeywords.length) tempItem.keywords.Faction = factionKeywords.map(keyword => keyword.keyword);
|
||||
|
||||
let options = data.options.filter(option => option.datasheet_id === unitId);
|
||||
tempItem.text = formatText(datasheet.unit_composition + '\n\n' + options.map(option => (option.button || '') + ' ' + option.description).join('\n\n') + '\n\n' + datasheet.psyker);
|
||||
|
||||
if(models[0]?.models_per_unit?.includes('-')){
|
||||
tempItem.stats[datasheet.name] = {
|
||||
statType: 'numeric',
|
||||
dynamic: true,
|
||||
visibility: 'always',
|
||||
};
|
||||
let stat = tempItem.stats[datasheet.name];
|
||||
let range = models[0].models_per_unit.split('-');
|
||||
stat.value = Number(range[0]);
|
||||
stat.min = Number(range[0]);
|
||||
stat.max = Number(range[1]);
|
||||
let basePlThresh = stat.min;
|
||||
if(!(stat.max % stat.min)){
|
||||
// console.log(datasheet.name,'has a clean threshold')
|
||||
stat.increment = {value: stat.min};
|
||||
}
|
||||
else if(!((stat.max + 1) % (stat.min + 1)) && models[1]?.models_per_unit == 1){
|
||||
// console.log(datasheet.name,'has a sergeant')
|
||||
stat.increment = {value: stat.min + 1};
|
||||
// console.log(stat)
|
||||
basePlThresh ++;
|
||||
}else tempItem.text += '\n\nERROR: there might be a problem with incrementation that will require inputting by hand.';
|
||||
let PLArr = datasheet.unit_composition.split(/(\<b\>Power Rating |\<\/b\>)/).map(el => Number(el.replace('+','plus'))).filter(el => !isNaN(el));
|
||||
if(PLArr.length){
|
||||
let tempInc = PLArr[0] - datasheet.power_points;
|
||||
// console.log(datasheet.name,basePlThresh,tempInc,PLArr)
|
||||
for (let i = 0; i < PLArr.length; i++) {
|
||||
if(PLArr[i] !== ((i+1) * tempInc) + Number(datasheet.power_points)){
|
||||
// console.log(PLArr[i],tempInc,Number(datasheet.power_points), ((i+1) * tempInc) + Number(datasheet.power_points))
|
||||
tempItem.text += '\n\nERROR: there might be a problem with Power Rating that will require a custom rule.';
|
||||
tempInc = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(tempInc){
|
||||
tempItem.stats.poweri = {value:tempInc};
|
||||
for (let i = 0; i < PLArr.length; i++) {
|
||||
tempItem.stats['power'+(i+1)] = {
|
||||
"value": (basePlThresh * (i + 1)) + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}else if(datasheet.unit_composition.includes('Power Rating')) tempItem.text += '\n\nERROR: there might be a problem with Power Rating that will require a custom rule.';
|
||||
}
|
||||
let modelList = [];
|
||||
models.forEach(model => {
|
||||
let [minQty,maxQty] = model.models_per_unit.split('-').map(qty => Number(qty));
|
||||
let statlineName = model.itemKey.replace('Model§','Statline§');
|
||||
if(minQty){
|
||||
let defaultStatline = assetCatalog[statlineName];
|
||||
// console.log(defaultStatline)
|
||||
let tempTrait = {item: model.itemKey};
|
||||
if(minQty > 1) tempTrait.quantity = minQty;
|
||||
// console.log(datasheet.name,model.name,model.models_per_unit,models.length)
|
||||
if(model.models_per_unit == 1 && models.length == 1){
|
||||
tempTrait.stats = tempTrait.stats || {};
|
||||
tempTrait.stats.Points = tempTrait.stats.Points || {};
|
||||
tempTrait.stats.Points.visibility = 'hidden';
|
||||
}
|
||||
let tempStatline = {...tempTrait,item: statlineName};
|
||||
delete tempStatline.quantity;
|
||||
// console.log(tempTrait)
|
||||
// console.log(tempStatline)
|
||||
if(Object.keys(tempStatline).length === 1) tempStatline = statlineName;
|
||||
if(Object.keys(tempTrait).length === 1) tempTrait = model.itemKey;
|
||||
tempItem.assets.traits = tempItem.assets.traits || [];
|
||||
tempItem.assets.traits.push(tempTrait);
|
||||
modelList.push(model)
|
||||
tempItem.assets.traits.push(tempStatline);
|
||||
}
|
||||
if(minQty > 1 || maxQty > 1){
|
||||
tempItem.allowed = tempItem.allowed || {};
|
||||
tempItem.allowed.items = tempItem.allowed.items || [];
|
||||
tempItem.allowed.items.push(model.itemKey)
|
||||
}
|
||||
});
|
||||
|
||||
let abilities = data.abilities.composed.filter(ability => ability.datasheet_id === unitId);
|
||||
let abilityList = abilities.filter(ability => ability.datasheet_id === unitId && !ability.is_other_wargear);
|
||||
let wargearList = abilities.filter(ability => ability.datasheet_id === unitId && ability.is_other_wargear);
|
||||
abilityList.forEach(ability => {
|
||||
tempItem.assets = tempItem.assets || {};
|
||||
tempItem.assets.traits = tempItem.assets.traits || [];
|
||||
tempItem.assets.traits.push(ability.itemKey);
|
||||
});
|
||||
const order = ['Statline§', 'Ability§', 'Wargear§', 'Psychic Power§', 'Model§'];
|
||||
tempItem.assets.traits.sort((a, b) => stringSimilarity.findBestMatch((a.item || a),order).bestMatchIndex - stringSimilarity.findBestMatch((b.item || b),order).bestMatchIndex);
|
||||
|
||||
if(datasheet.psyker?.includes('Smite')){
|
||||
tempItem.assets = tempItem.assets || {};
|
||||
tempItem.assets.traits = tempItem.assets.traits || [];
|
||||
tempItem.assets.traits.push('Psychic Power§Smite');
|
||||
}
|
||||
Array.from(new Set(data.psychicPowers.map(power => power.type))).forEach(discipline => {
|
||||
// console.log(discipline)
|
||||
// console.log(datasheet.psyker)
|
||||
let test = new RegExp(discipline,'gi')
|
||||
if(test.test(datasheet.psyker)){
|
||||
tempItem.allowed = tempItem.allowed || {};
|
||||
tempItem.allowed.classifications = tempItem.allowed.classifications || [];
|
||||
tempItem.allowed.classifications.push(discipline);
|
||||
}
|
||||
});
|
||||
|
||||
wargearList.forEach(wargear => {
|
||||
let tempWargear = wargear.cost === assetCatalog[wargear.itemKey].stats?.Points?.value ? wargear.itemKey : {
|
||||
item: wargear.itemKey,
|
||||
stats: {
|
||||
Points: {value: wargear.cost}
|
||||
}
|
||||
};
|
||||
tempItem.stats = tempItem.stats || {};
|
||||
tempItem.stats[wargear.name] = {
|
||||
value: 0,
|
||||
statType: 'rank',
|
||||
statOrder: 10,
|
||||
ranks: {
|
||||
0: {order: 0,number: 0,icons: ['cancel']},
|
||||
1: {order: 1,number: 1,icons: ['confirmed'],traits: [{trait: tempWargear}]}
|
||||
},
|
||||
visibility: 'active',
|
||||
dynamic: true
|
||||
}
|
||||
});
|
||||
// console.log(datasheet.name,unitId,wargearList)
|
||||
|
||||
let wargearArr = data.wargear.composed.filter(wargear => wargear.datasheet_id == unitId).sort((a,b) => a.itemKey.localeCompare(b.itemKey));
|
||||
wargearArr.slice().forEach((gear,i) => {
|
||||
if(wargearArr[i].itemKey?.includes(' (melee)') && wargearArr[i+1]?.includes(' (shooting)')){
|
||||
wargearArr[i].itemKey = wargearArr[i].itemKey.replace('Weapon§','Wargear§').replace(' (melee)','');
|
||||
delete wargearArr[i+1];
|
||||
}
|
||||
});
|
||||
wargearArr = Object.values(wargearArr);
|
||||
let equippedWargearArr = datasheet.unit_composition?.replace(/is equipped<br>with/g,'is equipped with').replace(/(<br>|<ul><li>|<li><li>|<\/li><\/ul>|<\/b> |\.\s)/g,'. ').split('. ').filter(el => el.includes('is equipped')).map(el => el.split(/is equipped with/).map(subEl => subEl.split('; ').map(equip => equip.replace(/^([:Aa1]\s)*/,''))));
|
||||
// console.log(datasheet.name,unitId,wargearArr,datasheet.unit_composition)
|
||||
equippedWargearArr?.forEach(modelLoadout => {
|
||||
// console.log(modelLoadout[0][0],modelLoadout[1])
|
||||
if(!modelLoadout[1]?.includes(' nothing.')){
|
||||
let upgradeQty = modelLoadout[1]?.length ? (modelLoadout[1].length + 1) : 0;
|
||||
if(
|
||||
stringSimilarity.compareTwoStrings(modelLoadout[0][0],'Every model') > .5
|
||||
|| stringSimilarity.compareTwoStrings(modelLoadout[0][0],'Each model') > .5
|
||||
|| stringSimilarity.compareTwoStrings(modelLoadout[0][0],'This model') > .5
|
||||
){
|
||||
models.forEach(modelData => {
|
||||
let tempItem = assetCatalog[modelData.itemKey];
|
||||
if(upgradeQty) tempItem.stats = tempItem.stats || {};
|
||||
for (let i = 0; i < upgradeQty; i++) {
|
||||
tempItem.stats['loadout'+(i+1)] = createWargearStat(i,wargearArr,modelLoadout[1],assetCatalog);
|
||||
// console.log(tempItem,upgradeQty)
|
||||
}
|
||||
});
|
||||
}else{
|
||||
let modelNames = models.map(thisModel => thisModel.name);
|
||||
let modelIndex = stringSimilarity.findBestMatch(modelLoadout[0][0],modelNames).bestMatchIndex;
|
||||
let tempItem = assetCatalog[models[modelIndex].itemKey];
|
||||
if(upgradeQty) tempItem.stats = tempItem.stats || {};
|
||||
for (let i = 0; i < upgradeQty; i++) {
|
||||
tempItem.stats['loadout'+(i+1)] = createWargearStat(i,wargearArr,modelLoadout[1],assetCatalog);
|
||||
// console.log(tempItem,upgradeQty)
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let source = data.sources.filter(source => source.source_id == datasheet.source_id)[0];
|
||||
// console.log(source)
|
||||
if(source){
|
||||
let errataDate = source.errata_date.split(' ')[0].split('.').reverse().join('-');
|
||||
tempItem.meta = tempItem.meta || {};
|
||||
tempItem.meta.Publication = `[${source.name} (${source.type}) ${ordinalize(source.edition)} ed. – ${source.version || ''} @${errataDate}](${source.errata_link})`;
|
||||
}
|
||||
// TODO implement dynamic stats
|
||||
|
||||
let modelDamage = data.damage.filter(dmgLine => dmgLine.datasheet_id == unitId);
|
||||
if(modelDamage.length){
|
||||
let modelItemKey = models.filter(model => model.datasheet_id === unitId)[0].itemKey;
|
||||
// console.log(unitId,modelItemKey)
|
||||
assetCatalog[modelItemKey].stats['W'] = {
|
||||
value: assetCatalog[modelItemKey].stats['W'].value,
|
||||
max: assetCatalog[modelItemKey].stats['W'].value,
|
||||
min: 1,
|
||||
dynamic: true,
|
||||
increment: {value: 1},
|
||||
statType: 'numeric',
|
||||
visibility: 'always',
|
||||
}
|
||||
assetCatalog[modelItemKey].rules = assetCatalog[modelItemKey].rules || {};
|
||||
assetCatalog[modelItemKey].rules.dynamicDamageMid = generateDamageRule(modelDamage[0],modelDamage[2]);
|
||||
assetCatalog[modelItemKey].rules.dynamicDamageLow = generateDamageRule(modelDamage[0],modelDamage[3]);
|
||||
}
|
||||
|
||||
assetCatalog[datasheet.role + '§' + datasheet.name] = tempItem;
|
||||
});
|
||||
}
|
||||
generateDamageRule = (damageRows,currentRow) => {
|
||||
// console.log(damageRows,currentRow)
|
||||
let [min,max] = currentRow.col1.split('-');
|
||||
let newRule = {
|
||||
evals: [
|
||||
{
|
||||
paths: [
|
||||
['{self}','stats','W','value']
|
||||
],
|
||||
max: max,
|
||||
min: min,
|
||||
operator: 'AND',
|
||||
not: false,
|
||||
actionable: true
|
||||
}
|
||||
],
|
||||
failState: 'pass',
|
||||
evaluate: 'AND',
|
||||
actions: [
|
||||
{
|
||||
paths: [
|
||||
['{self}','stats',damageRows.col2,'value']
|
||||
],
|
||||
actionType: 'set',
|
||||
value: typeof currentRow.col2 === 'number' ? currentRow.col2 : currentRow.col2?.replace('"',''),
|
||||
iterations: 1
|
||||
},
|
||||
{
|
||||
paths: [
|
||||
['{self}','stats',damageRows.col3,'value']
|
||||
],
|
||||
actionType: 'set',
|
||||
value: typeof currentRow.col3 === 'number' ? currentRow.col3 : currentRow.col3?.replace('"',''),
|
||||
iterations: 1
|
||||
},
|
||||
{
|
||||
paths: [
|
||||
['{self}','stats',damageRows.col4,'value']
|
||||
],
|
||||
actionType: 'set',
|
||||
value: typeof currentRow.col4 === 'number' ? currentRow.col4 : currentRow.col4?.replace('"',''),
|
||||
iterations: 1
|
||||
}
|
||||
]
|
||||
}
|
||||
return newRule
|
||||
}
|
||||
processFactions = (data,assetTaxonomy) => {
|
||||
let fac = data.factions[0].main_faction_id;
|
||||
// console.log(fac,data.factions.length)
|
||||
data.factCurrent = subFacNames[fac];
|
||||
if(data.factions.length > 1){
|
||||
assetTaxonomy.Detachment = {
|
||||
stats: {
|
||||
[subFacNames[fac]]: {
|
||||
statType: 'rank',
|
||||
value: '-',
|
||||
ranks: {
|
||||
'-': {
|
||||
order: 0
|
||||
},
|
||||
},
|
||||
dynamic: true,
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
'populate faction': {
|
||||
evals: [
|
||||
{
|
||||
paths: [
|
||||
["{self}","stats","Brotherhood","value"]
|
||||
],
|
||||
value: "-",
|
||||
operator: "AND",
|
||||
not: true,
|
||||
actionable: true
|
||||
}
|
||||
],
|
||||
failState: 'pass',
|
||||
evaluate: 'OR',
|
||||
actions: [
|
||||
{
|
||||
paths: [
|
||||
[
|
||||
'{self}',
|
||||
'assets',
|
||||
'templateClass',
|
||||
'Unit',
|
||||
'traits',
|
||||
'classification',
|
||||
'Ability',
|
||||
'stats',
|
||||
subFacNames[fac],
|
||||
'value',
|
||||
]
|
||||
],
|
||||
actionType: 'set',
|
||||
value: [
|
||||
'{self}',
|
||||
'stats',
|
||||
subFacNames[fac],
|
||||
'value',
|
||||
],
|
||||
iterations: 1
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
data.factions.filter(faction => faction.faction_id != faction.main_faction_id).forEach((faction,i) => {
|
||||
let newRank = {order:i+1}
|
||||
assetTaxonomy.Detachment.stats[subFacNames[fac]].ranks[faction.name] = newRank;
|
||||
});
|
||||
assetTaxonomy.Unit = {
|
||||
rules: {
|
||||
'replace subfaction keyword': {
|
||||
evals: [
|
||||
{
|
||||
paths: [
|
||||
['{parent}','stats',data.factCurrent,'value']
|
||||
],
|
||||
value: '-',
|
||||
operator: 'AND',
|
||||
not: true
|
||||
},
|
||||
{
|
||||
paths: [
|
||||
['{self}','keywords','Faction']
|
||||
],
|
||||
value: `<${data.factCurrent}>`,
|
||||
contains: true,
|
||||
operator: 'AND',
|
||||
not: false,
|
||||
actionable: true
|
||||
}
|
||||
],
|
||||
failState: 'pass',
|
||||
evaluate: 'AND',
|
||||
actions: [
|
||||
{
|
||||
paths: [
|
||||
['{self}','keywords','Faction']
|
||||
],
|
||||
actionType: 'remove',
|
||||
value: `<${data.factCurrent}>`,
|
||||
iterations: 1
|
||||
},
|
||||
{
|
||||
paths: [
|
||||
['{self}','keywords','Faction']
|
||||
],
|
||||
actionType: 'add',
|
||||
value: ['{parent}','stats',data.factCurrent,'processed','rank','current'],
|
||||
iterations: 1
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
processPsychicClasses = (data,assetTaxonomy) => {
|
||||
data.psychicPowers.forEach(power => {
|
||||
if(power.type){
|
||||
assetTaxonomy[power.type] = assetTaxonomy[power.type] || {
|
||||
templateClass: 'Psychic Power',
|
||||
stats:{Roll:{
|
||||
value: null
|
||||
}}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
module.exports = { processItems };
|
||||
8
wahapedia_import/exportion/public/stylesheets/style.css
Normal file
8
wahapedia_import/exportion/public/stylesheets/style.css
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
body {
|
||||
padding: 50px;
|
||||
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #00B7FF;
|
||||
}
|
||||
270
wahapedia_import/exportion/routes/index.js
Normal file
270
wahapedia_import/exportion/routes/index.js
Normal file
|
|
@ -0,0 +1,270 @@
|
|||
var express = require('express');
|
||||
var router = express.Router();
|
||||
const pool = require('../config/data');
|
||||
const SqlString = require('sqlstring');
|
||||
const { processItems } = require('../public/javascripts/manifest.process');
|
||||
|
||||
/* GET home page. */
|
||||
router.get('/', function(req, res, next) {
|
||||
console.log(req.body)
|
||||
// var sql = SqlString.format("SELECT * FROM datasheets;");
|
||||
var sql = SqlString.format("SELECT * FROM factions;");
|
||||
console.log(sql)
|
||||
pool.query(sql, function (error, results, fields) {
|
||||
if(error) {
|
||||
console.log(error);
|
||||
res.send(sql);
|
||||
return;
|
||||
}
|
||||
console.log(results)
|
||||
let factionList = results.filter(faction => faction.faction_id === faction.main_faction_id).sort((a,b) => a.name.localeCompare(b.name));
|
||||
console.log(factionList)
|
||||
|
||||
//if we actually get a result
|
||||
|
||||
res.render('index', { title: 'Wahapedia Exportion', data: factionList});
|
||||
// res.send(JSON.stringify(results.map(datasheet => `${datasheet.datasheet_id}: ${datasheet.name} – ${datasheet.unit_composition}`)));
|
||||
});
|
||||
});
|
||||
router.get('/favicon.ico', function(req, res, next) {})
|
||||
|
||||
router.get('/:faction', async function (req, res, next) {
|
||||
console.log('req.body',req.body)
|
||||
let sql = '';
|
||||
let allResults = {};
|
||||
allResults.factions = await getFactions(req.params.faction);
|
||||
allResults.datasheets = await getDatasheets(req.params.faction);
|
||||
let datasheetList = Array.from(new Set(allResults.datasheets.map(datasheet => datasheet.datasheet_id)));
|
||||
console.log(datasheetList)
|
||||
allResults.keywords = await getKeywords(datasheetList);
|
||||
allResults.models = await getModels(datasheetList);
|
||||
allResults.damage = await getDamage(datasheetList);
|
||||
allResults.wargear = await getWargear(datasheetList);
|
||||
allResults.abilities = await getAbilities(datasheetList);
|
||||
allResults.options = await getOptions(datasheetList);
|
||||
allResults.psychicPowers = await getPsychicPowers(req.params.faction);
|
||||
allResults.stratagems = await getStrategems(req.params.faction);
|
||||
allResults.warlordTraits = await getWarlordTraits(req.params.faction);
|
||||
allResults.sources = await getSources();
|
||||
// console.log('allresults',allResults)
|
||||
allResults['!'] = processInfo(allResults,req.params.faction);
|
||||
allResults['!'].manifest.assetTaxonomy = processClasses(allResults);
|
||||
allResults['!'].manifest.assetCatalog = processItems(allResults);
|
||||
res.send(JSON.stringify(allResults['!']));
|
||||
});
|
||||
|
||||
|
||||
let getFactions = async (fac) => {
|
||||
const sql = SqlString.format("SELECT * FROM factions WHERE main_faction_id = ?",[fac]);
|
||||
console.log('query',fac,sql)
|
||||
let results = await new Promise((resolve, reject) => pool.query(sql, (error, results) => {
|
||||
if(error) {
|
||||
console.log(error);
|
||||
reject(error);
|
||||
return;
|
||||
}else{
|
||||
resolve(results);
|
||||
}
|
||||
}));
|
||||
// console.log('factions',results)
|
||||
return results;
|
||||
}
|
||||
|
||||
let getDatasheets = async (fac) => {
|
||||
const sql = SqlString.format("SELECT * FROM datasheets WHERE faction_id = ?",[fac]);
|
||||
let results = await new Promise((resolve, reject) => pool.query(sql, (error, results) => {
|
||||
if(error) {
|
||||
console.log(error);
|
||||
reject(error);
|
||||
return;
|
||||
}else{
|
||||
resolve(results);
|
||||
}
|
||||
}));
|
||||
// console.log('datasheets',results)
|
||||
return results;
|
||||
}
|
||||
|
||||
let getKeywords = async (datasheets) => {
|
||||
const sql = SqlString.format("SELECT * FROM datasheets_keywords WHERE datasheet_id in (?)",[datasheets]);
|
||||
console.log('query',sql)
|
||||
let results = datasheets.length ? await new Promise((resolve, reject) => pool.query(sql, (error, results) => {
|
||||
if(error) {
|
||||
console.log(error);
|
||||
reject(error);
|
||||
return;
|
||||
}else{
|
||||
resolve(results);
|
||||
}
|
||||
})) : {};
|
||||
// console.log('keywords',results)
|
||||
return results;
|
||||
}
|
||||
|
||||
let getModels = async (datasheets) => {
|
||||
const sql = SqlString.format("SELECT * FROM datasheets_models WHERE datasheet_id in (?)",[datasheets]);
|
||||
console.log('query',sql)
|
||||
let results = datasheets.length ? await new Promise((resolve, reject) => pool.query(sql, (error, results) => {
|
||||
if(error) {
|
||||
console.log(error);
|
||||
reject(error);
|
||||
return;
|
||||
}else{
|
||||
resolve(results);
|
||||
}
|
||||
})) : {};
|
||||
// console.log('models',results)
|
||||
return results;
|
||||
}
|
||||
|
||||
let getDamage = async (datasheets) => {
|
||||
const sql = SqlString.format("SELECT * FROM datasheets_damage WHERE datasheet_id in (?)",[datasheets]);
|
||||
console.log('query',sql)
|
||||
let results = datasheets.length ? await new Promise((resolve, reject) => pool.query(sql, (error, results) => {
|
||||
if(error) {
|
||||
console.log(error);
|
||||
reject(error);
|
||||
return;
|
||||
}else{
|
||||
resolve(results);
|
||||
}
|
||||
})) : {};
|
||||
// console.log('models',results)
|
||||
return results;
|
||||
}
|
||||
|
||||
let getWargear = async (datasheets) => {
|
||||
let sql = SqlString.format("SELECT * FROM datasheets_wargear WHERE datasheet_id in (?)",[datasheets]);
|
||||
let datasheets_wargear = await new Promise((resolve, reject) => pool.query(sql, (error, results) => {
|
||||
if(error) {
|
||||
console.log(error);
|
||||
reject(error);
|
||||
return;
|
||||
}else{
|
||||
resolve(results);
|
||||
}
|
||||
}));
|
||||
let wargearIDs = Array.from(new Set(datasheets_wargear?.map(wargear => wargear?.wargear_id)));
|
||||
sql = SqlString.format("SELECT * FROM wargear_list WHERE wargear_id in (?)",[wargearIDs]);
|
||||
let wargear_list = wargearIDs.length ? await new Promise((resolve, reject) => pool.query(sql, (error, results) => {
|
||||
if(error) {
|
||||
console.log(error);
|
||||
reject(error);
|
||||
return;
|
||||
}else{
|
||||
resolve(results);
|
||||
}
|
||||
})) : {};
|
||||
sql = SqlString.format("SELECT * FROM wargear WHERE wargear_id in (?)",[wargearIDs]);
|
||||
let wargear = wargearIDs.length ? await new Promise((resolve, reject) => pool.query(sql, (error, results) => {
|
||||
if(error) {
|
||||
console.log(error);
|
||||
reject(error);
|
||||
return;
|
||||
}else{
|
||||
resolve(results);
|
||||
}
|
||||
})) : {};
|
||||
// console.log('models',results)
|
||||
return {
|
||||
datasheets_wargear:datasheets_wargear,
|
||||
wargear_list:wargear_list,
|
||||
wargear:wargear,
|
||||
};
|
||||
}
|
||||
|
||||
let getAbilities = async (datasheets) => {
|
||||
let sql = SqlString.format("SELECT * FROM datasheets_abilities WHERE datasheet_id in (?)",[datasheets]);
|
||||
let datasheets_abilities = await new Promise((resolve, reject) => pool.query(sql, (error, results) => {
|
||||
if(error) {
|
||||
console.log(error);
|
||||
reject(error);
|
||||
return;
|
||||
}else{
|
||||
resolve(results);
|
||||
}
|
||||
}));
|
||||
let abilityIDs = Array.from(new Set(datasheets_abilities.map(ability => ability.ability_id)));
|
||||
sql = SqlString.format("SELECT * FROM abilities WHERE ability_id in (?)",[abilityIDs]);
|
||||
let abilities = await new Promise((resolve, reject) => pool.query(sql, (error, results) => {
|
||||
if(error) {
|
||||
console.log(error);
|
||||
reject(error);
|
||||
return;
|
||||
}else{
|
||||
resolve(results);
|
||||
}
|
||||
}));
|
||||
// console.log('models',results)
|
||||
return {
|
||||
datasheets_abilities:datasheets_abilities,
|
||||
abilities:abilities,
|
||||
};
|
||||
}
|
||||
let getOptions = async (datasheets) => {
|
||||
const sql = SqlString.format("SELECT * FROM datasheets_options WHERE datasheet_id in (?)",[datasheets]);
|
||||
let results = await new Promise((resolve, reject) => pool.query(sql, (error, results) => {
|
||||
if(error) {
|
||||
console.log(error);
|
||||
reject(error);
|
||||
return;
|
||||
}else{
|
||||
resolve(results);
|
||||
}
|
||||
}));
|
||||
return results;
|
||||
}
|
||||
let getPsychicPowers = async (fac) => {
|
||||
const sql = SqlString.format("SELECT * FROM psychic_powers WHERE faction_id = ?",[fac]);
|
||||
let results = await new Promise((resolve, reject) => pool.query(sql, (error, results) => {
|
||||
if(error) {
|
||||
console.log(error);
|
||||
reject(error);
|
||||
return;
|
||||
}else{
|
||||
resolve(results);
|
||||
}
|
||||
}));
|
||||
return results;
|
||||
}
|
||||
let getStrategems = async (fac) => {
|
||||
const sql = SqlString.format("SELECT * FROM strategems WHERE faction_id = ?",[fac]);
|
||||
let results = await new Promise((resolve, reject) => pool.query(sql, (error, results) => {
|
||||
if(error) {
|
||||
console.log(error);
|
||||
reject(error);
|
||||
return;
|
||||
}else{
|
||||
resolve(results);
|
||||
}
|
||||
}));
|
||||
return results;
|
||||
}
|
||||
let getWarlordTraits = async (fac) => {
|
||||
const sql = SqlString.format("SELECT * FROM warlord_traits WHERE faction_id = ?",[fac]);
|
||||
let results = await new Promise((resolve, reject) => pool.query(sql, (error, results) => {
|
||||
if(error) {
|
||||
console.log(error);
|
||||
reject(error);
|
||||
return;
|
||||
}else{
|
||||
resolve(results);
|
||||
}
|
||||
}));
|
||||
return results;
|
||||
}
|
||||
let getSources = async () => {
|
||||
const sql = SqlString.format("SELECT * FROM sources");
|
||||
let results = await new Promise((resolve, reject) => pool.query(sql, (error, results) => {
|
||||
if(error) {
|
||||
console.log(error);
|
||||
reject(error);
|
||||
return;
|
||||
}else{
|
||||
resolve(results);
|
||||
}
|
||||
}));
|
||||
return results;
|
||||
}
|
||||
|
||||
module.exports = router;
|
||||
6
wahapedia_import/exportion/views/error.jade
Normal file
6
wahapedia_import/exportion/views/error.jade
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
extends layout
|
||||
|
||||
block content
|
||||
h1= message
|
||||
h2= error.status
|
||||
pre #{error.stack}
|
||||
7
wahapedia_import/exportion/views/index.jade
Normal file
7
wahapedia_import/exportion/views/index.jade
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
extends layout
|
||||
|
||||
block content
|
||||
h1= title
|
||||
each faction in data
|
||||
p
|
||||
a(href=`/${faction.faction_id}`)= faction.name
|
||||
7
wahapedia_import/exportion/views/layout.jade
Normal file
7
wahapedia_import/exportion/views/layout.jade
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
doctype html
|
||||
html
|
||||
head
|
||||
title= title
|
||||
link(rel='stylesheet', href='/stylesheets/style.css')
|
||||
body
|
||||
block content
|
||||
Loading…
Add table
Add a link
Reference in a new issue