student_progress 0.1.2 → 0.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4d9dea94b9cd8654f0adc44aee02f20d47c2960550c225cdca11b83c83485d03
4
- data.tar.gz: d81aeaf2c9d5724ccb1f42ddc42b0c0fdd74716e734d580d9268c052b6f30ae0
3
+ metadata.gz: 429b3f920a6cba30aa9acc9f355dc9d9c68e1e2f1dc429b356645ccc0fcf4da3
4
+ data.tar.gz: 30097be3a7e0c598b58a52a04074499df3eeb49d243e099f8f04fc54de4d127c
5
5
  SHA512:
6
- metadata.gz: c52570801505fd77e3d6a3be41d9496f9307a538e811daa56c9f60a330e391ae6ce4872e2bd001bb2b13478130d496347217de541390f9b63f0081863327474a
7
- data.tar.gz: ee0dd4fc7f72210c1112405dc8f0d675236e04b7bf4637906c746e6a1cde7ed575cf38f86b3606289c6715679e0da681e599fdc93e6304a10eec957712cabf3e
6
+ metadata.gz: 46dd020fb09416d02df9a3d5ad11b92a8677da10a60a0d72d8f8173eb86f7b75268cbf8116344ae62977b12310d535b567136bbf467ced87d4161690a527b020
7
+ data.tar.gz: 65f7b13ade40d3a4ef3d4b159e34ed3efda6790162c8bea7a20c78f3859201e96a919bac16a04f9b6046dd784d2e063946d72d56141c74c4f91a1d18ab4733e6
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- student_progress (0.1.2)
4
+ student_progress (0.2.0)
5
5
  json
6
6
  nokogiri
7
7
  poltergeist
@@ -40,7 +40,7 @@ GEM
40
40
  method_source (~> 0.9.0)
41
41
  public_suffix (3.0.2)
42
42
  rack (2.0.5)
43
- rack-test (1.0.0)
43
+ rack-test (1.1.0)
44
44
  rack (>= 1.0, < 3)
45
45
  rake (10.5.0)
46
46
  rspec (3.7.0)
@@ -64,6 +64,29 @@ unless DB.table_exists? :students
64
64
  end
65
65
  end
66
66
 
67
+ unless DB.table_exists? :completed_lessons
68
+ DB.create_table :completed_lessons do
69
+ primary_key :id
70
+ Integer :lesson_id
71
+ end
72
+ end
73
+
74
+ unless DB[:completed_lessons].columns.include?(:date)
75
+ DB.add_column :completed_lessons, :date, :date
76
+ end
77
+
78
+ unless DB[:cohorts].columns.include?(:periscope_url)
79
+ DB.add_column :cohorts, :periscope_url, :string
80
+ end
81
+
82
+ unless DB[:completed_lessons].columns.include?(:student_id)
83
+ DB.add_column :completed_lessons, :student_id, :integer
84
+ end
85
+
86
+ unless DB[:student_reports].columns.include?(:current_topic_status)
87
+ DB.add_column :student_reports, :current_topic_status, :string
88
+ end
89
+
67
90
  require_relative "./student_progress/version"
68
91
  require_relative "./student_progress/cli"
69
92
  require_relative "./student_progress/student"
@@ -74,6 +97,8 @@ require_relative "./student_progress/topic"
74
97
  require_relative "./student_progress/unit"
75
98
  require_relative "./student_progress/student_report"
76
99
  require_relative "./student_progress/progress_report"
100
+ require_relative "./student_progress/progress_importer"
101
+ require_relative "./student_progress/completed_lesson"
77
102
 
78
103
 
79
104
  # module StudentProgress
@@ -1,7 +1,7 @@
1
1
  class StudentProgress::CLI
2
2
  def call
3
3
  puts "Hello from CLI"
4
- prompt_for_login
4
+ prompt_for_login
5
5
  StudentProgress::Scraper.scrape_lessons
6
6
  main_menu
7
7
  goodbye
@@ -14,7 +14,10 @@ class StudentProgress::CLI
14
14
  puts "\n"
15
15
  print "Password: "
16
16
  password = STDIN.noecho(&:gets).chomp
17
- StudentProgress::Scraper.login_user(email, password)
17
+ unless StudentProgress::Scraper.login_user(email, password)
18
+ prompt_for_login
19
+ end
20
+ true
18
21
  end
19
22
 
20
23
  def main_menu
