Almirah 0.4.2 → 0.4.3

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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/bin/almirah +2 -2
  3. data/lib/almirah/doc_fabric.rb +7 -0
  4. data/lib/almirah/doc_items/blockquote.rb +15 -16
  5. data/lib/almirah/doc_items/code_block.rb +19 -21
  6. data/lib/almirah/doc_items/controlled_paragraph.rb +2 -2
  7. data/lib/almirah/doc_items/controlled_table.rb +11 -11
  8. data/lib/almirah/doc_items/controlled_table_row.rb +15 -18
  9. data/lib/almirah/doc_items/doc_footer.rb +10 -13
  10. data/lib/almirah/doc_items/doc_item.rb +2 -2
  11. data/lib/almirah/doc_items/heading.rb +1 -1
  12. data/lib/almirah/doc_items/image.rb +25 -27
  13. data/lib/almirah/doc_items/markdown_list.rb +2 -2
  14. data/lib/almirah/doc_items/markdown_table.rb +9 -2
  15. data/lib/almirah/doc_items/scope_table.rb +188 -0
  16. data/lib/almirah/doc_items/text_line.rb +26 -22
  17. data/lib/almirah/doc_items/todo_block.rb +15 -16
  18. data/lib/almirah/doc_items/work_item.rb +129 -0
  19. data/lib/almirah/doc_parser.rb +14 -8
  20. data/lib/almirah/doc_types/base_document.rb +21 -5
  21. data/lib/almirah/doc_types/coverage.rb +3 -3
  22. data/lib/almirah/doc_types/critical_chain_page.rb +218 -0
  23. data/lib/almirah/doc_types/decision.rb +152 -7
  24. data/lib/almirah/doc_types/decision_grouping.rb +17 -0
  25. data/lib/almirah/doc_types/decisions_overview.rb +591 -31
  26. data/lib/almirah/doc_types/implementation.rb +98 -98
  27. data/lib/almirah/doc_types/index.rb +11 -12
  28. data/lib/almirah/doc_types/persistent_document.rb +1 -1
  29. data/lib/almirah/doc_types/planning_dates.rb +17 -0
  30. data/lib/almirah/doc_types/protocol.rb +16 -20
  31. data/lib/almirah/doc_types/source_file.rb +1 -1
  32. data/lib/almirah/doc_types/traceability.rb +124 -133
  33. data/lib/almirah/dom/doc_section.rb +1 -1
  34. data/lib/almirah/navigation_pane.rb +9 -13
  35. data/lib/almirah/project/critical_chain.rb +117 -0
  36. data/lib/almirah/project/doc_linker.rb +4 -4
  37. data/lib/almirah/project/fever_chart.rb +94 -0
  38. data/lib/almirah/project/project_data.rb +8 -2
  39. data/lib/almirah/project/work_item_scheduler.rb +166 -0
  40. data/lib/almirah/project/working_calendar.rb +112 -0
  41. data/lib/almirah/project.rb +146 -9
  42. data/lib/almirah/project_configuration.rb +126 -29
  43. data/lib/almirah/project_template.rb +6 -6
  44. data/lib/almirah/project_utility.rb +3 -5
  45. data/lib/almirah/search/specifications_db.rb +2 -2
  46. data/lib/almirah/source_file_parser.rb +2 -3
  47. data/lib/almirah/templates/css/main.css +160 -0
  48. data/lib/almirah/templates/scripts/main.js +3 -1
  49. data/lib/almirah.rb +1 -2
  50. metadata +11 -2
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'fileutils'
4
4
  require_relative 'doc_fabric'
5
+ require_relative 'doc_items/work_item'
5
6
  require_relative 'navigation_pane'
6
7
  require_relative 'doc_types/traceability'
7
8
  require_relative 'doc_types/index'
@@ -12,7 +13,7 @@ require_relative 'project/project_data'
12
13
  require_relative 'console_reporter'
13
14
  require_relative 'relative_url'
14
15
 
15
- class Project # rubocop:disable Metrics/ClassLength,Style/Documentation
16
+ class Project
16
17
  attr_accessor :index, :project, :configuration, :project_data
