verso 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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