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.
@@ -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