17
18
 
18
19
  def initialize(configuration)
@@ -39,7 +40,7 @@ class Project # rubocop:disable Metrics/ClassLength,Style/Documentation
39
40
  FileUtils.copy_entry(src_folder, dst_folder)
40
41
  end
41
42
 
42
- def specifications_and_protocols # rubocop:disable Metrics/MethodLength,Metrics/AbcSize
43
+ def specifications_and_protocols
43
44
  parse_all_specifications
44
45
  parse_all_protocols
45
46
  parse_all_source_files
@@ -50,6 +51,7 @@ class Project # rubocop:disable Metrics/ClassLength,Style/Documentation
50
51
  link_all_decisions
51
52
  check_wrong_specification_referenced
52
53
  build_link_registry
54
+ link_work_items
53
55
  create_index
54
56
  render_all_specifications(@project_data.specifications)
55
57
  render_all_specifications(@project_data.traceability_matrices)
@@ -58,14 +60,16 @@ class Project # rubocop:disable Metrics/ClassLength,Style/Documentation
58
60
  render_all_source_files
59
61
  render_all_specifications(@project_data.implementation_matrices) # intentionally after source file rendering
60
62
  render_decisions_overview
63
+ render_critical_chain_page
61
64
  render_all_decisions
62
65
  render_index
63
66
  create_search_data
64
67
  report_broken_links
68
+ report_kit_violations
65
69
  report_rendered
66
70
  end
67
71
 
68
- def specifications_and_results(test_run) # rubocop:disable Metrics/MethodLength,Metrics/AbcSize
72
+ def specifications_and_results(test_run)
69
73
  parse_all_specifications
70
74
  parse_test_run test_run
71
75
  parse_all_source_files
@@ -76,6 +80,7 @@ class Project # rubocop:disable Metrics/ClassLength,Style/Documentation
76
80
  link_all_decisions
77
81
  check_wrong_specification_referenced
78
82
  build_link_registry
83
+ link_work_items
79
84
  create_index
80
85
  render_all_specifications(@project_data.specifications)
81
86
  render_all_specifications(@project_data.traceability_matrices)
@@ -84,10 +89,12 @@ class Project # rubocop:disable Metrics/ClassLength,Style/Documentation
84
89
  render_all_source_files
85
90
  render_all_specifications(@project_data.implementation_matrices) # intentionally after source file rendering
86
91
  render_decisions_overview
92
+ render_critical_chain_page
87
93
  render_all_decisions
88
94
  render_index
89
95
  create_search_data
90
96
  report_broken_links
97
+ report_kit_violations
91
98
  report_rendered
92
99
  end
93
100
 
@@ -107,10 +114,115 @@ class Project # rubocop:disable Metrics/ClassLength,Style/Documentation
107
114
  broken.each { |b| puts ConsoleReporter.warn_detail(" #{b[:document] || '?'}: #{b[:target]}") }
108
115
  end
109
116
 
