plansheet 0.9.0 → 0.12.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a8132e26b8647ea119299716b5f88674af3e4264614f7b881133eb6cbd32d7db
4
- data.tar.gz: c04f8bf586f6866acf03e809ab581b8010b6fb64be486791abb5fdd3274ae6e2
3
+ metadata.gz: d1c4e7e5e45d00a1218ac7346c60ba9182c7b73ac2761958c24ea8c8dcf15d9d
4
+ data.tar.gz: 50cc492240c458e5bc13539f03203007b8922dcd2e00e5108d6f929c81419f2e
5
5
  SHA512:
6
- metadata.gz: 6426deb869f89a6ff87d5f760acbab8687a542dd3942cf829c536ceb49c3a8268b18ab188d0ad0cb91457fa435963eb7193dd9844a283ccdfb4114e4dece54d8
7
- data.tar.gz: 4c03feeae9aed94d4e4df6c931c1317039f1100e67d7475cdbf8b67dae14e753899853291ad46f025e198d93def4b9c67c0c12da24d352d8db0880ae5ebb2f99
6
+ metadata.gz: 2fe3310c09dfe7d4e79172a476f3bcfc0a3ef6261757a4070a6f49d9857673524663ee97622db603acae911201d5f1acc9cdb65d7c30547ea0e3f4610dc5e0bf
7
+ data.tar.gz: 58aee2a5ab4f95c114461a8ef614823b5c4e22e0961c792623d0720b033a40c1abbdf1d23887b7b5a38b4823138994116d3eb6b42f2675263d0825d567fee173
data/.rubocop_todo.yml CHANGED
@@ -9,28 +9,27 @@
9
9
  # Offense count: 1
10
10
  # Configuration parameters: CountComments, CountAsOne.
11
11
  Metrics/ClassLength:
12
- Max: 105
12
+ Enabled: false
13
13
 
14
14
  # Offense count: 1
15
15
  # Configuration parameters: IgnoredMethods.
16
16
  Metrics/CyclomaticComplexity:
17
- Max: 8
17
+ Enabled: false
18
18
 
19
19
  # Offense count: 2
20
20
  # Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods.
21
21
  Metrics/MethodLength:
22
- Max: 12
22
+ Enabled: false
23
23
 
24
24
  # Offense count: 1
25
25
  # Configuration parameters: IgnoredMethods.
26
26
  Metrics/PerceivedComplexity:
27
- Max: 10
27
+ Enabled: false
28
28
 
29
29
  # Offense count: 2
30
30
  # Configuration parameters: AllowedConstants.
31
31
  Style/Documentation:
32
32
  Exclude:
33
- - 'spec/**/*'
34
33
  - 'test/**/*'
35
34
  - 'lib/plansheet.rb'
36
35
  - 'lib/plansheet/project.rb'
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- plansheet (0.9.0)
4
+ plansheet (0.12.0)
5
5
  dc-kwalify (~> 1.0)
6
6
 
7
7
  GEM
data/exe/plansheet CHANGED
@@ -17,6 +17,10 @@ parser.on(
17
17
  "--cli",
18
18
  "CLI dump of projects (WIP)"
19
19
  )
20
+ parser.on(
21
+ "--location_filter LOCATION",
22
+ "location filter for CLI dump (WIP)"
23
+ )
20
24
  options = {}
21
25
  parser.parse!(into: options)
22
26
 
@@ -32,7 +36,10 @@ elsif options[:sort]
32
36
  Plansheet.resort_projects_in_dir config["projects_dir"]
33
37
  elsif options[:cli]
34
38
  project_arr = Plansheet.load_projects_dir config["projects_dir"]
35
- project_arr.sort.each do |proj|
39
+ project_arr.sort!
40
+ project_arr.delete_if { |x| x.status == "dropped" || x.status == "done" }
41
+ project_arr.select! { |x| x.location == options[:location_filter] } if options[:location_filter]
42
+ project_arr.each do |proj|
36
43
  puts proj
37
44
  puts "\n"
38
45
  end
@@ -8,10 +8,11 @@ module Plansheet
8
8
  "wip" => 1,
9
9
  "ready" => 2,
10
10
  "blocked" => 3,
11
- "planning" => 4,
12
- "idea" => 5,
13
- "dropped" => 6,
14
- "done" => 7
11
+ "waiting" => 4,
12
+ "planning" => 5,
13
+ "idea" => 6,
14
+ "dropped" => 7,
15
+ "done" => 8
15
16
  }.freeze
