pfrpg_core 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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