Module: VivlioStarter::CLI::Metrics::Readability
- Defined in:
- lib/vivlio_starter/cli/metrics/readability.rb
Overview
建石式リーダビリティーの算出ロジック。
Constant Summary collapse
- COEFFICIENTS =
建石・小野・山田 (1988) の確定係数。
{ ls: -0.12, la: -1.37, lh: 7.4, lc: -23.18, lk: -5.4, cp: -4.67 }.freeze
- CONSTANT =
115.79- SENTENCE_DELIMITER =
/[。!?!?]+/- PERIOD =
'。'- COMMA =
'、'
Class Method Summary collapse
-
.aggregate(features_list) ⇒ ReadabilityFeatures
章ごとの特徴量を合算する(全体 RS 算出用)。.
- .avg(sum, count) ⇒ Object
-
.character_class(char) ⇒ Object
1 文字の文字種を判定する(対象外は nil で連を区切る)。 長音符(ー)はカタカナ語に付くため、カタカナ連として扱う。.
-
.count_character_runs(text) ⇒ Object
文字種ごとに「連の数」と「連に含まれる文字数」を数える。.
-
.extract_features(text) ⇒ ReadabilityFeatures
テキストから RS 算出用の特徴量を抽出する。.
-
.label(score, thresholds) ⇒ Object
RS をしきい値で難易度ラベルに変換する(大きいほど易しい)。.
-
.score(features) ⇒ Float
特徴量から RS を算出する。値が大きいほど読みやすい。.
-
.sentence_lengths(text) ⇒ Object
文ごとの文字数(空白除く)。.
Class Method Details
.aggregate(features_list) ⇒ ReadabilityFeatures
章ごとの特徴量を合算する(全体 RS 算出用)。
109 110 111 112 113 114 |
# File 'lib/vivlio_starter/cli/metrics/readability.rb', line 109 def aggregate(features_list) return ReadabilityFeatures.zero if features_list.empty? ReadabilityFeatures.members.to_h { |field| [field, features_list.sum { it.public_send(field) }] } .then { ReadabilityFeatures.new(**it) } end |
.avg(sum, count) ⇒ Object
153 |
# File 'lib/vivlio_starter/cli/metrics/readability.rb', line 153 def avg(sum, count) = count.positive? ? sum.to_f / count : 0.0 |
.character_class(char) ⇒ Object
1 文字の文字種を判定する(対象外は nil で連を区切る)。 長音符(ー)はカタカナ語に付くため、カタカナ連として扱う。
144 145 146 147 148 149 150 151 |
# File 'lib/vivlio_starter/cli/metrics/readability.rb', line 144 def character_class(char) case char when /\p{Han}/ then :kanji when /\p{Hiragana}/ then :hira when /\p{Katakana}/, 'ー' then :kata when /[A-Za-z]/ then :alpha end end |
.count_character_runs(text) ⇒ Object
文字種ごとに「連の数」と「連に含まれる文字数」を数える。
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/vivlio_starter/cli/metrics/readability.rb', line 126 def count_character_runs(text) acc = %i[alpha hira kanji kata].to_h { [it, { runs: 0, chars: 0 }] } previous = nil text.each_char do |char| klass = character_class(char) if klass acc[klass][:chars] += 1 acc[klass][:runs] += 1 if klass != previous end previous = klass end acc end |
.extract_features(text) ⇒ ReadabilityFeatures
テキストから RS 算出用の特徴量を抽出する。
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/vivlio_starter/cli/metrics/readability.rb', line 65 def extract_features(text) sentences = sentence_lengths(text) runs = count_character_runs(text) ReadabilityFeatures.new( sentence_count: sentences.size, sentence_char_total: sentences.sum, alpha_run_count: runs[:alpha][:runs], alpha_char_total: runs[:alpha][:chars], hira_run_count: runs[:hira][:runs], hira_char_total: runs[:hira][:chars], kanji_run_count: runs[:kanji][:runs], kanji_char_total: runs[:kanji][:chars], kata_run_count: runs[:kata][:runs], kata_char_total: runs[:kata][:chars], period_count: text.count(PERIOD), comma_count: text.count(COMMA) ) end |
.label(score, thresholds) ⇒ Object
RS をしきい値で難易度ラベルに変換する(大きいほど易しい)。
99 100 101 102 103 104 |
# File 'lib/vivlio_starter/cli/metrics/readability.rb', line 99 def label(score, thresholds) return 'Easy' if score >= thresholds[:easy] return 'Standard' if score >= thresholds[:standard] 'Professional' end |
.score(features) ⇒ Float
特徴量から RS を算出する。値が大きいほど読みやすい。
84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/vivlio_starter/cli/metrics/readability.rb', line 84 def score(features) ls = avg(features.sentence_char_total, features.sentence_count) la = avg(features.alpha_char_total, features.alpha_run_count) lh = avg(features.hira_char_total, features.hira_run_count) lc = avg(features.kanji_char_total, features.kanji_run_count) lk = avg(features.kata_char_total, features.kata_run_count) cp = avg(features.comma_count, features.period_count) CONSTANT + (COEFFICIENTS[:ls] * ls) + (COEFFICIENTS[:la] * la) + (COEFFICIENTS[:lh] * lh) + (COEFFICIENTS[:lc] * lc) + (COEFFICIENTS[:lk] * lk) + (COEFFICIENTS[:cp] * cp) end |
.sentence_lengths(text) ⇒ Object
文ごとの文字数(空白除く)。
119 120 121 122 123 |
# File 'lib/vivlio_starter/cli/metrics/readability.rb', line 119 def sentence_lengths(text) text.split(SENTENCE_DELIMITER) .map { it.gsub(/\s/, '').length } .reject(&:zero?) end |