Class: VivlioStarter::CLI::Metrics::Runner

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

Overview

metrics コマンドの実行を制御する

Defined Under Namespace

Classes: ChapterAnalysis, PlaceholderChapter

Constant Summary collapse

CACHE_SCHEMA_VERSION =

キャッシュの構造バージョン。読解難度の特徴量導入や MATTR 追加など 互換性を破る変更時にインクリメントし、旧バージョンのキャッシュを無効化する。

6
LONG_SENTENCE_MIN =

「見直したい長い文」として挙げる下限文字数と最大件数。

80
LONG_SENTENCE_TOP =
5
CONTENT_WORD_TOP =

頻出内容語ランキングの表示件数。

15

Instance Method Summary collapse

Constructor Details

#initialize(targets, options = {}) ⇒ Runner

Returns a new instance of Runner.



52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/vivlio_starter/cli/metrics/runner.rb', line 52

def initialize(targets, options = {})
  @targets = Array(targets)
  @options = options
  @config = ConfigLoader.new
  @warning_checker = WarningChecker.new(@config)
  @formatter = Formatter.new(@config)
  @chapter_parser = ChapterParser.new(@warning_checker)
  @cache = Cache.new
  @parallel_runner = ParallelRunner.new
  @analysis_buffer = {}
  @analysis_mutex = Mutex.new
end

Instance Method Details

#callObject

メトリクス分析を実行する



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/vivlio_starter/cli/metrics/runner.rb', line 66

def call
  files = resolve_files
  return warn_no_targets if files.empty?

  # JSON/YAML 出力は一括処理
  return output_structured(:json, files) if options[:json]
  return output_structured(:yaml, files) if options[:yaml]

  puts '📚 章別の解析結果'
  puts ''

  placeholders = build_placeholder_chapters(files)
  resolve_relative_basis(placeholders)
  max_chars = [placeholders.map(&:chars).max || 1, 1].max
  file_order = files.each_with_index.to_h
  pending = {}
  next_display_index = 0

  all_analyses = analyze_chapters_with_progress(files) do |analysis|
    index = file_order[analysis.chapter.path]
    next unless index

    pending[index] = { analysis:, visible: analysis_visible?(analysis) }

    while pending.key?(next_display_index)
      entry = pending.delete(next_display_index)
      output_chapter_line(entry[:analysis], max_chars) if entry[:visible]
      next_display_index += 1
    end
  end

  visible_analyses = all_analyses.select { analysis_visible?(it) }
  if visible_analyses.empty?
    puts '(対象章がありません)'
    return warn_no_targets
  end

  final_basic, final_vocab, final_readability = aggregate_summary_from_analyses(all_analyses)
  output_chapter_count(all_analyses)
  output_final_summary(final_basic, final_vocab, final_readability)

  # --all のときだけ、推敲用の参考資料(A–G)を続けて出力する。
  output_advice(all_analyses) if options[:all]

  # 長い解析結果の最後を 1 行で締める(何章を対象にしたかが読み取れる)
  Common.log_result("#{all_analyses.size} 章を解析しました(本文 #{final_vocab.total_char_count} 文字)",
                    status: :success)
  0
end