seeds.rb 4.22 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 10
require 'thwait'
require 'httparty'
require 'nokogiri'
require 'json'

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

14 15 16 17 18 19 20
  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
21

22 23
  courses
end
Zac Wood's avatar
Zac Wood committed
24

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

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

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

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

50
  ThreadsWait.all_waits(*threads)
51

52 53
  sections_in
end
54

55 56 57 58 59 60 61 62 63 64 65
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],
66
                                         course_number: section[:course_number])
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82

      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,
83 84
                        instructor: instructor,
                        semester: semester)
85
    end
Zac Wood's avatar
Zac Wood committed
86

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

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

98
def load_closures
99 100
  # create closures for the days there will be no classes
  # see: https://registrar.gmu.edu/calendars/fall-2018/
101 102 103 104 105 106 107
  # fall2018 = Semester.find_by(season: 'Fall', year: '2018')
  # Closure.create! date: Date.new(2018, 9, 3), semester: fall2018
  # Closure.create! date: Date.new(2018, 10, 8), semester: fall2018
  # (21..25).each { |n| Closure.create! date: Date.new(2018, 11, n), semester: fall2018 }
  # (10..19).each { |n| Closure.create! date: Date.new(2018, 12, n), semester: fall2018 }
  spring2019 = Semester.find_by(season: 'Spring', year: '2019')
  (11..17).each { |day| Closure.find_or_create_by! date: Date.new(2019, 3, day), semester: spring2019 }
108 109 110
end

def main
111
  # wipe_db
112 113

  parser = PatriotWeb::Parser.new
114 115 116 117 118

  semesters = if ARGV.first == "update"
                [parser.parse_semesters.first]
              else
                # expand to include however many semesters you want
Zac Wood's avatar
Zac Wood committed
119
                parser.parse_semesters[0..6]
120 121
              end

Zac Wood's avatar
oops  
Zac Wood committed
122

123 124 125 126 127 128 129 130 131
  puts "\tParsing subjects..."
  subjects = parser.parse_subjects(semesters.first[:value])

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

  puts "\tLoading courses..."
  load_courses(courses)
  
132 133
  semesters.each do |semester|
    puts "#{semester[:season]} #{semester[:year]}"
134
    db_semester = Semester.find_or_create_by!(season: semester[:season], year: semester[:year])
135

136 137
    puts "\tParsing sections from Patriot Web..."
    sections_in = parse_sections(semester[:value], subjects)
138

139 140 141
    puts "\tLoading sections..."
    load_sections(sections_in, db_semester)
  end
Zac Wood's avatar
Zac Wood committed
142

143
  load_closures
Zac Wood's avatar
Zac Wood committed
144
end
Zac Wood's avatar
Zac Wood committed
145

146
main