@@ -48,7 +51,7 @@ class StudentProgress::CLI
48
51
 
49
52
  def list_choices
50
53
  puts "Choose an option below by number"
51
- puts "1. Select Cohort"
54
+ puts "1. Manage Cohorts"
52
55
  puts "2. Add Cohort"
53
56
  puts "3. Set goal for the week"
54
57
  puts "4. To view a list of past reports"
@@ -72,11 +75,86 @@ class StudentProgress::CLI
72
75
  puts "Whoops! Didn't understand that input"
73
76
  end
74
77
  end
75
- display_students
78
+ show_options_for_cohort
79
+ end
80
+
81
+ def show_options_for_cohort
82
+ puts "What would you like to do with the cohort?"
83
+ puts "1. Create Progress Report"
84
+ puts "2. Add a member(s) to the cohort"
85
+ puts "3. Remove a member from the cohort"
86
+ puts "4. Add a periscope URL to scrape progress from"
87
+ puts "5. Delete this cohort"
88
+ puts "type 'back' to return to the main menu or 'exit' to exit the CLI"
89
+ @input = gets.strip.downcase
90
+ return if ["back", "exit"].include?(@input)
91
+ case @input.to_i
92
+ when 1
93
+ display_students
94
+ when 2
95
+ add_students_to_cohort_view
96
+ when 3
97
+ remove_students_from_cohort_view
98
+ when 4
99
+ add_periscope_link_for_cohort_data
100
+ when 5
101
+ delete_this_cohort_view
102
+ else
103
+ puts "Whoops! didn't understand that input"
104
+ show_options_for_cohort
105
+ end
106
+ end
107
+
108
+ def add_students_to_cohort_view
109
+ puts "Enter the github usernames of the students you'd like to add as a comma separated list"
110
+ @input = gets.strip
111
+ return if ["back", "exit"].include?(@input.downcase)
112
+ usernames = @input.chomp.split(',').map(&:strip)
113
+ @selected_cohort.add_students(usernames)
114
+ puts "Just added #{usernames.count} students to your cohort"
115
+ puts "#{@selected_cohort.name} now has #{@selected_cohort.students.count} students"
116
+ show_options_for_cohort
76
117
  end
77
118
 
78
- def prompt_for_cohort_by_number
119
+ def remove_students_from_cohort_view
120
+ puts "Enter the github usernames of the students you'd like to remove as a comma separated list"
121
+ puts "Current usernames:"
122
+ puts @selected_cohort.students.collect{|s| s.github_username}.join(', ')
123
+ @input = gets.strip
124
+ return if ["back", "exit"].include?(@input.downcase)
125
+ usernames = @input.chomp.split(',').map(&:strip)
126
+ removed = @selected_cohort.remove_students(usernames)
127
+ puts "Just removed #{removed} students from the cohort"
128
+ puts "#{@selected_cohort.name} now has #{@selected_cohort.students.count} students"
129
+ show_options_for_cohort
130
+ end
131
+
132
+ def add_periscope_link_for_cohort_data
133
+ puts "Paste in the link to the periscope doc you'd like to use to import Cohort progress"
134
+ @input = gets.strip
135
+ @selected_cohort.periscope_url = @input
136
+ @selected_cohort.save
137
+ puts "Successfully added the periscope url to #{@selected_cohort.name}"
138
+ end
79
139
 
140
+ def delete_this_cohort_view
141
+ puts "Are you sure you want to delete the #{@selected_cohort.name} cohort?"
142
+ puts "type 'yes' to confirm or 'no' to go back to the cohort menu"
143
+ puts "You can also type 'back' to return to the main menu, or 'exit' to exit the CLI"
144
+ @input = gets.strip
145
+ return if ["back", "exit"].include?(@input.downcase)
146
+ case @input.downcase
147
+ when 'yes'
148
+ @selected_cohort.delete_and_unassign_students
149
+ @selected_cohort = nil
150
+ puts "cohort successfully deleted"
151
+ list_choices
152
+ when 'no'
153
+ show_options_for_cohort
154
+ else
155
+ puts "Whoops! Didn't understand that."
156
+ delete_this_cohort_view
157
+ end
80
158
  end
81
159
 
82
160
  def prompt_for_cohort_name
@@ -88,7 +166,7 @@ class StudentProgress::CLI
88
166
 
89
167
  def prompt_for_usernames
90
168
  puts "Please enter the GitHub usernames for the students you'd like info about (separated by commas)"
