VanaTime 1.2.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,8 @@
1
+ == 2.0.0 / 2007-09-08
2
+
3
+ * rewritten to support a callback based arch, added element information,
4
+ moved moon phase countdowns into their own class
5
+
1
6
  == 1.2.1 / 2007-09-02
2
7
 
3
8
  * fixed a silly typo describing the waxing gibbous moon phase. This corrects the
data/Manifest CHANGED
@@ -2,8 +2,12 @@ README
2
2
  Manifest
3
3
  LICENSE
4
4
  lib/vana_time.rb
5
+ lib/Vana/time_manager.rb
5
6
  lib/Vana/time.rb
7
+ lib/Vana/moon_countdown.rb
6
8
  lib/Vana/moon.rb
9
+ lib/Vana/element.rb
7
10
  lib/Vana/day.rb
8
11
  lib/Vana/constants.rb
12
+ lib/Vana/common.rb
9
13
  CHANGELOG
data/README CHANGED
@@ -1,7 +1,7 @@
1
- VanaTime 1.1.0 README
1
+ VanaTime 2.0.0 README
2
2
  =====================
3
3
 
4
- This document was last updated on Thu Aug 30 22:58:05 EDT 2007.
4
+ This document was last updated on Sat Sep 8 13:41:50 EDT 2007.
5
5
 
6
6
 
7
7
  Introduction to VanaTime
@@ -16,14 +16,48 @@ VanaTime is a work in progress and the API may change from time to time...
16
16
  you may want to use explicit versioning in any code depending on it.
17
17
 
18
18
 
19
+ FFXI::TimeManager
20
+ =================
21
+
22
+ This will probably be the only class you end up using. It wraps everything
23
+ else up in a convenient callback system that keeps things in sync, only
24
+ does updates when necessary, and fires off your code on events. Huzzah! Here's
25
+ a quick example text clock:
26
+
27
+ include FFXI::Constants
28
+ tm = FFXI::TimeManager.now
29
+ tm.callback(MS_SECOND) {|time| puts "Vana'diel Time: #{time}" }
30
+ loop {tm.earth_time=(Time.now) ; sleep 0.04}
31
+
32
+ If you want to manage existing VanaTime, VanaDay, and VanaMoon objects you
33
+ can create a blank TimeManager and call manage on them:
34
+
35
+ tm = FFXI::TimeManager.new
36
+ tm.manage(time, day, moon)
37
+
38
+ The following are the supported events for adding callbacks:
39
+
40
+ MS_SECOND
41
+ MS_MINUTE
42
+ MS_HOUR
43
+ MS_DAY
44
+ MS_MONTH
45
+ MS_YEAR
46
+ day (of the week, fires off seperately from MS_DAY)
47
+ moon_days
48
+ moon_percent
49
+ moon_phase
50
+ next_optimal_phase
51
+ next_phase_countdown
52
+ optimal_phase_countdown
53
+
19
54
  FFXI::VanaTime API
20
55
  ==================
21
56
 
22
57
  * new(Time)
23
- accepts a Time object to initialize a new VanaTime, using the current
24
- time if no Time object is passed
58
+ accepts a Time object to initialize a new VanaTime
25
59
  * now
26
- an alias for new as a convenience method
60
+ calls new with Time.now
27
61
  * at(VanaTime)
28
62
  accepts a VanaTime object, int, or float representing vana time to
29
63
  initialize a new VanaTime object
@@ -38,20 +72,26 @@ FFXI::VanaTime API
38
72
  returns a float with the internal representation of vana time without
39
73
  losing any accuracy
40
74
  * year
75
+ * year_start
41
76
  * month
77
+ * month_start
42
78
  * date
79
+ * date_start
80
+ * tomorrow
43
81
  * hour
82
+ * hour_start
44
83
  * minute
84
+ * minute_start
45
85
  * second
86
+ * second_start
46
87
  these methods return various times, what we're interested in
47
88
  * to_s
48
89
  returns a string in the format:
49
90
  YYYY-MM-DD hh:mm:ss
50
- * day
51
- returns a VanaDay object initialized with the current VanaTime
52
- * moon
53
- returns a VanaMoon object initialized with the current time
54
-
91
+ * time_string
92
+ returns just the time portion of to_s
93
+ * date_string
94
+ returns just the date portion of to_s
55
95
 
56
96
  FFXI::VanaDay API
57
97
  =================
@@ -65,19 +105,32 @@ FFXI::VanaDay API
65
105
  returns a base zero number representing the day of the week
66
106
  * to_s
67
107
  returns the name of the day of the week
