Module: VivlioStarter::CLI::Metrics::Consistency

Defined in:
lib/vivlio_starter/cli/metrics/consistency.rb

Overview

章間のばらつきを算出する。

Constant Summary collapse

OUTLIER_LIMIT =

高め/低めとして挙げる章の最大数。

3

Class Method Summary collapse

Class Method Details

.build(metric_label:, unit:, high_label:, low_label:, entries:) ⇒ ConsistencyMetric

Parameters:

  • entries (Array<[String, Numeric]>)

    [章ラベル, 値] の配列

Returns:



32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/vivlio_starter/cli/metrics/consistency.rb', line 32

def build(metric_label:, unit:, high_label:, low_label:, entries:)
  values = entries.map { it[1] }
  mean = values.sum.to_f / values.size
  stdev = Math.sqrt(values.sum { (it - mean)**2 } / values.size)

  # ばらつきが無い(全章同じ)ときは外れ章なし。threshold が平均と一致して
  # 全章が拾われるのを防ぐ。
  high = stdev.positive? ? outliers(entries, threshold: mean + stdev, order: :desc) : []
  low = stdev.positive? ? outliers(entries, threshold: mean - stdev, order: :asc) : []

  ConsistencyMetric.new(
    label: metric_label, unit:, high_label:, low_label:, mean:, stdev:, high:, low:
  )
end

.outliers(entries, threshold:, order:) ⇒ Object

平均±標準偏差を超える章を、外れの大きい順に最大 OUTLIER_LIMIT 件返す。



48
49
50
51
52
# File 'lib/vivlio_starter/cli/metrics/consistency.rb', line 48

def outliers(entries, threshold:, order:)
  selected = order == :desc ? entries.select { it[1] >= threshold } : entries.select { it[1] <= threshold }
  sorted = order == :desc ? selected.sort_by { -it[1] } : selected.sort_by { it[1] }
  sorted.first(OUTLIER_LIMIT)
end