Module: PredictabilityEngine::TerminalVisualizer
- Defined in:
- lib/predictability_engine/terminal_visualizer.rb,
lib/predictability_engine/terminal_visualizer/cfd_renderer.rb
Defined Under Namespace
Modules: CfdRenderer
Class Method Summary collapse
- .aging_wip(items, color: false, pcts: DEFAULT_PERCENTILES) ⇒ Object
- .cfd_plot(work_items, title: 'Cumulative Flow Diagram', color: false, **_opts) ⇒ Object
- .cycle_time_bands(items, title: 'Cycle Time Bands Over Time', color: false) ⇒ Object
- .cycle_time_scatter(items, title: 'Cycle Time Scatter Plot', color: false, pcts: DEFAULT_PERCENTILES) ⇒ Object
- .forecasted_cfd_plot(work_items, title: 'Forecasted Cumulative Flow Diagram', color: false, percentiles: PredictabilityEngine::DEFAULT_PERCENTILES, **_opts) ⇒ Object
- .throughput_histogram(items, title: 'Throughput Histogram', color: false) ⇒ Object
Class Method Details
.aging_wip(items, color: false, pcts: DEFAULT_PERCENTILES) ⇒ Object
9 10 11 12 13 14 15 16 17 |
# File 'lib/predictability_engine/terminal_visualizer.rb', line 9 def self.aging_wip(items, color: false, pcts: DEFAULT_PERCENTILES, **) age_data = Calculators::Aging.item_age_data(items) return 'No items currently in progress.' if age_data.empty? PredictabilityEngine.mapped_percentiles(items, pcts) plot = UnicodePlot.(age_data.map { |d| d[:id].to_s }, age_data.map { |d| d[:age] }, title: 'Aging Work In Progress (Days)', color: color ? :blue : nil) render_to_string(plot, color: color) end |
.cfd_plot(work_items, title: 'Cumulative Flow Diagram', color: false, **_opts) ⇒ Object
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/predictability_engine/terminal_visualizer.rb', line 55 def self.cfd_plot(work_items, title: 'Cumulative Flow Diagram', color: false, **_opts) cfd = Calculators::Cfd.calculate(work_items) return 'No CFD data to plot.' if cfd.empty? start = cfd.first[:date] coords = Calculators::Cfd.to_coordinates(cfd, start) max_y = coords[:arrived].max || 0 max_x = coords[:dates].max || 0 # Arrivals first for legend and top boundary plot = UnicodePlot.stairs(coords[:dates], coords[:arrived], title: title, name: 'Arrivals', xlabel: "Days since #{PredictabilityEngine.format_date(start)}", ylabel: 'Total Items', color: :blue, xlim: [0, max_x], ylim: [0, max_y]) # Departures next UnicodePlot.stairs!(plot, coords[:dates], coords[:departed], name: 'Departures', color: :green) render_to_string(plot, color: color) end |
.cycle_time_bands(items, title: 'Cycle Time Bands Over Time', color: false) ⇒ Object
44 45 46 47 48 49 50 51 52 53 |
# File 'lib/predictability_engine/terminal_visualizer.rb', line 44 def self.cycle_time_bands(items, title: 'Cycle Time Bands Over Time', color: false, **) completed = PredictabilityEngine.completed_items(items) return 'No completed items to plot.' if completed.empty? labels = RawDataExporter::DONE_THRESHOLD_LABELS counts = Array.new(labels.size, 0) completed.each { |item| counts[RawDataExporter.threshold_index(item.cycle_time)] += 1 } plot = UnicodePlot.(labels, counts, title: title, xlabel: 'Items Completed') render_to_string(plot, color: color) end |
.cycle_time_scatter(items, title: 'Cycle Time Scatter Plot', color: false, pcts: DEFAULT_PERCENTILES) ⇒ Object
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/predictability_engine/terminal_visualizer.rb', line 19 def self.cycle_time_scatter(items, title: 'Cycle Time Scatter Plot', color: false, pcts: DEFAULT_PERCENTILES, **) completed = Calculators::CycleTime.completed_sorted(items) return 'No completed items to plot.' if completed.empty? start = completed.first.end_date x = completed.map { |i| (i.end_date - start).to_i } xlabel = "Days since #{PredictabilityEngine.format_date(start)}" plot = UnicodePlot.scatterplot(x, completed.map(&:cycle_time), title: title, xlabel: xlabel, ylabel: 'Cycle Time (days)') PredictabilityEngine.mapped_percentiles(items, pcts).each do |p| UnicodePlot.lineplot!(plot, x.minmax, [p[:val], p[:val]], name: p[:label]) end render_to_string(plot, color: color) end |
.forecasted_cfd_plot(work_items, title: 'Forecasted Cumulative Flow Diagram', color: false, percentiles: PredictabilityEngine::DEFAULT_PERCENTILES, **_opts) ⇒ Object
74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/predictability_engine/terminal_visualizer.rb', line 74 def self.forecasted_cfd_plot(work_items, title: 'Forecasted Cumulative Flow Diagram', color: false, percentiles: PredictabilityEngine::DEFAULT_PERCENTILES, **_opts) data = Calculators::Cfd.forecast_series(work_items, percentiles: percentiles) return cfd_plot(work_items, title: title, color: color) unless data params = CfdRenderer.build_forecast_params(data) plot = UnicodePlot.stairs(params[:x_coords], params[:arrivals], title: title, name: 'Arrivals', ylabel: 'Total Items', xlabel: "Days since #{PredictabilityEngine.format_date(params[:start])}", color: :blue, xlim: [0, params[:max_x]], ylim: [0, params[:total_items]]) CfdRenderer.add_forecast_layers!(plot, data, params, percentiles) render_to_string(plot, color: color) end |
.throughput_histogram(items, title: 'Throughput Histogram', color: false) ⇒ Object
36 37 38 39 40 41 42 |
# File 'lib/predictability_engine/terminal_visualizer.rb', line 36 def self.throughput_histogram(items, title: 'Throughput Histogram', color: false, **) daily = Calculators::Throughput.daily(items).values return 'No throughput data to plot.' if daily.empty? plot = UnicodePlot.histogram(daily, title: title, xlabel: 'Items per day', ylabel: 'Frequency') render_to_string(plot, color: color) end |