68
- * weak_element
69
- returns the element that the current day is weak to
70
- * day_start
71
- returns a VanaTime object representing the start of the current day
72
- * tomorrow
73
- returns a VanaTime object representing the start of the next vana day
108
+ * to_html
109
+ returns the day's name in a font tag with the day's color
110
+ * element
111
+ returns an Element object with the current day's element
112
+ * weakness
113
+ returns an Element object with the current day's elemental weakness
114
+
115
+ FFXI::ElementFactory::Element
116
+ =============================
74
117
 
118
+ * name
119
+ * strength
120
+ * weakness
121
+ * color
122
+ * enfeeble
123
+ * attribute
124
+ * ninjutsu
125
+ * avatar
75
126
 
76
127
  FFXI::VanaMoon API
77
128
  ==================
78
129
 
79
130
  * new(Time)
80
- Unlike VanaDay, VanaMoon is initialized with the current earth time
131
+ Unlike VanaDay, VanaMoon is initialized with earth time
132
+ * now
133
+ calls new with the current time
81
134
  * to_i
82
135
  returns a number representing the exact position along the progression
83
136
  of moon phases
@@ -87,17 +140,21 @@ FFXI::VanaMoon API
87
140
  returns the name of the current moon phase
88
141
  * to_s
89
142
  returns a string in the format: moon_percent.abs phase_name
143
+ * next_phase
144
+ returns the name of the next moon phase
145
+ * optimal_phase
146
+ returns the name of the next optimal moon phase
147
+
148
+ FFXI::VanaMoonCountdown API
149
+ ===========================
150
+
90
151
  * to_next_array
91
152
  returns an array containing the days, hours, minutes, and seconds until
92
153
  the next moon phase
93
154
  * to_next
94
155
  returns a formatted countdown until the next moon phase
95
- * next_phase
96
- returns the name of the next moon phase
97
156
  * to_optimal_array
98
157
  returns an array containing the days, hours, minutes, and seconds until
99
158
  the next optimal moon phase
100
159
  * to_optimal
101
160
  returns a formatted countdown until the next optimal moon phase
102
- * optimal_phase
103
- returns the name of the next optimal moon phase
@@ -1,11 +1,11 @@
1
1
 
2
- # Gem::Specification for Vanatime-1.2.1
2
+ # Gem::Specification for Vanatime-2.0.0
3
3
  # Originally generated by Echoe
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = %q{VanaTime}
7
- s.version = "1.2.1"
8
- s.date = %q{2007-09-02}
7
+ s.version = "2.0.0"
8
+ s.date = %q{2007-09-08}
9
9
  s.summary = %q{A library for converting realtime to vanadiel time}
10
10
  s.email = %q{ttilley@gmail.com}