117
+ # Builds the per-row WorkItem dependency network (ADR-194): registers every
118
+ # Scope-row work item, fills the intra-record step-order edges, then resolves
119
+ # each Depends On reference globally (LinkRegistry) to the activity-type-aligned
120
+ # work item of the target record, tagging each cross-record edge in-group or
121
+ # cross-group against the decision_groups boundary (ADR-197). Unresolved
122
+ # references are collected for report_kit_violations. Runs after
123
+ # build_link_registry (so every record resolves) and before rendering (so the
124
+ # overview Kit column is ready).
125
+ def link_work_items
126
+ @kit_unresolved = []
127
+ @project_data.decisions.each do |d|
128
+ d.scope_work_items.each { |wi| @project_data.work_items[wi.id] = wi }
129
+ end
130
+ link_intra_record_steps
131
+ link_cross_record_dependencies
132
+ end
133
+
134
+ # Each row's lower-numbered same-record steps are its predecessors; equal step
135
+ # numbers are concurrent (no edge). These edges are in-group by definition.
136
+ def link_intra_record_steps
137
+ @project_data.decisions.each do |d|
138
+ items = d.scope_work_items
139
+ items.each do |wi|
140
+ items.each do |other|
141
+ next if other.equal?(wi) || other.step >= wi.step
142
+
143
+ wi.add_predecessor(other, cross_group: false)
144
+ other.add_successor(wi)
145
+ end
146
+ end
147
+ end
148
+ end
149
+
150
+ def link_cross_record_dependencies
151
+ @project_data.decisions.each do |d|
152
+ d.scope_work_items.each do |wi|
153
+ wi.depends_on_refs.each { |ref| link_dependency(d, wi, ref) }
154
+ end
155
+ end
156
+ end
157
+
158
+ def link_dependency(record, work_item, ref)
159
+ target = @project_data.link_registry.find_by_id(ref)
160
+ unless target.is_a?(Decision)
161
+ @kit_unresolved << { record: record.id, target: ref }
162
+ return
163
+ end
164
+ prereq = aligned_work_item(target, work_item.activity)
165
+ return if prereq.nil? || prereq.equal?(work_item)
166
+
167
+ cross = decision_group_name(record) != decision_group_name(target)
168
+ work_item.add_predecessor(prereq, cross_group: cross)
169
+ prereq.add_successor(work_item)
170
+ anchor = target.scope_table&.step_column? ? prereq.row_anchor : nil
171
+ work_item.add_resolved_dependency(ref, target, anchor, prereq.id)
172
+ end
173
+
174
+ # The target record's work item whose activity (Item) matches `activity`,
175
+ # falling back to the nearest earlier activity by canonical phase order, then
176
+ # (when the target has only later activities) to its earliest row. nil only
177
+ # when the target has no Scope rows.
178
+ def aligned_work_item(target, activity)
179
+ items = target.scope_work_items
180
+ return nil if items.empty?
181
+
182
+ exact = items.select { |t| t.activity == activity }.min_by(&:step)
183
+ return exact if exact
184
+
185
+ rank = WorkItem::ACTIVITY_ORDER.index(activity) || WorkItem::ACTIVITY_ORDER.length
186
+ earlier = items.select { |t| t.activity_rank <= rank }
187
+ return items.min_by { |t| [t.activity_rank, t.step] } if earlier.empty?
188
+
189
+ earlier.min_by { |t| [-t.activity_rank, t.step] }
190
+ end
191
+
192
+ # The planning-group name (first-level decisions/ folder) a record belongs to,
193
+ # read from the decision_groups collection (ADR-197).
194
+ def decision_group_name(doc)
195
+ group = @project_data.decision_groups.find { |g| g.values.first.include?(doc) }
196
+ group&.keys&.first
197
+ end
198
+
199
+ # Reports the two kit gates and unresolved Depends On references (ADR-194), all
200
+ # as non-failing console warnings alongside report_broken_links.
201
+ def report_kit_violations
202
+ @kit_unresolved ||= []
203
+ phase = @project_data.work_items.each_value.select(&:phase_order_violation?)
204
+ cross = @project_data.work_items.each_value.select(&:cross_record_violation?)
205
+ total = phase.length + cross.length + @kit_unresolved.length
206
+ return if total.zero?
207
+
208
+ ConsoleReporter.warn('kit violations', total)
209
+ phase.each do |wi|
210
+ blocking = wi.intra_record_predecessors.reject(&:done?).map(&:id).join(', ')
211
+ puts ConsoleReporter.warn_detail(" phase order: #{wi.id} started before #{blocking}")
212
+ end
213
+ cross.each do |wi|
214
+ blocking = wi.cross_record_predecessors.reject(&:done?).map(&:id).join(', ')
215
+ puts ConsoleReporter.warn_detail(" not kitted: #{wi.id} needs #{blocking}")
216
+ end
217
+ @kit_unresolved.each do |u|
218
+ puts ConsoleReporter.warn_detail(" unresolved Depends On: #{u[:record]} -> #{u[:target]}")
219
+ end
220
+ end
221
+
110
222
  # Assigns each document its generated output path (relative to the build root)
