verso 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. data/.gitignore +5 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE.md +20 -0
  4. data/README.md +75 -0
  5. data/Rakefile +1 -0
  6. data/lib/verso.rb +33 -0
  7. data/lib/verso/cluster.rb +43 -0
  8. data/lib/verso/cluster_list.rb +19 -0
  9. data/lib/verso/correlation_list.rb +53 -0
  10. data/lib/verso/course.rb +84 -0
  11. data/lib/verso/course_list.rb +36 -0
  12. data/lib/verso/credential.rb +34 -0
  13. data/lib/verso/credential_list.rb +28 -0
  14. data/lib/verso/duty_area.rb +17 -0
  15. data/lib/verso/edition_list.rb +19 -0
  16. data/lib/verso/emphasis.rb +21 -0
  17. data/lib/verso/emphasis_list.rb +19 -0
  18. data/lib/verso/examination_list.rb +21 -0
  19. data/lib/verso/extra.rb +38 -0
  20. data/lib/verso/extras_list.rb +22 -0
  21. data/lib/verso/frontmatter.rb +18 -0
  22. data/lib/verso/http_get.rb +9 -0
  23. data/lib/verso/occupation.rb +25 -0
  24. data/lib/verso/occupation_data.rb +31 -0
  25. data/lib/verso/occupation_list.rb +32 -0
  26. data/lib/verso/pathway.rb +25 -0
  27. data/lib/verso/program_area.rb +39 -0
  28. data/lib/verso/program_area_list.rb +20 -0
  29. data/lib/verso/sol_correlation_list.rb +53 -0
  30. data/lib/verso/standard.rb +37 -0
  31. data/lib/verso/standards_list.rb +49 -0
  32. data/lib/verso/task.rb +30 -0
  33. data/lib/verso/task_list.rb +31 -0
  34. data/lib/verso/version.rb +3 -0
  35. data/spec/cluster_list_spec.rb +12 -0
  36. data/spec/cluster_spec.rb +18 -0
  37. data/spec/correlation_list_spec.rb +55 -0
  38. data/spec/course_list_spec.rb +36 -0
  39. data/spec/course_spec.rb +193 -0
  40. data/spec/credential_list_spec.rb +75 -0
  41. data/spec/credential_spec.rb +34 -0
  42. data/spec/duty_area_spec.rb +27 -0
  43. data/spec/edition_list_spec.rb +11 -0
  44. data/spec/emphasis_list_spec.rb +21 -0
  45. data/spec/emphasis_spec.rb +31 -0
  46. data/spec/examination_list_spec.rb +29 -0
  47. data/spec/extra_spec.rb +36 -0
  48. data/spec/extras_list_spec.rb +25 -0
  49. data/spec/frontmatter_spec.rb +11 -0
  50. data/spec/occupation_data_spec.rb +24 -0
  51. data/spec/occupation_list_spec.rb +21 -0
  52. data/spec/occupation_spec.rb +41 -0
  53. data/spec/pathway_spec.rb +41 -0
  54. data/spec/program_area_list_spec.rb +11 -0
  55. data/spec/program_area_spec.rb +39 -0
  56. data/spec/sol_correlation_list_spec.rb +74 -0
  57. data/spec/spec_helper.rb +23 -0
  58. data/spec/standard_spec.rb +53 -0
  59. data/spec/standards_list_spec.rb +51 -0
  60. data/spec/task_list_spec.rb +72 -0
  61. data/spec/task_spec.rb +55 -0
  62. data/verso.gemspec +25 -0
  63. metadata +189 -0