11
11
  s.homepage = %q{http://vanatime.rubyforge.org/}
@@ -13,13 +13,13 @@ Gem::Specification.new do |s|
13
13
  s.description = %q{A library for converting realtime to vanadiel time}
14
14
  s.has_rdoc = true
15
15
  s.authors = ["Travis Tilley"]
16
- s.files = ["README", "Manifest", "LICENSE", "lib/vana_time.rb", "lib/Vana/time.rb", "lib/Vana/moon.rb", "lib/Vana/day.rb", "lib/Vana/constants.rb", "CHANGELOG", "VanaTime.gemspec"]
16
+ s.files = ["README", "Manifest", "LICENSE", "lib/vana_time.rb", "lib/Vana/time_manager.rb", "lib/Vana/time.rb", "lib/Vana/moon_countdown.rb", "lib/Vana/moon.rb", "lib/Vana/element.rb", "lib/Vana/day.rb", "lib/Vana/constants.rb", "lib/Vana/common.rb", "CHANGELOG", "VanaTime.gemspec"]
17
17
  end
18
18
 
19
19
 
20
20
  # # Original Rakefile source (requires the Echoe gem):
21
21
  #
22
- # version = "1.2.1"
22
+ # version = "2.0.0"
23
23
  #
24
24
  # ENV['RUBY_FLAGS'] = ""
25
25
  #
@@ -0,0 +1,86 @@
1
+ module FFXI
2
+ module Common
3
+ include FFXI::Constants
4
+
5
+ def self.vana_to_earth(vana_time)
6
+ (((vana_time.to_f - ((898 * 360 + 30) * MS_DAY.to_f)) / 25) +
7
+ MS_BASIS_DATE.to_f) / MS_SECOND
8
+ end
9
+
10
+ def self.earth_to_vana(earth_time)
11
+ ((898 * 360 + 30) * MS_DAY) + ((earth_time.to_f * MS_SECOND) -
12
+ MS_BASIS_DATE) * 25
13
+ end
14
+
15
+ private
16
+
17
+ def start_of_period(vana_time, period)
18
+ vana_time.to_f - (vana_time.to_f % period )
19
+ end
20
+
21
+ def end_of_period(vana_time, period)
22
+ start_of_period(vana_time, period) + period
23
+ end
24
+
25
+ def period_has_passed_since(period, since, vana_time)
26
+ if since.nil?
27
+ true
28
+ else
29
+ elapsed = vana_time.to_f - since.to_f
30
+
31
+ if elapsed < 0
32
+ # if we're going -back- in time, we need to measure from the END of
33
+ # the period instead of the start.
34
+ elapsed = (since.to_f + period) - vana_time.to_f
35
+ end
36
+
37
+ elapsed >= period
38
+ end
39
+ end
40
+
41
+ def second_has_passed_since(since, vana_time)
42
+ period_has_passed_since(MS_SECOND, since, vana_time)
43
+ end
44
+
45
+ def minute_has_passed_since(since, vana_time)
46
+ period_has_passed_since(MS_MINUTE, since, vana_time)
47
+ end
48
+
49
+ def hour_has_passed_since(since, vana_time)
50
+ period_has_passed_since(MS_HOUR, since, vana_time)
51
+ end
52
+
53
+ def day_has_passed_since(since, vana_time)
54
+ period_has_passed_since(MS_DAY, since, vana_time)
55
+ end
56
+
57
+ def month_has_passed_since(since, vana_time)
58
+ period_has_passed_since(MS_MONTH, since, vana_time)
59
+ end
60
+
61
+ def year_has_passed_since(since, vana_time)
62
+ period_has_passed_since(MS_YEAR, since, vana_time)
63
+ end
64
+
65
+ def countdown(time)
66
+ day_left = time.to_f / MS_DAY
67
+ hour_left = (day_left.to_f - day_left.floor) * 24
68
+ min_left = (hour_left.to_f - hour_left.floor) * 60
69
+ sec_left = (min_left.to_f - min_left.floor) * 60
70
+
71
+ [day_left.floor, hour_left.floor, min_left.floor, sec_left.floor]
72
+ end
73
+
74
+ def format_countdown(countdown)
75
+ formatted = String.new
76
+ countdown[0..2].each do |part|
77
+ if (part > 0)
78
+ formatted += "%02d" % part
79
+ formatted += ":"
80
+ end
81
+ end
82
+ formatted += "%02d" % countdown[3]
83
+ formatted
84
+ end
85
+ end
86
+ end
@@ -30,6 +30,10 @@ module FFXI
30
30
  MS_HOUR = HOUR * MS_SECOND
31
31
  MS_MINUTE = MINUTE * MS_SECOND
32
32
 
33
+ # correct for the game time calculations anyways
34
+ MS_MONTH = 30 * MS_DAY
35
+ MS_YEAR = 360 * MS_DAY
36
+
33
37
  MS_GAME_DAY = (MS_DAY / 25)
34
38
 
35
39
  BASIS_DATE = Time.utc(2002,6,23,15,0,0,0)
@@ -1,52 +1,54 @@
1
1
  module FFXI
2
2
  class VanaDay
3
3
  include FFXI::Constants
4
+ include Observable
4
5
 
5
6
  VANA_DAYS = ["Firesday", "Earthsday", "Watersday", "Windsday", "Iceday",
6
7
  "Lightningday", "Lightsday", "Darksday"]
7
-
8
- DAY_WEAKNESS = ["Ice", "Lightning", "Fire", "Earth", "Wind", "Water",
9
- "Darkness", "Light"]
8
+ DAY_ELEMENTS = ["Fire", "Earth", "Water", "Wind", "Ice", "Thunder",
9
+ "Light", "Darkness"]
10
10
 
11
11
  def initialize(vana_time=VanaTime.now)
12
- self.vana_time = vana_time
12
+ self.vana_time = vana_time.to_f
13
13
  end
14
14
 
15
- attr_reader :vana_time
16
-
17
- def vana_time=(vana_time)
18
- @vana_time = vana_time
15
+ def vana_time=(vt)
16
+ if vt != @vana_time
17
+ @vana_time = vt
19
18
 
20
- vana_day = (@vana_time.to_f % (8 * MS_DAY)) / (MS_DAY)
21
-
22
- if @vana_day.nil?
23
- @vana_day = vana_day
24
- elsif @vana_day != vana_day
25
- @vana_day = vana_day
26
- @vana_day_start = nil
27
- @vana_day_tomorrow = nil
19
+ set_day
28
20
  end
29
21
  end
30
22
 
23
+ attr_reader :element, :weakness
24
+ attr_reader :vana_time
25
+
31
26
  def to_i
32
- @vana_day.to_i
27
+ @day.to_i
33
28
  end
34
29
 
35
30
  def to_s
36
- VANA_DAYS[@vana_day]
31
+ VANA_DAYS[@day]
37
32
  end
38
33
 
39
- def weak_element
40
- DAY_WEAKNESS[@vana_day]
34
+ def to_html
35
+ "<b><font color=\"#{@element.color}\">#{VANA_DAYS[@day]}</font></b>"
41
36
  end
42
37
 
43
- def day_start
44
- @vana_day_start ||=
45
- VanaTime.at(@vana_time.to_f - (@vana_time.to_f % MS_DAY ))
46
- end
38
+ private
39
+
40
+ def set_day
41
+ day = (@vana_time.to_f % (8 * MS_DAY)) / (MS_DAY)
42
+
43
+ if day != @day
44
+ @day = day
45
+ @element = FFXI::ElementFactory.send DAY_ELEMENTS[@day]
46
+ @weakness = FFXI::ElementFactory.send(@element.weakness)
47
47
 
48
- def tomorrow
49
- @vana_day_tomorrow ||= VanaTime.at(day_start.to_f + MS_DAY)
48
+ changed
49
+ notify_observers("day", self)
50
+ end
50
51
  end
52
+
51
53
  end
52
54
  end
@@ -0,0 +1,49 @@
1
+ module FFXI
2
+ module ElementFactory
3
+ Element = Struct.new(:name, :strength, :weakness, :color, :enfeeble,
4
+ :attribute, :ninjutsu, :avatar)
5
+
6
+ ELEMENTS = ["Fire", "Ice", "Wind", "Earth", "Thunder", "Water"]
7
+ ELEMENT_COLORS = ["red", "aqua", "green", "yellow", "purple", "blue"]
8
+ ELEMENT_ENFEEBLE = ["Burn", "Frost", "Choke", "Rasp", "Shock", "Drown"]
9
+ ELEMENT_ATTRIBUTE = ["STR", "INT", "AGI", "VIT", "DEX", "MND"]
10
+ ELEMENT_NINJUTSU = ["Katon", "Hyoton", "Huton", "Doton", "Raiton", "Suiton"]
11
+ ELEMENT_AVATAR = ["Ifrit", "Shiva", "Garuda", "Titan", "Ramuh", "Leviathan"]
12
+
13
+ SPECIAL_ELEMENTS = ["Light", "Darkness"]
14
+ SPECIAL_ELEMENT_COLORS = ["gray", "black"]
15
+ SPECIAL_ELEMENT_ENFEEBLE = ["Dia", "Bio"]
16
+ SPECIAL_ELEMENT_ATTRIBUTE = ["CHR", nil]
17
+ SPECIAL_ELEMENT_AVATAR = ["Carbuncle", ["Fenrir", "Diabolos"]]
18
+
19
+ def self.method_missing(name, *args)
20
+ element = name.to_s.capitalize
21
+
22
+ if SPECIAL_ELEMENTS.include? element
23
+ index = SPECIAL_ELEMENTS.index element
24
+ opposed = SPECIAL_ELEMENTS[(index - 1) % 2]
25
+ color = SPECIAL_ELEMENT_COLORS[index]
26
+ enfeeble = SPECIAL_ELEMENT_ENFEEBLE[index]
27
+ attribute = SPECIAL_ELEMENT_ATTRIBUTE[index]
28
+ avatar = SPECIAL_ELEMENT_AVATAR[index]
29
+
30
+ Element.new(element, opposed, opposed, color, enfeeble, attribute, nil,
31
+ avatar)
32
+ elsif ELEMENTS.include? element
33
+ index = ELEMENTS.index element
34
+ weakness = ELEMENTS[(index - 1) % 6]
35
+ strength = ELEMENTS[(index + 1) % 6]
36
+ color = ELEMENT_COLORS[index]
37
+ enfeeble = ELEMENT_ENFEEBLE[index]
38
+ attribute = ELEMENT_ATTRIBUTE[index]
39
+ ninjutsu = ELEMENT_NINJUTSU[index]
40
+ avatar = ELEMENT_AVATAR[index]
41
+
42
+ Element.new(element, strength, weakness, color, enfeeble, attribute,
43
+ ninjutsu, avatar)
44
+ else
45
+ raise "Unknown element"
46
+ end
47
+ end
48
+ end
49
+ end
@@ -1,17 +1,88 @@
1
1
  module FFXI
2
2
  class VanaMoon
3
3
  include FFXI::Constants
4
+ include FFXI::Common
5
+ include Observable
4
6
 
5
7
  MOON_PHASES = ["Full", "Waning Gibbous", "Last Quarter", "Waning Crescent",
6
8
  "New Moon", "Waxing Crescent", "First Quarter", "Waxing Gibbous"]
7
9
 
8
- def initialize(time = Time.now)
9
- localtime = (time.to_f * 1000).to_i
10
+ def initialize(time = nil)
11
+ self.earth_time = time if ! time.nil?
12
+ end
13
+
14
+ def self.now
15
+ self.new(Time.now)
16
+ end
17
+
18
+ def earth_time=(time)
19
+ raise "Input needs to be a Time object" if ! time.is_a? Time
20
+ if time != @earth_time
21
+ @earth_time = time
22
+
23
+ set_moon_days
24
+ set_percent
25
+ set_phase
26
+ set_optimal
27
+ end
28
+ end
29
+
30
+ attr_reader :moon_days, :next_phase_target, :optimal_phase_target
31
+ attr_reader :earth_time
32
+
33
+ def to_i
34
+ @moon_percent
35
+ end
36
+
37
+ def percent
38
+ "#{@moon_percent.abs}%"
39
+ end
40
+
41
+ def phase
42
+ MOON_PHASES[@moon_phase]
43
+ end
44
+
45
+ def to_s
46
+ "#{percent} #{phase}"
47
+ end
48
+
49
+ def next_phase
50
+ MOON_PHASES[(@moon_phase + 1) % 8]
51
+ end
52
+
53
+ def optimal_phase
54
+ MOON_PHASES[@next_optimal_phase]
55
+ end
56
+
57
+ private
58
+
59
+ def set_moon_days
60
+ old_moon_days = @moon_days
61
+
10
62
  # Each lunar cycle takes exactly 84 game days
11
63
  # (3 days, 8 hours, 38 minutes, 24 seconds)
12
- @moon_days = ((localtime - MS_MOON_DATE.to_i) / MS_GAME_DAY).floor % 84
64
+ @moon_days = (((@earth_time.to_f * 1000).to_i -
65
+ MS_MOON_DATE.to_i) / MS_GAME_DAY).floor % 84
66
+
67
+ if @moon_days != old_moon_days
68
+ changed
69
+ notify_observers("moon_days", self)
70
+ end
71
+ end
72
+
73
+ def set_percent
74
+ old_moon_percent = @moon_percent
75
+
13
76
  @moon_percent = - ((42 - @moon_days).to_f / 42 * 100).round
14
- @elapsed_time = (localtime - MS_MOON_DATE.to_i) % MS_GAME_DAY
77
+
78
+ if @moon_percent != old_moon_percent
79
+ changed
80
+ notify_observers("moon_percent", self)
81
+ end
82
+ end
83
+
84
+ def set_phase
85
+ old_phase = @moon_phase
15
86
 
16
87
  case @moon_percent
17
88
  when (-100..-94)
@@ -43,6 +114,15 @@ module FFXI
43
114
  @next_phase_target = 80
44
115
  end
45
116
 
117
+ if @moon_phase != old_phase
118
+ changed
119
+ notify_observers("moon_phase", self)
120
+ end
121
+ end
122
+
123
+ def set_optimal
124
+ old_optimal = @next_optimal_phase
125
+
46
126
  case @moon_phase
47
127
  when (0..3)
48
128
  @next_optimal_phase = 4
@@ -52,75 +132,12 @@ module FFXI
52
132
  @next_optimal_phase = 0
53
133
  @optimal_phase_target = 80
54
134
  end
55
- end
56
-
57
- attr_reader :elapsed_time, :moon_days
58
-
59
- def to_i
60
- @moon_percent
61
- end
62
-
63
- def percent
64
- "#{@moon_percent.abs}%"
65
- end
66
-
67
- def phase
68
- MOON_PHASES[@moon_phase]
69
- end
70
-
71
- def to_s
72
- "#{percent} #{phase}"
73
- end
74
-
75
- def to_next_array
76
- countdown_to(@next_phase_target)
77
- end
78
135
 
79
- def to_next
80
- format_countdown(to_next_array)
81
- end
82
-
83
- def next_phase
84
- MOON_PHASES[(@moon_phase + 1) % 8]
85
- end
86
-
87
- def to_optimal_array
88
- countdown_to(@optimal_phase_target)
89
- end
90
-
91
- def to_optimal
92
- format_countdown(to_optimal_array)
93
- end
94
-
95
- def optimal_phase
96
- MOON_PHASES[@next_optimal_phase]
97
- end
98
-
99
- private
100
-
101
- def countdown(time)
102
- day_left = time.to_f / MS_DAY
103
- hour_left = (day_left.to_f - day_left.floor) * 24
104
- min_left = (hour_left.to_f - hour_left.floor) * 60
105
- sec_left = (min_left.to_f - min_left.floor) * 60
106
-
107
- [day_left.floor, hour_left.floor, min_left.floor, sec_left.floor]
108
- end
109
-
110
- def countdown_to(target)
111
- countdown((target - @moon_days) * MS_GAME_DAY - @elapsed_time)
112
- end
113
-
114
- def format_countdown(countdown)
115
- formatted = String.new
116
- countdown[0..2].each do |part|
117
- if (part > 0)
118
- formatted += "%02d" % part
119
- formatted += ":"
120
- end
136
+ if @next_optimal_phase != old_optimal
137
+ changed
138
+ notify_observers("next_optimal_phase", self)
121
139
  end
122
- formatted += "%02d" % countdown[3]
123
- formatted
124
140
  end
141
+
125
142
  end
126
143
  end
@@ -0,0 +1,67 @@
1
+ module FFXI
2
+ class VanaMoonCountdown
3
+ include FFXI::Constants
4
+ include FFXI::Common
5
+ include Observable
6
+
7
+ def initialize(moon)
8
+ self.moon = moon
9
+ end
10
+
11
+ def moon=(moon)
12
+ raise "Input needs to be a VanaMoon object" if ! moon.is_a? VanaMoon
13
+ @moon = moon
14
+ if @moon.earth_time != @earth_time
15
+ self.earth_time = @moon.earth_time
16
+ end
17
+ end
18
+
19
+ def earth_time=(earth_time)
20
+ raise "Input needs to be a Time object" if ! earth_time.is_a? Time
21
+
22
+ if earth_time != @earth_time
23
+ @earth_time = earth_time
24
+ localtime = (@earth_time.to_f * 1000).to_i
25
+ @elapsed_time = (localtime - MS_MOON_DATE.to_i) % MS_GAME_DAY
26
+
27
+ set_countdowns
28
+ end
29
+ end
30
+
31
+ attr_reader :to_next_array, :to_optimal_array
32
+ attr_reader :elapsed_time, :earth_time
33
+
34
+ def to_next
35
+ format_countdown(@to_next_array)
36
+ end
37
+
38
+ def to_optimal
39
+ format_countdown(@to_optimal_array)
40
+ end
41
+
42
+ private
43
+
44
+ def set_countdowns
45
+ to_next_array = countdown_to(@moon.next_phase_target)
46
+
47
+ if to_next_array != @to_next_array
48
+ @to_next_array = to_next_array
49
+ changed
50
+ notify_observers("next_phase_countdown", self)
51
+ end
52
+
53
+ to_optimal_array = countdown_to(@moon.optimal_phase_target)
54
+
55
+ if to_optimal_array != @to_optimal_array
56
+ @to_optimal_array = to_optimal_array
57
+ changed
58
+ notify_observers("optimal_phase_countdown", self)
59
+ end
60
+ end
61
+
62
+ def countdown_to(target)
63
+ countdown((target - @moon.moon_days) * MS_GAME_DAY - @elapsed_time)
64
+ end
65
+
66
+ end
67
+ end
@@ -1,50 +1,38 @@
1
1
  module FFXI
2
2
  class VanaTime
3
3
  include FFXI::Constants
4
+ include FFXI::Common
5
+ include Observable
4
6
 
5
- def initialize(time = Time.now)
6
- self.earth_time = time
7
+ def initialize(time = nil)
8
+ self.earth_time = time if ! time.nil?
7
9
  end
8
10
 
9
- def update_instance_variables
10
- # the day object knows how to update only what is necessary, so if there
11
- # is an existing VanaDay object, update it
12
- if ! @vDay.nil?
13
- @vDay.vana_time = @vana_time
14
- end
11
+ def self.at(vt)
12
+ self.new(Time.at(FFXI::Common.vana_to_earth(vt)))
13
+ end
15
14
 
16
- # nil these until they're used and updated later
17
- @vYear=@vMon=@vDate=@vHour=@vMin=@vSec=@vana_moon=nil
15
+ def self.now
16
+ self.new(Time.now)
18
17
  end
19
18
 
20
19
  def earth_time=(time)
21
20
  raise "input needs to be a Time object" if ! time.is_a? Time
22
-
23
21
  @earth_time = time
24
- ms_earth_time = @earth_time.to_f * MS_SECOND
25
- @vana_time = ((898 * 360 + 30) * MS_DAY) +
26
- (ms_earth_time - MS_BASIS_DATE) * 25
27
-
28
- update_instance_variables
22
+ vt = FFXI::Common.earth_to_vana(time)
23
+ set_instance_variables(vt)
29
24
  end
30
25
 
31
- attr_reader :earth_time
32
-
33
- def self.vana_to_earth(vana_time)
34
- (((vana_time.to_f - ((898 * 360 + 30) * MS_DAY.to_f)) / 25) +
35
- MS_BASIS_DATE.to_f) / MS_SECOND
26
+ def vana_time=(vt)
27
+ @earth_time = Time.at(FFXI::Common.vana_to_earth(vt))
28
+ set_instance_variables(vt)
36
29
  end
37
30
 
38
- def vana_time=(vana_time)
39
- @vana_time = vana_time.to_f
40
- @earth_time = Time.at(self.class.vana_to_earth(vana_time))
41
-
42
- update_instance_variables
43
- end
44
-
45
- def self.at(vana_time)
46
- self.new(Time.at(self.vana_to_earth(vana_time)))
47
- end
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
48
36
 
49
37
  def to_i
50
38
  @vana_time.to_i
@@ -54,46 +42,72 @@ module FFXI
54
42
  @vana_time.to_f
55
43
  end
56
44
 
57
- def year
58
- @vYear ||= (@vana_time / (360 * MS_DAY)).to_i
45
+ def time_string
46
+ "#{"%02d" % hour}:#{"%02d" % minute}:#{"%02d" % second}"
59
47
  end
60
48
 
61
- def month
62
- @vMon ||= (((@vana_time % (360 * MS_DAY)) / (30 * MS_DAY)) + 1).to_i
49
+ def date_string
50
+ "#{year}-#{"%02d" % month}-#{"%02d" % date}"
63
51
  end
64
52
 
65
- def date
66
- @vDate ||= (((@vana_time % (30 * MS_DAY)) / (MS_DAY)) + 1).to_i
53
+ def to_s
54
+ "#{date_string} #{time_string}"
67
55
  end
68
56
 
69
- def hour
70
- @vHour ||= ((@vana_time % MS_DAY) / MS_HOUR).to_i
71
- end
57
+ private
58
+
59
+ def set_instance_variables(vt)
60
+ @vana_time = vt.to_f
72
61
 
73
- def minute
74
- @vMin ||= ((@vana_time % MS_HOUR) / MS_MINUTE).to_i
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)
75
68
  end