111
223
  # and registers it for cross-document link resolution (ADR-186). Runs after all
112
224
  # documents are parsed and before any rendering, so link targets are known.
113
- def build_link_registry # rubocop:disable Metrics/MethodLength,Metrics/AbcSize
225
+ def build_link_registry
114
226
  reg = @project_data.link_registry
115
227
  TextLine.link_registry = reg
116
228
  TextLine.reset_broken_links
@@ -177,11 +289,26 @@ class Project # rubocop:disable Metrics/ClassLength,Style/Documentation
177
289
  rel_dir = File.dirname(f.sub("#{decisions_root}/", ''))
178
290
  doc.html_rel_path = rel_dir == '.' ? "#{doc.id}.html" : "#{rel_dir}/#{doc.id}.html"
179
291
  @project_data.decisions.append(doc)
292
+ add_to_decision_group(doc, rel_dir)
180
293
  end
181
294
  BaseDocument.show_decisions_link = @project_data.decisions.any?
182
295
  ConsoleReporter.count('parsing decisions', @project_data.decisions.length)
183
296
  end
184
297
 
298
+ # Add a decision record to its planning group, keyed on the first-level folder
299
+ # under decisions/ (a record directly under decisions/ has rel_dir '.', kept as
300
+ # its own '.' group rather than dropped). Groups are single-key hashes appended
301
+ # in folder-encounter order; the matching one is reused. See ADR-197.
302
+ def add_to_decision_group(doc, rel_dir)
303
+ group_name = rel_dir.split('/').first
304
+ group = @project_data.decision_groups.find { |g| g.key?(group_name) }
305
+ if group.nil?
306
+ @project_data.decision_groups.append({ group_name => [doc] })
307
+ else
308
+ group[group_name].append(doc)
309
+ end
310
+ end
311
+
185
312
  def parse_test_run(test_run)
186
313
  path = @configuration.project_root_directory
187
314
  Dir.glob("#{path}/tests/runs/#{test_run}/**/*.md").each do |f|
@@ -190,7 +317,7 @@ class Project # rubocop:disable Metrics/ClassLength,Style/Documentation
190
317
  end
191
318
  end
192
319
 
193
- def link_all_specifications # rubocop:disable Metrics/MethodLength,Metrics/AbcSize
320
+ def link_all_specifications
194
321
  comb_list = @project_data.specifications.combination(2)
195
322
  comb_list.each do |c|
196
323
  link_two_specifications(c[0], c[1])
@@ -209,7 +336,7 @@ class Project # rubocop:disable Metrics/ClassLength,Style/Documentation
209
336
  ConsoleReporter.count('traceability matrices', @project_data.traceability_matrices.length)
210
337
  end
211
338
 
212
- def link_all_protocols # rubocop:disable Metrics/MethodLength
339
+ def link_all_protocols
213
340
  @project_data.protocols.each do |p|
214
341
  @project_data.specifications.each do |s|
215
342
  if p.up_link_docs.key?(s.id.to_s)
@@ -250,7 +377,7 @@ class Project # rubocop:disable Metrics/ClassLength,Style/Documentation
250
377
  ConsoleReporter.count('implementation matrices', @project_data.implementation_matrices.length)
251
378
  end
252
379
 
253
- def check_wrong_specification_referenced # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
380
+ def check_wrong_specification_referenced
254
381
  available_specification_ids = {}
255
382
 
256
383
  @project_data.specifications.each do |s|
@@ -280,7 +407,7 @@ class Project # rubocop:disable Metrics/ClassLength,Style/Documentation
280
407
  end
281
408
  end
282
409
 
283
- def link_two_specifications(doc_a, doc_b) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
410
+ def link_two_specifications(doc_a, doc_b)
284
411
  if doc_b.up_link_docs.key?(doc_a.id.to_s)
285
412
  top_document = doc_a
286
413
  bottom_document = doc_b
@@ -383,7 +510,17 @@ class Project # rubocop:disable Metrics/ClassLength,Style/Documentation
383
510
  doc.to_html("#{path}/build/decisions/")