91
- usernames = gets.chomp.split(',').map(&:strip)
169
+ usernames = gets.chomp.split(',').map(&:strip).map(&:downcase)
92
170
  puts "Hang on a sec, adding #{usernames.count} students"
93
171
  @new_cohort.add_students(usernames)
94
172
  puts "All done!"
@@ -139,10 +217,11 @@ class StudentProgress::CLI
139
217
  output << "Students should #{@goal[:goal]} by the end of the week"
140
218
  output << "To do that, they'll have completed #{@goal[:lessons]} lessons and #{@goal[:labs]} labs"
141
219
  end
142
- headers = ['Student Name', 'Current Lab', 'Lessons', 'Labs']
220
+ headers = ['Student Name', 'Current Lab', 'Current Topic', 'Lessons', 'Labs']
143
221
  report = @selected_cohort.progress_reports.last
144
222
  rows = report.student_reports.collect.with_index(1) do |student_report|
145
- [student_report.student_name, student_report.current_lab, student_report.lessons_complete, student_report.labs_complete]
223
+ student_report.generate_current_topic_status
224
+ [student_report.student_name, student_report.current_lab, student_report.current_topic_status, student_report.lessons_complete, student_report.labs_complete]
146
225
  end
147
226
  table = Terminal::Table.new headings: headers, rows: rows
148
227
  output << table
@@ -3,10 +3,34 @@ class StudentProgress::Cohort < Sequel::Model
3
3
  one_to_many :progress_reports
4
4
  def add_students(usernames)
5
5
  usernames.each do |username|
6
- student = StudentProgress::Student.find_or_create(github_username: username)
7
- student.cohort_id = self.id
6
+ student = StudentProgress::Student.find_or_create(github_username: username.downcase)
7
+ self.add_student(student)
8
8
  student.save
9
9
  end
10
+ self.save
11
+ end
12
+
13
+ def remove_students(usernames)
14
+ removed = 0
15
+ usernames.each do |username|
16
+ student = self.students_dataset.first(github_username: username.downcase)
17
+ if student
18
+ self.remove_student(student)
19
+ removed += 1
20
+ else
21
+ puts "Student with github username: #{username} not found."
22
+ end
23
+ end
24
+ self.save
25
+ removed
26
+ end
27
+
28
+ def delete_and_unassign_students
29
+ students.each do |student|
30
+ student.cohort_id = nil
31
+ student.save
32
+ end
33
+ self.delete
10
34
  end
11
35
 
12
36
  def run_progress_report
@@ -0,0 +1,3 @@
1
+ class StudentProgress::CompletedLesson < Sequel::Model
2
+ many_to_one :student
3
+ end
@@ -53,6 +53,12 @@ class StudentProgress::Lesson
53
53
  lesson ? lesson.unit.title : "couldn't find that lesson"
54
54
  end
55
55
 
56
+ def self.topic_from_lesson_title(lesson_title)
57
+ lesson = @@all.find{ |l| l.title.strip == lesson_title.strip}
58
+ binding.pry unless lesson
59
+ lesson ? lesson.unit.topic : "couldn't find that lesson"
60
+ end
61
+
56
62
  def self.progress_when_unit_complete(unit_title)
57
63
  lessons = 0
58
64
  labs = 0
@@ -0,0 +1,42 @@
1
+ class StudentProgress::ProgressImporter
2
+ require 'csv'
3
+ require 'open-uri'
4
+
5
+ def self.import(url)
6
+ options = { headers: true, header_converters: :symbol }
7
+
8
+
9
+ csv_file = open(url)
10
+ content = File.new(csv_file)
11
+ CSV.foreach(content, options, &method(:create_and_associate_progress))
12
+
13
+ nil
14
+ end
15
+
16
+ def self.create_and_associate_progress(row)
17
+ # Example Row:
18
+ #<CSV::Row
19
+ # first_name:"Brennan"
20
+ # last_name:"Fulmer"
21
+ # deprecated_github_username:"BrennanFulmer"
22
+ # curriculum_id:"31648"
23
+ # completed_at:"2018-07-26 19:12:46.353279"
24
+ # track_id:"31303"
25
+ # title:"Rails Static Request"
26
+ # >
27
+ student = StudentProgress::Student.first(github_username: row[:deprecated_github_username].downcase)
28
+ lesson = StudentProgress::Lesson.find_by_id(row[:curriculum_id].to_i)
29
+ if student && lesson
30
+ if completed = StudentProgress::CompletedLesson.first(student_id: student.id, lesson_id: lesson.id)
31
+ return
32
+ else
33
+ completed = StudentProgress::CompletedLesson.create(student_id: student.id, lesson_id: lesson.id)
34
+ completed.date = row[:completed_at]
35
+ completed.save
36
+ end
37
+ else
38
+ binding.pry
39
+ end
40
+
41
+ end
42
+ end
@@ -1,5 +1,6 @@
1
1
  class StudentProgress::ProgressReport < Sequel::Model
