#!/usr/bin/perl use CGI; $query = new CGI; print "Content-type: text/html\n\n"; $query->import_names('R'); @lines = split /\r?\n/, $R::text; $resolution = $R::res; $hour24 = $R::tfhour; #$FILE = 'input.txt'; #$resolution = 1; # 1 = hour, 2 = half hour #$hour24 = 0; # 0 = 12 hour, 1 = 24 hour format @course_lines; # used for separating lines @courses; # used for parsed info @colors = ( '#ccbbff', '#ccffff', '#ffbb66', '#ffcccc', '#ccffaa', '#ddffff', '#ffffcc', '#dddddd', ); # Split into list of (list of lines) outer list is of course # Inner list is of each line of input assoc'd with a course # #open FP, "<$FILE"; @buf = (); for (@lines){ #while(){ # chomp; # s/^(.*)\r\n$/\1/; # s/^(.*)\n$/\1/; push @buf, $_; if(/nrolled/){ @buf2 = splice @buf, -2; if($was_dropped == 0){ push @course_lines, [@buf]; } $was_dropped = 0; @buf = @buf2; }elsif(/ropped/){ @buf2 = splice @buf, -2; if($was_dropped == 0){ push @course_lines, [@buf]; } $was_dropped = 1; @buf = @buf2; } } if($was_dropped == 0){ # add in the last one push @course_lines, [@buf]; } close FP; shift @course_lines; # remove first one since it's always blank # Process each course and turn them into hashes # $color_index = 0; %course_info; for $aref (@course_lines){ # The number of lines is 2-??? # If there are two instructors, then the second # instructor is on the third line. # @first_line_items = split /\t/, $$aref[0]; $course_info{'name'} = $first_line_items[1]; $course_info{'color'} = $colors[$color_index++]; $course_info{'name'} =~ s/\s*$//; $course_info{'title'} = $first_line_items[2]; @second_line_items = split /\t/, $$aref[1]; if($#second_line_items > 3){ # There's only one instructor # the new REGIS has a space between these two, not a tab # Thanks to Mike Huynh for pointing this out $section_and_prof = $second_line_items[2]; $section_and_prof =~ /(\S+)\s(.+)/; $course_info{'section'} = $1; $course_info{'prof'} = $2; if($#second_line_items > 4){ # There's only one meeting time $course_info{'times'} = $second_line_items[3]; $course_info{'loc'} = $second_line_items[4]; }else{ # There's more than one meeting time, each with it's own location $course_info{'times'} = $second_line_items[3]; $course_info{'loc'} = ''; for $cur_line (2..$#$aref){ @cur_line_items = split /\t/, $$aref[$cur_line]; if($#cur_line_items == 0){ # only one thing, a time or location if($cur_line_items[0] =~ /^[MTWRF]+ /){ # it's a time $course_info{'times'} .= "~$cur_line_items[0]"; }else{ $course_info{'loc'} .= "~$cur_line_items[0]"; } }elsif($#cur_line_items == 1){ # a time and a location $course_info{'times'} .= "~$cur_line_items[0]"; $course_info{'loc'} .= "~$cur_line_items[1]"; }else{ # a location, graded/PF, units $course_info{'loc'} .= "~$cur_line_items[0]"; } } } }else{ # more than one instructor, could be more than 2 } $course_info{'loc'} =~ s/^~(.*)$/\1/; push @courses, {%course_info}; } # For debugging #for $href (@courses){ # for $key ( keys %$href ){ # print "$key = $href->{$key}\n"; # } # print "\n"; #} %day_periods; # stores periods of time for each day $min_time = 2400; $max_time = 0; for $course (@courses){ @times_list = split /~/, $$course{'times'}; @locs_list = split /~/, $course->{'loc'}; $time_index = 0; for $times (@times_list){ $times =~ /(OM,)?([MTWRF]+) (.+) ?/; $days = $2; $hours = $3; @days_list = split //, $days; $hours =~ s/://g; @hours_list = split /[- ]/, $hours; undef %period; $period{'course'} = $course; $period{'start'} = $hours_list[0]; $period{'end'} = $hours_list[1]; if($time_index > 0){ $period{'section'} = $course->{'section'}; } $period{'loc'} = $locs_list[$time_index++]; if($min_time > int($hours_list[0])){ $min_time = int($hours_list[0]); } if($max_time < int($hours_list[1])){ $max_time = int($hours_list[1]); } for $day (@days_list){ $list_of_periods = $day_periods{$day}; push @{$list_of_periods}, {%period}; @{$day_periods{$day}} = @{$list_of_periods}; } } } sub print_text{ for $day (keys %day_periods){ @list_of_periods = @{$day_periods{$day}}; for $i (0..$#{$day_periods{$day}}){ print "$day_periods{$day}[$i]{'course'}{'name'} on $day, from $day_periods{$day}[$i]{'start'} to $day_periods{$day}[$i]{'end'}\n"; } } } #Time rounding: # round to nearest "hundred", where 30/resolution is the halfway point # hour resolution: # 315 = 3:15 -> 400 if it's an end time, 300 if it's a start time # 345 = 3:45 -> 400 if it's an end time, 300 if it's a start time # half-hour resolution: # -> 350 if it's an end time, 300 if it's a start time # -> 400 if it's an end time, 350 if it's a start time # # updown = 0 for round up, 1 for round down sub round_time{ $time = shift; $updown = shift; if($resolution == 1){ $factor = 100; }elsif($resolution == 2){ $factor = 30; }else{ $factor = 100; } $upper_digits = int($time / 100) * 100; $lower_digits = $time - $upper_digits - int(($time - int($time / 100) * 100) / $factor) * $factor; $upper_digits += int(($time - int($time / 100) * 100) / $factor) * 100/$resolution ; # not actually upper, just floor-ish # print "U: $upper_digits, L: $lower_digits\n"; if($updown == 1){ # round down the lower digits return $upper_digits + int($lower_digits / $factor) * (100/$resolution); }else{ return $upper_digits + int($lower_digits / $factor + 0.9999) * (100/$resolution); } } # At end, turn it into a table row offset: # $converted time = / (100/resolution) - $converted_min_time sub convert_time_offset{ $time = shift; $startend = shift; # 1 = start, 0 = end return ((round_time($time, $startend)-round_time($min_time, 1)) / (100/$resolution)); } sub unconvert_offset{ $o = shift; # number of time units per hour = resolution $number_of_hours = int($o / $resolution); $number_of_units = $o - $number_of_hours * $resolution; $rounded_min_time = round_time($min_time, 1); $unconverted_base_hundred = $rounded_min_time + $number_of_hours * 100 + 100/$resolution * $number_of_units; $hours = int($unconverted_base_hundred / 100) * 100; $nonhundred = $unconverted_base_hundred - $hours; $minutes = $nonhundred / (100/$resolution) * (60/$resolution); $hours /= 100; $append = ''; if($hour24 == 0){ if($hours > 12){ $hours -= 12; $append = ' PM'; } else{ $append = ' AM'; } } $retstr = "$hours:"; if($minutes < 10){ $retstr .= '0'; } $retstr .= $minutes.$append; return $retstr; } sub print_header{ print "\n\n Schedule\n\n"; print ' '; print "\n"; } sub print_footer{ print "\n\n"; } sub main_print{ print ''; $num_rows = convert_time_offset($max_time, 0); %skip_array = ('M' => 0, 'T' => 0, 'W' => 0, 'R' => 0, 'F' => 0); # rows to skip for each M T W R F for $row (0..$num_rows-1){ print ''; for $day (qw(M T W R F)){ $printed_something = 0; if($skip_array{$day} > 0){ --$skip_array{$day}; next; } for $i (0..$#{$day_periods{$day}}){ if(convert_time_offset($day_periods{$day}[$i]{'start'}, 1) <= $row && convert_time_offset($day_periods{$day}[$i]{'end'}, 0) > $row){ $skip_array{$day} = convert_time_offset($day_periods{$day}[$i]{'end'}, 0) - $row - 1; print ''; $printed_something = 1; last; } } if($printed_something == 0){ print ''; } } print "\n"; } print '
Monday Tuesday Wednesday Thursday Friday
'; print unconvert_offset($row).' - '.unconvert_offset($row+1); print ' 0){ print ' rowspan="',$skip_array{$day}+1,'">'; } else{ print '>'; } print '',$day_periods{$day}[$i]{'course'}{'name'}, '
'; print $day_periods{$day}[$i]{'loc'}, '
'; if($day_periods{$day}[$i]{'section'}){ print 'Section ', $day_periods{$day}[$i]{'section'}; }else{ print 'Prof. ', $day_periods{$day}[$i]{'course'}{'prof'}; } print '

'; } print_header(); main_print(); print_footer();