384
511
  end
385
512
 
386
- def render_all_decisions # rubocop:disable Metrics/MethodLength,Metrics/AbcSize
513
+ def render_critical_chain_page
514
+ return if @project_data.decisions.empty?
515
+
516
+ path = @configuration.project_root_directory
517
+ FileUtils.mkdir_p("#{path}/build/decisions")
518
+
519
+ doc = DocFabric.create_critical_chain_page(@project)
520
+ doc.to_html("#{path}/build/decisions/")
521
+ end
522
+
523
+ def render_all_decisions
387
524
  return if @project_data.decisions.empty?
388
525
 
389
526
  build_decisions_root = "#{@configuration.project_root_directory}/build/decisions"
@@ -1,42 +1,139 @@
1
1
  require 'yaml'
2
+ require 'date'
2
3
 
3
4
  class ProjectConfiguration
4
- attr_accessor :project_root_directory, :parameters
5
+ DEFAULT_WIP_LIMIT = 2
6
+ DEFAULT_BUFFER_RATIO = 0.5
7
+ DEFAULT_HOURS_PER_DAY = 8
5
8
 
6
- def initialize(path)
7
- @project_root_directory = File.expand_path(path)
8
- @parameters = {}
9
- load_project_file
10
- end
9
+ attr_accessor :project_root_directory, :parameters
11
10
 
12
- def load_project_file
13
- @parameters = YAML.load_file(@project_root_directory + '/project.yml')
14
- rescue Psych::SyntaxError => e
15
- puts "YAML syntax error: #{e.message}"
16
- rescue Errno::ENOENT
17
- puts 'Project file not found: project.yml'
18
- end
11
+ def initialize(path)
12
+ @project_root_directory = File.expand_path(path)
13
+ @parameters = {}
14
+ load_project_file
15
+ end
19
16
 
20
- def get_design_inputs
21
- if (@parameters.key? 'specifications') and (@parameters['specifications'].key? 'input')
22
- return @parameters['specifications']['input']
23
- end
17
+ def load_project_file
18
+ @parameters = YAML.load_file(@project_root_directory + '/project.yml')
19
+ rescue Psych::SyntaxError => e
20
+ puts "YAML syntax error: #{e.message}"
21
+ rescue Errno::ENOENT
22
+ puts 'Project file not found: project.yml'
23
+ end
24
24
 
25
- []
26
- end
25
+ def get_design_inputs
26
+ return @parameters['specifications']['input'] if (@parameters.key? 'specifications') and (@parameters['specifications'].key? 'input')
27
+
28
+ []
29
+ end
30
+
31
+ def get_repositories
32
+ return @parameters['repositories'] if @parameters.key? 'repositories'
33
+
34
+ []
35
+ end
36
+
37
+ def get_wip_limit
38
+ return DEFAULT_WIP_LIMIT unless @parameters.is_a?(Hash)
39
+
40
+ planning = @parameters['planning']
41
+ return DEFAULT_WIP_LIMIT unless planning.is_a?(Hash)
42
+
43
+ value = planning['wip_limit']
44
+ return DEFAULT_WIP_LIMIT unless value.is_a?(Integer) && value.positive?
45
+
46
+ value
47
+ end
48
+
49
+ # The CCPM project-buffer ratio (ADR-195): a fraction in (0, 1] cutting the
50
+ # aggregated chain safety. Absent or out-of-range falls back to the 0.5 default.
51
+ def get_buffer_ratio
52
+ return DEFAULT_BUFFER_RATIO unless @parameters.is_a?(Hash)
53
+
54
+ planning = @parameters['planning']
55
+ return DEFAULT_BUFFER_RATIO unless planning.is_a?(Hash)
56
+
57
+ value = planning['buffer_ratio']
58
+ return DEFAULT_BUFFER_RATIO unless value.is_a?(Numeric) && value.positive? && value <= 1
27
59
 
28
- def get_repositories
29
- return @parameters['repositories'] if @parameters.key? 'repositories'
60
+ value
61
+ end
30
62
 
