docfolio 0.0.0 → 0.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 99d2c5789c65b55841fd11b71cfb29448e1ea722
4
- data.tar.gz: d4221138fa97f72c806a8aaabd04f3881f0e4c76
3
+ metadata.gz: e45dbe3f14a1a7135af5c0172af46430bd17a683
4
+ data.tar.gz: 33c879f96cc800b3b1e7a264cb1903b08536d408
5
5
  SHA512:
6
- metadata.gz: f6afcea04d4231186c8ac92f138637f75fa447073668603d83fbc9f285771d68e5fb83b7872d3466710a742751018063e52d8c4cfe389d69cd9a84fadb3e8bea
7
- data.tar.gz: 27134b0e2c0d9151a33716307325fc8076a8994056776bef3c4abd197ce355e0e4d6e769a1d1d0373e7c61ed37bca1f2eb71062525ca1dddef86bb266c8e9a6b
6
+ metadata.gz: eef722b2f0ed517071307ed25ded7fa97faba77242cde022ad4681dcf90a8e27d628be498c902e8b62ef50a9abcc0e8370cc4c721bf2626e1466488cd9d8d52d
7
+ data.tar.gz: 208e402157fc17576d3578160afce37edeca054db9a6687ad01a1a008cb6b3f931476af32e85e494c5db96c59f15ca6fd359386290c987e1fc645ade1fb04900
@@ -41,6 +41,7 @@ module DateFormat
41
41
  [day, month, year]
42
42
  end
43
43
 
44
+ # A hash of text months and their corresponding month number
44
45
  MONTHS = {
45
46
  'jan' => 1,
46
47
  'feb' => 2,
@@ -68,6 +69,9 @@ module DateFormat
68
69
  'sept' => 9
69
70
  }
70
71
 
72
+ # Takes a text month to its corresponding number, case insensitive
73
+ # @param [String] month Month of year in text
74
+ # @return [Integer] Number of month in calander e.g. Feb is 2
71
75
  def convert_month_to_number(month)
72
76
  return month.to_i if month.to_i > 0 # already a number
73
77
  month = month.downcase
@@ -75,6 +79,9 @@ module DateFormat
75
79
  end
76
80
  end
77
81
 
82
+ # Extracts a date in seconds past UNIX epoc from a string date. The result
83
+ # can be used for other date operations. Converts from dd-mmm-yy and similar
84
+ # formats as commonly found in csv files
78
85
  def format_date(date)
79
86
  DateExtractor.new.format_date(date)
80
87
  end
@@ -1,5 +1,4 @@
1
1
  require_relative 'learning_diary.rb'
2
- # require 'stringio'
3
2
  require_relative 'views/collater_console_view.rb'
4
3
 
5
4
  # collection class for Learning Diarys / logs
@@ -25,6 +24,7 @@ class Logs
25
24
  log_file(file_or_directory) if File.file?(file_or_directory)
26
25
  end
27
26
 
27
+ # Implements Enumerable by iterating through each learning diary
28
28
  def each(&block)
29
29
  @logs.each { |p| block.call(p) }
30
30
  end
@@ -68,6 +68,7 @@ class Docfolio
68
68
  true
69
69
  end
70
70
 
71
+ # print all parsed logs to the console
71
72
  def print_logs
72
73
  @view.print_logs(@logs)
73
74
  end
@@ -7,16 +7,27 @@ require_relative 'views/diary_console_view.rb'
7
7
  class LearningDiary
8
8
  include Enumerable
9
9
 
10
+ # Array of paragraphs representing the parsed DSL from one file
10
11
  attr_reader :paragraphs
11
12
 
12
- # @param [String] file name of a text file containing text in docfile DSL
13
+ # @param [String] file name of a text file containing text in docfolio DSL
13
14
  def initialize(file)
14
15
  # preparation
15
16
  # @todo extract to an initialize_vars function, as in the paragraph class
16
17
  Paragraph.reset
17
18
  @console_view = DiaryConsoleView.new
19
+
20
+ # Array of paragraphs representing the parsed DSL from one file
18
21
  @paragraphs = []
19
- @standard_credits_array = []
22
+
23
+ # Array of elements of type [start_time, end_time, duration], one for
24
+ # each tag in all the paragraphs that earns standard credit
25
+ # @todo this perhaps would be better as a ||= in the corresponding function
26
+ @standard_credits_array = []
27
+
28
+ # Array of elements of type [start_time, end_time, duration], one for
29
+ # each tag in all the paragraphs that earns impact credit
30
+ # @todo this perhaps would be better as a ||= in the corresponding function
20
31
  @impact_credits_array = []
