diff --git a/src/app.rb b/src/app.rb index 2088f0c..3eee175 100755 --- a/src/app.rb +++ b/src/app.rb @@ -11,7 +11,7 @@ set :bind, ENV['HOST'] set :port, ENV['PORT'] CACHE = Mu::Cache.new :max_size => 128, :max_time => 30.0 -DATA = CharredData.load_data +DATA = Charred::Data.new.data helpers do def logger @@ -23,6 +23,10 @@ get '/' do erb :index end +get '/list_chars/:user' do + "{}" +end + get /\/([\w]+)_partial/ do partial = params['captures'].first erb "partials/#{partial}".to_sym diff --git a/src/data/dark_elf/lifepath.json b/src/data/dark_elf/lifepath.json new file mode 100755 index 0000000..17af7f8 --- /dev/null +++ b/src/data/dark_elf/lifepath.json @@ -0,0 +1,296 @@ +{ + "Path Of Spite Subsetting": { + "Griever": { + "time": 3, + "res": 0, + "skills": [ + [ + 3, + "Sorrow Of Truth", + "Dark Elf-wise" + ] + ], + "traits": [ + 1, + "Spite" + ] + }, + "Wastrel": { + "time": 25, + "res": 3, + "skills": [ + [ + 6, + "Scavenging", + "Brawling", + "Forest-wise", + "Wasteland-wise", + "Animal-wise" + ] + ], + "traits": [ + 2, + "Filthy", + "Feral" + ], + "requires": "Griever", + "requires_expr": [ + "griever" + ] + }, + "Thief": { + "time": 18, + "res": 6, + "stat": [ + [ + 1, + "pm" + ] + ], + "skills": [ + [ + 6, + "Lock Pick", + "Stealthy", + "Climbing", + "Sleight Of Hand", + "Dirge Of Night" + ] + ], + "traits": [ + 1, + "Thief" + ], + "requires": "Griever", + "requires_expr": [ + "griever" + ] + }, + "Assassin": { + "time": 15, + "res": 6, + "stat": [ + [ + 1, + "p" + ] + ], + "skills": [ + [ + 7, + "Intimidation", + "Poisons", + "Escape Artist", + "Knives", + "Garotte", + "Keen Of Terror" + ] + ], + "traits": [ + 1, + "Murderous", + "Callous", + "Cold Blooded" + ], + "requires": "Griever", + "requires_expr": [ + "griever" + ] + }, + "Stalker": { + "time": 20, + "res": 8, + "skills": [ + [ + 8, + "Hunting", + "Elf-wise", + "Tracking", + "Trapper", + "Observation", + "Stealthy", + "Throwing", + "Javelin", + "Supplication To Shadows" + ] + ], + "traits": [ + 1, + "Saturnine" + ], + "requires": "Griever", + "requires_expr": [ + "griever" + ] + }, + "Deceiver": { + "time": 35, + "res": 10, + "stat": [ + [ + 1, + "m" + ] + ], + "skills": [ + [ + 7, + "Sleight Of Hand", + "Disguise", + "Inconspicuous", + "Rhyme Of The Unraveller" + ] + ], + "traits": [ + 1, + "Deceptive" + ], + "requires": "Griever", + "requires_expr": [ + "griever" + ] + }, + "Liar": { + "time": 25, + "res": 8, + "stat": [ + [ + 1, + "m" + ] + ], + "skills": [ + [ + 6, + "Falsehood", + "Soothing Platitudes", + "Persuasion", + "Twisted Tongue" + ] + ], + "traits": [ + 1, + "Compulsive Liar" + ], + "requires": "Griever", + "requires_expr": [ + "griever" + ] + }, + "Siren": { + "time": 55, + "res": 20, + "stat": [ + [ + 1, + "pm" + ] + ], + "skills": [ + [ + 9, + "Seduction", + "Etiquette", + "Persuasion", + "Soothing Platitudes", + "Gossip-wise", + "Fugue Of Discord", + "Litany Of Fools" + ] + ], + "traits": [ + 2, + "Charismatic", + "Femme Fatale/Homme Fatale" + ], + "requires": "Assassin, Deceiver or Liar", + "requires_expr": [ + "assassin", + "deceiver", + "liar" + ] + }, + "Eremite": { + "time": 150, + "res": 15, + "stat": [ + [ + 1, + "m" + ] + ], + "skills": [ + [ + 12, + "Philosophy", + "Ugly Truth", + "Obscure History", + "Symbology", + "Strategy", + "Elf-wise", + "Orc-wise", + "Dwarf-wise", + "Man-wise", + "Paean To The Dark Fire" + ] + ], + "traits": [ + 2, + "Remote", + "Cold" + ], + "requires": "Siren, Wastrel or Stalker", + "requires_expr": [ + "siren", + "wastrel", + "stalker" + ] + }, + "Recluse": { + "time": 225, + "res": 25, + "stat": [ + [ + 1, + "p" + ] + ], + "skills": [ + [ + 2, + "Ancient History", + "Dwarf-wise", + "Elven Politics-wise", + "Cut Of The Quickened Mind" + ], + [ + 5, + "General" + ] + ], + "traits": [ + 1, + "Vengeful" + ], + "requires": "Eremite or any three Dark Elf lifepaths", + "requires_expr": [ + "+or", + [ + "eremite" + ], + [ + "+has_n_lifepaths_in", + 3, + "path of spite subsetting:griever", + "path of spite subsetting:wastrel", + "path of spite subsetting:thief", + "path of spite subsetting:assassin", + "path of spite subsetting:stalker", + "path of spite subsetting:deceiver", + "path of spite subsetting:liar", + "path of spite subsetting:siren" + ] + ] + } + } +} \ No newline at end of file diff --git a/src/data/dark_elf/skills.json b/src/data/dark_elf/skills.json new file mode 100755 index 0000000..9e26dfe --- /dev/null +++ b/src/data/dark_elf/skills.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/src/data/dark_elf/traits.json b/src/data/dark_elf/traits.json new file mode 100755 index 0000000..7fa8c96 --- /dev/null +++ b/src/data/dark_elf/traits.json @@ -0,0 +1,46 @@ +{ + "Callous": { + "cost": 1, + "type": "character" + }, + "Cold": { + "cost": 1, + "type": "character" + }, + "Compulsive Liar": { + "cost": 1, + "type": "character" + }, + "Deceptive": { + "cost": 1, + "type": "character" + }, + "Femme Fatale/Homme Fatale": { + "cost": 1, + "type": "character" + }, + "Feral": { + "cost": 1, + "type": "character" + }, + "Filthy": { + "cost": 1, + "type": "character" + }, + "Murderous": { + "cost": 1, + "type": "character" + }, + "Remote": { + "cost": 1, + "type": "character" + }, + "Saturnine": { + "cost": 1, + "type": "character" + }, + "Spite": { + "cost": 1, + "type": "character" + } +} \ No newline at end of file diff --git a/src/data/lifepaths/dwarf.json b/src/data/gold/lifepaths/dwarf.json similarity index 100% rename from src/data/lifepaths/dwarf.json rename to src/data/gold/lifepaths/dwarf.json diff --git a/src/data/lifepaths/elf.json b/src/data/gold/lifepaths/elf.json similarity index 100% rename from src/data/lifepaths/elf.json rename to src/data/gold/lifepaths/elf.json diff --git a/src/data/lifepaths/man.json b/src/data/gold/lifepaths/man.json similarity index 99% rename from src/data/lifepaths/man.json rename to src/data/gold/lifepaths/man.json index a3f228b..827ae94 100755 --- a/src/data/lifepaths/man.json +++ b/src/data/gold/lifepaths/man.json @@ -10853,6 +10853,7 @@ [ "+has_n_lifepaths_in", 2, + "seafaring setting:son of a gun", "seafaring setting:boy", "seafaring setting:galley slave", "seafaring setting:ratcatcher", diff --git a/src/data/lifepaths/orc.json b/src/data/gold/lifepaths/orc.json similarity index 100% rename from src/data/lifepaths/orc.json rename to src/data/gold/lifepaths/orc.json diff --git a/src/data/lifepaths/roden.json b/src/data/gold/lifepaths/roden.json similarity index 100% rename from src/data/lifepaths/roden.json rename to src/data/gold/lifepaths/roden.json diff --git a/src/data/lifepaths/wolf.json b/src/data/gold/lifepaths/wolf.json similarity index 100% rename from src/data/lifepaths/wolf.json rename to src/data/gold/lifepaths/wolf.json diff --git a/src/data/resources/dwarf.json b/src/data/gold/resources/dwarf.json similarity index 100% rename from src/data/resources/dwarf.json rename to src/data/gold/resources/dwarf.json diff --git a/src/data/resources/elf.json b/src/data/gold/resources/elf.json similarity index 100% rename from src/data/resources/elf.json rename to src/data/gold/resources/elf.json diff --git a/src/data/resources/man.json b/src/data/gold/resources/man.json similarity index 100% rename from src/data/resources/man.json rename to src/data/gold/resources/man.json diff --git a/src/data/resources/orc.json b/src/data/gold/resources/orc.json similarity index 100% rename from src/data/resources/orc.json rename to src/data/gold/resources/orc.json diff --git a/src/data/resources/roden.json b/src/data/gold/resources/roden.json similarity index 100% rename from src/data/resources/roden.json rename to src/data/gold/resources/roden.json diff --git a/src/data/resources/wolf.json b/src/data/gold/resources/wolf.json similarity index 100% rename from src/data/resources/wolf.json rename to src/data/gold/resources/wolf.json diff --git a/src/data/skills.json b/src/data/gold/skills.json similarity index 100% rename from src/data/skills.json rename to src/data/gold/skills.json diff --git a/src/data/starting_stat_pts/dwarf.json b/src/data/gold/starting_stat_pts/dwarf.json similarity index 100% rename from src/data/starting_stat_pts/dwarf.json rename to src/data/gold/starting_stat_pts/dwarf.json diff --git a/src/data/starting_stat_pts/elf.json b/src/data/gold/starting_stat_pts/elf.json similarity index 100% rename from src/data/starting_stat_pts/elf.json rename to src/data/gold/starting_stat_pts/elf.json diff --git a/src/data/starting_stat_pts/man.json b/src/data/gold/starting_stat_pts/man.json similarity index 100% rename from src/data/starting_stat_pts/man.json rename to src/data/gold/starting_stat_pts/man.json diff --git a/src/data/starting_stat_pts/orc.json b/src/data/gold/starting_stat_pts/orc.json similarity index 100% rename from src/data/starting_stat_pts/orc.json rename to src/data/gold/starting_stat_pts/orc.json diff --git a/src/data/starting_stat_pts/roden.json b/src/data/gold/starting_stat_pts/roden.json similarity index 100% rename from src/data/starting_stat_pts/roden.json rename to src/data/gold/starting_stat_pts/roden.json diff --git a/src/data/starting_stat_pts/wolf.json b/src/data/gold/starting_stat_pts/wolf.json similarity index 100% rename from src/data/starting_stat_pts/wolf.json rename to src/data/gold/starting_stat_pts/wolf.json diff --git a/src/data/traits.json b/src/data/gold/traits.json similarity index 100% rename from src/data/traits.json rename to src/data/gold/traits.json diff --git a/src/data/lifepaths/wizard.json b/src/data/wizard/lifepaths.json similarity index 100% rename from src/data/lifepaths/wizard.json rename to src/data/wizard/lifepaths.json diff --git a/src/data/wizard_skills.json b/src/data/wizard/skills.json similarity index 100% rename from src/data/wizard_skills.json rename to src/data/wizard/skills.json diff --git a/src/data/wizard_traits.json b/src/data/wizard/traits.json similarity index 100% rename from src/data/wizard_traits.json rename to src/data/wizard/traits.json diff --git a/src/lib/data.rb b/src/lib/data.rb index 8e9e648..f980345 100755 --- a/src/lib/data.rb +++ b/src/lib/data.rb @@ -1,176 +1,34 @@ -require 'json' +require_relative 'data/gold' +require_relative 'data/wizard' -module CharredData - def self.merge_data!(to, from) - from.keys.each do |k| - to[k] = from[k] - end - end - - def self.lifepath_requirements(expr) - if expr.is_a? Numeric - [] - elsif expr.is_a? String - if expr.start_with? "+" - [] - else - expr - end - elsif expr.is_a? Array - (expr.map { |e| self.lifepath_requirements(e) }).flatten - else - [] - end - end - - def self.load_wizard_burner(data) - puts 'Loading wizard burner' - file = File.read('data/lifepaths/wizard.json') - wizard_data = JSON.parse(file) - - file = File.read('data/wizard_skills.json') - wizard_skills = JSON.parse(file) - self.merge_data!(data[:skills], wizard_skills) - - file = File.read('data/wizard_traits.json') - wizard_traits = JSON.parse(file) - self.merge_data!(data[:traits], wizard_traits) +module Charred + class Data + include Charred::Gold + include Charred::Wizard - man = data[:lifepaths]['man'] + attr :data - man['College of Magic Setting'] = wizard_data['College of Magic Setting'] - man['Death Cult Setting'] = wizard_data['Death Cult Setting'] + def initialize + @data = {} - self.merge_data!(data[:lifepaths]['orc']['Servant Of The Dark Blood Subsetting'], wizard_data['Servant Of The Dark Blood Subsetting']) - - [ - 'Peasant Setting', - 'Villager Setting', - 'City Dweller Setting', - 'Noble Court Subsetting', - 'Outcast Subsetting' - ].each do |setting| - self.merge_data!(man[setting], wizard_data[setting]) - end - - [ - 'Peasant Setting', - 'Villager Setting', - 'City Dweller Setting', - 'Seafaring Setting', - 'Servitude And Captive Setting' - ].each do |setting| - self.merge_data!(man[setting], { - 'Gifted Child' => wizard_data['Special Gifted Lifepaths']['Gifted Child'] - }) + load_gold(@data) + load_wizard(@data) end - [ - 'Noble Court Subsetting', - 'Religious Subsetting', - 'Outcast Subsetting', - 'Professional Soldier Subsetting' - ].each do |setting| - self.merge_data!(man[setting], { - 'Apt Pupil' => wizard_data['Special Gifted Lifepaths']['Apt Pupil'] - }) - end - - leads_short = { - 'College of Magic Setting' => 'College', - 'Death Cult Setting' => 'Death', - } - - # backfill leads - leads_short.keys.each do |wiz_set| - wizard_data[wiz_set].keys.each do |wiz_lp| - lifepath = wizard_data[wiz_set][wiz_lp] - next if !lifepath['requires_expr'] - - requirements = self.lifepath_requirements(lifepath['requires_expr']) - - requirements.each do |req| - setting = nil - req_lp = req - setting, req_lp = req.split(':') if req.include? ':' - - man.keys.each do |man_set| - next if wiz_set.downcase == man_set.downcase - next if setting && setting != man_set.downcase - man[man_set].keys.each do |man_lp| - next if req_lp != man_lp.downcase - - #puts "adding #{wiz_set}:#{wiz_lp} lead to #{man_set}:#{man_lp}" - - man[man_set][man_lp]['key_leads'] |= [wiz_set] - man[man_set][man_lp]['leads'] |= [leads_short[wiz_set]] - end - end - end - end - end - - # backfill Apt Pupil == Neophyte Sorcerer connection - man.keys.each do |man_set| - man[man_set].keys.each do |man_lp| - requirements = self.lifepath_requirements(man[man_set][man_lp]['requires_expr']) - next if requirements.include? 'apt pupil' - requirements.each do |req| - setting = nil - req_lp = req - setting, req_lp = req.split(':') if req.include? ':' - - next unless req_lp.downcase == 'neophyte sorcerer' - - if man[man_set][man_lp]['requires_expr'].include? 'neophyte sorcerer' - man[man_set][man_lp]['requires_expr'] |= ['apt pupil'] - else - puts "warning, could not add apt pupil to deep requirements array at #{man_set}:#{man_lp}" - end + def lifepath_requirements(expr) + if expr.is_a? Numeric + [] + elsif expr.is_a? String + if expr.start_with? "+" + [] + else + expr end + elsif expr.is_a? Array + (expr.map { |e| self.lifepath_requirements(e) }).flatten + else + [] end end - - data[:lifepaths]['man'] = man - puts 'loaded!' - data - end - - def self.load_data - file = File.read('data/skills.json') - skills = JSON.parse(file) - - file = File.read('data/traits.json') - traits = JSON.parse(file) - - lifepaths = {} - resources = {} - stat_pts = {} - - stocks = ['dwarf', 'elf', 'man', 'orc', 'roden', 'wolf'] - - stocks.each do |stock| - file = File.read("data/lifepaths/#{stock}.json") - lifepaths[stock] = JSON.parse(file) - - file = File.read("data/resources/#{stock}.json") - resources[stock] = JSON.parse(file) - - file = File.read("data/starting_stat_pts/#{stock}.json") - stat_pts[stock] = JSON.parse(file) - end - - data = { - :stocks => stocks, - :skills => skills, - :traits => traits, - :lifepaths => lifepaths, - :resources => resources, - :stat_pts => stat_pts - } - - data = self.load_wizard_burner(data) - - data end end \ No newline at end of file diff --git a/src/lib/data/dark_elf.rb b/src/lib/data/dark_elf.rb new file mode 100755 index 0000000..13a98a8 --- /dev/null +++ b/src/lib/data/dark_elf.rb @@ -0,0 +1,15 @@ +require 'json' + +module Charred + module DarkElf + def load_dark_elf(data) + file = File.read('data/dark_elf/skills.json') + skills = JSON.parse(file) + data[:skills].merge! skills + + file = File.read('data/dark_elf/traits.json') + traits = JSON.parse(file) + data[:traits].merge! traits + end + end +end \ No newline at end of file diff --git a/src/lib/data/gold.rb b/src/lib/data/gold.rb new file mode 100755 index 0000000..febeff2 --- /dev/null +++ b/src/lib/data/gold.rb @@ -0,0 +1,39 @@ +require 'json' + +module Charred + module Gold + def load_gold(data) + file = File.read('data/gold/skills.json') + skills = JSON.parse(file) + + file = File.read('data/gold/traits.json') + traits = JSON.parse(file) + + lifepaths = {} + resources = {} + stat_pts = {} + + stocks = ['dwarf', 'elf', 'man', 'orc', 'roden', 'wolf'] + + stocks.each do |stock| + file = File.read("data/gold/lifepaths/#{stock}.json") + lifepaths[stock] = JSON.parse(file) + + file = File.read("data/gold/resources/#{stock}.json") + resources[stock] = JSON.parse(file) + + file = File.read("data/gold/starting_stat_pts/#{stock}.json") + stat_pts[stock] = JSON.parse(file) + end + + data.merge!({ + :stocks => stocks, + :skills => skills, + :traits => traits, + :lifepaths => lifepaths, + :resources => resources, + :stat_pts => stat_pts + }) + end + end +end \ No newline at end of file diff --git a/src/lib/data/wizard.rb b/src/lib/data/wizard.rb new file mode 100755 index 0000000..ba805b0 --- /dev/null +++ b/src/lib/data/wizard.rb @@ -0,0 +1,118 @@ +require 'json' + +module Charred + module Wizard + def load_wizard(data) + puts 'Loading wizard burner' + file = File.read('data/wizard/lifepaths.json') + wizard_data = JSON.parse(file) + + file = File.read('data/wizard/skills.json') + wizard_skills = JSON.parse(file) + data[:skills].merge! wizard_skills + + file = File.read('data/wizard/traits.json') + wizard_traits = JSON.parse(file) + data[:traits].merge! wizard_traits + + man = data[:lifepaths]['man'] + + man['College of Magic Setting'] = wizard_data['College of Magic Setting'] + man['Death Cult Setting'] = wizard_data['Death Cult Setting'] + + data[:lifepaths]['orc']['Servant Of The Dark Blood Subsetting'].merge!(wizard_data['Servant Of The Dark Blood Subsetting']) + + [ + 'Peasant Setting', + 'Villager Setting', + 'City Dweller Setting', + 'Noble Court Subsetting', + 'Outcast Subsetting' + ].each do |setting| + man[setting].merge!(wizard_data[setting]) + end + + [ + 'Peasant Setting', + 'Villager Setting', + 'City Dweller Setting', + 'Seafaring Setting', + 'Servitude And Captive Setting' + ].each do |setting| + man[setting].merge!({ + 'Gifted Child' => wizard_data['Special Gifted Lifepaths']['Gifted Child'] + }) + end + + [ + 'Noble Court Subsetting', + 'Religious Subsetting', + 'Outcast Subsetting', + 'Professional Soldier Subsetting' + ].each do |setting| + man[setting].merge!({ + 'Apt Pupil' => wizard_data['Special Gifted Lifepaths']['Apt Pupil'] + }) + end + + leads_short = { + 'College of Magic Setting' => 'College', + 'Death Cult Setting' => 'Death', + } + + # backfill leads + leads_short.keys.each do |wiz_set| + wizard_data[wiz_set].keys.each do |wiz_lp| + lifepath = wizard_data[wiz_set][wiz_lp] + next if !lifepath['requires_expr'] + + requirements = self.lifepath_requirements(lifepath['requires_expr']) + + requirements.each do |req| + setting = nil + req_lp = req + setting, req_lp = req.split(':') if req.include? ':' + + man.keys.each do |man_set| + next if wiz_set.downcase == man_set.downcase + next if setting && setting != man_set.downcase + man[man_set].keys.each do |man_lp| + next if req_lp != man_lp.downcase + + #puts "adding #{wiz_set}:#{wiz_lp} lead to #{man_set}:#{man_lp}" + + man[man_set][man_lp]['key_leads'] |= [wiz_set] + man[man_set][man_lp]['leads'] |= [leads_short[wiz_set]] + end + end + end + end + end + + # backfill Apt Pupil == Neophyte Sorcerer connection + man.keys.each do |man_set| + man[man_set].keys.each do |man_lp| + requirements = self.lifepath_requirements(man[man_set][man_lp]['requires_expr']) + next if requirements.include? 'apt pupil' + requirements.each do |req| + setting = nil + req_lp = req + setting, req_lp = req.split(':') if req.include? ':' + + next unless req_lp.downcase == 'neophyte sorcerer' + + if man[man_set][man_lp]['requires_expr'].include? 'neophyte sorcerer' + man[man_set][man_lp]['requires_expr'] |= ['apt pupil'] + else + puts "warning, could not add apt pupil to deep requirements array at #{man_set}:#{man_lp}" + end + end + end + end + + data[:lifepaths]['man'] = man + puts 'loaded!' + data + end + end +end \ No newline at end of file