VanaTime 1.2.1 → 2.0.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 +5 -0
- data/Manifest +4 -0
- data/README +78 -21
- data/VanaTime.gemspec +5 -5
- data/lib/Vana/common.rb +86 -0
- data/lib/Vana/constants.rb +4 -0
- data/lib/Vana/day.rb +28 -26
- data/lib/Vana/element.rb +49 -0
- data/lib/Vana/moon.rb +88 -71
- data/lib/Vana/moon_countdown.rb +67 -0
- data/lib/Vana/time.rb +67 -53
- data/lib/Vana/time_manager.rb +82 -0
- data/lib/vana_time.rb +7 -1
- metadata +43 -32
data/CHANGELOG
CHANGED
data/Manifest
CHANGED
data/README
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
VanaTime
|
1
|
+
VanaTime 2.0.0 README
|
2
2
|
=====================
|
3
3
|
|
4
|
-
This document was last updated on
|
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
|
24
|
-
time if no Time object is passed
|
58
|
+
accepts a Time object to initialize a new VanaTime
|
25
59
|
* now
|
26
|
-
|
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
|
-
*
|
51
|
-
returns
|
52
|
-
*
|
53
|
-
returns
|
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
|
-
*
|
69
|
-
returns the
|
70
|
-
*
|
71
|
-
returns
|
72
|
-
*
|
73
|
-
returns
|
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
|
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
|
data/VanaTime.gemspec
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
|
2
|
-
# Gem::Specification for Vanatime-
|
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 = "
|
8
|
-
s.date = %q{2007-09-
|
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 = "
|
22
|
+
# version = "2.0.0"
|
23
23
|
#
|
24
24
|
# ENV['RUBY_FLAGS'] = ""
|
25
25
|
#
|
data/lib/Vana/common.rb
ADDED
@@ -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
|
data/lib/Vana/constants.rb
CHANGED
@@ -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)
|
data/lib/Vana/day.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
16
|
-
|
17
|
-
|
18
|
-
@vana_time = vana_time
|
15
|
+
def vana_time=(vt)
|
16
|
+
if vt != @vana_time
|
17
|
+
@vana_time = vt
|
19
18
|
|
20
|
-
|
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
|
-
@
|
27
|
+
@day.to_i
|
33
28
|
end
|
34
29
|
|
35
30
|
def to_s
|
36
|
-
VANA_DAYS[@
|
31
|
+
VANA_DAYS[@day]
|
37
32
|
end
|
38
33
|
|
39
|
-
def
|
40
|
-
|
34
|
+
def to_html
|
35
|
+
"<b><font color=\"#{@element.color}\">#{VANA_DAYS[@day]}</font></b>"
|
41
36
|
end
|
42
37
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
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
|
-
|
49
|
-
|
48
|
+
changed
|
49
|
+
notify_observers("day", self)
|
50
|
+
end
|
50
51
|
end
|
52
|
+
|
51
53
|
end
|
52
54
|
end
|
data/lib/Vana/element.rb
ADDED
@@ -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
|
data/lib/Vana/moon.rb
CHANGED
@@ -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 =
|
9
|
-
|
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 = ((
|
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
|
-
|
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
|
-
|
80
|
-
|
81
|
-
|
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
|
data/lib/Vana/time.rb
CHANGED
@@ -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 =
|
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
|
10
|
-
|
11
|
-
|
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
|
-
|
17
|
-
|
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
|
-
|
25
|
-
|
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
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
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
|
58
|
-
|
45
|
+
def time_string
|
46
|
+
"#{"%02d" % hour}:#{"%02d" % minute}:#{"%02d" % second}"
|
59
47
|
end
|
60
48
|
|
61
|
-
def
|
62
|
-
|
49
|
+
def date_string
|
50
|
+
"#{year}-#{"%02d" % month}-#{"%02d" % date}"
|
63
51
|
end
|
64
52
|
|
65
|
-
def
|
66
|
-
|
53
|
+
def to_s
|
54
|
+
"#{date_string} #{time_string}"
|
67
55
|
end
|
68
56
|
|
69
|
-
|
70
|
-
|
71
|
-
|
57
|
+
private
|
58
|
+
|
59
|
+
def set_instance_variables(vt)
|
60
|
+
@vana_time = vt.to_f
|
72
61
|
|
73
|
-
|
74
|
-
|
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
|
78
|
-
@
|
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
|
82
|
-
@
|
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
|
86
|
-
@
|
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
|
90
|
-
|
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
|
94
|
-
|
95
|
-
|
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
|
data/lib/vana_time.rb
CHANGED
@@ -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/
|
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
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
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
|
-
|
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
|
-
|
41
|
-
|
42
|
-
|
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
|
-
|
48
|
-
|
57
|
+
|
58
|
+
dependencies: []
|
59
|
+
|