VanaTime 2.0.0 → 2.1.0
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.
- data/CHANGELOG +6 -0
- data/Manifest +3 -0
- data/README +95 -125
- data/VanaTime.gemspec +17 -17
- data/lib/Vana/common.rb +65 -65
- data/lib/Vana/constants.rb +20 -21
- data/lib/Vana/day.rb +47 -44
- data/lib/Vana/element.rb +45 -40
- data/lib/Vana/moon.rb +131 -139
- data/lib/Vana/moon_countdown.rb +48 -51
- data/lib/Vana/skillup_calculator.rb +142 -0
- data/lib/Vana/time.rb +98 -110
- data/lib/Vana/time_manager.rb +91 -64
- data/lib/util/log_listener.rb +15 -0
- data/lib/util/ruby_bean.rb +39 -0
- data/lib/vana_time.rb +7 -2
- metadata +35 -39
data/lib/Vana/moon_countdown.rb
CHANGED
@@ -1,67 +1,64 @@
|
|
1
1
|
module FFXI
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
include Observable
|
2
|
+
class VanaMoonCountdown < Util::RubyBean
|
3
|
+
include FFXI::Constants
|
4
|
+
include FFXI::Common
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
end
|
6
|
+
property :next_phase_countdown, :optimal_phase_countdown
|
7
|
+
property :next_phase_countdown_string, :optimal_phase_countdown_string
|
10
8
|
|
11
|
-
|
12
|
-
|
13
|
-
@moon = moon
|
14
|
-
if @moon.earth_time != @earth_time
|
15
|
-
self.earth_time = @moon.earth_time
|
16
|
-
end
|
17
|
-
end
|
9
|
+
alias to_next next_phase_countdown_string
|
10
|
+
alias to_optimal optimal_phase_countdown_string
|
18
11
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
localtime = (@earth_time.to_f * 1000).to_i
|
25
|
-
@elapsed_time = (localtime - MS_MOON_DATE.to_i) % MS_GAME_DAY
|
12
|
+
def initialize(opts={})
|
13
|
+
super()
|
14
|
+
add_listener(opts[:listener]) if opts[:listener]
|
15
|
+
update_moon(opts[:moon]) if opts[:moon]
|
16
|
+
end
|
26
17
|
|
27
|
-
|
28
|
-
|
29
|
-
end
|
18
|
+
def update_moon(moon)
|
19
|
+
raise "Input needs to be a VanaMoon object" if ! moon.is_a? VanaMoon
|
30
20
|
|
31
|
-
|
32
|
-
|
21
|
+
@next_phase_target = moon.next_phase_target
|
22
|
+
@optimal_phase_target = moon.optimal_phase_target
|
23
|
+
@moon_days = moon.moon_days
|
33
24
|
|
34
|
-
|
35
|
-
|
36
|
-
end
|
25
|
+
update_earth_time moon.earth_time
|
26
|
+
end
|
37
27
|
|
38
|
-
|
39
|
-
|
40
|
-
end
|
28
|
+
def update_earth_time(earth_time)
|
29
|
+
raise "Input needs to be a Time object" if ! earth_time.is_a? Time
|
41
30
|
|
42
|
-
|
31
|
+
@earth_time = earth_time
|
32
|
+
localtime = (@earth_time.to_f * 1000).to_i
|
33
|
+
@elapsed_time = (localtime - MS_MOON_DATE.to_i) % MS_GAME_DAY
|
43
34
|
|
44
|
-
|
45
|
-
|
35
|
+
update_countdowns if @moon_days
|
36
|
+
end
|
46
37
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
38
|
+
def update_vana_time(vt)
|
39
|
+
if vt.is_a? VanaTime
|
40
|
+
update_earth_time(vt.earth_time)
|
41
|
+
else
|
42
|
+
update_earth_time(FFXI::Common.vana_to_earth(vt))
|
43
|
+
end
|
44
|
+
end
|
52
45
|
|
53
|
-
|
46
|
+
attr_reader :elapsed_time, :earth_time
|
54
47
|
|
55
|
-
|
56
|
-
@to_optimal_array = to_optimal_array
|
57
|
-
changed
|
58
|
-
notify_observers("optimal_phase_countdown", self)
|
59
|
-
end
|
60
|
-
end
|
48
|
+
private
|
61
49
|
|
62
|
-
|
63
|
-
|
64
|
-
|
50
|
+
def update_countdowns
|
51
|
+
self.next_phase_countdown = countdown_to(@next_phase_target)
|
52
|
+
self.next_phase_countdown_string =
|
53
|
+
format_countdown(next_phase_countdown)
|
54
|
+
self.optimal_phase_countdown = countdown_to(@optimal_phase_target)
|
55
|
+
self.optimal_phase_countdown_string =
|
56
|
+
format_countdown(optimal_phase_countdown)
|
57
|
+
end
|
65
58
|
|
59
|
+
def countdown_to(target)
|
60
|
+
countdown((target - @moon_days) * MS_GAME_DAY - @elapsed_time)
|
66
61
|
end
|
67
|
-
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
module FFXI
|
2
|
+
class SkillupCalculator < Util::RubyBean
|
3
|
+
include FFXI::Constants
|
4
|
+
|
5
|
+
property :day_crystal_factor, :moon_phase_factor, :base_difficulty
|
6
|
+
property :skillup_difficulty
|
7
|
+
|
8
|
+
def initialize(opts={})
|
9
|
+
super()
|
10
|
+
|
11
|
+
add_listener(opts[:listener]) if opts[:listener]
|
12
|
+
|
13
|
+
@recipe_cap = opts[:recipe_cap] || 0
|
14
|
+
@skill = opts[:skill] || 0
|
15
|
+
update_base_difficulty
|
16
|
+
|
17
|
+
@crystal_element = opts[:crystal_element] if opts[:crystal_element]
|
18
|
+
|
19
|
+
if opts[:vana_day] and opts[:vana_moon]
|
20
|
+
update_day_and_moon(opts[:vana_day], opts[:vana_moon])
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def update_day_and_moon(vanaday, vanamoon)
|
25
|
+
if (! vanaday.is_a? VanaDay) || (! vanamoon.is_a? VanaMoon)
|
26
|
+
raise "invalid input. initialize with a VanaDay and VanaMoon object"
|
27
|
+
end
|
28
|
+
|
29
|
+
@day_element = vanaday.day_element
|
30
|
+
@moon_percent = vanamoon.moon_percent
|
31
|
+
|
32
|
+
if @day_element and @moon_percent
|
33
|
+
update_moon_phase_factor
|
34
|
+
|
35
|
+
if ! @crystal_element.nil?
|
36
|
+
update_day_crystal_factor
|
37
|
+
update_skillup_difficulty
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def crystal_element=(element)
|
43
|
+
@crystal_element = element
|
44
|
+
|
45
|
+
if ! @day_element.nil?
|
46
|
+
update_day_crystal_factor
|
47
|
+
update_skillup_difficulty
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def recipe_cap=(cap)
|
52
|
+
if @recipe_cap != cap
|
53
|
+
@recipe_cap = cap
|
54
|
+
update_base_difficulty
|
55
|
+
update_skillup_difficulty if ! @crystal_element.nil?
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def skill=(skill)
|
60
|
+
if @skill != skill
|
61
|
+
@skill = skill
|
62
|
+
update_base_difficulty
|
63
|
+
update_skillup_difficulty if ! @crystal_element.nil?
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
attr_reader :crystal_element, :recipe_cap, :skill
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def build_difficulty_hash(type)
|
72
|
+
sum_of_factors = self.base_difficulty - (self.moon_phase_factor +
|
73
|
+
self.day_crystal_factor)
|
74
|
+
|
75
|
+
case type
|
76
|
+
when :success
|
77
|
+
direction = @crystal_element.direction
|
78
|
+
direction_modifier = 0.5
|
79
|
+
when :quality
|
80
|
+
estr = ElementFactory.send "#{@crystal_element.strength}"
|
81
|
+
direction = estr.direction
|
82
|
+
direction_modifier = -0.5
|
83
|
+
when :neutral
|
84
|
+
direction = "Neutral"
|
85
|
+
direction_modifier = 0.0
|
86
|
+
end
|
87
|
+
|
88
|
+
difficulty_hash = {:direction => direction}
|
89
|
+
|
90
|
+
[[:advanced_support, 2], [:free_support, 1], [:no_support, 0]].each do |s,m|
|
91
|
+
support = s
|
92
|
+
support_modifier = m
|
93
|
+
|
94
|
+
difficulty_hash[support] =
|
95
|
+
(sum_of_factors - direction_modifier - support_modifier)
|
96
|
+
end
|
97
|
+
|
98
|
+
difficulty_hash
|
99
|
+
end
|
100
|
+
|
101
|
+
def update_skillup_difficulty
|
102
|
+
success = build_difficulty_hash(:success)
|
103
|
+
neutral = build_difficulty_hash(:neutral)
|
104
|
+
quality = build_difficulty_hash(:quality)
|
105
|
+
|
106
|
+
self.skillup_difficulty = {
|
107
|
+
:success => success,
|
108
|
+
:neutral => neutral,
|
109
|
+
:quality => quality
|
110
|
+
}
|
111
|
+
end
|
112
|
+
|
113
|
+
def update_base_difficulty
|
114
|
+
self.base_difficulty = @recipe_cap - @skill
|
115
|
+
end
|
116
|
+
|
117
|
+
def update_moon_phase_factor
|
118
|
+
self.moon_phase_factor = (@moon_percent.abs - 50.0) / 50
|
119
|
+
end
|
120
|
+
|
121
|
+
def update_day_crystal_factor
|
122
|
+
raise "@crystal_element is unset" if @crystal_element.nil?
|
123
|
+
|
124
|
+
day_element = @day_element.name
|
125
|
+
day_strength = @day_element.strength
|
126
|
+
crystal_element = @crystal_element.name
|
127
|
+
|
128
|
+
if day_element == "Light" and crystal_element != "Darkness"
|
129
|
+
self.day_crystal_factor = 1
|
130
|
+
elsif day_element == "Darkness" and crystal_element != "Light"
|
131
|
+
self.day_crystal_factor = -1
|
132
|
+
elsif day_element == crystal_element
|
133
|
+
self.day_crystal_factor = 1
|
134
|
+
elsif day_strength == crystal_element
|
135
|
+
self.day_crystal_factor = -1
|
136
|
+
else
|
137
|
+
self.day_crystal_factor = 0
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
end
|
data/lib/Vana/time.rb
CHANGED
@@ -1,113 +1,101 @@
|
|
1
1
|
module FFXI
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
18
|
-
|
19
|
-
def earth_time=(time)
|
20
|
-
raise "input needs to be a Time object" if ! time.is_a? Time
|
21
|
-
@earth_time = time
|
22
|
-
vt = FFXI::Common.earth_to_vana(time)
|
23
|
-
set_instance_variables(vt)
|
24
|
-
end
|
25
|
-
|
26
|
-
def vana_time=(vt)
|
27
|
-
@earth_time = Time.at(FFXI::Common.vana_to_earth(vt))
|
28
|
-
set_instance_variables(vt)
|
29
|
-
end
|
30
|
-
|
31
|
-
attr_reader :hour, :minute, :second
|
32
|
-
attr_reader :date, :month, :year, :tomorrow
|
33
|
-
attr_reader :hour_start, :minute_start, :second_start
|
34
|
-
attr_reader :date_start, :month_start, :year_start
|
35
|
-
attr_reader :vana_time, :earth_time
|
36
|
-
|
37
|
-
def to_i
|
38
|
-
@vana_time.to_i
|
39
|
-
end
|
40
|
-
|
41
|
-
def to_f
|
42
|
-
@vana_time.to_f
|
43
|
-
end
|
44
|
-
|
45
|
-
def time_string
|
46
|
-
"#{"%02d" % hour}:#{"%02d" % minute}:#{"%02d" % second}"
|
47
|
-
end
|
48
|
-
|
49
|
-
def date_string
|
50
|
-
"#{year}-#{"%02d" % month}-#{"%02d" % date}"
|
51
|
-
end
|
52
|
-
|
53
|
-
def to_s
|
54
|
-
"#{date_string} #{time_string}"
|
55
|
-
end
|
56
|
-
|
57
|
-
private
|
58
|
-
|
59
|
-
def set_instance_variables(vt)
|
60
|
-
@vana_time = vt.to_f
|
61
|
-
|
62
|
-
set_year if year_has_passed_since(@year_start, @vana_time)
|
63
|
-
set_month if month_has_passed_since(@month_start, @vana_time)
|
64
|
-
set_date if day_has_passed_since(@date_start, @vana_time)
|
65
|
-
set_hour if hour_has_passed_since(@hour_start, @vana_time)
|
66
|
-
set_minute if minute_has_passed_since(@minute_start, @vana_time)
|
67
|
-
set_second if second_has_passed_since(@second_start, @vana_time)
|
68
|
-
end
|
69
|
-
|
70
|
-
def set_year
|
71
|
-
@year = (@vana_time.to_f / MS_YEAR).to_i
|
72
|
-
@year_start = start_of_period(@vana_time, MS_YEAR)
|
73
|
-
changed
|
74
|
-
notify_observers(MS_YEAR, self)
|
75
|
-
end
|
76
|
-
|
77
|
-
def set_month
|
78
|
-
@month = (((@vana_time.to_f % MS_YEAR) / MS_MONTH) + 1).to_i
|
79
|
-
@month_start = start_of_period(@vana_time, MS_MONTH)
|
80
|
-
changed
|
81
|
-
notify_observers(MS_MONTH, self)
|
82
|
-
end
|
83
|
-
|
84
|
-
def set_date
|
85
|
-
@date = (((@vana_time.to_f % MS_MONTH) / MS_DAY) + 1).to_i
|
86
|
-
@date_start = start_of_period(@vana_time, MS_DAY)
|
87
|
-
@tomorrow = @date_start.to_f + MS_DAY
|
88
|
-
changed
|
89
|
-
notify_observers(MS_DAY, self)
|
90
|
-
end
|
91
|
-
|
92
|
-
def set_hour
|
93
|
-
@hour = ((@vana_time % MS_DAY) / MS_HOUR).to_i
|
94
|
-
@hour_start = start_of_period(@vana_time, MS_HOUR)
|
95
|
-
changed
|
96
|
-
notify_observers(MS_HOUR, self)
|
97
|
-
end
|
98
|
-
|
99
|
-
def set_minute
|
100
|
-
@minute = ((@vana_time % MS_HOUR) / MS_MINUTE).to_i
|
101
|
-
@minute_start = start_of_period(@vana_time, MS_MINUTE)
|
102
|
-
changed
|
103
|
-
notify_observers(MS_MINUTE, self)
|
104
|
-
end
|
105
|
-
|
106
|
-
def set_second
|
107
|
-
@second = ((@vana_time % MS_MINUTE) / MS_SECOND).to_i
|
108
|
-
@second_start = start_of_period(@vana_time, MS_SECOND)
|
109
|
-
changed
|
110
|
-
notify_observers(MS_SECOND, self)
|
111
|
-
end
|
2
|
+
class VanaTime < Util::RubyBean
|
3
|
+
include FFXI::Constants
|
4
|
+
include FFXI::Common
|
5
|
+
|
6
|
+
property :hour, :minute, :second
|
7
|
+
property :hour_start, :minute_start, :second_start
|
8
|
+
property :date, :month, :year, :tomorrow
|
9
|
+
property :date_start, :month_start, :year_start
|
10
|
+
property :earth_time, :vana_time
|
11
|
+
property :time_string, :date_string
|
12
|
+
|
13
|
+
def initialize(opts={})
|
14
|
+
super()
|
15
|
+
add_listener(opts[:listener]) if opts[:listener]
|
16
|
+
update_earth_time(opts[:earth_time]) if opts[:earth_time]
|
112
17
|
end
|
18
|
+
|
19
|
+
def self.at(vt, listener = nil)
|
20
|
+
opts = {:earth_time => Time.at(FFXI::Common.vana_to_earth(vt))}
|
21
|
+
opts[:listener] = listener if listener
|
22
|
+
self.new(opts)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.now(listener = nil)
|
26
|
+
opts = {:earth_time => Time.now}
|
27
|
+
opts[:listener] = listener if listener
|
28
|
+
self.new(opts)
|
29
|
+
end
|
30
|
+
|
31
|
+
def update_earth_time(time)
|
32
|
+
raise "input needs to be a Time object" if ! time.is_a? Time
|
33
|
+
self.earth_time = time
|
34
|
+
vt = FFXI::Common.earth_to_vana(time)
|
35
|
+
set_properties(vt)
|
36
|
+
end
|
37
|
+
|
38
|
+
def update_vana_time(vt)
|
39
|
+
self.earth_time = Time.at(FFXI::Common.vana_to_earth(vt))
|
40
|
+
set_properties(vt)
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_i
|
44
|
+
vana_time.to_i
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_f
|
48
|
+
vana_time.to_f
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_s
|
52
|
+
"#{date_string} #{time_string}"
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def set_properties(vt)
|
58
|
+
self.vana_time = vt.to_f
|
59
|
+
|
60
|
+
set_year if year_has_passed_since(year_start, vana_time)
|
61
|
+
set_month if month_has_passed_since(month_start, vana_time)
|
62
|
+
set_date if day_has_passed_since(date_start, vana_time)
|
63
|
+
set_hour if hour_has_passed_since(hour_start, vana_time)
|
64
|
+
set_minute if minute_has_passed_since(minute_start, vana_time)
|
65
|
+
set_second if second_has_passed_since(second_start, vana_time)
|
66
|
+
end
|
67
|
+
|
68
|
+
def set_year
|
69
|
+
self.year = (vana_time.to_f / MS_YEAR).to_i
|
70
|
+
self.year_start = start_of_period(vana_time, MS_YEAR)
|
71
|
+
end
|
72
|
+
|
73
|
+
def set_month
|
74
|
+
self.month = (((vana_time.to_f % MS_YEAR) / MS_MONTH) + 1).to_i
|
75
|
+
self.month_start = start_of_period(vana_time, MS_MONTH)
|
76
|
+
end
|
77
|
+
|
78
|
+
def set_date
|
79
|
+
self.date = (((vana_time.to_f % MS_MONTH) / MS_DAY) + 1).to_i
|
80
|
+
self.date_start = start_of_period(vana_time, MS_DAY)
|
81
|
+
self.tomorrow = date_start.to_f + MS_DAY
|
82
|
+
self.date_string = "#{year}-#{"%02d" % month}-#{"%02d" % date}"
|
83
|
+
end
|
84
|
+
|
85
|
+
def set_hour
|
86
|
+
self.hour = ((vana_time % MS_DAY) / MS_HOUR).to_i
|
87
|
+
self.hour_start = start_of_period(vana_time, MS_HOUR)
|
88
|
+
end
|
89
|
+
|
90
|
+
def set_minute
|
91
|
+
self.minute = ((vana_time % MS_HOUR) / MS_MINUTE).to_i
|
92
|
+
self.minute_start = start_of_period(vana_time, MS_MINUTE)
|
93
|
+
end
|
94
|
+
|
95
|
+
def set_second
|
96
|
+
self.second = ((vana_time % MS_MINUTE) / MS_SECOND).to_i
|
97
|
+
self.second_start = start_of_period(vana_time, MS_SECOND)
|
98
|
+
self.time_string = "#{"%02d" % hour}:#{"%02d" % minute}:#{"%02d" % second}"
|
99
|
+
end
|
100
|
+
end
|
113
101
|
end
|