Class: VivlioStarter::CLI::IndexCommands::TermRanking

Inherits:
Object
  • Object
show all
Defined in:
lib/vivlio_starter/cli/index/term_ranking.rb

Overview

登録語と候補を一列に並べて帯に分ける

Defined Under Namespace

Classes: Bands, Entry

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(sorted, target, pool_size) ⇒ TermRanking

Returns a new instance of TermRanking.



65
66
67
68
69
# File 'lib/vivlio_starter/cli/index/term_ranking.rb', line 65

def initialize(sorted, target, pool_size)
  @sorted = sorted
  @target = target
  @pool_size = pool_size
end

Class Method Details

.build(registered:, registered_scores:, candidate_scores:, target:, pool:) ⇒ Bands

Parameters:

  • registered (Array<Hash>)

    辞書の索引語('term' / 'source')

  • registered_scores (Hash{String => Float})

    登録語のスコア

  • candidate_scores (Hash{String => Float})

    候補のスコア

  • target (Integer)

    目安語数(帯の境目)

  • pool (Float)

    目安語数の何倍までを候補として提示するか

Returns:



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/vivlio_starter/cli/index/term_ranking.rb', line 46

def self.build(registered:, registered_scores:, candidate_scores:, target:, pool:)
  manual = registered.select { it['source'].to_s == 'manual_markup' }.map { it['term'] }.to_set
  names = registered.map { it['term'] }.to_set

  entries = registered.map do |entry|
    name = entry['term']
    Entry.new(term: name, score: registered_scores.fetch(name, 0.0),
              registered: true, manual: manual.include?(name))
  end
  entries += candidate_scores.reject { |term, _| names.include?(term) }
                             .map { |term, score| Entry.new(term:, score:, registered: false, manual: false) }

  # 同点は語名で決める——実行ごとに順位が揺れると差分が読めなくなる
  sorted = entries.sort_by { [-it.score, it.term] }
  pool_size = [(target * pool).round, target].max

  new(sorted, target, pool_size).bands
end

Instance Method Details

#bandsObject



71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/vivlio_starter/cli/index/term_ranking.rb', line 71

def bands
  inside = @sorted.first(@target)
  outside = @sorted.drop(@target)

  Bands.new(
    recommended: inside.select(&:unregistered?),
    general: outside.first(@pool_size - @target).select(&:unregistered?),
    review: outside.select { it.registered && !it.manual },
    hidden_count: [@sorted.size - @pool_size, 0].max,
    target: @target,
    pool_size: @pool_size,
    total: @sorted.size
  )
end