# Lib Schedule # Functions: # findDayInCycle - IN: date OUT: an integer for DayInCycle # fillDate - IN: isodate(1-1-2005) OUT: full isodate (01-01-2005) # findFutureClass - find a future class (subjsec) # IN - date, subjsec, classtimes, # RETURN - period, date. # prTeacherTimetable - IN: term,subjectref(ref to subjsec array) # - prints timetable. # mkTimetable #----------------- sub findDayInCycle { #----------------- use Date::Business; use Time::JulianDay; my $givendate = fillDate( shift ); # Passed a date to find day in cycle. # If database handle not available, look for passed value... if (not $dbh) { $dbh = shift; } # Check if given date is a non cycle day. If so return 0. my $sth = $dbh->prepare("select count(id) from dates where dayincycle = 'N' and to_days(date) = to_days('$givendate')"); $sth->execute; if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr; } if (my $count = $sth->fetchrow){ return 0; } # Check for Resets my ($resetdate, $resetvalue); # Check for starting value... first day of classes. my $startdate = fillDate($schoolstart); my $continueFlag = 1; while ($continueFlag) { # Check if given date is a non cycle day. If so return 0. my $sth = $dbh->prepare("select count(id) from dates where dayincycle = 'N' and to_days(date) = to_days('$startdate')"); $sth->execute; if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr; } if (my $count = $sth->fetchrow){ # bump the date and try again... my ($yr, $mo, $da) = split /-/,$startdate; my $jd = julian_day($yr, $mo,$da); $jd++; ($yr, $mo, $da) = inverse_julian_day($jd); $startdate = fillDate("$yr-$mo-$da"); } else { $continueFlag = 0; } } #print "Start Date: $startdate
\n"; # Now use the $startdate value as Day 1 $resetdate = $startdate; $resetvalue = 1; $resetdatejd = julian_day(split /-/,$resetdate); $givendatejd = julian_day( split /-/,$givendate); foreach my $rdate (keys %resetDate){ $rdatejd = julian_day(split /-/,$rdate); if ($rdatejd > $resetdatejd and $rdatejd <= $givendatejd){ $resetdate = $rdate; $resetvalue = $resetDate{$resetdate}; } } #print "
Reset Date: $resetdate Reset Value: $resetvalue
\n"; my $tmpgivendate = $givendate; my $tmpresetdate = $resetdate; $tmpgivendate =~ s/-//g; $tmpresetdate =~ s/-//g; my $givendateobj = new Date::Business(DATE => $tmpgivendate); my $resetdateobj = new Date::Business(DATE => $tmpresetdate); $givenoffset = $givendateobj->diffb($resetdateobj,'prev','next'); #print "GivenOffset: $givenoffset\n"; my $count; # remove any non DayInCycle days $sth = $dbh->prepare("select count(id) from dates where dayincycle = 'N' and to_days(date) > to_days('$resetdate') and to_days(date) <= to_days('$givendate')"); $sth->execute; if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr; } $count = $sth->fetchrow; my $daysBetween = $givenoffset - $count; #print "Count: $count daysBetween: $daysBetween\n"; # Now use mod function to get remainder. if (not $daysPerCycle){ print "daysPerCycle variable not defined in admin.conf!"; die; } my $remainder = $daysBetween % $daysPerCycle; #print "Days Between: $daysBetween Remainder: $remainder "; #print "daysPerCycle: $daysPerCycle
\n"; $remainder += $resetvalue; if ($remainder > $daysPerCycle){ $remainder = $remainder % $daysPerCycle; } return $remainder; } # End of findDayInCycle #----------- sub fillDate { # Fill in date values of form: 2006-1-1 into 2006-01-01 #----------- my $fulldate = shift; my ($year, $month, $day) = split /-/,$fulldate; if (length($month) == 1){ $month = '0'.$month;} if (length($day) == 1){ $day = '0'.$day;} return "$year-$month-$day"; } #------------------ sub findFutureClass { #------------------ # passed startdate, startperiod, userid, term, subjsec, $skipclasses # return futuredate (fdate), fperiod(fperiod) my ($startdate, $startperiod, $userid, $term, $subjsec, $skipclasses) = @_; my $subjref = &mkTimetable($userid, $term); my $days = $#{$subjref}; my $periods = $#{$subjref->[1]}; my $day = &findDayInCycle($startdate); # Loops to construct array of periods, @slots for my $d (1..$days) { for my $p (1..$periods){ #print "Sub: ${$subjref}[$p][$d]Subjsec: $subjsec\n"; if (${$subjref}[$p][$d] eq $subjsec){ push @slots, "$d:$p"; } #print "$d:$p ${$subjref}[$p][$d] "; } } # test @slots # foreach my $slot (@slots){ print "$slot\n"; } # Find starting point in array for (0..$#slots){ if ($slots[$_] eq "$day:$startperiod"){ # print "Match for $slots[$_]\n"; $currindex = $_; last; } } if (not defined $currindex){ print "No match for Day $day Period $startperiod"; die; } my $cyclesize = $#slots + 1; my $nextindex = $currindex + 1; my $totaldays; #print "DpC: $daysPerCycle Classes per Cycle: $cyclesize\n"; # print "SkipClasses: $skipclasses\n"; # Loop through to calc the number of days to skip. for (1..$skipclasses){ # how many jumps my ($currday,$cp) = split /:/,$slots[$currindex]; my ($nextday,$np) = split /:/,$slots[$nextindex]; my $jumps = $nextday - $currday; if ($jumps < 0){ $jumps += $daysPerCycle;} $totaldays += $jumps; $currindex++; if ($currindex > $cyclesize){ $currindex = 0;} $nextindex++; if ($nextindex > $cyclesize){ $nextindex = 0;} } $startdate =~ s/-//g; my $startdateobj = new Date::Business(DATE => $startdate); my $sth = $dbh->prepare("select count(id) from dates where date = ? and dayincycle = 'N'"); my ($nd,$i); while ($i < $totaldays){ $startdateobj->nextb; $nd = $startdateobj->image(); # print "ND: $nd\n"; $sth->execute($nd); $count = $sth->fetchrow; if (not $count){ $i++;} } #print "Final: $nd\n"; return $nd; } #-------------- sub prTeacherTimetable { # print timetable for 1 teacher for 1 term. #-------------- my ($term, $subjref) = @_; # passed term and ref to subjects. # Prep for loop finding the subjects my $sth = $dbh->prepare("select day, period from schedat where term = '$term' and subjsec = ? "); my @subject; #loop through all subject-sections foreach my $subjsec (@{$subjref}){ $sth->execute($subjsec); if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr;} # Create 2D subject array (of [period][day] indexes) while (my ($day, $period) = $sth->fetchrow){ if ($subject[$period][$day] != $subjsec){ $subject[$period][$day] .= "$subjsec "; } } } my $tblrows = $#subject; my $tblcols; for $i (1..$tblrows){ if ($#{$subject[$i]} > $tblcols){ $tblcols = $#{$subject[$i]};} } $sth = $dbh->prepare("select description,smdesc from subject where subjsec = ?"); print "\n"; # heading print ""; for (1..$tblcols){ print ""; } print "\n"; # Main body of table. for $i (1..$tblrows){ print ""; for (1..$tblcols){ if ($subject[$i][$_]){ # if we have a subjsec value; my $firstflag = 1; @subjval = split /\s/,$subject[$i][$_]; print ""; } else { print ""; } } print "\n"; } print "
Day $_
Period $i"; foreach my $sv (@subjval){ if (not $firstflag){ print "
";} else { $firstflag = 0;} $sth->execute($sv); if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr;} my ($description,$smdesc) = $sth->fetchrow; if (not $smdesc){ $smdesc = substr($description,0,8);} print "$smdesc ($sv)"; } print "
No Value
\n"; } # End of prTeacherTimetable #-------------- sub mkTimetable { #-------------- # make timetable structure (2D array), passed teacher userid, and term. my ($userid, $term) = @_; my (@subjects, @bigsubjects); # Get the subject info; stuff into 'subjects' array. my $sth = $dbh->prepare("select description,smdesc,subjsec from subject where teacher $sql{like} '%($userid%' order by description"); $sth->execute; if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr;} # Prep for loop finding the subjects my $sth1 = $dbh->prepare("select day, period from schedat where term = '$term' and subjsec = ? "); while (my ($description,$smdesc,$subjsec) = $sth->fetchrow){ push @bigsubjects,"$description ($subjsec)"; push @subjects,$subjsec; $sth1->execute($subjsec); if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr;} # Create 2D subject array (of [period][day] indexes) while (my ($day, $period) = $sth1->fetchrow){ if (not $subject[$period][$day]){ # if empty, fill it. $subject[$period][$day] = $subjsec; } elsif ($subject[$period][$day] eq $subjsec){ # Do nothing if it matches... } else { # Add one on. $subject[$period][$day] .= " $subjsec"; } } } return \@subject; # pass ref to 2D subject array. } # End of mkTimetable 1;