76
69
 
77
- def second
78
- @vSec ||= ((@vana_time % MS_MINUTE) / MS_SECOND).to_i
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)
79
75
  end
80
76
 
81
- def day
82
- @vDay ||= VanaDay.new(@vana_time)
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)
83
82
  end
84
83
 
85
- def moon
86
- @vana_moon ||= VanaMoon.new(@earth_time)
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)
87
90
  end
88
91
 
89
- def self.now
90
- self.new
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)
91
97
  end
92
98
 
93
- def to_s
94
- "#{year}-#{"%02d" % month}-#{"%02d" % date}" +
95
- " #{"%02d" % hour}:#{"%02d" % minute}:#{"%02d" % second}"
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)
96
104
  end
97
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
98
112
  end
99
113
  end
@@ -0,0 +1,82 @@
1
+ module FFXI
2
+ class TimeManager
3
+ include FFXI::Constants
4
+
5
+ def initialize(earth_time=nil)
6
+ @callbacks = {}
7
+ setup(earth_time) if ! earth_time.nil?
8
+ end
9
+
10
+ def self.now
11
+ self.new(Time.now)
12
+ end
13
+
14
+ def reset
15
+ earth_time = @time.earth_time
16
+ setup(earth_time)
17
+ end
18
+
19
+ def manage(time, day, moon)
20
+ raise "time needs to be a VanaTime" if ! time.is_a? VanaTime
21
+ raise "day needs to be a VanaDay" if ! day.is_a? VanaDay
22
+ raise "moon needs to be a VanaMoon" if ! moon.is_a? VanaMoon
23
+
24
+ @time = time
25
+ @day = day
26
+ @moon = moon
27
+ @moon_countdown = VanaMoonCountdown.new(@moon)
28
+
29
+ observe
30
+ end
31
+
32
+ def earth_time=(earth_time)
33
+ raise "I don't have a VanaTime to update" if @time.nil?
34
+ raise "Input needs to be a Time object" if ! earth_time.is_a? Time
35
+
36
+ @time.earth_time=(earth_time)
37
+ end
38
+
39
+ def callback_proc(type, callback)
40
+ raise "callback needs to be a Proc/lambda" if ! callback.is_a? Proc
41
+
42
+ @callbacks[type] = [] if @callbacks[type].nil?
43
+ @callbacks[type] << callback
44
+ end
45
+
46
+ def callback(type, &block)
47
+ callback_proc(type, block)
48
+ end
49
+
50
+ def update(type, updater)
51
+ case type
52
+ when MS_SECOND
53
+ @moon_countdown.earth_time = @time.earth_time
54
+ when MS_DAY
55
+ @day.vana_time = @time.to_f
56
+ @moon.earth_time = @time.earth_time
57
+ when "moon_days"
58
+ @moon_countdown.moon = @moon
59
+ end
60
+
61
+ @callbacks[type].each {|c| c.call(updater)} if ! @callbacks[type].nil?
62
+ end
63
+
64
+ private
65
+
66
+ def setup(time)
67
+ @time = VanaTime.new(time)
68
+ @day = VanaDay.new(@time.date_start)
69
+ @moon = VanaMoon.new(@time.earth_time)
70
+ @moon_countdown = VanaMoonCountdown.new(@moon)
71
+
72
+ observe
73
+ end
74
+
75
+ def observe
76
+ @time.add_observer(self)
77
+ @day.add_observer(self)
78
+ @moon.add_observer(self)
79
+ @moon_countdown.add_observer(self)
80
+ end
81
+ end
82
+ end
@@ -1,6 +1,12 @@
1
1
  $:.unshift File.dirname(__FILE__)
