blob: fa916c862d25a8a2736cf8069613bc97592f5bbe [file] [log] [blame]
class Minutes
def self.draft(agenda_txt, minutes_yaml)
minutes = File.read(agenda_txt)
@@notes = YAML.load_file(minutes_yaml) rescue {}
minutes.mreplace(/\n\s1\.\sCall\sto\sorder\n+(.*?:)\n\n
((?:^\s{12}[^\n]*\n+)+\n)
(.*?)\n\n\s2\.\sRoll\sCall/mx) do |meeting, number, backup|
start = notes('Call to order') || '??:??'
meeting.gsub! "is scheduled", "was scheduled"
meeting.gsub! "will begin as", "began at"
meeting.gsub! "soon thereafter that", "#{start} when"
meeting.gsub! "quorum is", "quorum was"
meeting.gsub! "will be", "was"
meeting.gsub! /:\z/, "."
backup.gsub! "will be", "was"
[meeting.reflow(4,64), '', backup.reflow(4, 68)]
end
minutes.sub! /^ +ASF members are welcome to attend board meetings.*?\n\n/m,
''
minutes.mreplace(/\n\s2\.\sRoll\sCall\n\n
(.*?)\n\n+\s3.\sMinutes
/mx) do |rollcall|
if notes('Roll Call')
notes('Roll Call').gsub(/\r\n/,"\n").gsub(/\n*\Z/,'').
gsub(/^([^\n])/, ' \1')
else
rollcall.gsub(/ \(expected.*?\)/, '')
end
end
minutes.mreplace(/\n\s3\.\sMinutes\sfrom\sprevious\smeetings\n\n
(.*?\n\n)
\s4\.\sExecutive\sOfficer\sReports
/mx) do |prior_minutes|
prior_minutes.mreplace(/\n\s+(\w)\.\sThe\smeeting\sof\s(.*?)\n.*?\n
(\s{7}\[.*?\])\n\n
/mx) do |attach, title, pub_minutes|
notes = notes(title)
if notes and !notes.empty?
notes = 'Approved by General Consent.' if notes == 'approved'
notes = 'Tabled.' if notes == 'tabled'
[attach, title, notes.reflow(7,62)]
else
[attach, title, ' Tabled.']
end
end
end
minutes.mreplace(/\n\s4\.\sExecutive\sOfficer\sReports\n
(\n.*?\n\n)
\s5\.\sAdditional\sOfficer\sReports
/mx) do |reports|
reports.mreplace(/\n\s\s\s\s(\w)\.\s(.*?)\[.*?\](.*?)
()(?:\n+\s\s\s\s\w\.|\n\n\z)
/mx) do |section, title, report, comments|
notes = notes(title)
if notes and !notes.empty?
[section, title, report, "\n\n" + notes.reflow(7,62)]
elsif report.strip.empty?
[section, title, report, "\n\n No report was submitted."]
else
[section, title, report, ""]
end
end
end
minutes.mreplace(/\n\s5\.\sAdditional\sOfficer\sReports\n
(\n.*?\n\n)
\s7\.\sSpecial\sOrders
/mx) do |reports|
reports.mreplace(/
\n\s\s\s\s\s?(\w+)\.\s([^\n]*?) # section, title
\[([^\n]+)\]\n\n # owners
\s{7}See\s\s?Attachment\s\s?(\w+)[^\n]* # attach (title)
(\s+\[\s.*?approved:\s*?.*? # approved
\s*comments:.*?\n\s{9}\]) # comments
/mx) do |section, title, owners, attach, comments|
notes = notes(title.sub('VP of','').strip)
if notes and !notes.empty?
comments = "\n\n" + notes.to_s.reflow(7,62)
else
comments = ''
end
[section, title, owners, attach, comments]
end
end
minutes.mreplace(/\n\s7\.\sSpecial\sOrders\n
(.*?)
\n\s8\.\sDiscussion\sItems
/mx) do |reports|
break if reports.empty?
reports.mreplace(/\n\s\s\s\s(\w)\.(.*?)\n(.*?)()\s+(?:\s*\n\s\s\s\s\w\.|\z)
/mx) do |section, title, order, comments|
order.sub! /\n \[.*?\n +\]\n/m, ''
notes = notes(title.strip)
if !notes or notes.empty? or notes.strip == 'tabled'
notes = "was tabled."
elsif notes == 'unanimous'
notes = "was approved by Unanimous Vote of the directors present."
end
notes = "Special Order 7#{section}, #{title}, " + notes
order += "\n" unless order =~ /\n\Z/
[section, title, order, "\n" + notes.reflow(7,62)]
end
end
minutes.mreplace(/\n\s8\.\sDiscussion\sItems
(.*?)
\n\s9\.\s.*Action\sItems
/mx) do |reports|
break unless reports =~ /\n\s{3,5}[A-Z]\.\s/
reports.mreplace(/\n\s\s\s\s(\w)\.(.*?)\n(.*?)()\s+(?:\s*\n\s\s\s\s\w\.|\z)
/mx) do |section, title, item, comments|
item.sub! /\n \[.*?\n +\]\n/m, ''
item += "\n" unless item =~ /\n\Z/
notes = notes(title.strip) || ''
[section, title, item, "\n" + notes.reflow(7,70)]
end
end
minutes.mreplace(/
^((?:\s[89]|1\d)\.)\s
(.*?)\n
(.*?)
(?=\n[\s1]\d\.|\n===)
/mx) do |attach, title, comments|
notes = notes(title)
if notes and !notes.empty?
if title =~ /Action Items/
comments = notes.gsub(/\r\n/,"\n").gsub(/^/,' ')
elsif title == 'Adjournment'
comments = "\n Adjourned at #{notes} UTC\n"
else
comments += "\n" + notes.to_s.reflow(4,68) + "\n"
end
elsif title == 'Adjournment'
comments = "\n Adjourned at ??:?? UTC\n"
end
[attach, title, comments]
end
missing = minutes.scan(/^Attachment (\w\w?):.*\s*\n---/).flatten
missing.each do |attach|
minutes.sub! /^(\s+)See Attachment #{attach}$/, '\1No report was submitted.'
end
minutes.sub! 'Minutes (in Subversion) are found under the URL:',
'Published minutes can be found at:'
minutes.sub! ASF::SVN.svnpath!('foundation_board'),
'http://www.apache.org/foundation/board/calendar.html'
minutes.sub!(/ \d\. Committee Reports.*?\n\s+A\./m) do |heading|
heading.sub('reports require further', 'reports required further')
end
minutes[/^() 5. Additional Officer Reports/,1] =
" Executive officer reports approved as submitted by General Consent.\n\n"
minutes[/^() 6. Committee Reports/,1] =
" Additional officer reports approved as submitted by General Consent.\n\n"
minutes[/^() 7. Special Orders/,1] =
" Committee reports approved as submitted by General Consent.\n\n"
minutes.sub! 'Meeting Agenda', 'Meeting Minutes'
minutes.sub! /^End of agenda/, 'End of minutes'
# remove block of lines (and preceding whitespace including blank lines)
# where the first line starts with <private> and the last line ends with
# </private>.
minutes.gsub! /^\s*<private>.*?<\/private>\s*?\n/mi, ''
# remove inline <private>...</private> sections (and preceding spaces
# and tabs) where the <private> and </private> are on the same line.
minutes.gsub! /[ \t]*<private>.*?<\/private>/i, ''
minutes.gsub! /\n( *)\[ comments:.*?\n\1 ? ?\]/m, ''
minutes
end
def self.notes(index)
index = index.strip
return @@notes[index] if @@notes[index]
index.sub! /^Report from the VP of /, ''
index.sub! /^Report from the /, ''
index.sub! /^Status report for the /, ''
index.sub! /^Resolution to /, ''
index.sub! /^Apache /, ''
index.sub! /\sTeam$/, ''
index.sub! /\sCommittee$/, ''
index.sub! /\sthe\s/, ' '
index.sub! /\sApache\s/, ' '
index.sub! /\sCommittee\s/, ' '
index.sub! /\sProject$/, ''
index.sub! /\sPMC$/, ''
index.sub! /\sProject\s/, ' '
@@notes[index]
end
end