seeds.rb 4 KB
Newer Older
Zac Wood's avatar
Zac Wood committed
1
2
# This file should contain all the record creation needed to seed the database with its default values.
# The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup).
3

Zac Wood's avatar
Zac Wood committed
4
require_relative 'patriot_web_parser'
5
require_relative 'courses_loader'
Zac Wood's avatar
Zac Wood committed
6
7
8
9
require 'thwait'
require 'httparty'
require 'nokogiri'
require 'json'
10
require 'set'
11
require 'yaml/store'
Zac Wood's avatar
Zac Wood committed
12

13
14
def parse_courses(subjects)
  courses = []
Zac Wood's avatar
Zac Wood committed
15

16
17
18
19
20
21
22
  threads = subjects.map do |subject|
    Thread.new do
      courses.push(*get_courses(subject.downcase))
    end
  end

  ThreadsWait.all_waits(*threads)
Zac Wood's avatar
Zac Wood committed
23

24
25
  courses
end
Zac Wood's avatar
Zac Wood committed
26

27
def load_courses(courses)
28
29
30
31
32
33
34
  insert_hashes = courses.map do |course|
    {
      subject: course[:subject],
      title: course[:title],
      course_number: course[:course_number],
      credits: course[:credits],
      description: course[:description],
35
      prereqs: course[:prereqs],
36
    }
37
  end
38

39
  insert_hashes.each { |c| Course.find_or_create_by!(c) }
Zac Wood's avatar
Zac Wood committed
40
41
end

42
def parse_sections(semester, subjects)
43
44
45
46
47
  parser = PatriotWeb::Parser.new
  sections_in = {}

  threads = subjects.map do |subject|
    Thread.new do
48
      sections_in[subject] = parser.parse_courses_in_subject(semester, subject)
49
50
51
    end
  end

52
  ThreadsWait.all_waits(*threads)
53

54
55
  sections_in
end
56

57
58
59
60
61
62
63
64
65
66
67
def load_sections(sections_in, semester)
  sections_in.each do |subject, sections|
    all_sections = []

    sections.each do |section|
      if section.nil? || !section.key?(:subj) || !section.key?(:course_number)
        puts "#{subject} failed section: #{section.class}"
        next
      end

      course = Course.find_or_create_by!(subject: section[:subj],
68
                                         course_number: section[:course_number])
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

      instructor = Instructor.find_or_create_by!(name: section[:instructor])

      section_name = "#{section[:subj]} #{section[:course_number]} #{section[:section]}"

      all_sections.push(name: section_name,
                        crn: section[:crn],
                        section_type: section[:type],
                        title: section[:title],
                        start_date: section[:start_date],
                        end_date: section[:end_date],
                        days: section[:days],
                        start_time: section[:start_time],
                        end_time: section[:end_time],
                        location: section[:location],
                        course: course,
85
86
                        instructor: instructor,
                        semester: semester)
87
    end
Zac Wood's avatar
Zac Wood committed
88

89
    all_sections.each { |s| CourseSection.find_or_create_by! s }
Zac Wood's avatar
Zac Wood committed
90
  end
91
92
93
94
95
96
97
98
99
end

def wipe_db
  Closure.delete_all
  CourseSection.delete_all
  Course.delete_all
  Semester.delete_all
end

100
def load_closures
Zac Wood's avatar
Zac Wood committed
101
102
103
104
105
106
107
108
109
  semesters = YAML.load_file("db/closures.yaml")
  semesters.each do |semester, dates|
    season, year = semester.split
    s = Semester.find_by(season: season, year: year)
    next if s.nil?
    dates.each do |date|
      Closure.create!(date: Date.strptime(date, "%Y-%m-%d"), semester: s)
    end
  end
110
111
112
end

def main
113
  # wipe_db
114
115

  parser = PatriotWeb::Parser.new
116
117

  semesters = if ARGV.first == "update"
Zac Wood's avatar
clean    
Zac Wood committed
118
                [parser.parse_semesters.first]
119
120
              else
                # expand to include however many semesters you want
Zac Wood's avatar
Zac Wood committed
121
                parser.parse_semesters[1..7]
122
123
              end

124
  puts "\tParsing subjects..."
125
  subjects = [].to_set
Zac Wood's avatar
clean    
Zac Wood committed
126
127
  # merge all of the subjects
  semesters.each { |s| subjects.merge(parser.parse_subjects(s[:value])) }
128
  subjects = subjects.to_a
129
130
131
132
133
134

  puts "\tParsing courses from catalog.gmu.edu..."
  courses = parse_courses(subjects) if courses.nil?

  puts "\tLoading courses..."
  load_courses(courses)
Zac Wood's avatar
Zac Wood committed
135

136
137
  semesters.each do |semester|
    puts "#{semester[:season]} #{semester[:year]}"
138
    db_semester = Semester.find_or_create_by!(season: semester[:season], year: semester[:year])
139

140
141
    puts "\tParsing sections from Patriot Web..."
    sections_in = parse_sections(semester[:value], subjects)
142

143
144
145
    puts "\tLoading sections..."
    load_sections(sections_in, db_semester)
  end
Zac Wood's avatar
Zac Wood committed
146

147
  load_closures
Zac Wood's avatar
Zac Wood committed
148
end
Zac Wood's avatar
Zac Wood committed
149

150
main