Module: PredictabilityEngine::ReportGenerator
- Defined in:
- lib/predictability_engine/report_generator.rb
Overview
Logic for generating and writing reports.
Constant Summary collapse
- FORMAT_TO_EXT =
{ markdown: 'md', md: 'md', confluence: 'conf', conf: 'conf', landscape: 'html', dashboard: 'html', a3_landscape: 'pdf', ppt: 'pptx', png: 'png', raw_csv: 'csv', xlsx: 'xlsx' }.freeze
Class Method Summary collapse
- .build_nav_links(format, reports, current_slot) ⇒ Object
- .clean_report_dir(file) ⇒ Object
- .dashboard_filename(format, ext) ⇒ Object
- .each_facet_entry(reports) {|:all, reports[:all]| ... } ⇒ Object
- .export_links_for(slot) ⇒ Object
- .facet_dirname(facet_key) ⇒ Object
- .facet_total(reports) ⇒ Object
- .format_to_ext(format) ⇒ Object
- .generate_images_if_needed(file, format, report) ⇒ Object
- .generate_multi_reports(file, format, reports, **opts) ⇒ Object
- .generate_single_report(file, format, report, **opts) ⇒ Object
- .html_format?(format) ⇒ Boolean
- .main_dashboard_url(current_slot) ⇒ Object
- .nav_entry(slot, current_slot, label:) ⇒ Object
- .nav_url(slot, current_slot) ⇒ Object
- .report_dir(file, **opts) ⇒ Object
-
.run_report(file, format, items: nil, reports: nil) ⇒ Object
rubocop:disable Metrics/ModuleLength.
-
.write_report(file, format, content, output, slot: :all) ⇒ Object
rubocop:disable Metrics/ParameterLists.
Class Method Details
.build_nav_links(format, reports, current_slot) ⇒ Object
66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/predictability_engine/report_generator.rb', line 66 def self.build_nav_links(format, reports, current_slot) return unless html_format?(format) links = [nav_entry(:all, current_slot, label: 'All')] Report::FACETS.each do |facet| values = (reports[facet[:key]] || {}).keys next if values.empty? links << { separator: true } values.each { |value| links << nav_entry([facet[:key], value], current_slot, label: value) } end links + export_links_for(current_slot) end |
.clean_report_dir(file) ⇒ Object
141 142 143 144 |
# File 'lib/predictability_engine/report_generator.rb', line 141 def self.clean_report_dir(file, **) dir = report_dir(file, **) FileUtils.rm_rf(dir) end |
.dashboard_filename(format, ext) ⇒ Object
146 147 148 149 150 151 152 153 |
# File 'lib/predictability_engine/report_generator.rb', line 146 def self.dashboard_filename(format, ext) case format when :html, :landscape, :dashboard then 'dashboard.html' when :a3_landscape then 'dashboard_a3.pdf' when :png then 'dashboard.png' else "dashboard.#{ext}" end end |
.each_facet_entry(reports) {|:all, reports[:all]| ... } ⇒ Object
23 24 25 26 27 28 |
# File 'lib/predictability_engine/report_generator.rb', line 23 def self.each_facet_entry(reports) yield :all, reports[:all] Report::FACETS.each do |facet| (reports[facet[:key]] || {}).each { |value, report| yield [facet[:key], value], report } end end |
.export_links_for(slot) ⇒ Object
84 85 86 87 88 |
# File 'lib/predictability_engine/report_generator.rb', line 84 def self.export_links_for(slot) prefix = slot.is_a?(Array) ? '../' : '' [{ label: 'CSV', url: "#{prefix}dashboard.csv", download: true }, { label: 'XLSX', url: "#{prefix}dashboard.xlsx", download: true }] end |
.facet_dirname(facet_key) ⇒ Object
109 110 111 |
# File 'lib/predictability_engine/report_generator.rb', line 109 def self.facet_dirname(facet_key) Report::FACETS.find { |f| f[:key] == facet_key }[:dirname] end |
.facet_total(reports) ⇒ Object
19 20 21 |
# File 'lib/predictability_engine/report_generator.rb', line 19 def self.facet_total(reports) Report::FACETS.sum { |f| (reports[f[:key]] || {}).size } end |
.format_to_ext(format) ⇒ Object
166 167 168 |
# File 'lib/predictability_engine/report_generator.rb', line 166 def self.format_to_ext(format) FORMAT_TO_EXT[format] || format.to_s end |
.generate_images_if_needed(file, format, report) ⇒ Object
57 58 59 60 61 62 63 64 |
# File 'lib/predictability_engine/report_generator.rb', line 57 def self.generate_images_if_needed(file, format, report, **) return unless %i[markdown md confluence conf].include?(format) dir = report_dir(file, **) report.generate_chart_images(dir) rescue StandardError => e PredictabilityEngine.warn_chart_failure(e, context: 'Inline images will be omitted.') end |
.generate_multi_reports(file, format, reports, **opts) ⇒ Object
43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/predictability_engine/report_generator.rb', line 43 def self.generate_multi_reports(file, format, reports, **opts) fmt = format.to_sym msgs = [] each_facet_entry(reports) do |slot, report| generate_images_if_needed(file, fmt, report, **opts) links = build_nav_links(fmt, reports, slot) content = report.render(fmt, sub_reports: links, **opts) msg = write_report(file, format, content, opts[:output], slot: slot, **opts) PredictabilityEngine.logger.info { msg } msgs << msg end "#{msgs.size} reports generated" end |
.generate_single_report(file, format, report, **opts) ⇒ Object
30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/predictability_engine/report_generator.rb', line 30 def self.generate_single_report(file, format, report, **opts) fmt = format.to_sym generate_images_if_needed(file, fmt, report, **opts) opts = opts.merge(sub_reports: export_links_for(:all)) if html_format?(fmt) && !opts[:sub_reports] content = report.render(fmt, **opts) if opts[:output] || fmt != :terminal write_report(file, format, content, opts[:output], **opts) else content end end |
.html_format?(format) ⇒ Boolean
80 81 82 |
# File 'lib/predictability_engine/report_generator.rb', line 80 def self.html_format?(format) %i[html landscape].include?(format) end |
.main_dashboard_url(current_slot) ⇒ Object
105 106 107 |
# File 'lib/predictability_engine/report_generator.rb', line 105 def self.main_dashboard_url(current_slot) current_slot.is_a?(Array) ? '../dashboard.html' : 'dashboard.html' end |
.nav_entry(slot, current_slot, label:) ⇒ Object
90 91 92 |
# File 'lib/predictability_engine/report_generator.rb', line 90 def self.nav_entry(slot, current_slot, label:) { label: label, url: nav_url(slot, current_slot), active: slot == current_slot } end |
.nav_url(slot, current_slot) ⇒ Object
94 95 96 97 98 99 100 101 102 103 |
# File 'lib/predictability_engine/report_generator.rb', line 94 def self.nav_url(slot, current_slot) return main_dashboard_url(current_slot) if slot == :all target_facet_key, value = slot target_dir = facet_dirname(target_facet_key) return "#{value}.html" if current_slot.is_a?(Array) && current_slot[0] == target_facet_key return "../#{target_dir}/#{value}.html" if current_slot.is_a?(Array) "#{target_dir}/#{value}.html" end |
.report_dir(file, **opts) ⇒ Object
131 132 133 134 135 136 137 138 139 |
# File 'lib/predictability_engine/report_generator.rb', line 131 def self.report_dir(file, **opts) base_dir = if opts[:output_dir] opts[:output_dir] else input_dir = File.dirname(file) input_dir == '.' ? 'reports' : File.join(input_dir, 'reports') end Pathname.new(File.join(base_dir, File.basename(file, '.*'))).cleanpath.to_s end |
.run_report(file, format, items: nil, reports: nil) ⇒ Object
rubocop:disable Metrics/ModuleLength
8 9 10 11 12 13 14 15 16 17 |
# File 'lib/predictability_engine/report_generator.rb', line 8 def self.run_report(file, format, items: nil, reports: nil, **) items ||= PredictabilityEngine.load_items(file, **) reports ||= Report.generate_all(items) if facet_total(reports).zero? || format.to_sym == :terminal generate_single_report(file, format, reports[:all], **) else generate_multi_reports(file, format, reports, **) end end |
.write_report(file, format, content, output, slot: :all) ⇒ Object
rubocop:disable Metrics/ParameterLists
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/predictability_engine/report_generator.rb', line 113 def self.write_report(file, format, content, output, slot: :all, **) # rubocop:disable Metrics/ParameterLists ext = format_to_ext(format.to_sym) dir = report_dir(file, **) if slot == :all FileUtils.mkdir_p(dir) unless output || File.exist?(dir) output ||= File.join(dir, dashboard_filename(format.to_sym, ext)) else facet_key, value = slot dir = File.join(dir, facet_dirname(facet_key)) FileUtils.mkdir_p(dir) output = File.join(dir, "#{value}.#{ext}") end File.binwrite(output, content) "Report generated at #{output}" end |