@@ -0,0 +1,49 @@
1
+ module Verso
2
+ class StandardsList
3
+ include Enumerable
4
+
5
+ def initialize(raw, context=nil)
6
+ @raw_standards = raw.is_a?(Array) ? raw : raw.values
7
+ @context = context
8
+ end
9
+
10
+ def self.from_course(course)
11
+ raw_standards = JSON.parse(
12
+ Net::HTTP.get('api.cteresource.org',
13
+ "/courses/#{course.code},#{course.edition}/standards/",
14
+ 80)
15
+ )["standards"]
16
+ StandardsList.new(raw_standards, course)
17
+ end
18
+
19
+ def standards
20
+ @standards ||= @raw_standards.
21
+ sort_by { |s| s["title"] }.
22
+ collect { |raw_standard| Standard.new(raw_standard, @context) }
23
+ end
24
+
25
+ def each &block
26
+ standards.each &block
27
+ end
28
+
29
+ def last
30
+ standards[-1]
31
+ end
32
+
33
+ def empty?
34
+ standards.empty?
35
+ end
36
+
37
+ def sol_titles
38
+ ['English', 'History and Social Science', 'Mathematics', 'Science']
39
+ end
40
+
41
+ def sols
42
+ @sols ||= select { |s| sol_titles.include?(s.title) }
43
+ end
44
+
45
+ def non_sols
46
+ @non_sols ||= reject { |s| sol_titles.include?(s.title) }
47
+ end
48
+ end
49
+ end
data/lib/verso/task.rb ADDED
@@ -0,0 +1,30 @@
1
+ module Verso
2
+ class Task
3
+ include HTTPGet
4
+
5
+ def initialize(raw_task)
6
+ @raw_task = raw_task
7
+ end
8
+
9
+ def method_missing(mname)
10
+ if !@raw_task.has_key?(mname.to_s)
11
+ @raw_task.merge!(JSON.parse(
12
+ http_get("/courses/#{code},#{edition}/tasks/#{id}")
13
+ ))
14
+ end
15
+ @raw_task[mname.to_s]
16
+ end
17
+
18
+ def essential
19
+ sensitive ? true : @raw_task["essential"]
20
+ end
21
+
22
+ def standards
23
+ @standards ||= StandardsList.new(goals)
24
+ end
25
+
26
+ def bare?
27
+ definition.empty? && standards.sols.empty?
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,31 @@
1
+ module Verso
2
+ class TaskList
3
+ include Enumerable
4
+ include HTTPGet
5
+
6
+ attr_accessor :code, :edition
7
+
8
+ def initialize(params)
9
+ @code = params[:code]
10
+ @edition = params[:edition]
11
+ end
12
+
13
+ def duty_areas
14
+ @duty_areas ||= JSON.parse(
15
+ http_get("/courses/#{code},#{edition}/tasks/")
16
+ )["duty_areas"].to_a
17
+ end
18
+
19
+ def has_optional_task?
20
+ any? { |da| da.tasks.any? { |t| !t.essential } }
21
+ end
22
+
23
+ def has_sensitive_task?
24
+ any? { |da| da.tasks.any? { |t| t.sensitive } }
25
+ end
26
+
27
+ def each &block
28
+ duty_areas.each { |da| block.call(DutyArea.new(da, self)) }
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module Verso
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Verso::ClusterList do
4
+ use_vcr_cassette :record => :new_episodes
5
+
6
+ it "responds to #first, #last" do
7
+ list = Verso::ClusterList.new
8
+ list.first.title.strip.should eq("Agriculture, Food and Natural Resources")
9
+ list.last.title.strip.
10
+ should eq("Transportation, Distribution and Logistics")
11
+ end
12
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe Verso::Cluster do
4
+ before do
5
+ @pathway = { "title" => "Agribusiness Systems", "id" => 306 }
6
+ @raw_cluster = { "title" => "Information Technology",
7
+ "pathways" => [@pathway] }
8
+ @cluster = Verso::Cluster.new(@raw_cluster)
9
+ end
10
+
11
+ it 'should respond to title' do
12
+ @cluster.title.should eq("Information Technology")
13
+ end
14
+
15
+ it 'should respond to pathways' do
16
+ @cluster.pathways.first.title.should eq("Agribusiness Systems")
17
+ end
18
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ describe Verso::CorrelationList do
4
+ before do
5
+ @goal = OpenStruct.new({ "title" => "goal title",
6
+ "description" => "goal description" })
7
+ @standard = double("Standard", :title => "standard title",
8
+ :name => "standard_name",
9
+ :description => "standard description",
10
+ :goals => [@goal], :sections => [])
11
+ @standards_list = [@standard]
12
+ @standards_list.stub(:non_sols).
13
+ and_return([OpenStruct.new(:name => "standard_name"),
14
+ OpenStruct.new(:name => "science")])
15
+ @task = double("Task", :statement => "task statement", :id => "111",
16
+ :standards => @standards_list)
17
+ @tasks = [@task]
18
+ @duty_areas = [OpenStruct.new(:tasks => @tasks)]
19
+ @course = double("Course", :title => "course title", :edition => "1929",
20
+ :code => "0000", :duration => 36, :hours => nil,
21
+ :co_op => true, :related_resources => ["tasks"],
22
+ :standards => @standards_list,
23
+ :duty_areas => @duty_areas, :certifications => [])
24
+ correlations1 = { "correlations" => [
25
+ {"id" => "111", "statement" => "task statement",
26
+ "goals" => {
27
+ "standard_name" => { "title" => "English", "description" => "",
28
+ "sections" => [],
29
+ "goals" => [
30
+ { "title" => "english goal title",
31
+ "description" => "english goal description" }
32
+ ] }
33
+ }
34
+ }
35
+ ]}.to_json
36
+ @correlations = Verso::CorrelationList.new(@course, "standard_name")
37
+ Net::HTTP.stub(:get).and_return(correlations1)
38
+ end
39
+
40
+ it 'is enumerable' do
41
+ @correlations.first.statement.should eq('task statement')
42
+ end
43
+
44
+ it 'numbers the correlations' do
45
+ @correlations.first.number.should eq(1)
46
+ end
47
+
48
+ it 'has a goal' do
49
+ @correlations.first.standards.count.should_not eq(0)
50
+ end
51
+
52
+ it 'responds to #title' do
53
+ @correlations.title.should eq("standard title")
54
+ end
55
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe Verso::CourseList do
4
+ use_vcr_cassette :record => :new_episodes
5
+
6
+ it "searches by text" do
7
+ results = Verso::CourseList.new(:text => "6321")
8
+ results.first.title.strip.should eq("Accounting, Advanced")
9
+ end
10
+
11
+ it "should return no results when query is empty" do
12
+ results = Verso::CourseList.new(:text => nil)
13
+ results.count.should == 0
14
+ end
15
+
16
+ it "searches by cluster" do
17
+ results = Verso::CourseList.new(:cluster => "education and training")
18
+ results.first.title.strip.
19
+ should eq("Equine Management Production")
20
+ end
21
+
22
+ it "can find courses by program area too" do
23
+ results = Verso::CourseList.new(:program_area => "across the board")
24
+ results.first.title.strip.should eq("Work-Based Learning through Service")
25
+ end
26
+
27
+ it "should return empty results when query is empty" do
28
+ Verso::CourseList.new({}).count.should == 0
29
+ [:text, :program_area, :cluster].each do |k|
30
+ Verso::CourseList.new(k => nil).count.should == 0
31
+ Verso::CourseList.new(k => '').count.should == 0
32
+ end
33
+ Verso::CourseList.new(:text => '', :program_area => '', :cluster => '').
34
+ count.should == 0
35
+ end
36
+ end
@@ -0,0 +1,193 @@
1
+ require 'spec_helper'
2
+
3
+ describe Verso::Course do
4
+ before do
5
+ credentials = [{
6
+ "title" => "Certification 1", "type" => "Certification"
7
+ },
8
+ {"title" => "License 1", "type" => "License" }]
9
+ prerequisite_courses = [{
10
+ "code" => "2222", "hours" => nil, "duration" => 36,
11
+ "title" => "Basketweaving", "co_op" => true
12
+ }]
13
+ occupation_data = [{
14
+ "cluster" => { "title" => "Information Technology" },
15
+ "pathway" => { "title" => "Information and Support Services" },
16
+ "occupations" => [{ "title" => "Database Analyst" }]
17
+ }]
18
+ @extra = double("ExtrasList", :title => "Extra Title",
19
+ :name => "extra_name")
20
+ @course = Verso::Course.new("code" => "6321", "duration" => 36,
21
+ "title" => "Accounting, Advanced",
22
+ "hours" => nil, "edition" => "2011",
23
+ "co_op" => true,
24
+ "related_resources" => ["extras"],
25
+ "grade_levels" => "8 9 10",
26
+ "credentials" => credentials,
27
+ "occupation_data" => occupation_data,
28
+ "related_courses" => prerequisite_courses,
29
+ "prerequisite_courses" => prerequisite_courses)
30
+ end
31
+
32
+ it "responds to #extras" do
33
+ Verso::ExtrasList.should_receive(:new).and_return([@extra])
34
+ @course.extras.first.title.should eq("Extra Title")
35
+ end
36
+
37
+ it "responds to #related_courses" do
38
+ @course.related_courses.first.code.should eq('2222')
39
+ end
40
+
41
+ it "responds to #is_ms?" do
42
+ @course.is_ms?.should eq(true)
43
+ end
44
+
45
+ it "responds to #is_hs?" do
46
+ @course.is_hs?.should eq(true)
47
+ end
48
+
49
+ it "responds to #code" do
50
+ @course.code.should eq("6321")
51
+ end
52
+
53
+ it "responds to #duration" do
54
+ @course.duration.should eq(36)
55
+ end
56
+
57
+ it "responds to #title" do
58
+ @course.title.strip.should eq("Accounting, Advanced")
59
+ end
60
+
61
+ it "responds to #edition" do
62
+ @course.edition.should eq("2011")
63
+ end
64
+
65
+ it "responds to #hours" do
66
+ dental = Verso::Course.new("hours" => 280)
67
+ dental.hours.should eq(280)
68
+ end
69
+
70
+ it "responds to #co_op" do
71
+ @course.co_op.should eq(true)
72
+ Verso::Course.new("co_op" => false).co_op.should eq(false)
73
+ end
74
+
75
+ it "responds to #duty_areas" do
76
+ @task = double("Task", :statement => "a task", :id => "999999",
77
+ :sensitive => false, :essential => true)
78
+ @duty_area = double("DutyArea", :title => "A Duty Area",
79
+ :tasks => [@task])
80
+ Verso::TaskList.should_receive(:new).
81
+ with(:code => "6321", :edition => "2011").
82
+ and_return([@duty_area])
83
+ @course.duty_areas.first.should eq(@duty_area)
84
+ end
85
+
86
+ it "responds to #occupation_data" do
87
+ @occupation = double("Occupation", :title => "Database Analyst")
88
+ @pathway = double("Pathway", :title => "Information Support and Services")
89
+ @cluster = double("Cluster", :title => "Information Technology")
90
+ @occlist = double("OccupationData",
91
+ :cluster => @cluster,
92
+ :occupations => [@occupation],
93
+ :pathway => @pathway)
94
+ Verso::OccupationData.should_receive(:new).and_return(@occlist)
95
+ @course.occupation_data.first.should eq(@occlist)
96
+ end
97
+
98
+ it "responds to prerequisites" do
99
+ @course.prerequisites.first.code.should eq('2222')
100
+ end
101
+
102
+ it "responds to credentials" do
103
+ @course.credentials.first.title.should eq("Certification 1")
104
+ @course.credentials.last.title.should eq("License 1")
105
+ end
106
+
107
+ it "responds to certifications" do
108
+ @course.certifications.first.title.should eq("Certification 1")
109
+ @course.certifications.count.should eq(1)
110
+ end
111
+
112
+ it "responds to licenses" do
113
+ @course.licenses.first.title.should eq("License 1")
114
+ @course.licenses.count.should eq(1)
115
+ end
116
+
117
+ it "responds to #standards" do
118
+ Verso::StandardsList.
119
+ should_receive(:from_course).
120
+ with(@course).
121
+ and_return(["phony"])
122
+ @course.stub(:method_missing).and_return(["standards"])
123
+ @course.standards.first.should eq("phony")
124
+ end
125
+
126
+ it "responds to #task" do
127
+ t = Verso::Task.new("code" => @course.code, "edition" => @course.edition,
128
+ "id" => 99999999)
129
+ Verso::Task.should_receive(:new).
130
+ with("code" => @course.code,
131
+ "edition" => @course.edition,
132
+ "id" => 99999999).
133
+ and_return(t)
134
+ t = @course.task(99999999)
135
+ t.code.should eq(@course.code)
136
+ end
137
+
138
+ it "responds to #frontmatter" do
139
+ Verso::Frontmatter.should_receive(:new).
140
+ with("code" => @course.code,
141
+ "edition" => @course.edition).
142
+ and_return("phony")
143
+ @course.stub(:related_resources).and_return(["frontmatter"])
144
+ @course.frontmatter.should eq("phony")
145
+ end
146
+
147
+ it "#frontmatter returns nil if there is no frontmatter" do
148
+ @course.stub(:related_resources).and_return([])
149
+ @course.frontmatter.should eq(nil)
150
+ end
151
+
152
+ context "Only code and edition specified" do
153
+ use_vcr_cassette :record => :new_episodes
154
+
155
+ before do
156
+ @course = Verso::Course.new("code" => 6320, "edition" => "2011")
157
+ end
158
+
159
+ it "responds to #title" do
160
+ @course.title.should eq("Accounting")
161
+ end
162
+ end
163
+
164
+ context "MS-only course" do
165
+ before do
166
+ @course = Verso::Course.new("code" => "6320", "edition" => "2011",
167
+ "grade_levels" => "8")
168
+ end
169
+
170
+ it 'knows it is ms' do
171
+ @course.is_ms?.should eq(true)
172
+ end
173
+
174
+ it 'knows it is not hs' do
175
+ @course.is_hs?.should eq(false)
176
+ end
177
+ end
178
+
179
+ context 'HS-only course' do
180
+ before do
181
+ @course = Verso::Course.new("code" => "6320", "edition" => "2011",
182
+ "grade_levels" => "10")
183
+ end
184
+
185
+ it 'knows it is not ms' do
186
+ @course.is_ms?.should eq(false)
187
+ end
188
+
189
+ it 'knows it is hs' do
190
+ @course.is_hs?.should eq(true)
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+
3
+ describe Verso::CredentialList do
4
+ context "complete list" do
5
+ before do
6
+ Net::HTTP.
7
+ should_receive(:get).
8
+ with('api.cteresource.org', "/credentials", 80).
9
+ and_return(
10
+ JSON.pretty_generate(
11
+ :credentials => [ { :type => "Certification",
12
+ :source => { :title => "NOCTI" },
13
+ :title => "Business Financial Management",
14
+ :id => 845 } ]
15
+ )
16
+ )
17
+ @credentials = Verso::CredentialList.new
18
+ end
19
+
20
+ it 'responds to #first' do
21
+ credential = @credentials.first
22
+ credential.title.should eq("Business Financial Management")
23
+ credential.id.should eq(845)
24
+ end
25
+
26
+ it 'responds to #last' do
27
+ credential = @credentials.last
28
+ credential.title.should eq("Business Financial Management")
29
+ credential.id.should eq(845)
30
+ end
31
+
32
+ it 'responds to #empty?' do
33
+ @credentials.empty?.should eq(false)
34
+ end
35
+ end
36
+
37
+ context "search list" do
38
+ before do
39
+ Net::HTTP.
40
+ should_receive(:get).
41
+ with('api.cteresource.org', "/credentials?text=nocti", 80).
42
+ and_return(
43
+ JSON.pretty_generate(
44
+ :credentials => [ { :type => "Certification",
45
+ :source => { :title => "NOCTI" },
46
+ :title => "Basket weaving",
47
+ :id => 855 } ]
48
+ )
49
+ )
50
+ @credentials = Verso::CredentialList.new(:text => 'nocti')
51
+ end
52
+
53
+ it 'searches credentials' do
54
+ credential = @credentials.first
55
+ credential.title.should eq("Basket weaving")
56
+ credential.id.should eq(855)
57
+ end
58
+ end
59
+
60
+ context "search list with empty string" do
61
+ before do
62
+ Net::HTTP.
63
+ should_receive(:get).
64
+ with('api.cteresource.org', "/credentials", 80).
65
+ and_return(
66
+ JSON.pretty_generate(:credentials => [])
67
+ )
68
+ @credentials = Verso::CredentialList.new(:text => '')
69
+ end
70
+
71
+ it 'searches credentials' do
72
+ @credentials.empty?
73
+ end
74
+ end
75
+ end