pfrpg_core 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 04e10d025ab0c0eabc6af56107b277194255e478
4
+ data.tar.gz: 7c2dfb7e770d7399d495ab5eae8aaedabcd97adc
5
+ SHA512:
6
+ metadata.gz: 5f755c54bebcc8ede1c1cdcd7c5aa094b00de3f63e3e46d7cec2f40d6c97f7538fb5af38d6bfee79fc6763ef39c8e014c8e912536cb72bbcf479681f7ba85e97
7
+ data.tar.gz: a69a83f0f8d0e08596b5f2f49cd2fa94475862194449c6ba6d5af2765eff2c5ad1aed2b896866a7ff1e5f9623cc1370be5a36a3f765005951b78857605f31adb
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs.push "lib"
5
+ t.test_files = FileList['test/*_test.rb']
6
+ t.verbose = true
7
+ end
@@ -0,0 +1,7 @@
1
+ module PfrpgCore
2
+ module Affectable
3
+ def get_effects
4
+ Effect.load(effects)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ module PfrpgCore
2
+ module Bonus
3
+ def get_bonus(bonus)
4
+ apply_bonuses if @bonuses == nil
5
+ NullObject.maybe(@bonuses.get(bonus))
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,57 @@
1
+ module PfrpgCore
2
+ class Bonuses
3
+ attr_reader :bonus_pool
4
+ def initialize
5
+ @bonus_pool = {}
6
+ end
7
+
8
+ def specials
9
+ ['speed', 'damage_reduction', 'spell_resistance', 'class_skill']
10
+ end
11
+
12
+ def get(key)
13
+ if specials.include? key
14
+ return self.send(key)
15
+ else
16
+ return NullObject.maybe(@bonus_pool[key])
17
+ end
18
+ end
19
+
20
+ def plus(key, value)
21
+ begin
22
+ v = MathHelper.is_number(value) ? value.to_i : value
23
+ if specials.include? key
24
+ if @bonus_pool[key]
25
+ @bonus_pool[key] << value
26
+ else
27
+ @bonus_pool[key] = [value]
28
+ end
29
+ elsif @bonus_pool[key]
30
+ @bonus_pool[key] += v
31
+ else
32
+ @bonus_pool[key] = v
33
+ end
34
+ rescue Exception => e
35
+ ap @bonus_pool
36
+ ap "Trying to add #{key}, #{value}"
37
+ end
38
+ end
39
+
40
+ def speed
41
+ [ @bonus_pool['speed'] ].flatten
42
+ end
43
+
44
+ def class_skill
45
+ [ @bonus_pool['class_skill'] ].flatten
46
+ end
47
+
48
+ def damage_reduction
49
+ [ @bonus_pool['damage_reduction'] ].flatten
50
+ end
51
+
52
+ def spell_resistance
53
+ [ @bonus_pool['spell_resistance'] ].flatten
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,39 @@
1
+ class PfrpgCore::Effect
2
+ attr_accessor :type, :key, :value, :affect
3
+ def initialize(type, key, value, affect=nil)
4
+ # standard effect proc; add a value
5
+ basic = Proc.new do |character, attribute, value|
6
+ character.bonuses.plus(attribute, value)
7
+ end
8
+ affect ||= basic
9
+ @type = type
10
+ @key = key
11
+ @value = value
12
+ @affect = affect
13
+ end
14
+
15
+ def self.load(effects_string)
16
+ return effects_string if effects_string.instance_of? Array
17
+ return [ effects_string ] if effects_string.instance_of? PfrpgCore::Effect
18
+ return [] if effects_string.nil? || effects_string.empty?
19
+ unless effects_string.instance_of? String
20
+ ap "Error effect: "
21
+ ap effects_string
22
+ end
23
+ raise Exception unless effects_string.instance_of? String
24
+ effects_string.split(";").map { |effect| parse_effect(effect) }
25
+ end
26
+
27
+ def self.parse_effect(string)
28
+ p = string.split(":")
29
+ type = p[0]
30
+ key = p[1]
31
+ value = p[2]
32
+ PfrpgCore::Effect.new(type, key, value)
33
+ end
34
+
35
+ def apply(character)
36
+ @affect.call(character, @key, @value)
37
+ end
38
+
39
+ end
@@ -0,0 +1,49 @@
1
+ module PfrpgCore
2
+ class EffectProcessor
3
+ attr_reader :character, :effects
4
+ def initialize(character, effects)
5
+ @character = character
6
+ @effects = effects
7
+ end
8
+
9
+ def process_effects
10
+ final = []
11
+ no_stacking = effects_hash(@effects)
12
+ no_stacking.keys.each do |key|
13
+ if Tables::Bonus.stackable?(key) || Tables::Bonus.special?(key)
14
+ final << no_stacking[key]
15
+ else
16
+ final << find_max(no_stacking[key])
17
+ end
18
+ end
19
+ return final.flatten
20
+ end
21
+
22
+ def effects_hash(effects)
23
+ hash = {}
24
+ effects.each do |effect|
25
+ if hash[effect.key] == nil
26
+ hash[effect.key] = []
27
+ end
28
+ hash[effect.key] << effect
29
+ end
30
+ hash
31
+ end
32
+
33
+ def find_max(effects)
34
+ max = nil
35
+ effects.each do |e|
36
+ if max == nil || is_larger(e.value, max.value)
37
+ max = e
38
+ end
39
+ end
40
+ return max
41
+ end
42
+
43
+ def is_larger(a, b)
44
+ int_a = MathHelper.is_number(a) ? a.to_i : -999
45
+ int_b = MathHelper.is_number(b) ? b.to_i : -999
46
+ int_a > int_b
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,49 @@
1
+ module PfrpgCore
2
+ class FeatFinder
3
+ attr_reader :entity, :feats
4
+ def initialize(entity, feats)
5
+ @entity = entity
6
+ @feats = feats
7
+ end
8
+
9
+ def find_feats
10
+ feats = @feats
11
+ feats = filter_feats_by_owned(feats, entity)
12
+ feats = filter_feats_by_prereq(feats, entity)
13
+ return feats
14
+ end
15
+
16
+ def filter_feats_by_owned(feats, entity)
17
+ owned_feats = entity.feats
18
+ feats.select do |f|
19
+ repeat_list.include?(f.name) ||
20
+ doesnt_include_feat(owned_feats, f)
21
+ end
22
+ end
23
+
24
+ def doesnt_include_feat(feats, feat)
25
+ !(feats.find { |x| x.name == feat.name })
26
+ end
27
+
28
+ def filter_feats_by_prereq(feats, entity)
29
+ feats.select do |f|
30
+ prereq_check(entity, f)
31
+ end
32
+ end
33
+
34
+ def prereq_check(entity, feat)
35
+ prereqs = Prerequisite.load(feat.prereq_code)
36
+ prereqs.all? { |x| x.match(entity) }
37
+ end
38
+
39
+ def repeat_list
40
+ [
41
+ 'Exotic Weapon Proficiency',
42
+ 'Martial Weapon Proficiency',
43
+ 'Weapon Focus',
44
+ 'Spell Focus',
45
+ 'Custom Feat'
46
+ ]
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,11 @@
1
+ module PfrpgCore::Filterable
2
+ def apply_filters
3
+ @filters.each do |f|
4
+ begin
5
+ self.filter_str << "Filtering #{f.class}"
6
+ f.filter(self)
7
+ rescue Exception => e
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,34 @@
1
+ module PfrpgCore
2
+ class LevelParser
3
+ attr_reader :level_string, :levels
4
+ def initialize(level_string)
5
+ @level_string = level_string
6
+ @levels = parse
7
+ end
8
+
9
+ def total
10
+ return @levels.values.inject(0) { |sum, l| sum + l }
11
+ end
12
+
13
+ def parse
14
+ levels = {}
15
+ splits = @level_string.split(';')
16
+ raise Exception if splits[0].empty?
17
+
18
+ splits.each do |s|
19
+ level = s.split(':')[1].to_i
20
+ hc = s.split(':')[0]
21
+ raise Exception if (hc.empty?)
22
+ levels[hc] = level
23
+ end
24
+ return levels
25
+ end
26
+
27
+ def valid_total_level
28
+ return total <= 20
29
+ rescue Exception
30
+ return false
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,6 @@
1
+ class PfrpgCore::MathHelper
2
+ def self.is_number(s)
3
+ s.to_s.match(/\A[+-]?\d+?(\.\d+)?\Z/) == nil ? false : true
4
+ end
5
+
6
+ end
@@ -0,0 +1,37 @@
1
+ class PfrpgCore::NullObject < Numeric
2
+ def to_a; []; end
3
+ def to_s; ""; end
4
+ def to_str; ""; end
5
+ def to_f; 0.0; end
6
+ def to_i; 0; end
7
+
8
+ def empty?
9
+ true
10
+ end
11
+
12
+ def as_json(options={})
13
+ ""
14
+ end
15
+
16
+ def method_missing(*args, &block)
17
+ self
18
+ end
19
+
20
+ def self.maybe(value)
21
+ case value
22
+ when nil then NullObject.new
23
+ else value
24
+ end
25
+ end
26
+
27
+ def +(other)
28
+ case other
29
+ when String
30
+ to_s + other
31
+ when Fixnum
32
+ to_i + other
33
+ when Float
34
+ to_f + other
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,58 @@
1
+ module PfrpgCore
2
+ class Prerequisite
3
+
4
+ def initialize(attribute, value, matcher=nil)
5
+ default_matcher = Proc.new do |character, attribute, value|
6
+ true
7
+ end
8
+ @attribute = attribute
9
+ @value = value
10
+ @matcher = matcher || default_matcher
11
+ end
12
+
13
+ def self.load(prereq_string)
14
+ begin
15
+ prereqs = []
16
+ p = prereq_string.split(";")
17
+ p.each { |x| prereqs << parse_prereq(x) }
18
+ prereqs
19
+ rescue Exception
20
+ []
21
+ end
22
+ end
23
+
24
+ def self.parse_prereq(string)
25
+ p = string.split(":")
26
+ type = p[0]
27
+ attribute = p[1]
28
+ value = p[2]
29
+ case type
30
+ when "class"
31
+ Prerequisite::ClassPrereq.new(attribute, value)
32
+ when "attribute"
33
+ Prerequisite::AttributePrereq.new(attribute, value)
34
+ when "alignment"
35
+ Prerequisite::AlignmentPrereq.new(attribute, value)
36
+ when "feat"
37
+ Prerequisite::FeatPrereq.new(attribute, value)
38
+ when "skill"
39
+ Prerequisite::SkillPrereq.new(attribute, value)
40
+ when "class_feature"
41
+ Prerequisite::HeroclassFeaturePrereq.new(attribute, value)
42
+ when "combat"
43
+ Prerequisite::BabPrereq.new(attribute, value)
44
+ when "language"
45
+ Prerequisite::LanguagePrereq.new(attribute, value)
46
+ when "misc"
47
+ Prerequisite::MiscPrereq.new(attribute, value)
48
+ else
49
+ Prerequisite.new(attribute, value)
50
+ end
51
+ end
52
+
53
+ def match(character)
54
+ @matcher.call(character, @attribute, @value)
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,37 @@
1
+ # basic class math. classes must provide latest_levels method
2
+ # with a map of heroclass name & level
3
+ module PfrpgCore
4
+ module QuickClassed
5
+ def get_class_level(heroclass)
6
+ l = latest_levels[heroclass.name]
7
+ l ||= 0
8
+ return l
9
+ end
10
+
11
+ def explode_levels
12
+ # TODO: implement me
13
+ []
14
+ end
15
+
16
+ def get_total_level
17
+ latest_levels.keys.inject(0) do |key, sum|
18
+ sum = sum + latest_levels[key]
19
+ end
20
+ end
21
+
22
+ def hit_dice
23
+ get_total_level
24
+ end
25
+
26
+ def get_caster_level
27
+ # TODO constantize somewhere better
28
+ caster_classes = ['Bard', 'Cleric', 'Druid', 'Paladin', 'Ranger', 'Sorcerer', 'Wizard']
29
+ caster_levels = []
30
+ latest_levels.keys.each do |key|
31
+ caster_levels << latest_levels[key] if caster_classes.include? key
32
+ end
33
+ ek_level = get_class_level(Heroclass.by_name('Eldritch Knight'))
34
+ return (caster_levels.max + ek_level) || 0
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,3 @@
1
+ module PfrpgCore
2
+ VERSION = "0.0.1"
3
+ end
data/lib/pfrpg_core.rb ADDED
@@ -0,0 +1,11 @@
1
+ require 'pfrpg_core/effect'
2
+ require 'pfrpg_core/effect_processor'
3
+ require 'pfrpg_core/math_helper'
4
+ require 'pfrpg_core/null_object'
5
+
6
+ Dir[File.expand_path(File.join(File.dirname(File.absolute_path(__FILE__)), 'pfrpg_core/')) + "/**/*.rb"].each do |file|
7
+ require file
8
+ end
9
+
10
+ module PfrpgCore
11
+ end
@@ -0,0 +1,14 @@
1
+ require 'minitest/autorun'
2
+ require 'test/helper'
3
+
4
+ class FeatFinderTest < Minitest::Test
5
+
6
+ def test_filter_feats_by_owned
7
+ e = PsuedoEntity.new
8
+ feats = [ PsuedoFeat.new('Feat1') ]
9
+ finder = FeatFinder.new(e, feats)
10
+ assert finder.find_feats.empty?
11
+ end
12
+
13
+
14
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,20 @@
1
+ class Helper
2
+
3
+ PsuedoFeat = Struct.new(:name) do
4
+ def prereq_code
5
+ nil
6
+ end
7
+ end
8
+
9
+ class PsuedoEntity
10
+ attr_accessor :feats
11
+ def initialize(feats = nil)
12
+ @feats = feats
13
+ @feats ||= default_feats
14
+ end
15
+
16
+ def default_feats
17
+ [ PsuedoFeat.new('Feat1') ]
18
+ end
19
+ end
20
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pfrpg_core
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jordan OMara
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-11-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 4.1.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 4.1.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: sqlite3
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: core
42
+ email:
43
+ - jordan@herosheets.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - Rakefile
49
+ - lib/pfrpg_core.rb
50
+ - lib/pfrpg_core/affectable.rb
51
+ - lib/pfrpg_core/bonus.rb
52
+ - lib/pfrpg_core/bonuses.rb
53
+ - lib/pfrpg_core/effect.rb
54
+ - lib/pfrpg_core/effect_processor.rb
55
+ - lib/pfrpg_core/feat_finder.rb
56
+ - lib/pfrpg_core/filterable.rb
57
+ - lib/pfrpg_core/level_parser.rb
58
+ - lib/pfrpg_core/math_helper.rb
59
+ - lib/pfrpg_core/null_object.rb
60
+ - lib/pfrpg_core/prerequisite.rb
61
+ - lib/pfrpg_core/quick_classed.rb
62
+ - lib/pfrpg_core/version.rb
63
+ - test/feat_totaler_test.rb
64
+ - test/helper.rb
65
+ homepage: http://herosheets.com
66
+ licenses: []
67
+ metadata: {}
68
+ post_install_message:
69
+ rdoc_options: []
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ requirements: []
83
+ rubyforge_project:
84
+ rubygems_version: 2.2.2
85
+ signing_key:
86
+ specification_version: 4
87
+ summary: PFRPG core
88
+ test_files:
89
+ - test/feat_totaler_test.rb
90
+ - test/helper.rb