21
32
 
22
33
  # read the whole txt file in one go
@@ -31,36 +42,52 @@ class LearningDiary
31
42
  calc_impact_credits
32
43
  end
33
44
 
45
+ # Implements Enuemerable module by iterating through each paragraph in the
46
+ # learning diary
34
47
  def each(&block)
35
48
  @paragraphs.each { |p| block.call(p) }
36
49
  end
37
50
 
51
+ # Implements [] by indexing the @paragraphs instance variable
38
52
  def [](index)
39
53
  @paragraphs[index]
40
54
  end
41
55
 
56
+ # @return [Integer] The sum of the standard credits in minutes
42
57
  def standard_credits_total
43
58
  @standard_credits_array.reduce(0) { |a, e| a + e[2] }
44
59
  end
45
60
 
61
+ # @return [Array] The array of standard credits, each element of
62
+ # type [start_time, end_time, duration]
46
63
  def standard_credits
47
64
  @standard_credits_array
48
65
  end
49
66
 
67
+ # @return [Integer] The sum of the impact credits in minutes
50
68
  def impact_credits_total
51
69
  @impact_credits_array.reduce(0) { |a, e| a + e[2] }
52
70
  end
53
71
 
54
- def credits_total
55
- impact_credits_total + standard_credits_total
56
- end
57
-
72
+ # @return [Array] The array of impact credits, each element of
73
+ # type [start_time, end_time, duration]
58
74
  def impact_credits
59
75
  @impact_credits_array
60
76
  end
61
77
 
78
+ # @return [Integer] The sum of the impact and standard credits in minutes
79
+ def credits_total
80
+ impact_credits_total + standard_credits_total
81
+ end
82
+
62
83
  private
63
84
 
85
+ # @todo Deal with edge case where the start and end times of different
86
+ # elements overlap to avoid claiming credit for the same moments in
87
+ # time more than once
88
+ # @return [Array] Array of elements of type
89
+ # [start_time, end_time, duration], one for each tag in all the paragraphs
90
+ # that earns standard credit
64
91
  def calc_standard_credits
65
92
  @paragraphs.each do |p|
66
93
  next unless p.creditable?
@@ -72,11 +99,12 @@ class LearningDiary
72
99
  @standard_credits_array.uniq!
73
100
  end
74
101
 
102
+ # @return [Array] Array of elements of type
103
+ # [start_time, end_time, duration], one for each tag in all the paragraphs
104
+ # that earns impact credit
75
105
  def calc_impact_credits
76
-
77
106
  @paragraphs.each do |p|
78
107
  next unless p.impact_creditable?
79
- # p p
80
108
  start = p.start_time
81
109
  finish = p.end_time
82
110
  duration = p.period
@@ -29,7 +29,6 @@ module MyTime
29
29
  end
30
30
 
31
31
  private
32
-
33
32
 
34
33
  # @param [Number] f_hour From hours
35
34
  # @param [Number] f_min From minutes
@@ -41,6 +40,11 @@ module MyTime
41
40
  has(@start_time) && (!has @end_time) ? true : start_t(f_hour, f_min)
42
41
  end
43
42
 
43
+ # Set the end time to the current paragraph date at t_hour and t_min.
44
+ # If the end time is before the start time, assume the end time is for the
45
+ # next day and add a day.
46
+ # @param [Number] t_hour To hours
47
+ # @param [Number] t_min To minutes
44
48
  def to_end_time(t_hour, t_min)
45
49
  # extract_time_object simply adds hours and mins to date
46
50
  @end_time = extract_time_object(t_hour, t_min, @date)
@@ -108,10 +112,19 @@ class Paragraph
108
112
 
109
113
  # initialize class date, start and class end time class instance variables
110
114
  @cst = @cet = @date = nil
111
- @section = @id = 0 # :TITLE
112
115
 
116
+
117
+ # initialize the section class instance variable. The section is an integer
118
+ # that is an index to the array of tags called SECTIONS declared in the
119
+ # module Tags
120
+ @section = 0 # :TITLE
121
+
122
+ @id = 0
123
+
124
+ # Declaration of class instance variables
113
125
  class << self
