Class: VivlioStarter::CLI::Metrics::ConfigLoader

Inherits:
Object
  • Object
show all
Defined in:
lib/vivlio_starter/cli/metrics/config_loader.rb

Overview

metrics 設定を読み込み解決する

Constant Summary collapse

RELATIVE_RATIOS =

相対モード(use: relative)の帯。その本自身の章の本文字数の中央値に 対する倍率で判定する。章立ての粒度は著者の設計判断なので、絶対値の帯では 正しく評価できない本が構造的に出る——リファレンス寄りの本ほど章が細かくなる。 倍率は 2 通りの導出(確定プリセットの形/刊行書 128 章の比の分布)が一致した 値で、min と max は互いに逆数の関係にある(1/1.5 ≒ 0.65)。刊行書に当てると 「短い」10%・「長い」10% と両裾が釣り合う(chapter-volume-calibration-data.md §7.2.0)。

{ min: 0.65, ideal_min: 0.80, ideal_max: 1.20, max: 1.50 }.freeze
RELATIVE_MIN_CHAPTERS =

相対モードで中央値が安定する最小章数。これを下回ると絶対帯へ落とす。

5
PRESET_BY_TOTAL =

総本文字数からプリセットを選ぶ境界(相対モードのフォールバック先)。

[[35_000, :compact], [65_000, :handy],
[90_000, :standard], [150_000, :commercial]].freeze
DEFAULT_SECTION =

節の基準はプリセット共通。刊行書 408 節の実測が 200 頁以上の本からしか 採れておらず、規模別に分ける根拠が無いため (chapter-volume-calibration-data.md §3.4)。

{ min: 400, ideal: [1000, 2800], max: 4000 }.freeze
DEFAULT_PRESETS =

プリセットの既定値。すべて本文(コードと記法を除いた地の文)の文字数で、 刊行済み技術書の実測から引いた(chapter-volume-calibration-data.md §7.1)。 min は 10・ideal は 25〜75・max は 90 パーセンタイル。 選ぶ軸は総本文字数(頁数は判型・余白・図版量で動くため単独では決まらない)。

{
  # 〜3.5 万字(20〜50 頁)/実測 3 記事 24 章
  compact: {
    chapter: { min: 800, ideal: [1100, 3400], max: 4200 },
    section: DEFAULT_SECTION
  },
  # 3.5 万〜6.5 万字(50〜100 頁)/両隣の実測からの内挿(§7.2.1)
  handy: {
    chapter: { min: 2900, ideal: [3400, 5700], max: 6800 },
    section: DEFAULT_SECTION
  },
  # 6.5 万〜9 万字(100〜200 頁)/実測 2 冊 16 章
  standard: {
    chapter: { min: 4200, ideal: [4800, 8500], max: 9700 },
    section: DEFAULT_SECTION
  },
  # 9 万〜15 万字(200〜350 頁)/実測 4 冊 36 章
  commercial: {
    chapter: { min: 6400, ideal: [7800, 14_600], max: 17_800 },
    section: DEFAULT_SECTION
  },
  # 15 万字〜(350 頁以上)/実測 3 冊 52 章
  heavy: {
    chapter: { min: 9200, ideal: [11_000, 16_000], max: 19_600 },
    section: DEFAULT_SECTION
  }
}.freeze
DEFAULT_VOCABULARY =
{
  kanji_ratio: { min: 20, ideal: [25, 35], max: 45 },
  word_length: { min: 1.5, ideal: [2.0, 2.5], max: 3.0 },
  ttr: { min: 0.3, ideal: [0.5, 0.7], max: 1.0 }
}.freeze
DEFAULT_READABILITY =

建石式 RS は値が大きいほど読みやすい。easy/standard は各バンドの下限。 RS >= easy → Easy(やさしい)、>= standard → Standard、未満 → Professional。 既定値は建石式の絶対尺度上の目安(児童書 60+/実用書 40〜60/専門書 〜40)。

{ easy: 60, standard: 40 }.freeze
DEFAULT_LABELS =

章別リストに添える文言。分量は too_short / just_right / too_long の 3 状態で 対になっており、文章の質は monotonous / too_complex の 2 つ。 chapter.ideal は範囲を表す数値キーなので、こちらの語は just_right にして 名前の衝突を避けている。

{
  too_short: '加筆検討',
  just_right: '丁度良い',
  too_long: 'やや長い',
  monotonous: '表現が単調',
  too_complex: 'やや難解'
}.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(book_config = nil) ⇒ ConfigLoader

