Skip to content

Instantly share code, notes, and snippets.

@sunaku
Last active August 29, 2015 14:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sunaku/276e7717bdf51998b3bb to your computer and use it in GitHub Desktop.
Save sunaku/276e7717bdf51998b3bb to your computer and use it in GitHub Desktop.
Dumps course prerequisites for the given SJSU (San Jose State University http://www.sjsu.edu/) degree program as a DOT (Graphviz http://www.graphviz.org/) graph. You can play with the resulting graph by pasting it into the Vis.js playground (http://visjs.org/examples/graph/15_dot_language_playground.html) or you can convert it into a PDF with cl…
#!/usr/bin/env ruby
#
# Usage: ruby sjsu-course-prereqs.rb [PROGRAM_INFO_URL]
#
# Dumps course prerequisites for the given SJSU degree program as a DOT graph.
# If no PROGRAM_INFO_URL is given, the M.S. Computer Science program is used:
#
# http://www.sjsu.edu/cs/programs/mscs/program-info/
#
# You can convert the graph into a PDF with clickable course links like this:
#
# ruby sjsu-course-prereqs.rb | dot -Tps2 | ps2pdf - output.pdf
#
# You can play with the graph by pasting it into the Vis.js playground here:
#
# http://visjs.org/examples/graph/15_dot_language_playground.html
#
# Written in 2014 by Suraj N. Kurapati <https://github.com/sunaku>
#
program_url = ARGV.shift || 'http://www.sjsu.edu/cs/programs/mscs/program-info/'
#-----------------------------------------------------------------------------
# list courses in degree program
#-----------------------------------------------------------------------------
require 'open-uri'
course_urls = open(program_url).read.scan(%r{"(.*?/courses/.*?)"}).flatten
course_url_prefix = File.dirname(course_urls.first)
courses = course_urls.map do |course_url|
File.basename(course_url, File.extname(course_url)).sub(/(?=\d)/, ' ')
end
#-----------------------------------------------------------------------------
# calculate course prerequisites
#-----------------------------------------------------------------------------
def prereqs_for_courses courses, url_prefix
Hash[
courses.map do |course|
course_url = url_for_course(course, url_prefix)
prereqs = (open(course_url).read[/Prereq.*/] rescue warn course_url)
.to_s.scan(/([A-Z]{2,} \d+\w*)/).flatten
[course, prereqs]
end
]
end
def url_for_course course, url_prefix
"#{url_prefix}/#{course.sub(/ /,'')}.html"
end
prereqs_by_course = {}
loop do
new_courses = courses - prereqs_by_course.keys
break if new_courses.empty?
prereqs_by_course.merge! prereqs_for_courses(new_courses, course_url_prefix)
courses = prereqs_by_course.to_a.flatten.uniq
end
#-----------------------------------------------------------------------------
# print prerequisites as a graph
#-----------------------------------------------------------------------------
graph = [
'digraph G {',
"graph [label=#{program_url.inspect}, labelloc=t];",
'node [fontcolor=blue];',
prereqs_by_course.flat_map do |course, prereqs|
course_url = url_for_course(course, course_url_prefix)
prereqs.map {|prereq| "#{course.inspect} -> #{prereq.inspect};" }
.unshift("#{course.inspect} [URL=#{course_url.inspect}];")
end.sort.join(?\n),
'}'
].join(?\n)
puts graph
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment