workpattern 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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. The #base year
7
- # is the first year and the #span is the number of years including that year that is covered.
8
- # The #Workpattern is given a unique name so it can be easily identified amongst other Workpatterns.
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
- def initialize(name=DEFAULT_NAME,base_year=DEFAULT_BASE_YEAR,span=DEFAULT_SPAN)
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 = base_year
50
+ @base = base
28
51
  @span = span
29
- @from = DateTime.new(base_year.abs - offset)
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
- # Sets a work or resting pattern in the _Workpattern_.
60
- #
61
- # Can also use <tt>resting</tt> and <tt>working</tt> methods leaving off the
62
- # :work_type
63
- #
64
- # === Parameters
65
- #
66
- # * <tt>:start</tt> - The first date to apply the pattern. Defaults
67
- # to the _Workpattern_ <tt>start</tt>.
68
- # * <tt>:finish</tt> - The last date to apply the pattern. Defaults to
69
- # the _Workpattern_ <tt>finish</tt>.
70
- # * <tt>:days</tt> - The specific day or days the pattern will apply to. This
71
- # references _Workpattern::DAYNAMES_. It defailts to <tt>:all</tt> which is
72
- # everyday. Valid values are <tt>:sun, :mon, :tue, :wed, :thu, :fri, :sat,
73
- # :weekend, :weekday</tt> and <tt>:all</tt>
74
- # * <tt>:start_time</tt> - The first time in the selected days to apply the pattern.
75
- # Must implement #hour and #min to get the Hours and Minutes for the time. It will default to
76
- # the first time in the day <tt>00:00</tt>.
77
- # * <tt>:finish_time</tt> - The last time in the selected days to apply the pattern.
78
- # Must implement #hour and #min to get the Hours and Minutes for the time. It will default to
79
- # to the last time in the day <tt>23:59</tt>.
80
- # * <tt>:work_type</tt> - type of pattern is either working (1 or <tt>Workpattern::WORK</tt>) or
81
- # resting (0 or <tt>Workpattern::REST</tt>). Alternatively make use of the <tt>working</tt>
82
- # or <tt>resting</tt> methods that will set this value for you
83
- #
84
- def workpattern(args={})
85
-
86
- #
87
- upd_start = args[:start] || @from
88
- upd_start = dmy_date(upd_start)
89
- args[:start] = upd_start
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,type)
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,type)
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,type)
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,type)
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
- # Identical to the <tt>workpattern</tt> method apart from it always creates
145
- # resting patterns so there is no need to set the <tt>:work_type</tt> argument
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
- # Identical to the <tt>workpattern</tt> method apart from it always creates
153
- # working patterns so there is no need to set the <tt>:work_type</tt> argument
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
- # :call-seq: calc(start,duration) => DateTime
161
- # Calculates the resulting date when #duration is added to #start date using the #Workpattern.
162
- # Duration is always in whole minutes and can be a negative number, in which case it subtracts
163
- # the minutes from the date.
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
- # :call-seq: working?(start) => Boolean
184
- # Returns true if the given minute is working and false if it isn't
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 DateTime.new(2000,1,1,date.hour,date.min)
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.0
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-07-19 00:00:00.000000000 Z
12
+ date: 2012-10-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake