pcr-ruby 0.1 → 0.2
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.
- data/.gitignore +1 -3
- data/README.md +25 -18
- data/lib/classes/array.rb +18 -0
- data/lib/classes/course.rb +89 -0
- data/lib/classes/errors.rb +6 -0
- data/lib/classes/instructor.rb +130 -0
- data/lib/classes/section.rb +53 -0
- data/lib/classes/string.rb +68 -0
- data/lib/pcr-ruby.rb +4 -4
- data/lib/pcr-ruby/version.rb +5 -0
- metadata +9 -2
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -4,11 +4,11 @@ pcr-ruby is a simple, intuitive way to retrieve course data from the Penn Course
|
|
4
4
|
|
5
5
|
## How to use pcr-ruby #
|
6
6
|
|
7
|
-
*This section
|
7
|
+
*This section may change a lot as pcr-ruby is developed. As such, this section may not be fully accurate, but I will try to keep the instructions as current as possible.*
|
8
8
|
|
9
9
|
pcr-ruby follows the structure of the PCR API, with a few name changes to make object identities and roles clearer in your code. (Before using pcr-ruby, you should most definitely read the PCR API documentation, the link to which you should recieve upon being granted your API token.)
|
10
10
|
|
11
|
-
The PCR API essentially consists of four types of objects: 'Courses', 'Sections', 'Instructors', and 'Course Histories'. pcr-ruby aims to provide intuitive access to the data contained in these four object types while abstracting you and your user from background processing and unnecessary data. To that end, pcr-ruby (thus far) consists of two types of objects: 'Courses'
|
11
|
+
The PCR API essentially consists of four types of objects: 'Courses', 'Sections', 'Instructors', and 'Course Histories'. pcr-ruby aims to provide intuitive access to the data contained in these four object types while abstracting you and your user from background processing and unnecessary data. To that end, pcr-ruby (thus far) consists of two types of objects: 'Courses', 'Sections', and 'Instructors'.
|
12
12
|
|
13
13
|
### 'Courses' in pcr-ruby ###
|
14
14
|
|
@@ -16,7 +16,9 @@ Course objects in the PCR API are essentially a group of that Course's Sections
|
|
16
16
|
|
17
17
|
To create a Course:
|
18
18
|
```ruby
|
19
|
-
|
19
|
+
require 'pcr-ruby'
|
20
|
+
pcr = PCR.new(api_token)
|
21
|
+
course = pcr.course(course_code)
|
20
22
|
```
|
21
23
|
All other instance variables will auto-populate based on data from the PCR API.
|
22
24
|
|
@@ -38,7 +40,9 @@ In pcr-ruby, Sections are single offerings of a Course. Each Section is associa
|
|
38
40
|
|
39
41
|
To create a Section:
|
40
42
|
```ruby
|
41
|
-
|
43
|
+
require 'pcr-ruby'
|
44
|
+
pcr = PCR.new(api_token)
|
45
|
+
section = pcr.section(id)
|
42
46
|
```
|
43
47
|
Possible instance variables available for setting in the Section initialize method are: aliases, id, name, path, semester.
|
44
48
|
|
@@ -51,10 +55,8 @@ Sections have the following instance variables:
|
|
51
55
|
* **description** -- a string containing the class description, which is written by the Section's Instructor and details the scope and characteristics of the class.
|
52
56
|
* **comments** -- a string containing PCR's comments about the Section. The comments are the most major part of the written review, and are sourced from student exit surveys.
|
53
57
|
* **ratings** -- a Hash of metrics and the ratings of the Section for each metric.
|
54
|
-
* **
|
55
|
-
|
56
|
-
Sections have the following instance methods:
|
57
|
-
* **reviews()** -- retrieves the Section's review data from PCR. Returns a Hash in the format {"comments" => @comments, "ratings" => @ratings}.
|
58
|
+
* **instructors** an Array of the Section's instructors.
|
59
|
+
* **reviews** -- a Hash of the Section's review data, in the format {"comments" => @comments, "ratings" => @ratings}.
|
58
60
|
|
59
61
|
### 'Instructors' in pcr-ruby ###
|
60
62
|
|
@@ -62,20 +64,19 @@ Instructors are arguably the most important part of PCR -- many students use PCR
|
|
62
64
|
|
63
65
|
To create an Instructor:
|
64
66
|
```ruby
|
65
|
-
|
67
|
+
require 'pcr-ruby'
|
68
|
+
pcr = PCR.new(api_token)
|
69
|
+
instructor = pcr.instructor(id)
|
66
70
|
```
|
67
|
-
(You really only need to pass the id argument, as pcr-ruby will automatically retrieve the other information from PCR.)
|
68
71
|
|
69
|
-
Insctructors have the following instance variables:
|
70
|
-
* **id** -- the Instructor's PCR id, a String in the form of "ID#-FIRST-M-LAST".
|
72
|
+
Insctructors have the following instance variables. All variables other than **id**, which is user-specified, will be filled from the PCR API:
|
73
|
+
* **id** -- the Instructor's PCR id, a String in the form of "ID#-FIRST-M-LAST". The PCR API also accepts a String in the form of "ID#".
|
71
74
|
* **name** -- the Instructor's name, a String in the form of "FIRST-M-LAST".
|
72
75
|
* **path** -- the PCR sub-path that leads to the Instructor, a String in the form of "/instructors/id".
|
73
76
|
* **sections** -- a Hash of sections taught by Instructor.
|
74
77
|
* **reviews** -- a Hash of reviews of Instructor in JSON.
|
75
78
|
|
76
79
|
Instructors have the following instance methods:
|
77
|
-
* **getInfo** -- a utility method to fill in missing info in Instructor object (used to minimize unnecessary API hits)
|
78
|
-
* **getReviews** -- a utility method to get review info for Instructor object (used to minimize unnecessary API hits)
|
79
80
|
* **average(metric)** -- returns the average value, across all Sections taught by Instructor, of "metric" as a Float. "Metric" must be a recognized rating in the PCR API. (Currently the names of these ratings are not intuitive, so I may provide plain-English access to rating names in the future.)
|
80
81
|
* **recent(metric)** -- returns the average value of "metric" for the most recent semester in which the Instructor taught as a float. (For example, if the professor taught 3 classes in the most recent semester, this would return the average of "metric" over the three classes.) "Metric" must be a recognized rating in the PCR API. (Currently the names of these ratings are not intuitive, so I may provide plain-English access to rating names in the future.)
|
81
82
|
|
@@ -89,7 +90,8 @@ Let's say we want to find the average course quality rating for Introduction to
|
|
89
90
|
```ruby
|
90
91
|
require 'pcr.rb'
|
91
92
|
course_code = "PSCI-150"
|
92
|
-
|
93
|
+
pcr = PCR.new(API_TOKEN)
|
94
|
+
course = pcr.course(course_code)
|
93
95
|
puts course.average("rCourseQuality") #=> 3.041
|
94
96
|
```
|
95
97
|
|
@@ -97,7 +99,9 @@ Or, even more briefly:
|
|
97
99
|
|
98
100
|
```ruby
|
99
101
|
require 'pcr.rb'
|
100
|
-
|
102
|
+
pcr = PCR.new(API_TOKEN)
|
103
|
+
puts pcr.course("PSCI-150")course.average("rCourseQuality")
|
104
|
+
#=> 3.041
|
101
105
|
```
|
102
106
|
|
103
107
|
### Get most recent course difficulty rating ###
|
@@ -105,16 +109,19 @@ Finding the most recent section's course difficulty rating is just as easy:
|
|
105
109
|
|
106
110
|
```ruby
|
107
111
|
require 'pcr.rb'
|
108
|
-
|
112
|
+
pcr = PCR.new(API_TOKEN)
|
113
|
+
course = pcr.course("PSCI-150")
|
109
114
|
puts course.recent("rDifficulty") #=> 2.5
|
110
115
|
```
|
111
116
|
|
112
117
|
### Get professor's average "ability to stimulate student interest" rating ###
|
113
118
|
```ruby
|
114
119
|
require 'pcr.rb'
|
115
|
-
|
120
|
+
pcr = PCR.new(API_TOKEN)
|
121
|
+
instructor = pcr.instructor("1090-LINDA-H-ZHAO")
|
116
122
|
puts instructor.average("rStimulateInterest").round(2) #=> 1.7
|
117
123
|
```
|
118
124
|
|
119
125
|
## TODO ##
|
126
|
+
* Implement stricter checks on course code arguments
|
120
127
|
* Implement search by professor last/first name rather than by ID. ID is unintuitive. Will probably need to see if I can make a lookup method, or simply pull down a database of all instructors and do a search on that database.
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#Add useful array methods
|
2
|
+
class Array
|
3
|
+
def binary_search(target)
|
4
|
+
self.search_iter(0, self.length-1, target)
|
5
|
+
end
|
6
|
+
|
7
|
+
def search_iter(lower, upper, target)
|
8
|
+
return -1 if lower > upper
|
9
|
+
mid = (lower+upper)/2
|
10
|
+
if (self[mid] == target)
|
11
|
+
mid
|
12
|
+
elsif (target < self[mid])
|
13
|
+
self.search_iter(lower, mid-1, target)
|
14
|
+
else
|
15
|
+
self.search_iter(mid+1, upper, target)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
#Course object matches up with the coursehistory request of the pcr api.
|
2
|
+
#A Course essentially is a signle curriculum and course code, and includes all Sections across time (semesters).
|
3
|
+
class Course < PCR
|
4
|
+
attr_accessor :course_code, :sections, :id, :name, :path, :reviews
|
5
|
+
|
6
|
+
def initialize(course_code)
|
7
|
+
if course_code.is_a? String and course_code.isValidCourseCode?
|
8
|
+
@course_code = course_code
|
9
|
+
|
10
|
+
#Read JSON from the PCR API
|
11
|
+
api_url = @@api_endpt + "coursehistories/" + self.course_code + "/?token=" + @@token
|
12
|
+
json = JSON.parse(open(api_url).read)
|
13
|
+
|
14
|
+
#Create array of Section objects, containing all Sections found in the API JSON for the Course
|
15
|
+
@sections = []
|
16
|
+
json["result"]["courses"].each do |c|
|
17
|
+
@sections << Section.new(c["id"])
|
18
|
+
end
|
19
|
+
|
20
|
+
#Set variables according to Course JSON data
|
21
|
+
@id = json["result"]["id"]
|
22
|
+
@name = json["result"]["name"]
|
23
|
+
@path = json["result"]["path"]
|
24
|
+
|
25
|
+
#Get reviews for the Course -- unfortunately this has to be a separate query
|
26
|
+
api_url_reviews = @@api_endpt + "coursehistories/" + self.id.to_s + "/reviews?token=" + @@token
|
27
|
+
json_reviews = JSON.parse(open(api_url_reviews).read)
|
28
|
+
@reviews = json_reviews["result"]["values"]
|
29
|
+
|
30
|
+
else
|
31
|
+
raise CourseError, "Invalid course code specified. Use format [DEPT-###]."
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def average(metric)
|
36
|
+
#Ensure that we know argument type
|
37
|
+
if metric.is_a? Symbol
|
38
|
+
metric = metric.to_s
|
39
|
+
end
|
40
|
+
|
41
|
+
if metric.is_a? String
|
42
|
+
#Loop vars
|
43
|
+
total = 0
|
44
|
+
n = 0
|
45
|
+
|
46
|
+
#For each section, check if ratings include metric arg -- if so, add metric rating to total and increment counting variable
|
47
|
+
self.reviews.each do |review|
|
48
|
+
ratings = review["ratings"]
|
49
|
+
if ratings.include? metric
|
50
|
+
total = total + review["ratings"][metric].to_f
|
51
|
+
n = n + 1
|
52
|
+
else
|
53
|
+
raise CourseError, "No ratings found for \"#{metric}\" in #{self.name}."
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
#Return average score as a float
|
58
|
+
(total/n)
|
59
|
+
|
60
|
+
else
|
61
|
+
raise CourseError, "Invalid metric format. Metric must be a string or symbol."
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def recent(metric)
|
66
|
+
#Ensure that we know argument type
|
67
|
+
if metric.is_a? Symbol
|
68
|
+
metric = metric.to_s
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
if metric.is_a? String
|
73
|
+
#Get the most recent section
|
74
|
+
section = self.sections[-1]
|
75
|
+
|
76
|
+
#Iterate through all the section reviews, and if the section review id matches the id of the most recent section, return that rating
|
77
|
+
self.reviews.each do |review|
|
78
|
+
if review["section"]["id"].to_s[0..4].to_i == section.id
|
79
|
+
return review["ratings"][metric]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
raise CourseError, "No ratings found for #{metric} in #{section.semester}."
|
84
|
+
|
85
|
+
else
|
86
|
+
raise CourseError, "Invalid metric format. Metric must be a string or symbol."
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
#Instructor is a professor. Instructors are not tied to a course or section, but will have to be referenced from Sections.
|
2
|
+
class Instructor < PCR
|
3
|
+
attr_accessor :id, :name, :path, :sections, :reviews
|
4
|
+
|
5
|
+
def initialize(id)
|
6
|
+
#Assign args. ID is necessary because that's how we look up Instructors in the PCR API.
|
7
|
+
if id.is_a? String
|
8
|
+
@id = id
|
9
|
+
else
|
10
|
+
raise InstructorError("Invalid Instructor ID specified.")
|
11
|
+
end
|
12
|
+
|
13
|
+
#Hit PCR API to get missing info based on id
|
14
|
+
self.getInfo
|
15
|
+
self.getReviews
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
#Hit the PCR API to get all missing info
|
20
|
+
#Separate method in case we want to conduct it separately from a class init
|
21
|
+
def getInfo
|
22
|
+
api_url = @@api_endpt + "instructors/" + self.id + "?token=" + @@token
|
23
|
+
json = JSON.parse(open(api_url).read)
|
24
|
+
|
25
|
+
@name = json["result"]["name"].downcase.titlecase unless @name
|
26
|
+
@path = json["result"]["path"] unless @path
|
27
|
+
@sections = json["result"]["reviews"]["values"] unless @sections #Mislabeled reviews in PCR API
|
28
|
+
end
|
29
|
+
|
30
|
+
#Separate method for getting review data in case we don't want to make an extra API hit each init
|
31
|
+
def getReviews
|
32
|
+
if not self.reviews #make sure we don't already have reviews
|
33
|
+
api_url = @@api_endpt + "instructors/" + self.id + "/reviews?token=" + @@token
|
34
|
+
json = JSON.parse(open(api_url).read)
|
35
|
+
|
36
|
+
@reviews = json["result"]["values"] #gets array
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
#Get average value of a certain rating for Instructor
|
41
|
+
def average(metric)
|
42
|
+
#Ensure that we know argument type
|
43
|
+
if metric.is_a? Symbol
|
44
|
+
metric = metric.to_s
|
45
|
+
end
|
46
|
+
|
47
|
+
if metric.is_a? String
|
48
|
+
#Loop vars
|
49
|
+
total = 0
|
50
|
+
n = 0
|
51
|
+
|
52
|
+
#For each section, check if ratings include metric arg -- if so, add metric rating to total and increment counting variable
|
53
|
+
self.getReviews
|
54
|
+
self.reviews.each do |review|
|
55
|
+
ratings = review["ratings"]
|
56
|
+
if ratings.include? metric
|
57
|
+
total = total + review["ratings"][metric].to_f
|
58
|
+
n = n + 1
|
59
|
+
else
|
60
|
+
raise CourseError, "No ratings found for \"#{metric}\" for #{self.name}."
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
#Return average score as a float
|
65
|
+
(total/n)
|
66
|
+
|
67
|
+
else
|
68
|
+
raise CourseError, "Invalid metric format. Metric must be a string or symbol."
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
#Get most recent value of a certain rating for Instructor
|
73
|
+
def recent(metric)
|
74
|
+
#Ensure that we know argument type
|
75
|
+
if metric.is_a? Symbol
|
76
|
+
metric = metric.to_s
|
77
|
+
end
|
78
|
+
|
79
|
+
if metric.is_a? String
|
80
|
+
#Iterate through reviews and create Section for each section reviewed, presented in an array
|
81
|
+
sections = []
|
82
|
+
section_ids = []
|
83
|
+
self.getReviews
|
84
|
+
self.reviews.each do |review|
|
85
|
+
if section_ids.index(review["section"]["id"].to_i).nil?
|
86
|
+
s = PCR::Section.new(review["section"]["id"].to_i, false)
|
87
|
+
sections << s
|
88
|
+
section_ids << s.id
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
#Get only most recent Section(s) in the array
|
93
|
+
sections.reverse! #Newest first
|
94
|
+
targets = []
|
95
|
+
sections.each do |s|
|
96
|
+
s.hit_api(:get_reviews => true)
|
97
|
+
if sections.index(s) == 0
|
98
|
+
targets << s
|
99
|
+
elsif s.semester == sections[0].semester and s.id != sections[0].id
|
100
|
+
targets << s
|
101
|
+
else
|
102
|
+
break
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
#Calculate recent rating
|
107
|
+
total = 0
|
108
|
+
num = 0
|
109
|
+
targets.each do |section|
|
110
|
+
#Make sure we get the rating for the right Instructor
|
111
|
+
section.ratings.each do |rating|
|
112
|
+
if rating.key?(self.id)
|
113
|
+
if rating[self.id][metric].nil?
|
114
|
+
raise InstructorError, "No ratings found for #{metric} for #{self.name}."
|
115
|
+
else
|
116
|
+
total = total + rating[self.id][metric].to_f
|
117
|
+
num += 1
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# Return recent rating
|
124
|
+
total / num
|
125
|
+
|
126
|
+
else
|
127
|
+
raise CourseError, "Invalid metric format. Metric must be a string or symbol."
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
#Section is an individual class under the umbrella of a general Course
|
2
|
+
class Section < PCR
|
3
|
+
attr_accessor :aliases, :id, :name, :path, :semester, :description, :comments, :ratings, :instructors, :reviews
|
4
|
+
|
5
|
+
def initialize(id, hit_api = true)
|
6
|
+
# Set instance vars
|
7
|
+
@id = id
|
8
|
+
|
9
|
+
# Hit api to fill additional info
|
10
|
+
self.hit_api() unless hit_api == false
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
def hit_api()
|
15
|
+
data = ["aliases", "name", "path", "semester", "description"]
|
16
|
+
api_url = @@api_endpt + "courses/" + self.id.to_s + "?token=" + @@token
|
17
|
+
json = JSON.parse(open(api_url).read)
|
18
|
+
|
19
|
+
data.each do |d|
|
20
|
+
case d
|
21
|
+
when "aliases"
|
22
|
+
self.instance_variable_set("@#{d}", json["result"]["aliases"])
|
23
|
+
when "name"
|
24
|
+
self.instance_variable_set("@#{d}", json["result"]["name"])
|
25
|
+
when "path"
|
26
|
+
self.instance_variable_set("@#{d}", json["result"]["path"])
|
27
|
+
when "semester"
|
28
|
+
self.instance_variable_set("@#{d}", json["result"]["semester"])
|
29
|
+
when "description"
|
30
|
+
self.instance_variable_set("@#{d}", json["result"]["description"])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Get review data
|
35
|
+
self.get_reviews
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_reviews()
|
40
|
+
api_url = @@api_endpt + "courses/" + self.id.to_s + "/reviews?token=" + @@token
|
41
|
+
json = JSON.parse(open(api_url).read)
|
42
|
+
@comments = []
|
43
|
+
@ratings = []
|
44
|
+
@instructors = []
|
45
|
+
json["result"]["values"].each do |a|
|
46
|
+
@comments << {a["instructor"]["id"] => a["comments"]}
|
47
|
+
@ratings << {a["instructor"]["id"] => a["ratings"]}
|
48
|
+
@instructors << a["instructor"]
|
49
|
+
end
|
50
|
+
@reviews = {"comments" => @comments, "ratings" => @ratings}
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
#Add some useful String methods
|
2
|
+
class ::String
|
3
|
+
#Checks if String is valid Penn course code format
|
4
|
+
def isValidCourseCode?
|
5
|
+
test = self.split('-')
|
6
|
+
if test[0].length == 4 and test[1].length == 3
|
7
|
+
true
|
8
|
+
else
|
9
|
+
false
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
#Methods to convert strings to titlecase.
|
14
|
+
#Thanks https://github.com/samsouder/titlecase
|
15
|
+
def titlecase
|
16
|
+
small_words = %w(a an and as at but by en for if in of on or the to v v. via vs vs.)
|
17
|
+
|
18
|
+
x = split(" ").map do |word|
|
19
|
+
# note: word could contain non-word characters!
|
20
|
+
# downcase all small_words, capitalize the rest
|
21
|
+
small_words.include?(word.gsub(/\W/, "").downcase) ? word.downcase! : word.smart_capitalize!
|
22
|
+
word
|
23
|
+
end
|
24
|
+
# capitalize first and last words
|
25
|
+
x.first.smart_capitalize!
|
26
|
+
x.last.smart_capitalize!
|
27
|
+
# small words after colons are capitalized
|
28
|
+
x.join(" ").gsub(/:\s?(\W*#{small_words.join("|")}\W*)\s/) { ": #{$1.smart_capitalize} " }
|
29
|
+
end
|
30
|
+
|
31
|
+
def smart_capitalize
|
32
|
+
# ignore any leading crazy characters and capitalize the first real character
|
33
|
+
if self =~ /^['"\(\[']*([a-z])/
|
34
|
+
i = index($1)
|
35
|
+
x = self[i,self.length]
|
36
|
+
# word with capitals and periods mid-word are left alone
|
37
|
+
self[i,1] = self[i,1].upcase unless x =~ /[A-Z]/ or x =~ /\.\w+/
|
38
|
+
end
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
def smart_capitalize!
|
43
|
+
replace(smart_capitalize)
|
44
|
+
end
|
45
|
+
|
46
|
+
#Method to compare semesters. Returns true if self is later, false if self is before, 0 if same
|
47
|
+
#s should be a string like "2009A"
|
48
|
+
def compareSemester(s)
|
49
|
+
year = self[0..3]
|
50
|
+
season = self[4]
|
51
|
+
compYear = s[0..3]
|
52
|
+
compSeason = s[4]
|
53
|
+
|
54
|
+
if year.to_i > compYear.to_i #Later year
|
55
|
+
return true
|
56
|
+
elsif year.to_i < compYear.to_i #Earlier year
|
57
|
+
return false
|
58
|
+
elsif year.to_i == compYear.to_i #Same year, so test season
|
59
|
+
if season > compSeason #Season is later
|
60
|
+
return true
|
61
|
+
elsif season = compSeason #Exact same time
|
62
|
+
return 0
|
63
|
+
elsif season < compSeason #compSeason is later
|
64
|
+
return false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/lib/pcr-ruby.rb
CHANGED
@@ -15,12 +15,12 @@ class PCR
|
|
15
15
|
Course.new(course_code)
|
16
16
|
end
|
17
17
|
|
18
|
-
def section(
|
19
|
-
Section.new(
|
18
|
+
def section(id, hit_api = true)
|
19
|
+
Section.new(id, hit_api)
|
20
20
|
end
|
21
21
|
|
22
|
-
def instructor(id
|
23
|
-
Instructor.new(id
|
22
|
+
def instructor(id)
|
23
|
+
Instructor.new(id)
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pcr-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.2'
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-10-
|
12
|
+
date: 2012-10-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: json
|
@@ -38,7 +38,14 @@ files:
|
|
38
38
|
- LICENSE
|
39
39
|
- README.md
|
40
40
|
- Rakefile
|
41
|
+
- lib/classes/array.rb
|
42
|
+
- lib/classes/course.rb
|
43
|
+
- lib/classes/errors.rb
|
44
|
+
- lib/classes/instructor.rb
|
45
|
+
- lib/classes/section.rb
|
46
|
+
- lib/classes/string.rb
|
41
47
|
- lib/pcr-ruby.rb
|
48
|
+
- lib/pcr-ruby/version.rb
|
42
49
|
- pcr-ruby.gemspec
|
43
50
|
homepage: ''
|
44
51
|
licenses: []
|