16
17
 
17
18
  PROJECT_PRIORITY = {
@@ -44,9 +45,10 @@ module Plansheet
44
45
  type: str
45
46
  enum:
46
47
  - wip # project is a work-in-progress
47
- - ready # project is fully scoped, ready to go
48
- - blocked # project is blocked, but otherwise ready/wip
49
- - planning # project in planning phase
48
+ - ready # project has tasks, ready to go
49
+ - waiting # project in waiting on some external person/event
50
+ - blocked # project is blocked by another project, but otherwise ready/wip
51
+ - planning # project in planning phase (set manually)
50
52
  - idea # project is little more than an idea
51
53
  - dropped # project has been explicitly dropped, but
52
54
  # want to keep around for reference, etc
@@ -58,12 +60,35 @@ module Plansheet
58
60
  "notes":
59
61
  desc: Free-form notes string
60
62
  type: str
63
+ "time_estimate":
64
+ desc: The estimated amount of time before a project is completed
65
+ type: str
66
+ "frequency":
67
+ desc: The amount of time before a recurring project moves to ready status again from when it was last done (WIP)
68
+ type: str
69
+ pattern: /\\d+[dwDW]/
70
+ "lead_time":
71
+ desc: The amount of time before a recurring project is "due" moved to ready where the project (sort of a deferral mechanism) (WIP)
72
+ type: str
73
+ pattern: /\\d+[dwDW]/
61
74
  "due":
62
75
  desc: Due date of the task
63
76
  type: date
64
77
  "defer":
65
78
  desc: Defer task until this day
66
79
  type: date
80
+ "created_on":
81
+ desc: When the project was created
82
+ type: date
83
+ "starts_on":
84
+ desc: For ICS (WIP)
85
+ type: date
86
+ "last_reviewed":
87
+ desc: When the project was last reviewed (WIP)
88
+ type: date
89
+ "last_done":
90
+ desc: When the recurring project was last completed (WIP)
91
+ type: date
67
92
  "dependencies":
68
93
  desc: The names of projects that need to be completed before this project can be started/completed
69
94
  type: seq
@@ -89,9 +114,21 @@ module Plansheet
89
114
  type: seq
90
115
  sequence:
91
116
  - type: str
117
+ "tags":
118
+ desc: List of tags (WIP)
119
+ type: seq
120
+ sequence:
121
+ - type: str
92
122
  YAML
93
123
  PROJECT_SCHEMA = YAML.safe_load(PROJECT_YAML_SCHEMA)
94
124
 
125
+ def self.parse_date_duration(str)
126
+ return Regexp.last_match(1).to_i if str.strip.match(/(\d+)[dD]/)
127
+ return (Regexp.last_match(1).to_i * 7) if str.strip.match(/(\d+)[wW]/)
128
+
129
+ raise "Can't parse time duration string #{str}"
130
+ end
131
+
95
132
  # The use of instance_variable_set/get probably seems a bit weird, but the
96
133
  # intent is to avoid object allocation on non-existent project properties, as
97
134
  # well as avoiding a bunch of copy-paste boilerplate when adding a new
@@ -101,10 +138,18 @@ module Plansheet
101
138
  class Project
102
139
  include Comparable
103
140
 
141
+ DEFAULT_COMPARISON_ORDER = %w[
142
+ completeness
143
+ dependency
144
+ priority
145
+ defer
146
+ due
147
+ status
148
+ ].map { |x| "compare_#{x}".to_sym }.freeze
104
149
  # NOTE: The order of these affects presentation!
105
- STRING_PROPERTIES = %w[priority status location notes].freeze
106
- DATE_PROPERTIES = %w[due defer].freeze
107
- ARRAY_PROPERTIES = %w[dependencies externals urls tasks done].freeze
150
+ STRING_PROPERTIES = %w[priority status location notes time_estimate frequency lead_time].freeze
151
+ DATE_PROPERTIES = %w[due defer created_on starts_on last_done last_reviewed].freeze
152
+ ARRAY_PROPERTIES = %w[dependencies externals urls tasks done tags].freeze
108
153
 
109
154
  ALL_PROPERTIES = STRING_PROPERTIES + DATE_PROPERTIES + ARRAY_PROPERTIES
110
155
 
@@ -132,14 +177,7 @@ module Plansheet
132
177
 
133
178
  def <=>(other)
134
179
  ret_val = 0
135
- %i[
136
- compare_completeness
137
- compare_dependency
138
- compare_priority
139
- compare_due
140
- compare_defer
141
- compare_status
142
- ].each do |method|
180
+ DEFAULT_COMPARISON_ORDER.each do |method|
143
181
  ret_val = send(method, other)
144
182
  break if ret_val != 0
145
183
  end
@@ -177,40 +215,101 @@ module Plansheet
177
215
 
178
216
  def compare_dependency(other)
179
217
  return 0 if @dependencies.nil? && other.dependencies.nil?
218
+
180
219
  if @dependencies.nil?
181
- return -1 if other.dependencies.any? {|dep|
220
+ return -1 if other.dependencies.any? do |dep|
182
221
  @name.downcase == dep.downcase
183
- }
184
- else
185
- return 1 if @dependencies.any? {|dep|
186
- other.name.downcase == dep.downcase
187
- }
222
+ end
223
+ elsif @dependencies.any? do |dep|
224
+ other.name.downcase == dep.downcase
225
+ end
226
+ return 1
188
227
  end
189
- return 0
228
+ 0
190
229
  end
191
230
 
192
231
  # Projects that are dropped or done are considered "complete", insofar as
193
232
  # they are only kept around for later reference.
194
233
  def compare_completeness(other)
195
- return 0 if self.dropped_or_done? && other.dropped_or_done?
196
- return 0 if !self.dropped_or_done? && !other.dropped_or_done?
197
- self.dropped_or_done? ? 1 : -1
234
+ return 0 if dropped_or_done? && other.dropped_or_done?
235
+ return 0 if !dropped_or_done? && !other.dropped_or_done?
236
+
237
+ dropped_or_done? ? 1 : -1
198
238
  end
199
239
 
200
240
  def status
201
241
  return @status if @status
242
+ return recurring_status if recurring?
243
+ return task_based_status if (@tasks || @done)
244
+ # TODO: return done if done count is positive...
202
245
 
203
- if @tasks&.count&.positive?
204
- if @done&.count&.positive?
205
- "wip"
206
- else
207
- "planning"
208
- end
246
+ "idea"
247
+ end
248
+
249
+ def task_based_status
250
+ if @tasks&.count&.positive? && @done&.count&.positive?
251
+ "wip"
252
+ elsif @tasks&.count&.positive?
253
+ "ready"
254
+ elsif @done&.count&.positive?
255
+ "done"
209
256
  else
210
257
  "idea"
211
258
  end
212
259
  end
213
260
 
261
+ def recurring_status
262
+ # add frequency to last_done
263
+ unless @last_done
264
+ # This recurring project is being done for the first time
265
+ task_based_status
266
+ else
267
+ # This project has been done once before
268
+ subsequent_recurring_status
269
+ end
270
+ end
271
+
272
+ def subsequent_recurring_status
273
+ return "done" if @lead_time && defer > Date.today
274
+ return "done" if due > Date.today
275
+ task_based_status
276
+ end
277
+
278
+ def process_recurring
279
+ # TODO: Tasks will be moved from done->tasks if recurring project is
280
+ # starting again
281
+ end
282
+
283
+ # Due date either explicit or recurring
284
+ def due
285
+ return @due if @due
286
+ return recurring_due_date if recurring?
287
+ nil
288
+ end
289
+
290
+ def recurring_due_date
291
+ if @last_done
292
+ @last_done + Plansheet.parse_date_duration(@frequency)
293
+ else
294
+ Date.today
295
+ end
296
+ end
297
+
298
+ def defer
299
+ return @defer if @defer
300
+ return lead_time_deferral if @lead_time && due
301
+ nil
302
+ end
303
+
304
+ def lead_time_deferral
305
+ [(due - Plansheet.parse_date_duration(@lead_time)),
306
+ Date.today].max
307
+ end
308
+
309
+ def recurring?
310
+ !@frequency.nil?
311
+ end
312
+
214
313
  def dropped_or_done?
215
314
  status == "dropped" || status == "done"
216
315
  end
@@ -10,7 +10,7 @@ module Plansheet
10
10
  projects_str = String.new
11
11
  projects_str << sheet_header
12
12
 
13
- sorted_arr.first(60).each do |p|
13
+ sorted_arr.each do |p|
14
14
  projects_str << project_minipage(p)
15
15
  end
16
16
  puts "Writing to #{output_file}"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Plansheet
4
- VERSION = "0.9.0"
4
+ VERSION = "0.12.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plansheet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Crosby
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-06-04 00:00:00.000000000 Z
11
+ date: 2022-06-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dc-kwalify