114
- # class starttime and class end time
126
+ # class starttime and class end time, date, section
127
+ # @todo find out what id is and does!
115
128
  attr_accessor :st, :et, :date, :section, :id
116
129
  end
117
130
 
@@ -172,19 +185,37 @@ class Paragraph
172
185
  end
173
186
 
174
187
  # @todo should this be private?
188
+ # Initialize the paragraph variables.
175
189
  def initialize_vars
176
190
  @date_specified = @end_time_specified = @start_time_specified = false
177
191
  @start_time = @end_time = nil
192
+
193
+ # Array of tagged content. e.g.
194
+ # @tags
195
+ # => [:TITLE, 'My Title']
196
+ # @tags
197
+ # => [:INTRO, 'My introduction.']
198
+ # @tags
199
+ # => [:LP, 'Something I have learnt']
178
200
  @tags = []
201
+
202
+ # Give the instance instance an id number that is kept track of by a
203
+ # class instance id, then increment the class instance id
179
204
  @id = Paragraph.id
180
205
  Paragraph.id += 1
181
206
  end
182
207
 
183
- # each on paragraph iterates through the tags
208
+ # Iterates through the instance tags
209
+ # @todo Find out if this is the tags for the paragraph or the whole
210
+ # document. Common sense says just the paragraph as this is just an
211
+ # instance instance variable
184
212
  def each(&block)
185
213
  @tags.each { |t| block.call(t) }
186
214
  end
187
215
 
216
+ # Implements [] for paragraph
217
+ # @return [Array] an element of the tags array, itself an element
218
+ # of type [:tag, 'content']
188
219
  def [](index)
189
220
  tags[index]
190
221
  end
@@ -195,17 +226,20 @@ class Paragraph
195
226
  false
196
227
  end
197
228
 
198
- # true is the paragraph contains a tag that can earn impact credit
229
+ # true if the paragraph contains a tag that can earn impact credit
199
230
  def impact_creditable?
200
231
  @tags.each { |t| return true if t[0] == :I }
201
232
  false
202
233
  end
203
234
 
235
+ # @return [Integer] the interval in minutes between start and end times
204
236
  def period
205
237
  return 0 if @end_time.nil? || @start_time.nil?
206
238
  (@end_time - @start_time).to_i / 60
207
239
  end
208
240
 
241
+ # @return end time if exists or failing that the start time if exists
242
+ # or failing that nil
209
243
  def latest_time
210
244
  return @end_time unless @end_time.nil?
211
245
  return @start_time unless @start_time.nil?
@@ -214,9 +248,15 @@ class Paragraph
214
248
 
215
249
  private
216
250
 
251
+ # Indexes for the elements of a tabbed array. Elements are of
252
+ # type [:tag, 'content']
217
253
  TAG = 0
254
+
255
+ # Content index number
218
256
  CONTENT = 1
219
257
 
258
+ # Setter for the class instance variables for the start time, end time
259
+ # and date
220
260
  def assign_class_dates(array)
221
261
  Paragraph.st, Paragraph.et, Paragraph.date = array
222
262
  end
@@ -227,28 +267,54 @@ class Paragraph
227
267
  [Paragraph.st, Paragraph.et, Paragraph.date]
228
268
  end
229
269
 
270
+ # @todo split/rename the actions of this function
271
+ # Extracts all the tag for the paragraph
272
+ # @param [String] str Paragraph from which tags are to be extracted
273
+ # @return [Boolean] True if any tags have been extracted
230
274
  def tags_extracted?(str)
231
275
  (@tags.count) < (@tags += extract_tags(str)).count
232
276
  end
233
277
 
278
+ # Add a single tagged content element of type
279
+ # [:symbol (tag), String (content)] to the @tags instance instance variable
280
+ # using the current value of the section class instance variable as an
281
+ # index to reference the correct section tag symbol from the SECTIONS array
282
+ # @param [String] str the content to tag
234
283
  def tag_section(str)
235
284
  tag_it(SECTIONS[Paragraph.section], str)
236
285
  end
237
286
 
287
+ # Joins all content in @tags of with a tag of type tag
288
+ # @param [Symbol] tag The tag for which content that should be selected.
289
+ # @param [String] str An optional string that can be passed to the function
290
+ # to which selected content will be appended.
238
291
  def content(tag, str = '')
239
292
  @tags.each { |t| str << t[CONTENT] + ' ' if t[TAG] == tag }
240
293
  str
241
294
  end
242
295
 
