Class: CycletimeScatterplot
- Inherits:
-
TimeBasedScatterplot
- Object
- ChartBase
- TimeBasedChart
- TimeBasedScatterplot
- CycletimeScatterplot
- Defined in:
- lib/jirametrics/cycletime_scatterplot.rb
Constant Summary collapse
- PROXY_FOR_MOST_PERCENTILE =
The number that the "reasonable proxy for most" claim is actually about. That claim is only defensible near this value: at the median half the work runs longer, and at the 98th you are describing the worst case, not the typical one. So the sentence appears when this percentile is on the chart and is silently dropped when it is not, rather than being reworded into something that sounds authoritative and is wrong.
85
Constants inherited from TimeBasedScatterplot
TimeBasedScatterplot::OVERALL_LABEL
Constants inherited from TimeBasedChart
TimeBasedChart::VALUE_AXIS_LABELS
Constants inherited from ChartBase
ChartBase::LABEL_POSITIONS, ChartBase::OKABE_ITO_PALETTE
Instance Attribute Summary collapse
-
#possible_statuses ⇒ Object
Returns the value of attribute possible_statuses.
Attributes inherited from TimeBasedScatterplot
#percentage_lines, #y_axis_cap_percentile
Attributes included from GroupableIssueChart
#group_by_block, #issue_hints, #issue_periods
Attributes inherited from ChartBase
#aggregated_project, #all_boards, #atlassian_document_format, #board_id, #canvas_height, #canvas_width, #color_palette, #data_quality, #date_range, #file_system, #fix_versions, #holiday_dates, #issues, #settings, #time_range, #timezone_offset, #x_axis_title, #y_axis_title
Instance Method Summary collapse
- #all_items ⇒ Object
-
#cycletime_unit(unit) ⇒ Object
Days-only until the working-days cycletime engine grows sub-day resolution.
-
#initialize(block) ⇒ CycletimeScatterplot
constructor
A new instance of CycletimeScatterplot.
- #minimum_y_value ⇒ Object
- #per_type_sentence(lines) ⇒ Object
-
#percentile_description ⇒ Object
The prose follows the configuration, so it has to read well for one percentile or several, and say nothing at all for none.
-
#percentile_summary_sentence(lines) ⇒ Object
Mechanical and true whatever the configured percentiles are.
-
#proxy_for_most_sentence(lines) ⇒ Object
Only emitted when 85 is actually among the configured percentiles.
- #title_value(item, rules: nil) ⇒ Object
- #x_value(item) ⇒ Object
- #y_value(item) ⇒ Object
Methods inherited from TimeBasedScatterplot
#cap_y_axis, #compute_cap, #create_datasets, #data_for_item, #legend_annotation_map, #percentile_label, #percentile_lines_for, #percentile_value, #percentiles, #run, #show_trend_lines, #trend_line_data_set, #trend_line_description, #value_axis_title=
Methods included from PercentileValidation
validate_percentile, validate_percentiles
Methods included from GroupableIssueChart
#accumulate_issue_for_group, #group_issues, #grouping_rules, #init_configuration_block, #reconcile_percentiles
Methods inherited from TimeBasedChart
#duration_in_unit, #label_cycletime
Methods inherited from ChartBase
#aggregated_project?, #before_run, #call_before_run, #canvas, #canvas_responsive?, #chart_format, #collapsible_issues_panel, #color_block, #color_for, #comma_and, #completed_issues_in_range, #current_board, #cycletime, #cycletime_for_issue, #daily_chart_dataset, #date_annotation, #describe_non_working_days, #description_text, #format_integer, #format_status, #header_text, #holidays, #html_directory, #icon_span, #link_to_issue, #next_id, #next_palette_color, #non_working_day?, #normalize_annotation_datetime, #not_visible_icon, #not_visible_text, #ordinal, #percentile_of, #render, #render_axis_title, #render_top_text, #resolve_status, #stagger_label_positions, #status_category_color, #to_human_readable, #working_days_annotation, #wrap_and_render
Constructor Details
#initialize(block) ⇒ CycletimeScatterplot
Returns a new instance of CycletimeScatterplot.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/jirametrics/cycletime_scatterplot.rb', line 8 def initialize block super() header_text 'Cycletime Scatterplot' description_text <<-HTML <div class="p"> This chart shows only completed work and indicates both what day it completed as well as how many days it took to get done. Hovering over a dot will show you the ID of the work item. </div> <%= percentile_description %> <%= trend_line_description %> #{describe_non_working_days} HTML @x_axis_title = 'Date completed' @y_axis_title = 'Cycletime in days' init_configuration_block block do grouping_rules do |issue, rule| rule.label = issue.type rule.color = color_for type: issue.type end end end |
Instance Attribute Details
#possible_statuses ⇒ Object
Returns the value of attribute possible_statuses.
6 7 8 |
# File 'lib/jirametrics/cycletime_scatterplot.rb', line 6 def possible_statuses @possible_statuses end |
Instance Method Details
#all_items ⇒ Object
43 44 45 |
# File 'lib/jirametrics/cycletime_scatterplot.rb', line 43 def all_items completed_issues_in_range include_unstarted: false end |
#cycletime_unit(unit) ⇒ Object
Days-only until the working-days cycletime engine grows sub-day resolution. Inherited from TimeBasedChart so the option exists, but the unbuilt path fails loudly rather than mislabelling the axis while the value stays in days. See jirametrics-en5.
35 36 37 |
# File 'lib/jirametrics/cycletime_scatterplot.rb', line 35 def cycletime_unit unit raise NotImplementedError, "#{self.class} only supports :days for now (see jirametrics-en5)" unless unit == :days end |
#minimum_y_value ⇒ Object
39 40 41 |
# File 'lib/jirametrics/cycletime_scatterplot.rb', line 39 def minimum_y_value 1 # Values under 1 day are data quality problems; they're flagged in the quality report instead end |
#per_type_sentence(lines) ⇒ Object
119 120 121 122 123 124 125 126 |
# File 'lib/jirametrics/cycletime_scatterplot.rb', line 119 def per_type_sentence lines if lines.size == 1 "The other lines reflect the #{lines.first[:percentile]}% line for that respective type of work." else 'Each type of work also gets its own lines in its own colour, at whichever percentiles ' \ 'were configured for that type. Hover any line to see which one it is and its value.' end end |
#percentile_description ⇒ Object
The prose follows the configuration, so it has to read well for one percentile or several, and say nothing at all for none. Values come from percentage_lines because run has already computed them, and because this string is not run through ERB a second time.
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/jirametrics/cycletime_scatterplot.rb', line 73 def percentile_description overall_lines = percentage_lines.select { |line| line[:dataset_index].nil? } return '' if overall_lines.empty? sentences = [ percentile_summary_sentence(overall_lines), proxy_for_most_sentence(overall_lines), per_type_sentence(overall_lines) ].compact <<-HTML <div class="p"> #{sentences.join ' '} </div> HTML end |
#percentile_summary_sentence(lines) ⇒ Object
Mechanical and true whatever the configured percentiles are. Singular phrasing is preserved word for word from the original so the default chart reads exactly as it always has.
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/jirametrics/cycletime_scatterplot.rb', line 91 def percentile_summary_sentence lines swatch = color_block '--cycletime-scatterplot-overall-trendline-color' if lines.size == 1 percentile = lines.first[:percentile] "The #{swatch} line indicates the #{ordinal percentile} percentile " \ "(#{lines.first[:value]} days). #{percentile}% of all items on this chart fall on or " \ "below the line and the remaining #{100 - percentile}% are above the line." else # No values inline here. With several lines the sentence turns into a wall of parentheses, # and each value is already on the line's hover label and in that group's legend entry. described = lines.collect { |line| ordinal line[:percentile] } "The #{swatch} lines indicate the #{comma_and described} percentiles of all items on " \ 'this chart. For each line, that percentage of items fall on or below it and the rest ' \ 'are above.' end end |
#proxy_for_most_sentence(lines) ⇒ Object
Only emitted when 85 is actually among the configured percentiles. See PROXY_FOR_MOST_PERCENTILE.
109 110 111 112 113 114 115 116 117 |
# File 'lib/jirametrics/cycletime_scatterplot.rb', line 109 def proxy_for_most_sentence lines line = lines.find { |candidate| candidate[:percentile] == PROXY_FOR_MOST_PERCENTILE } return nil unless line "#{PROXY_FOR_MOST_PERCENTILE}% is a " \ '<a href="https://jirametrics.org/faq/#why-85">reasonable proxy</a> for "most" so that we ' \ 'can say that based on this data set, we can predict that most work of this type will ' \ "complete in #{line[:value]} days or less." end |
#title_value(item, rules: nil) ⇒ Object
55 56 57 58 |
# File 'lib/jirametrics/cycletime_scatterplot.rb', line 55 def title_value item, rules: nil hint = @issue_hints&.fetch(item, nil) "#{item.key} : #{item.summary} (#{label_days(y_value(item))})#{" #{hint}" if hint}" end |
#x_value(item) ⇒ Object
47 48 49 |
# File 'lib/jirametrics/cycletime_scatterplot.rb', line 47 def x_value item item.started_stopped_times.last end |
#y_value(item) ⇒ Object
51 52 53 |
# File 'lib/jirametrics/cycletime_scatterplot.rb', line 51 def y_value item item.board.cycletime.cycletime(item) end |