VanaTime 2.0.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|