31
- []
63
+ # The calendar anchor for working day 1 (ADR-205), a Date parsed from a
64
+ # DD-MM-YYYY planning.start_date. Absent or unparseable falls back to today,
65
+ # so an unconfigured project still renders (a moving anchor).
66
+ def get_start_date
67
+ date = parse_planning_date(planning_value('start_date'))
68
+ date || Date.today
69
+ end
70
+
71
+ # Per-group planning start dates (ADR-211): a map from a decision group's
72
+ # first-level folder name (under decisions/) to its start Date, read from
73
+ # planning.groups as DD-MM-YYYY entries. Non-string or unparseable values are
74
+ # dropped; empty when unset. A group absent from the map sequences after the
75
+ # previous group rather than carrying a declared start.
76
+ def get_group_start_dates
77
+ value = planning_value('groups')
78
+ return {} unless value.is_a?(Hash)
79
+
80
+ value.each_with_object({}) do |(name, raw), acc|
81
+ date = parse_planning_date(raw)
82
+ acc[name.to_s] = date if date
32
83
  end
84
+ end
85
+
86
+ # The non-working holiday dates (ADR-205) from planning.holidays, each a
87
+ # DD-MM-YYYY entry; unparseable entries are dropped. Empty when unset.
88
+ def get_holidays
89
+ value = planning_value('holidays')
90
+ return [] unless value.is_a?(Array)
91
+
92
+ value.filter_map { |entry| parse_planning_date(entry) }
93
+ end
94
+
95
+ # Working hours per day (ADR-196): converts logged effort hours into the
96
+ # working-day unit the estimates use. Absent or non-positive falls back to 8.
97
+ def get_hours_per_day
98
+ return DEFAULT_HOURS_PER_DAY unless @parameters.is_a?(Hash)
99
+
100
+ planning = @parameters['planning']
101
+ return DEFAULT_HOURS_PER_DAY unless planning.is_a?(Hash)
102
+
103
+ value = planning['hours_per_day']
104
+ return DEFAULT_HOURS_PER_DAY unless value.is_a?(Numeric) && value.positive?
33
105
 
34
- def is_spec_db_shall_be_created
35
- if @parameters.key? 'output'
36
- @parameters['output'].each do |p|
37
- return true if p == 'specifications_db'
38
- end
39
- end
40
- false
106
+ value
107
+ end
108
+
109
+ def is_spec_db_shall_be_created
110
+ if @parameters.key? 'output'
111
+ @parameters['output'].each do |p|
112
+ return true if p == 'specifications_db'
113
+ end
41
114
  end
115
+ false
116
+ end
117
+
118
+ # A value under the planning: key, or nil when planning is absent.
119
+ def planning_value(key)
120
+ return nil unless @parameters.is_a?(Hash)
121
+
122
+ planning = @parameters['planning']
123
+ planning.is_a?(Hash) ? planning[key] : nil
124
+ end
125
+
126
+ # Parse a planning date that may already be a Date (YAML ISO form) or a
127
+ # DD-MM-YYYY string; nil when neither.
128
+ def parse_planning_date(value)
129
+ return value if value.is_a?(Date)
130
+ return nil unless value.is_a?(String)
131
+
132
+ match = /\A(\d{2})-(\d{2})-(\d{4})\z/.match(value.strip)
133
+ return nil unless match
134
+
135
+ Date.new(match[3].to_i, match[2].to_i, match[1].to_i)
136
+ rescue ArgumentError
137
+ nil
138
+ end
42
139
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'fileutils'
4
4
 
5
- class ProjectTemplate # rubocop:disable Style/Documentation
5
+ class ProjectTemplate
6
6
  attr_accessor :project_root
7
7
 
8
8
  def initialize(project_name)
@@ -324,11 +324,11 @@ class ProjectTemplate # rubocop:disable Style/Documentation
324
324
 
325
325
  # Scope
326
326
 
