odyssey 0.1.8
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +96 -0
- data/Rakefile +12 -0
- data/lib/formulas/ari.rb +14 -0
- data/lib/formulas/coleman_liau.rb +14 -0
- data/lib/formulas/fake_formula.rb +10 -0
- data/lib/formulas/flesch_kincaid_gl.rb +14 -0
- data/lib/formulas/flesch_kincaid_re.rb +14 -0
- data/lib/formulas/formula.rb +29 -0
- data/lib/formulas/gunning_fog.rb +24 -0
- data/lib/formulas/smog.rb +23 -0
- data/lib/odyssey.rb +74 -0
- data/lib/odyssey/engine.rb +146 -0
- data/lib/odyssey/version.rb +3 -0
- data/odyssey.gemspec +26 -0
- data/spec/odyssey_spec.rb +229 -0
- data/spec/spec_helper.rb +27 -0
- metadata +134 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Cameron Sutter
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
# Odyssey
|
2
|
+
|
3
|
+
Odyssey is an extendible text analyzing gem that outputs the readability score of text. It has several of the common readability formulas available, but defaults to the Flesch-Kincaid Reading Ease score.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'odyssey'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle install
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install odyssey
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
require 'odyssey'
|
22
|
+
|
23
|
+
Odyssey.formula_name(text, all_stats)
|
24
|
+
|
25
|
+
Example:
|
26
|
+
|
27
|
+
Odyssey.flesch_kincaid_re("See Spot run.", true)
|
28
|
+
|
29
|
+
if all_stats is false, this returns a simple score. If it is true, it returns a Hash:
|
30
|
+
|
31
|
+
|
32
|
+
{
|
33
|
+
'name' => String,
|
34
|
+
'formula' => formula_class,
|
35
|
+
'score' => Float,
|
36
|
+
'string_length' => Fixnum,
|
37
|
+
'letter_count' => Fixnum,
|
38
|
+
'syllable_count' => Fixnum,
|
39
|
+
'word_count' => Fixnum,
|
40
|
+
'sentence_count' => Fixnum,
|
41
|
+
'average_words_per_sentence' => Float,
|
42
|
+
'average_syllables_per_word' => Float
|
43
|
+
}
|
44
|
+
|
45
|
+
|
46
|
+
##Extending Odyssey
|
47
|
+
|
48
|
+
To extend Odyssey, you can create a class that inherits from Formula.
|
49
|
+
|
50
|
+
class Cool_new_formula < Formula
|
51
|
+
|
52
|
+
def score(text, stats)
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
def name
|
57
|
+
"Cool new formula"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
text will be a Hash like so:
|
62
|
+
|
63
|
+
data = {
|
64
|
+
'raw' => String,
|
65
|
+
'words' => Array,
|
66
|
+
'sentences' => Array,
|
67
|
+
'syllables' => Array
|
68
|
+
}
|
69
|
+
|
70
|
+
stats will be a Hash like so:
|
71
|
+
|
72
|
+
{
|
73
|
+
'string_length' => Fixnum,
|
74
|
+
'letter_count' => Fixnum,
|
75
|
+
'syllable_count' => Fixnum,
|
76
|
+
'word_count' => Fixnum,
|
77
|
+
'sentence_count' => Fixnum,
|
78
|
+
'average_words_per_sentence' => Float,
|
79
|
+
'average_syllables_per_word' => Float
|
80
|
+
}
|
81
|
+
|
82
|
+
That is all you need.
|
83
|
+
To call your formula you just use
|
84
|
+
|
85
|
+
Odyssey.cool_new_formula('See Spot run.', true)
|
86
|
+
|
87
|
+
Because you have access to the formula's class (when the 'all_stats' flag is true),
|
88
|
+
you have access to any other methods or class variables.
|
89
|
+
|
90
|
+
## Contributing
|
91
|
+
|
92
|
+
1. Fork it
|
93
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
94
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
95
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
96
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/lib/formulas/ari.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
class Automated_readability < Formula
|
2
|
+
|
3
|
+
def score(text, stats)
|
4
|
+
calc_score(stats['letter_count'], stats['word_count'], stats['sentence_count'])
|
5
|
+
end
|
6
|
+
|
7
|
+
def calc_score(letter_count, word_count, sentence_count)
|
8
|
+
(((4.71 * (letter_count.to_f / word_count.to_f)) + (0.5 * (word_count.to_f / sentence_count.to_f))) - 21.43).round(1)
|
9
|
+
end
|
10
|
+
|
11
|
+
def name
|
12
|
+
'Automated Readability Index'
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class Coleman_liau < Formula
|
2
|
+
|
3
|
+
def score(text, stats)
|
4
|
+
calc_score(stats['letter_count'], stats['word_count'], stats['sentence_count'])
|
5
|
+
end
|
6
|
+
|
7
|
+
def calc_score(letter_count, word_count, sentence_count)
|
8
|
+
((5.89 * (letter_count.to_f / word_count.to_f)) - (0.3 * (sentence_count.to_f / word_count.to_f)) - 15.8).round(1)
|
9
|
+
end
|
10
|
+
|
11
|
+
def name
|
12
|
+
'Coleman-Liau Index'
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class Flesch_kincaid_GL < Formula
|
2
|
+
|
3
|
+
def score(text, stats)
|
4
|
+
calc_score(stats['average_words_per_sentence'], stats['average_syllables_per_word'])
|
5
|
+
end
|
6
|
+
|
7
|
+
def calc_score(avg_words, avg_syllables)
|
8
|
+
(((0.39 * avg_words) + (11.8 * avg_syllables)) - 15.59).round(1)
|
9
|
+
end
|
10
|
+
|
11
|
+
def name
|
12
|
+
'Flesch-Kincaid Grade Level'
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class Flesch_kincaid_RE < Formula
|
2
|
+
|
3
|
+
def score(text, stats)
|
4
|
+
calc_score(stats['average_words_per_sentence'], stats['average_syllables_per_word'])
|
5
|
+
end
|
6
|
+
|
7
|
+
def calc_score(avg_words, avg_syllables)
|
8
|
+
((206.835 - (1.015 * avg_words)) - (84.6 * avg_syllables)).round(1)
|
9
|
+
end
|
10
|
+
|
11
|
+
def name
|
12
|
+
'Flesch-Kincaid Reading Ease'
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Formula
|
2
|
+
|
3
|
+
# text will be a Hash like so:
|
4
|
+
# data = {
|
5
|
+
# 'raw' => String,
|
6
|
+
# 'words' => Array,
|
7
|
+
# 'sentences' => Array,
|
8
|
+
# 'syllables' => Array
|
9
|
+
# }
|
10
|
+
#
|
11
|
+
# stats will be a Hash like so:
|
12
|
+
# {
|
13
|
+
# 'string_length' => Fixnum,
|
14
|
+
# 'letter_count' => Fixnum,
|
15
|
+
# 'syllable_count' => Fixnum,
|
16
|
+
# 'word_count' => Fixnum,
|
17
|
+
# 'sentence_count' => Fixnum,
|
18
|
+
# 'average_words_per_sentence' => Float,
|
19
|
+
# 'average_syllables_per_word' => Float
|
20
|
+
# }
|
21
|
+
|
22
|
+
def score(text, stats)
|
23
|
+
0
|
24
|
+
end
|
25
|
+
|
26
|
+
def name
|
27
|
+
'Generic'
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class Gunning_fog < Formula
|
2
|
+
|
3
|
+
def score(text, stats)
|
4
|
+
percent = three_syllables(stats['word_count'], text['syllables'])
|
5
|
+
calc_score(stats['average_words_per_sentence'], percent)
|
6
|
+
end
|
7
|
+
|
8
|
+
#percentage of words with three syllables
|
9
|
+
def three_syllables(word_count, syllables)
|
10
|
+
with_three = 0
|
11
|
+
syllables.each do |s|
|
12
|
+
with_three += 1 if s > 2
|
13
|
+
end
|
14
|
+
(with_three / word_count) * 100
|
15
|
+
end
|
16
|
+
|
17
|
+
def calc_score(avg_words, percent_with_three)
|
18
|
+
((avg_words + percent_with_three) * 0.4).round(1)
|
19
|
+
end
|
20
|
+
|
21
|
+
def name
|
22
|
+
'Gunning-Fog Score'
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Smog < Formula
|
2
|
+
|
3
|
+
def score(text, stats)
|
4
|
+
with_three = three_syllables(text['syllables'])
|
5
|
+
calc_score(stats['sentence_count'], with_three)
|
6
|
+
end
|
7
|
+
|
8
|
+
def three_syllables(syllables)
|
9
|
+
with_three = 0
|
10
|
+
syllables.each do |s|
|
11
|
+
with_three += 1 if s > 2
|
12
|
+
end
|
13
|
+
with_three
|
14
|
+
end
|
15
|
+
|
16
|
+
def calc_score(sentence_count, with_three)
|
17
|
+
(1.043 * Math.sqrt(with_three * (30.0 / sentence_count)) + 3.1291).round(1)
|
18
|
+
end
|
19
|
+
|
20
|
+
def name
|
21
|
+
'SMOG Index'
|
22
|
+
end
|
23
|
+
end
|
data/lib/odyssey.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
require "odyssey/version"
|
2
|
+
|
3
|
+
module Odyssey
|
4
|
+
|
5
|
+
DEFAULT_FORMULA = 'Flesch_kincaid_RE'
|
6
|
+
|
7
|
+
#main method
|
8
|
+
def self.analyze(text, formula_name = DEFAULT_FORMULA, all_stats = false)
|
9
|
+
#catch nils
|
10
|
+
formula_name = DEFAULT_FORMULA if formula_name == nil
|
11
|
+
|
12
|
+
@engine = Odyssey::Engine.new(formula_name)
|
13
|
+
score = @engine.score(text)
|
14
|
+
|
15
|
+
#return all stats?
|
16
|
+
if all_stats
|
17
|
+
output = @engine.get_stats
|
18
|
+
else
|
19
|
+
output = score
|
20
|
+
end
|
21
|
+
|
22
|
+
output
|
23
|
+
end
|
24
|
+
|
25
|
+
#run whatever method was given as if it were a shortcut to a formula
|
26
|
+
def self.method_missing(*args)
|
27
|
+
method_string = args[0].to_s
|
28
|
+
|
29
|
+
#capitalize the first letter
|
30
|
+
first_letter = method_string[0].upcase
|
31
|
+
method_string[0] = first_letter
|
32
|
+
|
33
|
+
#send to the main method
|
34
|
+
analyze(args[1], method_string, args[2] || false)
|
35
|
+
end
|
36
|
+
|
37
|
+
#define this here, so it doesn't get sent to method_missing()
|
38
|
+
def self.to_ary
|
39
|
+
[]
|
40
|
+
end
|
41
|
+
|
42
|
+
#######################################################
|
43
|
+
# pre-built methods that act as shortcuts to formulas #
|
44
|
+
#######################################################
|
45
|
+
|
46
|
+
def self.flesch_kincaid_reading_ease(text, all_stats = false)
|
47
|
+
analyze(text, 'Flesch_kincaid_RE', all_stats)
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.flesch_kincaid_grade_level(text, all_stats = false)
|
51
|
+
analyze(text, 'Flesch_kincaid_GL', all_stats)
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.gunning_fog(text, all_stats = false)
|
55
|
+
analyze(text, 'Gunning_fog', all_stats)
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.coleman_liau(text, all_stats = false)
|
59
|
+
analyze(text, 'Coleman_liau', all_stats)
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.smog(text, all_stats = false)
|
63
|
+
analyze(text, 'Smog', all_stats)
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.ari(text, all_stats = false)
|
67
|
+
analyze(text, 'Automated_readability', all_stats)
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
require 'require_all'
|
73
|
+
require 'odyssey/engine'
|
74
|
+
require_rel 'formulas'
|
@@ -0,0 +1,146 @@
|
|
1
|
+
module Odyssey
|
2
|
+
class Engine
|
3
|
+
|
4
|
+
#class variables
|
5
|
+
@formula
|
6
|
+
@score
|
7
|
+
@stats
|
8
|
+
@words
|
9
|
+
@sentences
|
10
|
+
@syllables
|
11
|
+
|
12
|
+
#regex
|
13
|
+
LETTER_REGEX = /[A-z]/
|
14
|
+
WORD_REGEX = /[^\W][A-z\-']*/
|
15
|
+
SENTENCE_REGEX = /[^\.!?\s][^\.!?]*(?:[\.!?](?!['"]?\s|$)[^\.!?]*)*[\.!?]?['"]?(?=\s|$)/
|
16
|
+
|
17
|
+
#words that cause the syllable analyzer to fail
|
18
|
+
# word => syllables
|
19
|
+
PROBLEM_WORDS = {
|
20
|
+
'ion' => 2
|
21
|
+
}
|
22
|
+
|
23
|
+
def initialize(formula_name)
|
24
|
+
reset
|
25
|
+
klass = Module.const_get formula_name
|
26
|
+
@formula = klass.new
|
27
|
+
rescue
|
28
|
+
@formula = Formula.new
|
29
|
+
end
|
30
|
+
|
31
|
+
def score(_text)
|
32
|
+
#sanitize the text
|
33
|
+
text = sanitize(_text)
|
34
|
+
|
35
|
+
#first get all the statistics
|
36
|
+
@stats = {
|
37
|
+
'string_length' => string_length(text),
|
38
|
+
'letter_count' => letter_count(text),
|
39
|
+
'word_count' => word_count(text),
|
40
|
+
'syllable_count' => syllable_count(text),
|
41
|
+
'sentence_count' => sentence_count(text),
|
42
|
+
}
|
43
|
+
|
44
|
+
@stats['average_words_per_sentence'] = average_words_per_sentence(text)
|
45
|
+
@stats['average_syllables_per_word'] = average_syllables_per_word(text)
|
46
|
+
|
47
|
+
#prepare the parameter to the score method
|
48
|
+
data = {
|
49
|
+
'raw' => text,
|
50
|
+
'words' => @words,
|
51
|
+
'sentences' => @sentences,
|
52
|
+
'syllables' => @syllables
|
53
|
+
}
|
54
|
+
|
55
|
+
#now run all that through the formula
|
56
|
+
@score = @formula.score(data, @stats)
|
57
|
+
end
|
58
|
+
|
59
|
+
def string_length(text)
|
60
|
+
text.length
|
61
|
+
end
|
62
|
+
|
63
|
+
def letter_count(text)
|
64
|
+
matches = text.scan LETTER_REGEX
|
65
|
+
matches.size
|
66
|
+
end
|
67
|
+
|
68
|
+
def syllable_count(text)
|
69
|
+
count = 0
|
70
|
+
@words.each do |w|
|
71
|
+
num = analyze_syllables(w)
|
72
|
+
count += num
|
73
|
+
@syllables << num
|
74
|
+
end
|
75
|
+
count
|
76
|
+
end
|
77
|
+
|
78
|
+
def word_count(text)
|
79
|
+
@words = text.scan WORD_REGEX
|
80
|
+
@words.size
|
81
|
+
end
|
82
|
+
|
83
|
+
def sentence_count(text)
|
84
|
+
@sentences = text.scan SENTENCE_REGEX
|
85
|
+
@sentences.size
|
86
|
+
end
|
87
|
+
|
88
|
+
def average_words_per_sentence(text)
|
89
|
+
@stats['word_count'].to_f / @stats['sentence_count'].to_f
|
90
|
+
end
|
91
|
+
|
92
|
+
def average_syllables_per_word(text)
|
93
|
+
@stats['syllable_count'].to_f / @stats['word_count'].to_f
|
94
|
+
end
|
95
|
+
|
96
|
+
# for now this just removes html tags
|
97
|
+
# but it could do more in the future
|
98
|
+
def sanitize(text)
|
99
|
+
output = text.gsub(/<\/?[^>]+>/, '')
|
100
|
+
end
|
101
|
+
|
102
|
+
def analyze_syllables(_word)
|
103
|
+
#remove non-alpha characters
|
104
|
+
word = _word.gsub(/[^A-z]/, '')
|
105
|
+
count = 0
|
106
|
+
|
107
|
+
if PROBLEM_WORDS.has_key?(word)
|
108
|
+
count = PROBLEM_WORDS[word]
|
109
|
+
else
|
110
|
+
#this is an approximation, but it is fairly close
|
111
|
+
word.downcase!
|
112
|
+
return 1 if word.length <= 3
|
113
|
+
word.sub!(/(?:[^laeiouy]es|ed|[^laeiouy]e)$/, '')
|
114
|
+
word.sub!(/^y/, '')
|
115
|
+
count = word.scan(/[aeiouy]{1,2}/).size
|
116
|
+
end
|
117
|
+
|
118
|
+
count
|
119
|
+
end
|
120
|
+
|
121
|
+
def get_stats
|
122
|
+
{
|
123
|
+
'name' => @formula.name,
|
124
|
+
'formula' => @formula,
|
125
|
+
'score' => @score,
|
126
|
+
'string_length' => @stats['string_length'],
|
127
|
+
'letter_count' => @stats['letter_count'],
|
128
|
+
'syllable_count' => @stats['syllable_count'],
|
129
|
+
'word_count' => @stats['word_count'],
|
130
|
+
'sentence_count' => @stats['sentence_count'],
|
131
|
+
'average_words_per_sentence' => @stats['average_words_per_sentence'],
|
132
|
+
'average_syllables_per_word' => @stats['average_syllables_per_word']
|
133
|
+
}
|
134
|
+
end
|
135
|
+
|
136
|
+
def reset
|
137
|
+
@formula = nil
|
138
|
+
@score = 0
|
139
|
+
@stats = {}
|
140
|
+
@words = nil
|
141
|
+
@sentences = nil
|
142
|
+
@syllables = []
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
end
|
data/odyssey.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'odyssey/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "odyssey"
|
8
|
+
spec.version = Odyssey::VERSION
|
9
|
+
spec.authors = ["Cameron Sutter"]
|
10
|
+
spec.email = ["cameronsutter0@gmail.com"]
|
11
|
+
spec.description = %q{Odyssey is an extendible text analyzing gem that outputs the readability score of text. It has several of the common readability formulas available, but defaults to the Flesch-Kincaid Reading Ease score.}
|
12
|
+
spec.summary = %q{Text readability analyzer using Flesch-Kincaid and others}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.add_dependency "require_all"
|
17
|
+
|
18
|
+
spec.files = `git ls-files`.split($/)
|
19
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
spec.add_development_dependency "rspec"
|
26
|
+
end
|
@@ -0,0 +1,229 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Odyssey do
|
4
|
+
|
5
|
+
context 'default formula' do
|
6
|
+
it 'should return something' do
|
7
|
+
result = Odyssey.analyze one_simple_sentence
|
8
|
+
result.should_not be_nil
|
9
|
+
end
|
10
|
+
|
11
|
+
describe 'get all stats' do
|
12
|
+
before :all do
|
13
|
+
@simple = Odyssey.analyze one_simple_sentence, nil, true
|
14
|
+
@double = Odyssey.analyze two_simple_sentences, nil, true
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should return formula name' do
|
18
|
+
@simple['name'].should == 'Flesch-Kincaid Reading Ease'
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should return score' do
|
22
|
+
@simple['score'].should == 119.2
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should return the formula' do
|
26
|
+
@simple['formula'].class.to_s.should == 'Flesch_kincaid_RE'
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should return string length' do
|
30
|
+
@simple['string_length'].should == 13
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should return letter count' do
|
34
|
+
@simple['letter_count'].should == 10
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should return syllable count' do
|
38
|
+
@simple['syllable_count'].should == 3
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should return word count' do
|
42
|
+
@simple['word_count'].should == 3
|
43
|
+
|
44
|
+
@double['word_count'].should == 6
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should return sentence count' do
|
48
|
+
@simple['sentence_count'].should == 1
|
49
|
+
|
50
|
+
@double['sentence_count'].should == 2
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should return average words per sentence' do
|
54
|
+
@simple['average_words_per_sentence'].should == 3
|
55
|
+
|
56
|
+
@double['average_words_per_sentence'].should == 3
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should return average syllables per word' do
|
60
|
+
@simple['average_syllables_per_word'].should == 1
|
61
|
+
|
62
|
+
@double['average_syllables_per_word'].should == 1
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'Flesch-Kincaid Reading Ease' do
|
69
|
+
|
70
|
+
describe 'get score' do
|
71
|
+
before :all do
|
72
|
+
@simple = Odyssey.flesch_kincaid_reading_ease one_simple_sentence
|
73
|
+
@double = Odyssey.flesch_kincaid_reading_ease two_simple_sentences
|
74
|
+
@complex = Odyssey.flesch_kincaid_reading_ease one_complex_sentence
|
75
|
+
@complex_double = Odyssey.flesch_kincaid_reading_ease two_complex_sentences
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'should return something' do
|
79
|
+
@simple.should_not be_nil
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should return the score' do
|
83
|
+
@simple.should == 119.2
|
84
|
+
@double.should == 119.2
|
85
|
+
@complex.should == 94.3
|
86
|
+
@complex_double.should == 88.7
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'Flesch-Kincaid Grade Level' do
|
93
|
+
|
94
|
+
describe 'get score' do
|
95
|
+
before :all do
|
96
|
+
@simple = Odyssey.flesch_kincaid_grade_level one_simple_sentence
|
97
|
+
@double = Odyssey.flesch_kincaid_grade_level two_simple_sentences
|
98
|
+
@complex = Odyssey.flesch_kincaid_grade_level one_complex_sentence
|
99
|
+
@complex_double = Odyssey.flesch_kincaid_grade_level two_complex_sentences
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'should return something' do
|
103
|
+
@simple.should_not be_nil
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'should return the score' do
|
107
|
+
@simple.should == -2.6
|
108
|
+
@double.should == -2.6
|
109
|
+
@complex.should == 2.3
|
110
|
+
@complex_double.should == 3
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
context 'Gunning-Fog Score' do
|
117
|
+
|
118
|
+
describe 'get score' do
|
119
|
+
before :all do
|
120
|
+
@simple = Odyssey.gunning_fog one_simple_sentence
|
121
|
+
@double = Odyssey.gunning_fog two_simple_sentences
|
122
|
+
@complex = Odyssey.gunning_fog one_complex_sentence
|
123
|
+
@complex_double = Odyssey.gunning_fog two_complex_sentences
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'should return something' do
|
127
|
+
@simple.should_not be_nil
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'should return the score' do
|
131
|
+
@simple.should == 1.2
|
132
|
+
@double.should == 1.2
|
133
|
+
@complex.should == 3.6
|
134
|
+
@complex_double.should == 3.4
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
context 'Coleman-Liau Index' do
|
141
|
+
|
142
|
+
describe 'get score' do
|
143
|
+
before :all do
|
144
|
+
@simple = Odyssey.coleman_liau one_simple_sentence
|
145
|
+
@double = Odyssey.coleman_liau two_simple_sentences
|
146
|
+
@complex = Odyssey.coleman_liau one_complex_sentence
|
147
|
+
@complex_double = Odyssey.coleman_liau two_complex_sentences
|
148
|
+
@very_complex = Odyssey.coleman_liau very_complex
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'should return something' do
|
152
|
+
@simple.should_not be_nil
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'should return the score' do
|
156
|
+
@simple.should == 3.7
|
157
|
+
@double.should == 4.7
|
158
|
+
@complex.should == 7.1
|
159
|
+
@complex_double.should == 9.1
|
160
|
+
@very_complex.should == 10.7
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
context 'SMOG Index' do
|
167
|
+
|
168
|
+
describe 'get score' do
|
169
|
+
before :all do
|
170
|
+
@simple = Odyssey.smog one_simple_sentence
|
171
|
+
@double = Odyssey.smog two_simple_sentences
|
172
|
+
@complex = Odyssey.smog one_complex_sentence
|
173
|
+
@complex_double = Odyssey.smog two_complex_sentences
|
174
|
+
@very_complex = Odyssey.smog very_complex
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'should return something' do
|
178
|
+
@simple.should_not be_nil
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'should return the score' do
|
182
|
+
@simple.should == 1.8
|
183
|
+
@double.should == 1.8
|
184
|
+
@complex.should == 1.8
|
185
|
+
@complex_double.should == 1.8
|
186
|
+
@very_complex.should == 10.1
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
end
|
191
|
+
|
192
|
+
context 'Automated Readability Index' do
|
193
|
+
|
194
|
+
describe 'get score' do
|
195
|
+
before :all do
|
196
|
+
@simple = Odyssey.ari one_simple_sentence
|
197
|
+
@double = Odyssey.ari two_simple_sentences
|
198
|
+
@complex = Odyssey.ari one_complex_sentence
|
199
|
+
@complex_double = Odyssey.ari two_complex_sentences
|
200
|
+
@very_complex = Odyssey.ari very_complex
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'should return something' do
|
204
|
+
@simple.should_not be_nil
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'should return the score' do
|
208
|
+
@simple.should == -4.2
|
209
|
+
@double.should == -3.4
|
210
|
+
@complex.should == 1.4
|
211
|
+
@complex_double.should == 2.8
|
212
|
+
@very_complex.should == 12.1
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
end
|
217
|
+
|
218
|
+
describe 'plugin formulas' do
|
219
|
+
it 'should run any formula using a shortcut method' do
|
220
|
+
result = Odyssey.fake_formula one_simple_sentence, true
|
221
|
+
result['name'].should == "It's fake"
|
222
|
+
end
|
223
|
+
|
224
|
+
it 'should default to Formula for a formula that does not exist' do
|
225
|
+
result = Odyssey.no_existe one_simple_sentence, true
|
226
|
+
result['name'].should == "Generic"
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'odyssey'
|
3
|
+
|
4
|
+
RSpec.configure do |config|
|
5
|
+
config.color_enabled = true
|
6
|
+
config.formatter = 'documentation'
|
7
|
+
end
|
8
|
+
|
9
|
+
def one_simple_sentence
|
10
|
+
"See Spot run."
|
11
|
+
end
|
12
|
+
|
13
|
+
def two_simple_sentences
|
14
|
+
"See Spot run. See Spot jump."
|
15
|
+
end
|
16
|
+
|
17
|
+
def one_complex_sentence
|
18
|
+
"The quick brown fox jumps over the lazy dog."
|
19
|
+
end
|
20
|
+
|
21
|
+
def two_complex_sentences
|
22
|
+
"The quick brown fox jumps over the lazy dog. Peter Piper picked a peck of pickled peppers."
|
23
|
+
end
|
24
|
+
|
25
|
+
def very_complex
|
26
|
+
"The best things in an artist's work are so much a matter of intuition, that there is much to be said for the point of view that would altogether discourage intellectual inquiry into artistic phenomena on the part of the artist. Intuitions are shy things and apt to disappear if looked into too closely. And there is undoubtedly a danger that too much knowledge and training may supplant the natural intuitive feeling of a student, leaving only a cold knowledge of the means of expression in its place. For the artist, if he has the right stuff in him"
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: odyssey
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.8
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Cameron Sutter
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-06-03 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: require_all
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: bundler
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '1.3'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '1.3'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rake
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rspec
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
description: Odyssey is an extendible text analyzing gem that outputs the readability
|
79
|
+
score of text. It has several of the common readability formulas available, but
|
80
|
+
defaults to the Flesch-Kincaid Reading Ease score.
|
81
|
+
email:
|
82
|
+
- cameronsutter0@gmail.com
|
83
|
+
executables: []
|
84
|
+
extensions: []
|
85
|
+
extra_rdoc_files: []
|
86
|
+
files:
|
87
|
+
- .gitignore
|
88
|
+
- Gemfile
|
89
|
+
- LICENSE.txt
|
90
|
+
- README.md
|
91
|
+
- Rakefile
|
92
|
+
- lib/formulas/ari.rb
|
93
|
+
- lib/formulas/coleman_liau.rb
|
94
|
+
- lib/formulas/fake_formula.rb
|
95
|
+
- lib/formulas/flesch_kincaid_gl.rb
|
96
|
+
- lib/formulas/flesch_kincaid_re.rb
|
97
|
+
- lib/formulas/formula.rb
|
98
|
+
- lib/formulas/gunning_fog.rb
|
99
|
+
- lib/formulas/smog.rb
|
100
|
+
- lib/odyssey.rb
|
101
|
+
- lib/odyssey/engine.rb
|
102
|
+
- lib/odyssey/version.rb
|
103
|
+
- odyssey.gemspec
|
104
|
+
- spec/odyssey_spec.rb
|
105
|
+
- spec/spec_helper.rb
|
106
|
+
homepage: ''
|
107
|
+
licenses:
|
108
|
+
- MIT
|
109
|
+
post_install_message:
|
110
|
+
rdoc_options: []
|
111
|
+
require_paths:
|
112
|
+
- lib
|
113
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
114
|
+
none: false
|
115
|
+
requirements:
|
116
|
+
- - ! '>='
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
|
+
none: false
|
121
|
+
requirements:
|
122
|
+
- - ! '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
requirements: []
|
126
|
+
rubyforge_project:
|
127
|
+
rubygems_version: 1.8.23
|
128
|
+
signing_key:
|
129
|
+
specification_version: 3
|
130
|
+
summary: Text readability analyzer using Flesch-Kincaid and others
|
131
|
+
test_files:
|
132
|
+
- spec/odyssey_spec.rb
|
133
|
+
- spec/spec_helper.rb
|
134
|
+
has_rdoc:
|