296
+ # Safely increments the class instance section invariable
243
297
  def next_section
244
298
  Paragraph.section += 1 unless Paragraph.section == (SECTIONS.count - 1)
245
299
  end
246
300
 
301
+ # Add a single tagged content element of type
302
+ # [:symbol (tag), String (content)] to the @tags instance instance variable.
303
+ # Move the section class instance variable up one (to current :INTRO) if
304
+ # it is at position 0 (currently :TITLE)
305
+ # @param [String] p the content to tag
306
+ # @param [Symbol] tag the tag to use
247
307
  def tag_it(tag, p)
248
308
  @tags << [tag, p]
249
309
  next_section if Paragraph.section == 0 # :TITLE
250
310
  end
251
311
 
312
+ # Acts and a getter and setter for tagged content. Adds a getter and setter
313
+ # methods for each tag with the name of the tag. For example:
314
+ # paragraph.intro('my intro')
315
+ # Would and an :INTRO tag with the text content of 'my intro'
316
+ # paragraph.intro
317
+ # Returns all content with a tag of :INTRO
252
318
  def method_missing(n, *args, &block)
253
319
  if args[0].nil? # tag getter
254
320
  ALL_TAGS.include?(n) ? content(n) : super(n, *args, &block)
data/lib/docfolio/tags.rb CHANGED
@@ -1,13 +1,24 @@
1
1
  require_relative 'date_format.rb'
2
2
  require 'English'
3
3
 
4
- # handles extraction of tagged or other significant content
4
+ # handles extraction of tagged or other significant content.
5
+ # Interface: extract_date, extract_tags
5
6
  module Tags
6
- # interface: extract_date, extract_tags
7
- TAGS = [:LP, :R, :DEN, :NOTE, :I] # recognized in text
8
- CREDITABLE = [:LP, :R, :I] # can earn cpd credit
9
- SECTIONS = [:TITLE, :INTRO, :NOTE] # assumed from position in document
7
+
8
+ # Tags that are part of the DSL and are recognized in text
9
+ TAGS = [:LP, :R, :DEN, :NOTE, :I]
10
+
11
+ # Tags that can earn CPD credit
12
+ CREDITABLE = [:LP, :R, :I]
13
+
14
+ # Tags that are applied to content based on the position in the document
15
+ SECTIONS = [:TITLE, :INTRO, :NOTE]
16
+
17
+ # Tags that are internal and which have no meaning derived from the DSL or
18
+ # the position in the document.
10
19
  SPECIAL = [:DATE] # internal tags with no meaning from content or position
20
+
21
+ # A combined array of all tags
11
22
  ALL_TAGS = SECTIONS + TAGS + SPECIAL
12
23
 
13
24
  # extracts and formats tags and pertaining text from a plain text paragraph
@@ -19,7 +30,9 @@ module Tags
19
30
  # returns a MatchData object. This can be used as an array, where indices
20
31
  # 1 - n are the matched backreferences of the last successful match
21
32
  # @param [String] paragraph_text a paragraph from a DSL text file
22
- # @param [Time] date of this paragraph. May be nil if not known.
33
+ # @param [Time] date Date of this paragraph. May be nil if not known.
34
+ # This date is taken from the Date class instance variable of the
35
+ # paragraph class.
23
36
  # @return [Array<String, Array, Time>] Array of values to be returned
24
37
  # [String return value] 'paragraph_text' the same paragraph that was passed to the function but without the matched date character if there were any.
25
38
  # [Array return value] 'time_array' array of 4 integer representing the hours and minutes of the from and to times
@@ -45,6 +58,12 @@ module Tags
45
58
  [paragraph_text, time_array, date]
46
59
  end
47
60
 
61
+ # Extracts a paragraph string to a tagged array with elements of type
62
+ # [:tag, 'content']. Called after the date/time info has been removed. If
63
+ # called before, will result in date info at the start being tagged as
64
+ # a :NOTE
65
+ # @param [String] paragraph_text Paragraph string after date info removed
66
+ # @return [Array] Tagged array
48
67
  def extract_tags(paragraph_text)
49
68
  tag_regex =~ paragraph_text ? extract_tag(paragraph_text) : []
50
69
  end
@@ -117,11 +136,25 @@ module Tags
117
136
  nil
118
137
  end
119
138
 
