workpattern 0.3.0 → 0.3.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.
- data/CHANGELOG +4 -0
- data/README.md +48 -3
- data/lib/workpattern.rb +58 -134
- data/lib/workpattern/clock.rb +40 -25
- data/lib/workpattern/day.rb +93 -29
- data/lib/workpattern/hour.rb +65 -26
- data/lib/workpattern/utility/base.rb +20 -2
- data/lib/workpattern/version.rb +3 -1
- data/lib/workpattern/week.rb +50 -35
- data/lib/workpattern/workpattern.rb +125 -78
- metadata +2 -2
@@ -1,19 +1,42 @@
|
|
1
|
-
|
2
|
-
|
3
1
|
module Workpattern
|
4
2
|
require 'set'
|
5
3
|
|
6
|
-
# Represents the working and resting periods across a number of whole years.
|
7
|
-
#
|
8
|
-
#
|
4
|
+
# Represents the working and resting periods across a given number of whole years. Each <tt>Workpattern</tt>
|
5
|
+
# has a unique name so it can be easily identified amongst all the other <tt>Workpattern</tt> objects.
|
6
|
+
#
|
7
|
+
# This and the <tt>Clock</tt> class are the only two that should be referenced by calling applications when
|
8
|
+
# using this gem.
|
9
|
+
#
|
10
|
+
# @since 0.2.0
|
9
11
|
#
|
10
12
|
class Workpattern
|
11
13
|
|
12
|
-
# Holds collection of <tt>Workpattern</tt> objects
|
14
|
+
# Holds collection of <tt>Workpattern</tt> objects
|
13
15
|
@@workpatterns = Hash.new()
|
14
|
-
attr_accessor :name, :base, :span, :from, :to, :weeks
|
15
16
|
|
16
|
-
|
17
|
+
# @!attribute [r] name
|
18
|
+
# Name given to the <tt>Workpattern</tt>
|
19
|
+
# @!attribute [r] base
|
20
|
+
# Starting year
|
21
|
+
# @!attribute [r] span
|
22
|
+
# Number of years
|
23
|
+
# @!attribute [r] from
|
24
|
+
# First date in <tt>Workpattern</tt>
|
25
|
+
# @!attribute [r] to
|
26
|
+
# Last date in <tt>Workpattern</tt>
|
27
|
+
# @!attribute [r] weeks
|
28
|
+
# The <tt>Week</tt> objects that make up this workpattern
|
29
|
+
#
|
30
|
+
attr_reader :name, :base, :span, :from, :to, :weeks
|
31
|
+
|
32
|
+
# The new <tt>Workpattern</tt> object is created with all working minutes.
|
33
|
+
#
|
34
|
+
# @param [String] name Every workpattern has a unique name
|
35
|
+
# @param [Integer] base Workpattern starts on the 1st January of this year.
|
36
|
+
# @param [Integer] span Workpattern spans this number of years ending on 31st December.
|
37
|
+
# @raise [NameError] if the given name already exists
|
38
|
+
#
|
39
|
+
def initialize(name=DEFAULT_NAME,base=DEFAULT_BASE_YEAR,span=DEFAULT_SPAN)
|
17
40
|
|
18
41
|
raise(NameError, "Workpattern '#{name}' already exists and can't be created again") if @@workpatterns.key?(name)
|
19
42
|
|
@@ -24,9 +47,9 @@ module Workpattern
|
|
24
47
|
end
|
25
48
|
|
26
49
|
@name = name
|
27
|
-
@base =
|
50
|
+
@base = base
|
28
51
|
@span = span
|
29
|
-
@from = DateTime.new(
|
52
|
+
@from = DateTime.new(base.abs - offset)
|
30
53
|
@to = DateTime.new(@from.year + span.abs - 1,12,31,23,59)
|
31
54
|
@weeks = SortedSet.new
|
32
55
|
@weeks << Week.new(@from,@to,1)
|
@@ -35,19 +58,32 @@ module Workpattern
|
|
35
58
|
@@workpatterns[name]=self
|
36
59
|
end
|
37
60
|
|
61
|
+
# Deletes all <tt>Workpattern</tt> objects
|
62
|
+
#
|
38
63
|
def self.clear
|
39
64
|
@@workpatterns.clear
|
40
65
|
end
|
41
66
|
|
67
|
+
# Returns an Array containing all the <tt>Workpattern</tt> objects
|
68
|
+
# @return [Array] all <tt>Workpattern</tt> objects
|
69
|
+
#
|
42
70
|
def self.to_a
|
43
71
|
@@workpatterns.to_a
|
44
72
|
end
|
45
73
|
|
74
|
+
# Returns the specific named <tt>Workpattern</tt>
|
75
|
+
# @param [String] name of the required <tt>Workpattern</tt>
|
76
|
+
# @raise [NameError] if a <tt>Workpattern</tt> of the supplied name does not exist
|
77
|
+
#
|
46
78
|
def self.get(name)
|
47
79
|
return @@workpatterns[name] if @@workpatterns.key?(name)
|
48
80
|
raise(NameError, "Workpattern '#{name}' doesn't exist so can't be retrieved")
|
49
81
|
end
|
50
82
|
|
83
|
+
# Deletes the specific named <tt>Workpattern</tt>
|
84
|
+
# @param [String] name of the required <tt>Workpattern</tt>
|
85
|
+
# @return [Boolean] true if the named <tt>Workpattern</tt> existed or false if it doesn't
|
86
|
+
#
|
51
87
|
def self.delete(name)
|
52
88
|
if @@workpatterns.delete(name).nil?
|
53
89
|
return false
|
@@ -56,55 +92,41 @@ module Workpattern
|
|
56
92
|
end
|
57
93
|
end
|
58
94
|
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
65
|
-
#
|
66
|
-
#
|
67
|
-
#
|
68
|
-
#
|
69
|
-
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
78
|
-
#
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
args[:
|
90
|
-
|
91
|
-
upd_finish = args[:finish] || @to
|
92
|
-
upd_finish = dmy_date(upd_finish)
|
93
|
-
args[:finish] = upd_finish
|
94
|
-
|
95
|
-
#args[:days] = args[:days] || :all
|
96
|
-
days= args[:days] || :all
|
97
|
-
from_time = args[:from_time] || FIRST_TIME_IN_DAY
|
98
|
-
from_time = hhmn_date(from_time)
|
99
|
-
#args[:from_time] = upd_from_time
|
100
|
-
|
101
|
-
to_time = args[:to_time] || LAST_TIME_IN_DAY
|
102
|
-
to_time = hhmn_date(to_time)
|
103
|
-
#args[:to_time] = upd_to_time
|
104
|
-
|
105
|
-
args[:work_type] = args[:work_type] || WORK
|
106
|
-
type= args[:work_type] || WORK
|
95
|
+
# Applys a working or resting pattern to the <tt>Workpattern</tt> object.
|
96
|
+
#
|
97
|
+
# The #resting and #working methods are convenience methods that call
|
98
|
+
# this with the appropriate <tt>:work_type</tt> already set.
|
99
|
+
#
|
100
|
+
# @param [Hash] opts the options used to apply a workpattern
|
101
|
+
# @option opts [Date] :start The first date to apply the pattern. Defaults
|
102
|
+
# to the <tt>start</tt> attribute.
|
103
|
+
# @option opts [Date] :finish The last date to apply the pattern. Defaults
|
104
|
+
# to the <tt>finish</tt> attribute.
|
105
|
+
# @option opts [DAYNAMES] :days The specific day or days the pattern will apply to.
|
106
|
+
# It defaults to <tt>:all</tt>
|
107
|
+
# @option opts [(#hour, #min)] :start_time The first time in the selected days to apply the pattern.
|
108
|
+
# Defaults to <tt>00:00</tt>.
|
109
|
+
# @option opts [(#hour, #min)] :finish_time The last time in the selected days to apply the pattern.
|
110
|
+
# Defaults to <tt>23:59</tt>.
|
111
|
+
# @option opts [(WORK || REST)] :work_type Either working or resting. Defaults to working.
|
112
|
+
# @see #working
|
113
|
+
# @see #resting
|
114
|
+
#
|
115
|
+
def workpattern(opts={})
|
116
|
+
|
117
|
+
args={:start => @from, :finish => @to, :days => :all,
|
118
|
+
:from_time => FIRST_TIME_IN_DAY, :to_time => LAST_TIME_IN_DAY,
|
119
|
+
:work_type => WORK}
|
120
|
+
|
121
|
+
args.merge! opts
|
122
|
+
|
123
|
+
args[:start] = dmy_date(args[:start])
|
124
|
+
args[:finish] = dmy_date(args[:finish])
|
125
|
+
from_time = hhmn_date(args[:from_time])
|
126
|
+
to_time = hhmn_date(args[:to_time])
|
107
127
|
|
128
|
+
upd_start=args[:start]
|
129
|
+
upd_finish=args[:finish]
|
108
130
|
while (upd_start <= upd_finish)
|
109
131
|
|
110
132
|
current_wp=find_weekpattern(upd_start)
|
@@ -113,11 +135,11 @@ module Workpattern
|
|
113
135
|
clone_wp=current_wp.duplicate
|
114
136
|
current_wp.adjust(upd_finish+1,current_wp.finish)
|
115
137
|
clone_wp.adjust(upd_start,upd_finish)
|
116
|
-
clone_wp.workpattern(days,from_time,to_time,
|
138
|
+
clone_wp.workpattern(args[:days],from_time,to_time,args[:work_type])
|
117
139
|
@weeks<< clone_wp
|
118
140
|
upd_start=upd_finish+1
|
119
141
|
else # (current_wp.finish == upd_finish)
|
120
|
-
current_wp.workpattern(days,from_time,to_time,
|
142
|
+
current_wp.workpattern(args[:days],from_time,to_time,args[:work_type])
|
121
143
|
upd_start=current_wp.finish + 1
|
122
144
|
end
|
123
145
|
else
|
@@ -125,7 +147,7 @@ module Workpattern
|
|
125
147
|
current_wp.adjust(current_wp.start,upd_start-1)
|
126
148
|
clone_wp.adjust(upd_start,clone_wp.finish)
|
127
149
|
if (clone_wp.finish <= upd_finish)
|
128
|
-
clone_wp.workpattern(days,from_time,to_time,
|
150
|
+
clone_wp.workpattern(args[:days],from_time,to_time,args[:work_type])
|
129
151
|
@weeks<< clone_wp
|
130
152
|
upd_start=clone_wp.finish+1
|
131
153
|
else
|
@@ -133,7 +155,7 @@ module Workpattern
|
|
133
155
|
after_wp.adjust(upd_finish+1,after_wp.finish)
|
134
156
|
@weeks<< after_wp
|
135
157
|
clone_wp.adjust(upd_start,upd_finish)
|
136
|
-
clone_wp.workpattern(days,from_time,to_time,
|
158
|
+
clone_wp.workpattern(args[:days],from_time,to_time,args[:work_type])
|
137
159
|
@weeks<< clone_wp
|
138
160
|
upd_start=clone_wp.finish+1
|
139
161
|
end
|
@@ -141,26 +163,31 @@ module Workpattern
|
|
141
163
|
end
|
142
164
|
end
|
143
165
|
|
144
|
-
#
|
145
|
-
#
|
166
|
+
# Convenience method that calls <tt>#workpattern</tt> with the <tt>:work_type</tt> specified as resting.
|
167
|
+
#
|
168
|
+
# @see #workpattern
|
146
169
|
#
|
147
170
|
def resting(args={})
|
148
171
|
args[:work_type]=REST
|
149
172
|
workpattern(args)
|
150
173
|
end
|
151
174
|
|
152
|
-
#
|
153
|
-
#
|
175
|
+
# Convenience method that calls <tt>#workpattern</tt> with the <tt>:work_type</tt> specified as working.
|
176
|
+
#
|
177
|
+
# @see #workpattern
|
154
178
|
#
|
155
179
|
def working(args={})
|
156
180
|
args[:work_type]=WORK
|
157
181
|
workpattern(args)
|
158
182
|
end
|
159
183
|
|
160
|
-
#
|
161
|
-
#
|
162
|
-
#
|
163
|
-
#
|
184
|
+
# Calculates the resulting date when the <tt>duration</tt> in minutes is added to the <tt>start</tt> date.
|
185
|
+
# The <tt>duration</tt> is always in whole minutes and subtracts from <tt>start</tt> when it is a
|
186
|
+
# negative number.
|
187
|
+
#
|
188
|
+
# @param [DateTime] start date to add or subtract minutes
|
189
|
+
# @param [Integer] duration in minutes to add or subtract to date
|
190
|
+
# @return [DateTime] the date when <tt>duration</tt> is added to <tt>start</tt>
|
164
191
|
#
|
165
192
|
def calc(start,duration)
|
166
193
|
return start if duration==0
|
@@ -180,16 +207,21 @@ module Workpattern
|
|
180
207
|
return start
|
181
208
|
end
|
182
209
|
|
183
|
-
#
|
184
|
-
#
|
210
|
+
# Returns true if the given minute is working and false if it is resting.
|
211
|
+
#
|
212
|
+
# @param [DateTime] start DateTime being tested
|
213
|
+
# @return [Boolean] true if working and false if resting
|
185
214
|
#
|
186
215
|
def working?(start)
|
187
216
|
return find_weekpattern(start).working?(start)
|
188
217
|
end
|
189
218
|
|
190
|
-
# :call-seq: diff(start,finish) => Duration
|
191
219
|
# Returns number of minutes between two dates
|
192
220
|
#
|
221
|
+
# @param [DateTime] start is the date to start from
|
222
|
+
# @param [DateTime] finish is the date to end with
|
223
|
+
# @return [Integer] number of minutes between the two dates
|
224
|
+
#
|
193
225
|
def diff(start,finish)
|
194
226
|
|
195
227
|
start,finish=finish,start if finish<start
|
@@ -201,13 +233,19 @@ module Workpattern
|
|
201
233
|
end
|
202
234
|
return duration
|
203
235
|
end
|
236
|
+
|
204
237
|
private
|
205
238
|
|
206
|
-
# Retrieve the correct pattern for the supplied date
|
239
|
+
# Retrieve the correct <tt>Week</tt> pattern for the supplied date.
|
240
|
+
#
|
241
|
+
# If the supplied <tt>date</tt> is outside the span of the <tt>Workpattern</tt> object
|
242
|
+
# then it returns an all working <tt>Week</tt> object for the calculation.
|
243
|
+
#
|
244
|
+
# @param [DateTime] date whose containing <tt>Week</tt> pattern is required
|
245
|
+
# @return [Week] <tt>Week</tt> object that includes the supplied <tt>date</tt> in it's range
|
207
246
|
#
|
208
247
|
def find_weekpattern(date)
|
209
248
|
# find the pattern that fits the date
|
210
|
-
# TODO: What if there is no pattern?
|
211
249
|
#
|
212
250
|
if date<@from
|
213
251
|
result = Week.new(DateTime.jd(0),@from-MINUTE,1)
|
@@ -222,13 +260,22 @@ module Workpattern
|
|
222
260
|
return result
|
223
261
|
end
|
224
262
|
|
225
|
-
|
263
|
+
# Strips off hours, minutes, seconds and so forth from a supplied <tt>Date</tt> or
|
264
|
+
# <tt>DateTime</tt>
|
265
|
+
#
|
266
|
+
# @param [DateTime] date
|
267
|
+
# @return [DateTime] with zero hours, minutes, seconds and so forth.
|
268
|
+
#
|
226
269
|
def dmy_date(date)
|
227
270
|
return DateTime.new(date.year,date.month,date.day)
|
228
271
|
end
|
229
|
-
|
272
|
+
|
273
|
+
# Extract the time into a <tt>Clock</tt> object
|
274
|
+
#
|
275
|
+
# @param [DateTime] date
|
276
|
+
# @return [Clock]
|
230
277
|
def hhmn_date(date)
|
231
|
-
return
|
278
|
+
return Clock.new(date.hour,date.min)
|
232
279
|
end
|
233
280
|
|
234
281
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: workpattern
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-10-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|