327
- | Item | Status | Start Date | Target Date | Description |
328
- |---|---|---|---|---|
329
- | Requirements | To Do | | | |
330
- | Code | To Do | | | |
331
- | Tests | To Do | | | |
327
+ | # | Item | Owner | Depends On | Est (focused) | Est (safe) | Status | Start Date | Target Date | Description |
328
+ |---|---|---|---|---|---|---|---|---|---|
329
+ | 1 | Requirements | BA | | 2 | 3 | To Do | | | |
330
+ | 2 | Code | DEV | | 3 | 5 | To Do | | | |
331
+ | 3 | Tests | TEST | | 2 | 4 | To Do | | | |
332
332
 
333
333
  # Out of Scope
334
334
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'fileutils'
4
4
 
5
- class ProjectUtility # rubocop:disable Style/Documentation
5
+ class ProjectUtility
6
6
  attr_accessor :configuration
7
7
 
8
8
  def initialize(configuration)
@@ -19,7 +19,7 @@ class ProjectUtility # rubocop:disable Style/Documentation
19
19
 
20
20
  private
21
21
 
22
- def combine(run_id) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
22
+ def combine(run_id)
23
23
  path = @configuration.project_root_directory
24
24
  dst_folder = "#{@configuration.project_root_directory}/build"
25
25
  FileUtils.mkdir_p(dst_folder)
@@ -29,9 +29,7 @@ class ProjectUtility # rubocop:disable Style/Documentation
29
29
  dst_f = File.open(dst_file, 'a')
30
30
 
31
31
  src_path = if run_id
32
- unless Dir.exist? "#{path}/tests/runs/#{run_id}"
33
- puts "\e[1m\e[31m Run #{run_id} folder does not exists"
34
- end
32
+ puts "\e[1m\e[31m Run #{run_id} folder does not exists" unless Dir.exist? "#{path}/tests/runs/#{run_id}"
35
33
  "#{path}/tests/runs/#{run_id}/**/*.md"
36
34
  else
37
35
  "#{path}/tests/protocols/**/*.md"
@@ -12,7 +12,7 @@ class SpecificationsDb
12
12
  create_data
13
13
  end
14
14
 
15
- def create_data # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
15
+ def create_data
16
16
  @specifications.each do |sp|
17
17
  sp.items.each do |i|
18
18
  if (i.instance_of? Paragraph) or (i.instance_of? ControlledParagraph)
@@ -31,7 +31,7 @@ class SpecificationsDb
31
31
  end
32
32
  end
33
33
 
34
- def add_markdown_list_item_to_db(data, item_for_reference, item_to_process) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
34
+ def add_markdown_list_item_to_db(data, item_for_reference, item_to_process)
35
35
  e = nil
36
36
  item_to_process.rows.each do |r|
37
37
  if r.is_a?(MarkdownList)
@@ -2,7 +2,7 @@ require_relative 'doc_items/doc_item'
2
2
  require_relative 'doc_items/heading'
3
3
  require_relative 'doc_items/source_code_paragraph'
4
4
 
5
- class SourceFileParser # rubocop:disable Style/Documentation
5
+ class SourceFileParser
6
6
  def self.parse(doc, file_lines)
7
7
  # restart section numbering for each new document
8
8
  Heading.reset_global_section_number
@@ -19,7 +19,7 @@ class SourceFileParser # rubocop:disable Style/Documentation
19
19
  doc.headings.append(item)
20
20
 
21
21
  # main loop
22
- file_lines.each do |s| # rubocop:disable Metrics/BlockLength
22
+ file_lines.each do |s|
23
23
  res = %r{<REQ>(.*)</REQ>}.match(s) # Document Referece Item
24
24
  next unless res
25
25
 
@@ -36,7 +36,6 @@ class SourceFileParser # rubocop:disable Style/Documentation
36
36
  up_links = []
37
37
  tmp.each do |ul|
38
38
  lnk = ul[0]
39
- #
40
39
  doc_id = /([a-zA-Z]+)-\d+/.match(lnk) # SRS
41
40
  up_links << lnk.upcase if doc_id
42
41
  # try to find the real end of text