139
+ # Paragraphs are broken down into a tagged array, with elements of type
140
+ # [:tag, 'text']. The first element of an array is of type string. If the
141
+ # paragraph begins with text before any tags, then this first element will
142
+ # contain this text, otherwise it will be an empty string. This function
143
+ # tests this string and returns it tagged as :NOTE unless empty in which
144
+ # case it returns an empty array []
145
+ # @param [Array] a An array of tagged content of the paragraph
146
+ # @return [Array] Another tagged array which is either empty, or just
147
+ # contains a single tagged content of the text at the beginning if there
148
+ # was any.
120
149
  def preface_with_note(a)
121
150
  str = a[0].strip
122
151
  str == '' ? [] : [[:NOTE, str]]
123
152
  end
124
153
 
154
+ # Turns an array of strings into a tagged array. Ignores the string variable at position [0]. This first string is turned into a tagged array by the function #preface_with_note and appended in #extract_tag
155
+ # @param [Array] a Array of strings from splitting the paragraph
156
+ # @return [Array] A tagged array with elements of the form
157
+ # [:tag, 'content']
125
158
  def tags_array(a)
126
159
  tags = []
127
160
  tag_count = (a.count - 1) / 2
@@ -133,12 +166,18 @@ module Tags
133
166
  tags
134
167
  end
135
168
 
169
+ # Splits the paragraph into an array of tags of type [:tag, 'content']
170
+ # @param [String] paragraph_text String text of the paragraph with any
171
+ # date and time info at the beginning, removed
172
+ # @return [Array] Tagged array of content with elements of type
173
+ # [:tag, 'content']
136
174
  def extract_tag(paragraph_text)
137
175
  a = paragraph_text.split(tag_regex)
138
176
  preface_with_note(a) + tags_array(a)
139
177
  end
140
178
  end
141
179
 
180
+ # Adds a given number and hours and minutes to a Time object
142
181
  # @param [Time] from time to which hours and minutes are added
143
182
  # @param [Number] hour hours to add to from
144
183
  # @param [Number] min minutes to add to from
@@ -148,10 +187,29 @@ module Tags
148
187
  Time.at(from.to_i + seconds)
149
188
  end
150
189
 
190
+ # Extracts a paragraph string to a tagged array with elements of type
191
+ # [:tag, 'content']. Called after the date/time info has been removed. If
192
+ # called before, will result in date info at the start being tagged as
193
+ # a :NOTE
194
+ # @param [String] paragraph_text Paragraph string after date info removed
195
+ # @return [Array] Tagged array
151
196
  def extract_tags(paragraph_text)
152
197
  TagFriend.new.extract_tags(paragraph_text)
153
198
  end
154
199
 
200
+ # Defined in the Tags module
201
+ # @todo move function to one of the date or time handling classes
202
+ # The $LAST_MATCH_INFO global is equivalent to Rexexp.last_match and
203
+ # returns a MatchData object. This can be used as an array, where indices
204
+ # 1 - n are the matched backreferences of the last successful match
205
+ # @param [String] paragraph_text a paragraph from a DSL text file
206
+ # @param [Time] date Date of this paragraph. May be nil if not known.
207
+ # This date is taken from the Date class instance variable of the
208
+ # paragraph class.
209
+ # @return [Array<String, Array, Time>] Array of values to be returned
210
+ # [String return value] 'paragraph_text' the same paragraph that was passed to the function but without the matched date character if there were any.
211
+ # [Array return value] 'time_array' array of 4 integer representing the hours and minutes of the from and to times
212
+ # [Time return value] 'date' the date in (day month year) of this paragraph taken from the matched date_regex if there was one. Will be nil if there was no match and if the date passed to the function was also nil.
155
213
  def extract_date(paragraph_text, date)
156
214
  TagFriend.new.extract_date(paragraph_text, date)
157
215
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: docfolio
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Bulmer
@@ -9,7 +9,21 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
  date: 2015-12-10 00:00:00.000000000 Z
12
- dependencies: []
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: colorize
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.7.7
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.7.7
13
27
  description: A domain specific language to aid recording of a personal learning portfolio
14
28
  for UK General Practitioners.
15
29
  email: n.bulmer@live.co.uk
@@ -38,7 +52,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
38
52
  requirements:
39
53
  - - ">="
40
54
  - !ruby/object:Gem::Version
41
- version: '0'
55
+ version: 2.1.5
42
56
  required_rubygems_version: !ruby/object:Gem::Requirement
43
57
  requirements:
44
58
  - - ">="