docfolio 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|