parseck2
Version:
Parse a Crusader Kings II saved game file into a usable JavaScript object.
791 lines (742 loc) • 23.9 kB
JavaScript
;
(function () {
var allDynasties = require('../data/dynasties.json');
var allTraits = require('../data/traits.json');
var allOpinions = require('../data/opinions.json');
var allAmbitions = require('../data/ambitions.json');
var allNicknames = require('../data/nicknames.json');
var allCultures = require('../data/cultures.json');
var allReligions = require('../data/religions.json');
var allFactions = require('../data/factions.json');
var allSocieties = require('../data/societies.json');
var allArtifacts = require('../data/artifacts.json');
String.prototype.capitalize = function() {
return this.charAt(0).toUpperCase() + this.slice(1);
}
// Derives a Date object from the YYYY.MM.DD formatted
// strings used through a Crusader Kings II saved game
function getDate(str) {
var parts = str.split('.');
var date = undefined;
if (parts.length >= 3) {
date = new Date(parts[0], (parts[1] - 1), parts[2]);
} else if (parts.length == 2) {
date = new Date(parts[0], (parts[1] - 1));
}
return date;
}
function getTable(data) {
var table = {};
data.forEach(function (datum) {
table[datum.id] = datum;
});
return table;
}
function transDynasties(data) {
var dynastyTable = {};
var keys = [ "name", "culture", "religion" ];
allDynasties.forEach(function (dynasty) {
dynastyTable[dynasty.id] = dynasty;
});
data.forEach(function (data) {
var dynasty = {};
var isNew = false;
if (dynastyTable.hasOwnProperty(data.key)) {
dynasty = dynastyTable[data.key];
} else {
dynasty.id = data.key;
isNew = true;
}
data.val.forEach(function (pair) {
if (keys.indexOf(pair.key) >= 0) {
dynasty[pair.key] = pair.val;
}
});
if (isNew) {
allDynasties.push(dynasty);
dynastyTable[dynasty.id] = dynasty;
}
});
return allDynasties;
}
function transCharacters(data) {
var characters = [];
data.forEach(function (data) {
var character = {
id: data.key,
spouses: [],
titles: [],
claims: [],
jobs: [],
scores: {},
opinions: [],
knownPlots: [],
factions: {
leading: [],
member: [],
inFavor: []
},
wars: {
attacking: [],
defending: []
},
treasury: []
};
data.val.forEach(function (pair) {
if (pair != null) {
if (pair.key == "bn") {
character.name = pair.val;
} else if (pair.key == "b_d") {
var bd = pair.val.split(".");
if (bd.length > 2) {
character.born = new Date(bd[0], bd[1], bd[2]);
} else {
character.born = pair.val;
}
} else if (pair.key == "att") {
var attr = pair.val;
if (attr.length > 4) {
character.attr = {
diplomacy: parseInt(attr[0]),
martial: parseInt(attr[1]),
stewardship: parseInt(attr[2]),
intrigue: parseInt(attr[3]),
learning: parseInt(attr[4])
};
}
} else if (pair.key == "traits") {
var traits = [];
pair.val.forEach(function (id) {
allTraits.forEach(function (trait) {
if (trait.id == id) {
traits.push(trait);
}
});
});
character.traits = traits;
} else if (pair.key == "claim") {
var claim = {
pressed: false,
weak: false
};
pair.val.forEach(function (pair) {
if ((pair.key == "title") && (pair.val != undefined) && (pair.val[0].key != undefined) && (pair.val[0].key == "title") && (pair.val[0].val != undefined)) {
claim.title = pair.val[0].val;
} else if ((pair.key == "pressed") || (pair.key == "weak")) {
claim[pair.key] = pair.val;
}
});
if (claim.title == undefined) { claim = undefined; }
character.claims.push(claim);
} else if (pair.key == "dnt") {
character.dynasty = pair.val;
} else if (pair.key == "fat") {
character.father = pair.val;
} else if (pair.key == "mot") {
character.mother = pair.val;
} else if (pair.key == "nick") {
allNicknames.forEach(function (nick) {
if (pair.val == nick.tag) {
character.nickname = nick.name;
}
});
} else if (pair.key == "spouse") {
character.spouses.push(pair.val);
} else if (pair.key == "cul") {
character.culture = pair.val;
} else if (pair.key == "rel") {
character.religion = pair.val;
} else if (pair.key == "fer") {
character.fertility = parseFloat(pair.val);
} else if (pair.key == "health") {
character.health = parseFloat(pair.val);
} else if (pair.key == "prs") {
character.scores.prestige = parseFloat(pair.val);
} else if (pair.key == "piety") {
character.scores.piety = parseFloat(pair.val);
} else if (pair.key == "wealth") {
character.scores.wealth = parseFloat(pair.val);
} else if (pair.key == "ambition_date") {
character.ambition_date = pair.val;
} else if (pair.key == "title") {
character.titles.push(pair.val);
} else if (pair.key == "job") {
character.jobs.push(pair.val);
} else if (pair.key == "known_plots") {
if (Array.isArray(pair.val)) {
pair.val.forEach(function (id) {
character.knownPlots.push(id);
});
}
}
}
});
characters.push(character);
});
return characters;
}
function transRelations(charTable, data) {
data.forEach(function (person) {
if ((person.key != undefined) && (person.key.substring(0,4) == "rel_")) {
var i = person.key.substring(4);
person.val.forEach(function (other) {
var u = other.key;
other.val.forEach(function (rel) {
allOpinions.forEach(function (opinion) {
if ((rel.key == opinion.tag) && (charTable[i].opinions != undefined)) {
charTable[i].opinions.push({
tag: opinion.tag,
description: opinion.description,
about: u
});
}
});
});
});
}
});
}
function transProvinces(data) {
var provinces = [];
data.forEach(function(pair) {
if (pair != null) {
var province = {
id: pair.key,
modifiers: [],
settlements: []
};
pair.val.forEach(function (pair) {
if (pair != null) {
if (pair.key == "name") {
province.name = pair.val;
} else if (pair.key == "culture") {
province.culture = pair.val.capitalize();
} else if (pair.key == "religion") {
province.religion = pair.val.capitalize();
} else if (pair.key == "modifier") {
pair.val.forEach(function (pair) {
if ((pair != null) && (pair.key == "modifier")) {
province.modifiers.push(pair.val);
}
});
} else if (pair.key.substring(0,2) == "b_") {
var settlement = {
tag: pair.key,
name: pair.key.substring(2).capitalize()
};
pair.val.forEach(function (pair) {
if ((pair != null) && (pair.key == "type")) {
settlement.type = pair.val;
}
});
province.settlements.push(settlement);
}
}
});
provinces.push(province);
}
});
return provinces;
}
function transTitles(data) {
var titles = [];
data.forEach(function (pair) {
var title = {
tag: pair.key,
history: [],
laws: []
};
pair.val.forEach(function (pair) {
if (pair != null) {
if (pair.key == "holder") {
title.holder = pair.val;
} else if (pair.key == "succession") {
title.succession = pair.val;
} else if (pair.key == "gender") {
title.gender = pair.val;
} else if (pair.key == "infamy") {
pair.val.forEach(function (pair) {
if ((pair != null) && (pair.key == "total_infamy")) {
title.infamy = pair.val;
}
});
} else if (pair.key == "liege") {
if (Array.isArray(pair.val)) {
pair.val.forEach(function (pair) {
if ((pair != null) && (pair.key == "title")) {
title.liege = pair.val;
}
});
} else {
title.liege = pair.val;
}
} else if (pair.key == "de_jure_liege") {
if (Array.isArray(pair.val)) {
pair.val.forEach(function (pair) {
if ((pair != null) && (pair.key == "title")) {
title.djliege = pair.val;
}
});
} else {
title.djliege = pair.val;
}
} else if (pair.key == "law") {
title.laws.push(pair.val);
} else if (pair.key == "history") {
pair.val.forEach(function (pair) {
if (pair != null) {
var event = {
date: getDate(pair.key),
};
pair.val.forEach(function (pair) {
if (pair != null) {
if (pair.key == "holder") {
if (typeof(pair.val) === "string") {
event.holder = pair.val;
} else {
pair.val.forEach(function (pair) {
if (pair != null) {
if (pair.key == "character") {
event.holder = pair.val;
} else if (pair.key == "type") {
event.type = pair.val;
}
}
});
}
}
}
});
title.history.push(event);
}
});
}
}
});
titles.push(title);
});
return titles;
}
function transAmbitions(charTable, data) {
data.forEach(function (data) {
var ambition = undefined;
var charID = undefined;
data.forEach(function (pair) {
if (pair != null) {
if (pair.key == "type") {
allAmbitions.forEach(function (a) {
if (a.tag == pair.val) {
ambition = a.name;
}
})
} else if (pair.key == "scope") {
pair.val.forEach(function (pair) {
if ((pair != null) && (pair.key == "char")) {
charID = pair.val;
}
});
}
}
if ((ambition != undefined) && (charID != undefined)) {
var a = {
description: ambition
};
if (charTable[charID].ambition_date != undefined) {
a.since = getDate(charTable[charID].ambition_date);
}
charTable[charID].ambition = a;
}
});
});
}
function transPlots(charTable, data) {
data.forEach(function (p) {
var plot = {
backers: []
};
p.forEach(function (pair) {
if (pair != null) {
if (pair.key == "type") {
plot.type = pair.val;
} else if (pair.key == "backer") {
plot.backers.push(pair.val);
} else if (pair.key == "scope") {
if (Array.isArray(pair.val)) {
pair.val.forEach(function (pair) {
if (pair != null) {
if (pair.key == "char") {
plot.target = pair.val;
} else if (pair.key == "from") {
if (Array.isArray(pair.val)) {
pair.val.forEach(function (pair) {
if ((pair != null) && (pair.key == "char")) {
plot.by = pair.val;
}
});
}
}
}
});
}
}
}
});
if (plot.by != undefined) {
charTable[plot.by].plot = plot;
if (plot.target != undefined) {
if (charTable[plot.target] != undefined) {
if (charTable[plot.target].plottingAgainst == undefined) {
charTable[plot.target].plottingAgainst = [];
}
charTable[plot.target].plottingAgainst.push(plot.by);
}
plot.backers.forEach(function (backer) {
if (charTable[backer] != undefined) {
if (charTable[backer].backing == undefined) {
charTable[backer].backing = [];
}
charTable[backer].backing.push(plot.by);
}
});
}
}
});
}
function transFaction(data) {
var faction = {
backers: []
};
data.forEach(function (pair) {
if (pair != null) {
if (pair.key == "type") {
allFactions.forEach(function (f) {
if (f.tag == pair.val) {
faction.name = f.name;
}
});
} else if (pair.key == "backer") {
faction.backers.push(pair.val);
} else if (pair.key == "scope") {
pair.val.forEach(function (pair) {
if (pair != null) {
if (pair.key == "title") {
if (typeof(pair.val) == "string") {
faction.title = pair.val;
} else if (Array.isArray(pair.val)) {
pair.val.forEach(function (pair) {
if ((pair != null) && (pair.key == "title") && (typeof(pair.val) == "string")) {
faction.title = pair.val;
}
});
}
} else if (pair.key == "new_char") {
faction.claimant = pair.val;
} else if (pair.key == "from") {
pair.val.forEach(function (pair) {
if (pair != null) {
if (pair.key == "char") {
faction.leader = pair.val;
}
}
});
}
}
});
}
}
});
return faction;
}
function transWar(data) {
var war = {};
var attackers = [];
var attackersJoined = [];
var defenders = [];
var defendersJoined = [];
var a = [];
var d = [];
data.forEach(function (pair) {
if (pair.key == "name") {
war.name = pair.val;
} else if (pair.key == "attacker") {
attackers.push(pair.val);
} else if (pair.key == "defender") {
defenders.push(pair.val);
} else if (pair.key == "attacker_dates") {
attackersJoined.push(getDate(pair.val));
} else if (pair.key == "defender_dates") {
defendersJoined.push(getDate(pair.val));
}
});
for (var i = 0; i < Math.min(attackers.length, attackersJoined.length); i++) {
a.push({
character: attackers[i],
joined: attackersJoined[i]
});
}
for (i = 0; i < Math.min(defenders.length, defendersJoined.length); i++) {
d.push({
character: defenders[i],
joined: defendersJoined[i]
});
}
war.attackers = a;
war.defenders = d;
return war;
}
function transSocieties(data) {
var societies = [];
data.forEach(function (pair) {
if (pair != null) {
var society = {
members: {}
};
pair.val.forEach(function (pair) {
if (pair != null) {
if (pair.key == "type") {
allSocieties.forEach(function (societyData) {
if (societyData.tag == pair.val) {
Object.assign(society, societyData);
}
});
} else if (pair.key == "society_leader") {
society.leader = pair.val;
} else if (pair.key == "member") {
var memberData = {};
pair.val.forEach(function (pair) {
if (pair != null) {
if (pair.key == "character") {
memberData.id = pair.val;
} else if (pair.key == "society_rank") {
memberData.rank = pair.val;
} else if (pair.key == "society_currency") {
memberData.currency = pair.val;
} else if (pair.key == "days_in_society") {
memberData.daysInSociety = pair.val;
} else if (pair.key == "days_at_current_society_rank") {
memberData.daysAtRank = pair.val;
}
}
});
society.members[memberData.id] = {
rank: memberData.rank,
currency: memberData.currency,
daysInSociety: memberData.daysInSociety,
daysAtRank: memberData.daysAtRank
};
}
}
});
if ((society.leader != undefined) && (society.members[society.leader] != undefined)) {
society.members[society.leader].leader = true;
}
societies.push(society);
}
});
return societies;
}
function transArtifacts(data) {
var artifacts = {};
data.forEach(function (pair) {
if (pair != null) {
var artifact = {
flags: []
};
pair.val.forEach(function (pair) {
if (pair != null) {
if (pair.key == "type") {
allArtifacts.forEach(function (artifactData) {
if (artifactData.tag == pair.val) {
Object.assign(artifact, artifactData);
}
});
} else if (pair.key == "owner") {
artifact.owner = pair.val;
} else if (pair.key == "org_owner") {
artifact.originalOwner = pair.val;
} else if (pair.key == "obtained") {
artifact.obtained = getDate(pair.val);
} else if (pair.key == "active") {
artifact.active = pair.val;
} else if (pair.key == "flags") {
var memberData = {};
pair.val.forEach(function (pair) {
if (pair != null) {
artifact.flags.push({
flag: pair.key,
date: getDate(pair.val)
});
}
});
}
}
});
if (artifact.tag != undefined) {
artifacts[artifact.tag] = artifact;
}
}
});
return artifacts;
}
function removeAmbitionDates(characters) {
characters.forEach(function (character) {
if (character["ambition_date"] != undefined) {
delete character["ambition_date"];
}
});
}
function compileCultureReligion(characters, dynasties) {
characters.forEach(function (character) {
if ((character.hasOwnProperty("dynasty")) && (dynasties.hasOwnProperty(character.dynasty))) {
var dynasty = dynasties[character.dynasty];
if (!character.hasOwnProperty("culture")) {
character.culture = dynasty.culture;
}
if (!character.hasOwnProperty("religion")) {
character.religion = dynasty.religion;
}
}
});
}
function parseNicknames(characters) {
characters.forEach(function (character) {
var culture = undefined;
var religion = undefined;
allCultures.forEach(function (c) {
if (c.tag == character.culture) {
culture = c;
}
});
allReligions.forEach(function (r) {
if (r.tag == character.religion) {
religion = r;
}
});
if ((character.nickname != undefined) && (culture != undefined)) {
character.nickname = character.nickname.replace('$CULTURE_SINGULAR', culture.individual);
character.nickname = character.nickname.replace('$CULTURE_PLURAL', culture.plural);
}
if ((character.nickname != undefined) && (religion != undefined)) {
character.nickname = character.nickname.replace('$RELIGION_SINGULAR', religion.individual);
character.nickname = character.nickname.replace('$GOD', religion.god);
character.nickname = character.nickname.replace('$DEVIL', religion.devil);
}
});
}
function parseFactions(factions, charTable) {
factions.forEach(function (faction, index) {
if (faction.title != undefined) {
faction.name = faction.name.replace('$TITLE', faction.title.substring(2).capitalize());
}
if ((faction.claimant != undefined) && (charTable[faction.claimant] != undefined)) {
charTable[faction.claimant].factions.inFavor.push(index);
faction.name = faction.name.replace('$CLAIMANT', charTable[faction.claimant].name);
}
if ((faction.leader != undefined) && (charTable[faction.leader] != undefined)) {
charTable[faction.leader].factions.leading.push(index);
}
faction.backers.forEach(function (backer) {
if (charTable[backer] != undefined) {
charTable[backer].factions.member.push(index);
}
});
});
}
function connectWars(wars, charTable) {
wars.forEach(function (war, index) {
war.attackers.forEach(function (attacker) {
if (charTable[attacker.character] != undefined) {
charTable[attacker.character].wars.attacking.push({
war: war.name,
index: index,
joined: attacker.joined
});
}
});
war.defenders.forEach(function (defender) {
if (charTable[defender.character] != undefined) {
charTable[defender.character].wars.defending.push({
war: war.name,
index: index,
joined: defender.joined
});
}
});
});
}
function connectSocieties(societies, charTable) {
societies.forEach(function (society) {
Object.keys(society.members).forEach(function (member) {
if (charTable[member] != undefined) {
charTable[member].society = society.tag;
}
});
});
}
function connectArtifacts(artifacts, charTable) {
Object.keys(artifacts).forEach(function (tag) {
var ownerID = artifacts[tag].owner;
if (charTable[ownerID] != undefined) {
charTable[ownerID].treasury.push(tag);
}
});
}
var transform = function (parsed) {
var obj = {
dynasties: [],
characters: [],
provinces: [],
titles: [],
factions: [],
wars: [],
societies: [],
artifacts: []
};
var second = {
relations: [],
ambitions: [],
plots: []
};
parsed.forEach(function (pair) {
if (pair != null) {
if (pair.key == "dynasties") {
obj.dynasties = transDynasties(pair.val);
} else if (pair.key == "character") {
obj.characters = transCharacters(pair.val);
} else if (pair.key == "relation") {
second.relations = pair.val;
} else if (pair.key == "provinces") {
obj.provinces = transProvinces(pair.val);
} else if (pair.key == "title") {
obj.titles = transTitles(pair.val);
} else if (pair.key == "active_ambition") {
second.ambitions.push(pair.val);
} else if (pair.key == "active_plot") {
second.plots.push(pair.val);
} else if (pair.key == "active_faction") {
obj.factions.push(transFaction(pair.val));
} else if (pair.key == "active_war") {
obj.wars.push(transWar(pair.val));
} else if (pair.key == "society") {
obj.societies = transSocieties(pair.val);
} else if (pair.key == "artifacts") {
obj.artifacts = transArtifacts(pair.val);
}
}
});
var charTable = getTable(obj.characters);
var dynastyTable = getTable(obj.dynasties);
transRelations(charTable, second.relations);
transAmbitions(charTable, second.ambitions);
removeAmbitionDates(obj.characters);
transPlots(charTable, second.plots);
compileCultureReligion(obj.characters, dynastyTable);
parseNicknames(obj.characters);
parseFactions(obj.factions, charTable);
connectWars(obj.wars, charTable);
connectSocieties(obj.societies, charTable);
connectArtifacts(obj.artifacts, charTable);
return obj;
};
module.exports = transform;
})();