Returns a new instance of ConfigLoader.

Parameters:

  • book_config (Hash, nil) (defaults to: nil)

    book.yml 相当の Hash(テスト用の差し替え口。 文字列キー・シンボルキーのどちらでも受け付ける)。 省略時は Common::CONFIG.metrics を使用する。



105
106
107
108
109
110
111
112
# File 'lib/vivlio_starter/cli/metrics/config_loader.rb', line 105

def initialize(book_config = nil)
  metrics = if book_config
              normalize_config(book_config)[:metrics]
            else
              normalize_config(Common::CONFIG&.metrics)
            end
  @metrics_config = metrics || {}
end

Class Method Details

.preset_for_total(total) ⇒ Object

総本文字数からプリセットを選ぶ。境界は実測に基づく (chapter-volume-calibration-data.md §7.1)。



146
147
148
# File 'lib/vivlio_starter/cli/metrics/config_loader.rb', line 146

def self.preset_for_total(total)
  PRESET_BY_TOTAL.find { |limit, _| total < limit }&.last || :heavy
end

Instance Method Details

#exclude_chaptersObject

除外する章番号のリストを取得する



151
152
153
154
# File 'lib/vivlio_starter/cli/metrics/config_loader.rb', line 151

def exclude_chapters
  raw = metrics_config[:exclude_chapters] || ConfigKeys::KEYS[%i[metrics exclude_chapters]].default
  expand_chapter_ranges(raw)
end

#labelsObject

警告ラベルを取得する



171
172
173
# File 'lib/vivlio_starter/cli/metrics/config_loader.rb', line 171

def labels
  DEFAULT_LABELS.merge(metrics_config[:labels] || {})
end

#readability_thresholdsObject

読解難度のしきい値を取得する



162
163
164
165
166
167
168
# File 'lib/vivlio_starter/cli/metrics/config_loader.rb', line 162

def readability_thresholds
  config_readability = metrics_config[:readability] || {}
  {
    easy: config_readability[:easy] || DEFAULT_READABILITY[:easy],
    standard: config_readability[:standard] || DEFAULT_READABILITY[:standard]
  }
end

#relative?Boolean

相対モード(metrics.use: relative)か

Returns:

  • (Boolean)


123
# File 'lib/vivlio_starter/cli/metrics/config_loader.rb', line 123

def relative? = preset_name == 'relative'

#resolve_relative_basis(judged_chars, total_prose) ⇒ Object

相対モードの基準を確定する。全章を読むまで中央値が決まらないので、 Runner が事前スキャンを終えた時点で一度だけ呼ぶ。

判定対象の章が少ないと中央値が 1 章の増減で動くため、 RELATIVE_MIN_CHAPTERS 未満なら総本文字数から選んだ絶対帯へ落とす (chapter-volume-calibration-data.md §7.2.0)。

Parameters:

  • judged_chars (Array<Integer>)

    分量判定の対象となる章の本文字数

  • total_prose (Integer)

    本全体の本文字数(フォールバック先の選択に使う)



133
134
135
136
137
138
139
140
141
142
# File 'lib/vivlio_starter/cli/metrics/config_loader.rb', line 133

def resolve_relative_basis(judged_chars, total_prose)
  return unless relative?

  @volume_thresholds = nil
  if judged_chars.size >= RELATIVE_MIN_CHAPTERS
    @relative_baseline = median(judged_chars)
  else
    @relative_fallback = self.class.preset_for_total(total_prose)
  end
end

#vocabulary_thresholdsObject

語彙難度のしきい値を取得する



157
158
159
# File 'lib/vivlio_starter/cli/metrics/config_loader.rb', line 157

def vocabulary_thresholds
  merge_with_defaults(metrics_config, DEFAULT_VOCABULARY, %i[kanji_ratio word_length ttr])
end

#volume_thresholdsObject

選択されたプリセットの章・節しきい値を取得する。 相対モードでは resolve_relative_basis が呼ばれるまで基準が決まらないため、 呼び出し側(Formatter / WarningChecker)は値を抱え込まず毎回ここへ問い合わせる。



117
118
119
120
# File 'lib/vivlio_starter/cli/metrics/config_loader.rb', line 117

def volume_thresholds
  @volume_thresholds ||= relative_thresholds ||
                         symbolize_thresholds(resolve_preset(effective_preset_name))
end