docfolio 0.0.1 → 0.0.2
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 +4 -4
- data/bin/docfolio +3 -0
- data/lib/docfolio/docfolio.rb +1 -75
- data/lib/docfolio/learning_diary.rb +113 -64
- data/lib/docfolio/logs.rb +63 -0
- data/lib/docfolio/paragraph.rb +63 -271
- data/lib/docfolio/paragraph_modules/date_times.rb +10 -0
- data/lib/docfolio/paragraph_modules/dates.rb +169 -0
- data/lib/docfolio/paragraph_modules/tags.rb +194 -0
- data/lib/docfolio/paragraph_modules/times.rb +74 -0
- data/lib/docfolio/views/diary_console_view.rb +13 -1
- data/lib/docfolio/views/view.rb +2 -2
- metadata +10 -6
- data/lib/docfolio.rb +0 -2
- data/lib/docfolio/date_format.rb +0 -88
- data/lib/docfolio/tags.rb +0 -216
@@ -5,6 +5,7 @@ require_relative 'view.rb'
|
|
5
5
|
class DiaryConsoleView < ConsoleView
|
6
6
|
def initialize(diary = nil)
|
7
7
|
return if diary.nil?
|
8
|
+
@diary = diary
|
8
9
|
@paragraphs = diary.paragraphs
|
9
10
|
@credits = diary.standard_credits
|
10
11
|
@credits_total = diary.standard_credits_total
|
@@ -22,11 +23,22 @@ class DiaryConsoleView < ConsoleView
|
|
22
23
|
|
23
24
|
def output_str
|
24
25
|
str = ''
|
26
|
+
sig_event = @diary.significant_event?
|
27
|
+
str += "SIGNIFICANT EVENT\n\n" if sig_event
|
25
28
|
str += section_str('TITLE', content(:TITLE))
|
29
|
+
str += section_str('DATE OF EVENT', content(:SEA))
|
30
|
+
str += section_str('WHO WAS INVOLVED', content(:INVOLVED))
|
26
31
|
str += section_str('INTRODUCTION', content(:INTRO))
|
32
|
+
str += section_str('WHAT HAPPENED?', content(:WHAT))
|
33
|
+
str += section_str('WHY DID IT HAPPEN?', content(:WHY))
|
34
|
+
str += section_str('HOW DID YOU AND THE OTHERS INVOLVED FEEL?', content(:FEELINGS))
|
35
|
+
str += section_str('WHAT WENT WELL?', content(:WELL))
|
36
|
+
str += section_str('WHAT COULD HAVE BEEN DONE DIFFERENTLY?', content(:DIFFERENT))
|
37
|
+
str += section_str('WHAT NEEDS TO CHANGE?', content(:CHANGE))
|
38
|
+
str += section_str('WHAT HAS CHANGED?', content(:CHANGED))
|
27
39
|
str += learning_str
|
28
40
|
str += credits_str
|
29
|
-
str
|
41
|
+
str.gsub(/ \n/, "\n")
|
30
42
|
end
|
31
43
|
|
32
44
|
def learning_str(str = '')
|
data/lib/docfolio/views/view.rb
CHANGED
@@ -18,8 +18,8 @@ class ConsoleView < View
|
|
18
18
|
to_console("#{title}") + "\n\n" +
|
19
19
|
to_console("• #{body.join("\n\n• ")}\n\n", 2, 4)
|
20
20
|
else
|
21
|
-
to_console("#{title}") +
|
22
|
-
to_console("#{body.join}\n\n")
|
21
|
+
to_console("#{title.gsub(/ $/, '')}") +
|
22
|
+
to_console("#{body.join}\n\n").gsub(/ $/, '')
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: docfolio
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Bulmer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-12-
|
11
|
+
date: 2015-12-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|
@@ -27,16 +27,20 @@ dependencies:
|
|
27
27
|
description: A domain specific language to aid recording of a personal learning portfolio
|
28
28
|
for UK General Practitioners.
|
29
29
|
email: n.bulmer@live.co.uk
|
30
|
-
executables:
|
30
|
+
executables:
|
31
|
+
- docfolio
|
31
32
|
extensions: []
|
32
33
|
extra_rdoc_files: []
|
33
34
|
files:
|
34
|
-
-
|
35
|
-
- lib/docfolio/date_format.rb
|
35
|
+
- bin/docfolio
|
36
36
|
- lib/docfolio/docfolio.rb
|
37
37
|
- lib/docfolio/learning_diary.rb
|
38
|
+
- lib/docfolio/logs.rb
|
38
39
|
- lib/docfolio/paragraph.rb
|
39
|
-
- lib/docfolio/
|
40
|
+
- lib/docfolio/paragraph_modules/date_times.rb
|
41
|
+
- lib/docfolio/paragraph_modules/dates.rb
|
42
|
+
- lib/docfolio/paragraph_modules/tags.rb
|
43
|
+
- lib/docfolio/paragraph_modules/times.rb
|
40
44
|
- lib/docfolio/views/collater_console_view.rb
|
41
45
|
- lib/docfolio/views/diary_console_view.rb
|
42
46
|
- lib/docfolio/views/view.rb
|
data/lib/docfolio.rb
DELETED
data/lib/docfolio/date_format.rb
DELETED
@@ -1,88 +0,0 @@
|
|
1
|
-
# convert the date from 'dd-Oct-yy' to seconds past UNIX epoc
|
2
|
-
# accepts dd_Mmm-yy dd-Mmmmmmm-yy dd-MMM-yy and other similar
|
3
|
-
module DateFormat
|
4
|
-
# Extracts a date in seconds past UNIX epoc from a string date. The result
|
5
|
-
# can be used for other date operations. Converts from dd-mmm-yy and similar
|
6
|
-
# formats as commonly found in csv files
|
7
|
-
class DateExtractor
|
8
|
-
def format_date(date)
|
9
|
-
day, month, year = components(date)
|
10
|
-
begin
|
11
|
-
Time.new(year, month, day).to_i
|
12
|
-
rescue ArgumentError => e
|
13
|
-
print_argument_error_msg(e)
|
14
|
-
return nil
|
15
|
-
rescue => e
|
16
|
-
raise e
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
def print_argument_error_msg(e)
|
23
|
-
puts "\n#{e.to_s.upcase}"
|
24
|
-
puts "date : #{date.inspect}"
|
25
|
-
puts "day : #{day}"
|
26
|
-
puts "month : #{month}"
|
27
|
-
puts "year : #{year}"
|
28
|
-
puts e.backtrace
|
29
|
-
end
|
30
|
-
|
31
|
-
# splits date into is component day month and time
|
32
|
-
def components(date)
|
33
|
-
date = date.split('-')
|
34
|
-
day = date[0].to_i
|
35
|
-
month = convert_month_to_number(date[1])
|
36
|
-
year = date[2].to_i
|
37
|
-
if year < 100 # no century
|
38
|
-
year > Time.now.year % 1000 ? century = 1900 : century = 2000
|
39
|
-
year += century
|
40
|
-
end
|
41
|
-
[day, month, year]
|
42
|
-
end
|
43
|
-
|
44
|
-
# A hash of text months and their corresponding month number
|
45
|
-
MONTHS = {
|
46
|
-
'jan' => 1,
|
47
|
-
'feb' => 2,
|
48
|
-
'mar' => 3,
|
49
|
-
'apr' => 4,
|
50
|
-
'may' => 5,
|
51
|
-
'jun' => 6,
|
52
|
-
'jul' => 7,
|
53
|
-
'aug' => 8,
|
54
|
-
'sep' => 9,
|
55
|
-
'oct' => 10,
|
56
|
-
'nov' => 11,
|
57
|
-
'dec' => 12,
|
58
|
-
'january' => 1,
|
59
|
-
'february' => 2,
|
60
|
-
'march' => 3,
|
61
|
-
'april' => 4,
|
62
|
-
'june' => 6,
|
63
|
-
'july' => 7,
|
64
|
-
'august' => 8,
|
65
|
-
'september' => 9,
|
66
|
-
'october' => 10,
|
67
|
-
'november' => 11,
|
68
|
-
'december' => 12,
|
69
|
-
'sept' => 9
|
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
|
75
|
-
def convert_month_to_number(month)
|
76
|
-
return month.to_i if month.to_i > 0 # already a number
|
77
|
-
month = month.downcase
|
78
|
-
MONTHS[month]
|
79
|
-
end
|
80
|
-
end
|
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
|
85
|
-
def format_date(date)
|
86
|
-
DateExtractor.new.format_date(date)
|
87
|
-
end
|
88
|
-
end
|
data/lib/docfolio/tags.rb
DELETED
@@ -1,216 +0,0 @@
|
|
1
|
-
require_relative 'date_format.rb'
|
2
|
-
require 'English'
|
3
|
-
|
4
|
-
# handles extraction of tagged or other significant content.
|
5
|
-
# Interface: extract_date, extract_tags
|
6
|
-
module Tags
|
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.
|
19
|
-
SPECIAL = [:DATE] # internal tags with no meaning from content or position
|
20
|
-
|
21
|
-
# A combined array of all tags
|
22
|
-
ALL_TAGS = SECTIONS + TAGS + SPECIAL
|
23
|
-
|
24
|
-
# extracts and formats tags and pertaining text from a plain text paragraph
|
25
|
-
class TagFriend
|
26
|
-
include DateFormat
|
27
|
-
|
28
|
-
# @todo move function to one of the date or time handling classes
|
29
|
-
# The $LAST_MATCH_INFO global is equivalent to Rexexp.last_match and
|
30
|
-
# returns a MatchData object. This can be used as an array, where indices
|
31
|
-
# 1 - n are the matched backreferences of the last successful match
|
32
|
-
# @param [String] paragraph_text a paragraph from a DSL text file
|
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.
|
36
|
-
# @return [Array<String, Array, Time>] Array of values to be returned
|
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.
|
38
|
-
# [Array return value] 'time_array' array of 4 integer representing the hours and minutes of the from and to times
|
39
|
-
# [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.
|
40
|
-
def extract_date(paragraph_text, date)
|
41
|
-
time_array = []
|
42
|
-
|
43
|
-
# if text contains a date match
|
44
|
-
if date_regex =~ paragraph_text
|
45
|
-
# $' (or $POSTMATCH), contains the characters after the match position
|
46
|
-
paragraph_text = $'
|
47
|
-
|
48
|
-
# strip whitespace if any remaining match or set to empty string
|
49
|
-
# if no match. If there is just white space after the match then
|
50
|
-
# this is truncated to an empty string
|
51
|
-
paragraph_text.nil? ? paragraph_text = '' : paragraph_text.strip!
|
52
|
-
|
53
|
-
# extracts the 'from' and 'to' times from the last match above. the
|
54
|
-
# time_array contains from_hour, from_min, to_hour, to_min, the
|
55
|
-
# date parameter is updated if the match found a new date
|
56
|
-
time_array, date = date_from_globals($LAST_MATCH_INFO, date)
|
57
|
-
end
|
58
|
-
[paragraph_text, time_array, date]
|
59
|
-
end
|
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
|
67
|
-
def extract_tags(paragraph_text)
|
68
|
-
tag_regex =~ paragraph_text ? extract_tag(paragraph_text) : []
|
69
|
-
end
|
70
|
-
|
71
|
-
private
|
72
|
-
|
73
|
-
# @todo move function to one of the date or time handling classes
|
74
|
-
# returns a date from the 26 globals returned by date_regex
|
75
|
-
# @param [MatchData] glob_a the MatchData object return when the date_regex
|
76
|
-
# was matched to the paragraph
|
77
|
-
# @param [Time] date the date of the paragraph; may be nil if not known
|
78
|
-
# @return [Array] array of 4 integer representing the
|
79
|
-
# hours and minutes of the from and to times
|
80
|
-
# @return [Time] 'date' the date (day month year) of this paragraph
|
81
|
-
def date_from_globals(glob_a, date)
|
82
|
-
from_hour = glob([1, 23], glob_a)
|
83
|
-
from_min = glob([2, 24], glob_a)
|
84
|
-
to_hour = glob([3, 25], glob_a)
|
85
|
-
to_min = glob([4, 26], glob_a)
|
86
|
-
day = glob([5, 8, 12, 14, 17, 21], glob_a)
|
87
|
-
month = glob([6, 9, 11, 15, 18, 20], glob_a)
|
88
|
-
year = glob([7, 10, 13, 16, 19, 22], glob_a)
|
89
|
-
date = Time.at(format_date("#{day}-#{month}-#{year}")) unless day.nil?
|
90
|
-
[[from_hour, from_min, to_hour, to_min], date]
|
91
|
-
end
|
92
|
-
|
93
|
-
# @todo move function to one of the date or time handling classes
|
94
|
-
# Returns a regular expression to be used to match dates and times of
|
95
|
-
# the paragraph.
|
96
|
-
# @return [Regex] a regular expression to use to match dates and times
|
97
|
-
# in the paragraph
|
98
|
-
def date_regex
|
99
|
-
dy = /(?<day>\d{1,2})/
|
100
|
-
mt = /(?<month>\w+)/
|
101
|
-
yr = /(?<year>\d{2,4})/
|
102
|
-
time = /(?<hour>\d{1,2}):(?<min>\d{2})/
|
103
|
-
period = /#{time}( ?(?:-|to) ?#{time})?/
|
104
|
-
date1 = %r{#{dy}/#{dy}/#{yr}} # d/m/y
|
105
|
-
date2 = /#{dy},? #{mt},? #{yr}/ # d Month Year
|
106
|
-
date3 = /#{mt},? #{dy},? #{yr}/ # Month d Year
|
107
|
-
date = /#{date1}|#{date2}|#{date3}/
|
108
|
-
/^(#{period} ?#{date}?|#{date} ?#{period}?)/
|
109
|
-
end
|
110
|
-
|
111
|
-
# @todo would str be better with join?
|
112
|
-
# Creates a regex that can be used to match for tags that are recognized
|
113
|
-
# as part of the DSL, currently :LP, :R, :DEN, :NOTE and :I
|
114
|
-
def tag_regex
|
115
|
-
str = ''
|
116
|
-
TAGS.each do |t|
|
117
|
-
str << "#{t}|"
|
118
|
-
end
|
119
|
-
str.gsub!(/\|$/, '')
|
120
|
-
/\b(#{str}): ?/
|
121
|
-
end
|
122
|
-
|
123
|
-
# Extracts a particular parameter from the MatchData object return when the
|
124
|
-
# paragraph was matched with the date regex. Treats the MatchData
|
125
|
-
# as an array, iterating through each index represented in the i_a
|
126
|
-
# array to find and return a value if there is one.
|
127
|
-
# @param [Array] i_a Array of integers representing positions to test in
|
128
|
-
# array glob_a
|
129
|
-
# @param [MatchData] glob_a Array of matched backreferences of the last
|
130
|
-
# successful regular expression match
|
131
|
-
# @return the first element in MatchData that is not nil. Returns
|
132
|
-
# nil if there are no elements in MatchData at the indices in i_a that
|
133
|
-
# are not nil.
|
134
|
-
def glob(i_a, glob_a)
|
135
|
-
i_a.each { |n| return glob_a[n] unless glob_a[n].nil? }
|
136
|
-
nil
|
137
|
-
end
|
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.
|
149
|
-
def preface_with_note(a)
|
150
|
-
str = a[0].strip
|
151
|
-
str == '' ? [] : [[:NOTE, str]]
|
152
|
-
end
|
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']
|
158
|
-
def tags_array(a)
|
159
|
-
tags = []
|
160
|
-
tag_count = (a.count - 1) / 2
|
161
|
-
1.upto(tag_count) do |i|
|
162
|
-
tag = a[(i * 2) - 1].to_sym
|
163
|
-
content = a[i * 2].strip
|
164
|
-
tags << [tag, content]
|
165
|
-
end
|
166
|
-
tags
|
167
|
-
end
|
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']
|
174
|
-
def extract_tag(paragraph_text)
|
175
|
-
a = paragraph_text.split(tag_regex)
|
176
|
-
preface_with_note(a) + tags_array(a)
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
# Adds a given number and hours and minutes to a Time object
|
181
|
-
# @param [Time] from time to which hours and minutes are added
|
182
|
-
# @param [Number] hour hours to add to from
|
183
|
-
# @param [Number] min minutes to add to from
|
184
|
-
# @return [Time] the result of hours and minutes after from
|
185
|
-
def extract_time_object(hour, min, from)
|
186
|
-
seconds = (hour.to_i * 3600) + (min.to_i * 60)
|
187
|
-
Time.at(from.to_i + seconds)
|
188
|
-
end
|
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
|
196
|
-
def extract_tags(paragraph_text)
|
197
|
-
TagFriend.new.extract_tags(paragraph_text)
|
198
|
-
end
|
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.
|
213
|
-
def extract_date(paragraph_text, date)
|
214
|
-
TagFriend.new.extract_date(paragraph_text, date)
|
215
|
-
end
|
216
|
-
end
|