2
2
  one_to_many :student_reports
3
+ many_to_one :cohort
3
4
 
4
5
  def on_track(labs_goal, cohort=nil)
5
6
  result = {}
@@ -14,4 +15,10 @@ class StudentProgress::ProgressReport < Sequel::Model
14
15
  end
15
16
  result
16
17
  end
18
+
19
+ def import_progress_from_periscope
20
+ if self.cohort.periscope_url
21
+ StudentProgress::ProgressImporter.import(self.cohort.periscope_url)
22
+ end
23
+ end
17
24
  end
@@ -9,7 +9,7 @@ class StudentProgress::Scraper
9
9
  end.each.with_index(1) do |username, index|
10
10
  @@session.visit("https://learn.co/#{username}")
11
11
  student = StudentProgress::Student.find_or_create(
12
- github_username: username
12
+ github_username: username.downcase
13
13
  )
14
14
  student.first_name = @@session.first('.media-block__content--fill').text.split("\n").first.split(' ').first
15
15
  student.last_name = @@session.first('.media-block__content--fill').text.split("\n").first.split(' ').slice(1)
@@ -22,9 +22,11 @@ class StudentProgress::Scraper
22
22
  student_id: student.id,
23
23
  progress_report_id: report.id
24
24
  )
25
-
26
25
  print "#{index}.."
27
26
  end
27
+ if cohort.periscope_url
28
+ StudentProgress::ProgressImporter.import(cohort.periscope_url)
29
+ end
28
30
  puts "Done!"
29
31
  end
30
32
 
@@ -37,6 +39,13 @@ class StudentProgress::Scraper
37
39
  puts "Signing in now..."
38
40
  sleep 0.5
39
41
  @@session.click_button "Sign in"
42
+ if @@session.current_path == "/account_check/failure" || @@session.current_path == "/"
43
+ puts "Invalid email or password"
44
+ puts "\n"
45
+ false
46
+ else
47
+ true
48
+ end
40
49
  end
41
50
 
42
51
  def self.scrape_lessons
@@ -1,6 +1,7 @@
1
1
  class StudentProgress::Student < Sequel::Model
2
2
  many_to_one :cohort
3
3
  one_to_many :student_reports
4
+ one_to_many :completed_lessons
4
5
 
5
6
  def current_lab
6
7
  student_reports.last.current_lab
@@ -5,4 +5,14 @@ class StudentProgress::StudentReport < Sequel::Model
5
5
  def student_name
6
6
  self.student && self.student.full_name
7
7
  end
8
+
9
+ def generate_current_topic_status
10
+ topic = StudentProgress::Lesson.topic_from_lesson_title(student.current_lab)
11
+ ratio = (topic.lessons.map(&:id) & student.completed_lessons.map(&:lesson_id)).length/topic.lessons.count.to_f
12
+ percent = (ratio*100).round(2)
13
+ status = student.cohort.periscope_url ? "#{topic.title}: #{percent}% complete" : "to track this, add perisocpe url to cohort"
14
+ self.current_topic_status = status
15
+ self.save
16
+ status
17
+ end
8
18
  end
@@ -1,3 +1,3 @@
1
1
  module StudentProgress
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: student_progress
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dakota Martinez
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-07-21 00:00:00.000000000 Z
11
+ date: 2018-07-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -187,7 +187,9 @@ files:
187
187
  - lib/student_progress.rb
188
188
  - lib/student_progress/cli.rb
189
189
  - lib/student_progress/cohort.rb
190
+ - lib/student_progress/completed_lesson.rb
190
191
  - lib/student_progress/lesson.rb
192
+ - lib/student_progress/progress_importer.rb
191
193
  - lib/student_progress/progress_report.rb
192
194
  - lib/student_progress/scraper.rb
193
195
  - lib/student_progress/student.rb