2
2
 
3
+ require 'observer'
4
+
3
5
  require 'Vana/constants'
6
+ require 'Vana/common'
7
+ require 'Vana/time'
8
+ require 'Vana/element'
4
9
  require 'Vana/day'
5
10
  require 'Vana/moon'
6
- require 'Vana/time'
11
+ require 'Vana/moon_countdown'
12
+ require 'Vana/time_manager'
metadata CHANGED
@@ -1,48 +1,59 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.4
3
+ specification_version: 1
4
+ name: VanaTime
5
+ version: !ruby/object:Gem::Version
6
+ version: 2.0.0
7
+ date: 2007-09-08 00:00:00 -04:00
8
+ summary: A library for converting realtime to vanadiel time
9
+ require_paths:
10
+ - lib
11
+ email: ttilley@gmail.com
2
12
  homepage: http://vanatime.rubyforge.org/
3
- extensions: []
4
- executables: []
5
- version: !ruby/object:Gem::Version
6
- version: 1.2.1
13
+ rubyforge_project: vanatime
14
+ description: A library for converting realtime to vanadiel time
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
7
28
  post_install_message:
8
- date: 2007-09-02 04:00:00 +00:00
29
+ authors:
30
+ - Travis Tilley
9
31
  files:
10
32
  - README
11
33
  - Manifest
12
34
  - LICENSE
13
35
  - lib/vana_time.rb
36
+ - lib/Vana/time_manager.rb
14
37
  - lib/Vana/time.rb
38
+ - lib/Vana/moon_countdown.rb
15
39
  - lib/Vana/moon.rb
40
+ - lib/Vana/element.rb
16
41
  - lib/Vana/day.rb
17
42
  - lib/Vana/constants.rb
43
+ - lib/Vana/common.rb
18
44
  - CHANGELOG
19
45
  - VanaTime.gemspec
20
- rubygems_version: 0.9.4
21
- rdoc_options: []
22
- signing_key:
23
- cert_chain:
24
- name: VanaTime
25
- has_rdoc: true
26
- platform: ruby
27
- summary: A library for converting realtime to vanadiel time
28
- default_executable:
29
- bindir: bin
30
- required_ruby_version: !ruby/object:Gem::Version::Requirement
31
- version:
32
- requirements:
33
- - - '>'
34
- - !ruby/object:Gem::Version
35
- version: 0.0.0
36
- require_paths:
37
- - lib
38
- specification_version: 1
39
46
  test_files: []
40
- dependencies: []
41
- description: A library for converting realtime to vanadiel time
42
- authors:
43
- - Travis Tilley
44
- email: ttilley@gmail.com
47
+
48
+ rdoc_options: []
49
+
45
50
  extra_rdoc_files: []
51
+
52
+ executables: []
53
+
54
+ extensions: []
55
+
46
56
  requirements: []
47
- rubyforge_project: vanatime
48
- autorequire:
57
+
58
+ dependencies: []
59
+