#! /usr/bin/perl
#  Copyright 2001-2022 Leslie Richardson

#  This file is part of Open Admin for Schools.

# Absent strings for matching set in admin.conf; Comparison at line
# 305 in this file.

my $self = 'rptPresent.pl';

my %lex = ('Main' => 'Main',
	   'Error' => 'Error',
	   'Month' => 'Month',
	   'Select' => 'Select',
	   'Attendance' => 'Attendance',

    );


use DBI;
use CGI;
use Time::JulianDay;
use Number::Format qw(:all);
use Cwd;


# Get current dir so know what path for config files.
my $configpath;
my $teachermode;
if ( getcwd() =~ /tcgi/ ){ # we are in tcgi
    $teachermode = 1;
    $configpath = '..'; # go back one to get to etc.
} else {
    $configpath = '../..'; # go back two to get to etc.
}

# only load passwords and users
eval require "$configpath/etc/admin.conf.root";
if ( $@ ) {
    print $lex{Error}. " $@<br>\n";
    die $lex{Error}. " $@\n";
}

eval require "$configpath/lib/libattend.pl";
if ( $@ ) {
    print $lex{Error}. " $@<br>\n";
    die $lex{Error}. " $@\n";
}

my $dbtype = 'mysql';
my $dsn = "DBI:$dbtype:dbname=$dbase";
my $dbh = DBI->connect($dsn,$user,$password);



# Load Configuration Variables;
my $sth = $dbh->prepare("select id, datavalue from conf_system where filename = 'admin'");
$sth->execute;
if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
while (	my ($id, $datavalue) = $sth->fetchrow ) {
    eval $datavalue;
    if ( $@ ) {
	print "$lex{Error}: $@<br>\n";
	die "$lex{Error}: $@\n";
    }
}


my @tim = localtime(time);
my $year = @tim[5] + 1900;
my $month = @tim[4] + 1;
my $day = @tim[3];
if (length($month) == 1){ $month = "0".$month;}
if (length($day) == 1){ $day = "0".$day;}
my $currdate = "$year-$month-$day";
my $currjd = julian_day(split('-', $currdate));


# Teachermode
if ( $teachermode ) { # running on teacher site
    $css = $tchcss;
    $homepage = $tchpage;
    $downloaddir = $tchdownloaddir;
    $webdownloaddir = $tchwebdownloaddir;
}

my $q = new CGI;
print $q->header( -charset, $charset );
my %arr = $q->Vars;



# Page Header
my $title = "Students Present Report";

print qq{$doctype\n<html><head><title>$title</title>\n};
print qq{<link rel="stylesheet" href="$css" type="text/css">\n};
print qq{<style type="text/css">.ra { text-align:right; }</style>\n};

print qq{$chartype\n</head><body style="padding:1em;"><a name="top"></a>\n};
print qq{[ <a href="$homepage">$lex{Main}</a> \n};
if ( not $teachermode ) {
    print qq{| <a href="$attpage">$lex{Attendance}</a> };
}
print qq{]\n};

print qq{<h1>$title</h1>\n};


# Show Start Page, if necessary.
if ( not $arr{page} ) {
    showStartPage();

} else {
    delete $arr{page};
    showPresent();
}


#--------------
sub showPresent {
#--------------
    
    # foreach my $key ( sort keys %arr ) { print qq{K:$key V:$arr{$key}<br>\n}; }
    # Passed: month in yyyy-mo format.
    
    my ($y,$m) = split('-',$arr{month});
    my $startjd = julian_day($y,$m,1);
    my $startdate = qq{$y-$m-01};

    print qq{<h3>$month[$m] $y</h3>\n};
    
    # Find end date of the month by going to next month start and backing up 1 day.
    my ( $nextyr,$nextmo );
    if ( $m == 12 ) {
	$nextmo = 1;  # reset month to 1
	$nextyr = $y + 1; # bump year
    } else {
	$nextmo = $m + 1;
	$nextyr = $y; # no year change;
    }
    my $nextjd = julian_day($nextyr,$nextmo,1);
    my $endjd = $nextjd - 1;

    # Check if in current month
    if ($currjd < $endjd ) {
	$endjd = $currjd - 1; # minus one, since we want previous day only
    }
    
    # We can now loop from startjd to endjd for the month selected.

    # Testing
#    my ($yr,$mon,$day) = inverse_julian_day($startjd);
#    print qq{START:$yr $mon $day<br>\n};
#    my ($yr,$mon,$day) = inverse_julian_day($endjd);
#    print qq{END:$yr $mon $day<br>\n};


    
    # Find the homerooms
    my (%homerooms,%ppd); # periods per day for each homeroom.
    my $sth = $dbh->prepare("select distinct homeroom, grade from student 
			    where homeroom is not NULL and homeroom != '' and 
			    grade is not NULL and grade != ''");
    $sth->execute;
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
    while ( my ($hr,$gr) = $sth->fetchrow ) {
	$homerooms{$hr} = 1;
	$ppd{$hr} = $g_ppd{$gr}; # don't care currently if more than 1 grade in homeroom.
	if ( not $ppd{$hr} ) {
	    print qq{<h3>Error: Missing Attendance Periods Per Day for HR:$hr GR:$gr</h3>\n};
	    print qq{</body></html>\n};
	    exit;
	}
#	print "HR:$hr GR:$gr PPD:$ppd{$hr}<br>\n";
    }


    # We now have to find the Starting Students - school wide is likely the best approach.
    
    # a) Get current students and add.
    # b) All students with transfer during this school year are added
    # as well. Gives us a complete list.
    # c) We will then eliminate those students withdrawn before a
    # particular month, to get a monthly starting list.
    # d) Any enrollment changes during the month will be done as we go
    # through the days of the month.

    # now add homeroom information (or could be grade if required on rewrite)
    
    my %studHR;  # could be studGR  $studHR{hr}{studnum};
    my %students; # {studnum};

    #    my $sth = $dbh->prepare("select homeroom from studentall where studnum = ?");
#    foreach my $studnum ( keys %students ) {
#	$sth->execute($studnum);
#	if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
#	my $hr = $sth->fetchrow;
#	$studHR{$hr}{$studnum} = 1;
#    }

    
    my $sth = $dbh->prepare("select studnum, homeroom from student");
    $sth->execute;
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
    while ( my ($studnum, $hr) = $sth->fetchrow ) {
	if (not $hr) {
	    print qq{<h3 style="color:red;">Missing Homeroom for student $studnum</h3>\n};
	    next;
	} # skip any without a homeroom.
	$students{$studnum} = $hr;
	$studHR{$hr}{$studnum} = 1;
    }

=head    
    # Data Test for studHR hash
    print qq{<h3>Start of Month Counts</h3>\n};
    my $total;
    foreach my $hr ( sort {$a <=> $b} keys %studHR ) {
	my $count;
	print qq{<div><b>$hr</b></div>\n};
	foreach my $studnum ( sort keys %{ $studHR{$hr}} ) {
	    $count++;
	    print qq{$studnum };

	}
	print qq{<div>HR:$count</div>\n};
	$total += $count;
    }
    print qq{<div>Total $total</div>\n};
=cut

    
    # Now back up from current date, adding and removing students until we get to the month of interest.

    my %enrolchg;
    my $sth1 = $dbh->prepare("select homeroom from studentall where studnum = ?");

    my $sth = $dbh->prepare("select * from transfer where to_days(date) >= to_days('$startdate') 
			    order by date desc");
    $sth->execute;
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
    while ( my $ref = $sth->fetchrow_hashref ) { 
	my %r = %$ref;
	my $tempjd = julian_day( split('-', $r{date}) );
#	my $diff = $startjd - $tempjd;
#	print qq{Temp:$tempjd Start:$startjd End:$endjd Diff:$diff<br>\n};
#	my $sd = join('-', inverse_julian_day($startjd));
#	my $ed = join('-', inverse_julian_day($endjd));
#	print "Start:$sd End:$ed<br>\n";
		      

	if ( $tempjd >= $startjd and $tempjd <= $endjd ) { # within the month of interest
	    # add info studnum, type, date
#	    print "ECH:$r{date} / $r{studnum} / $r{type}<br>\n";
	    $enrolchg{ $r{date} }{ $r{studnum} } = $r{type};
	}

	# Update %students, studHR;
	if ( $r{type} eq 'enrol' ) { # then withdraw/remove student.
	    my $hr = $students{$r{studnum}};
	    delete $students{ $r{studnum} };
	    delete $studHR{$hr}{$r{studnum}};
	    
	} elsif ( $r{type} eq 'withdraw' ) { # then add them

	    # Get Homeroom
	    $sth1->execute( $r{studnum} );
	    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
	    my $hr = $sth1->fetchrow;
	    if ( not $hr ) {
		print qq{<div>Error! Missing homeroom  for student $r{studnum}</div>\n};
		next;
	    }

	    $students{ $r{studnum} } = $hr;
	    $studHR{$hr}{$r{studnum}} = 1;
			 
	} else {
	    print qq{<div>Error! transfer type is incorrect! $r{studnum} - $r{date} - $r{type}</div>\n};
	}
    }

    # Check Enrollment Change
#   print qq{<div>Enrollment Change</div>\n};
#   foreach my $date ( sort keys %enrolchg ) {
#	foreach my $studnum ( sort keys %{ $enrolchg{$date}} ) {
#	    print qq{<div>$date / $studnum / $enrolchg{$date}{$studnum}\n</div>\n};
#	}
#    }

 	
    # %students now has students at start of month; %enrolchg has list
    # of enrollment changes during the month of interst.


    # Dates closed in month.
    my %closed;
    my $sth = $dbh->prepare("select date from dates where dayfraction > 0.99 and 
			    month(date) = '$m' and year(date) = '$y'");
    $sth->execute;
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
    while ( my $date = $sth->fetchrow ) {  # Note will have leading zeros!
#	print "Date Closed: $date<br>\n";
	$closed{$date} = 1;
    }

   
    # Get Teacher Name for this homeroom
    my $sth1 = $dbh->prepare("select lastname, firstname from staff s, staff_multi m where
			     m.field_name = 'homeroom' and s.userid = m.userid and m.field_value = ?");

    # Get Homeroom
    my $sth2 = $dbh->prepare("select homeroom from studentall where studnum = ?");
    
    # Get Absence count for a homeroom on a particular date
    my $sth = $dbh->prepare("select count(*) from attend a, studentall s where s.homeroom = ?
			    and s.studnum = a.studentid and absdate = ? and 
			    a.reason like '%Absent%' ");

    
    # Table Start
    print qq{<table cellspacing="0" cellpadding="3" border="1">\n};
    print qq{<caption style="font-size:120%;text-align:left;">};
    print qq{Counts,Homerooms are Hoverable &#9405;</caption>\n};

    # Days Row
    print qq{<tr><th>HRoom</th>\n};
    foreach my $jd ( $startjd .. $endjd ) {
	my ($yr,$mon,$day) = inverse_julian_day($jd);
	my $dow = day_of_week($jd);
	if ( $dow == 0 or $dow == 6 ) { next; } # skip weekend.
	print qq{<th>$dowstd[$dow]<br>$s_month[$mon] $day</th>\n};
    }
    print qq{</tr>\n};

    my $rowcount = 1; # for alternating color
    
    my (%totalenrol, %totalpresent);  # key is date.
    
    foreach my $hr ( sort {$a <=> $b} keys %homerooms ) {

	# Get Teacher
	$sth1->execute($hr);
	if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
	my ($lastname, $firstname) = $sth1->fetchrow;

	# Color change
	if ( $rowcount % 2 == 0 ) { # make it gray
	    print qq{<tr style="background-color:#DDD;"><td class="bcn" 
			 title="$firstname $lastname">$hr</td>\n};
	} else {
	    print qq{<tr><td class="bcn" title="$firstname $lastname">$hr</td>\n};
	}

	# Loop through all days of the month for this homeroom
	foreach my $jd ( $startjd .. $endjd ) {
	    my $dow = day_of_week($jd);
	    if ( $dow == 0 or $dow == 6 ) { next; } # skip weekend.
	    
	    my ($yr,$mon,$day) = inverse_julian_day($jd);
	    if ( length $day == 1 ) { $day = '0'. $day; }
	    if ( length $mon == 1 ) { $mon = '0'. $mon; }
	    my $date = qq{$yr-$mon-$day};
#	    print "Date:$date<br>\n";
	    if ( $closed{$date} ) {
		print qq{<td class="cn" title="Closed - $date">Closed</td>\n};
		next;
	    } else { # find absences, update totals
		
		$sth->execute($hr,$date);
		if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
		my $abscount = $sth->fetchrow;
		
		my $absent = round($abscount / $ppd{$hr}, 1);
		my $studcount = scalar %{ $studHR{$hr} }; # students in the room today
	
		my $present = $studcount - $absent;
		
		$totalpresent{$date} += $present;
		$totalenrol{$date} += $studcount;

		# update studHR for this hr for this date;
		foreach my $studnum ( keys %{ $enrolchg{$date}} ) {
		    # Get Homeroom
		    $sth2->execute( $studnum );
		    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
		    my $hr = $sth2->fetchrow;
		    if ( not $hr ) {
			print qq{<div>Error! Missing homeroom during enrollment update };
			print qq{for student $studnum</div>\n};
			next;
		    }

		    my $type = $enrolchg{$date}{$studnum};
		    if ( $type eq 'enrol' ) {
	#		print qq{<div>Adding Student $studnum to $hr</div>\n};
			$studHR{$hr}{$studnum} = 1;
		    } else { # withdrawal
	#		print qq{<div>Removing Student $studnum from $hr</div>\n};
			delete $studHR{$hr}{$studnum};
		    }
		}	

		print qq{<td title="Absent Count (periods) $abscount">$present / $studcount</td>};
	    }
	    
	} # end of HR loop for month
	print qq{</tr>\n\n};
	$rowcount++;
    }

    # Totals Line
    print qq{<tr style="background-color:#CCC;"><td class="bcn">Total</td>\n};
    foreach my $jd ( $startjd .. $endjd ) {
	my $dow = day_of_week($jd);
	if ( $dow == 0 or $dow == 6 ) { next; } # skip weekend.
	    
	my ($yr,$mon,$day) = inverse_julian_day($jd);
	if ( length $day == 1 ) { $day = '0'. $day; }
	if ( length $mon == 1 ) { $mon = '0'. $mon; }
	my $date = qq{$yr-$mon-$day};

	if ( $closed{$date} ) {
	    print qq{<td class="bcn" title="Closed - $date">Closed</td>\n};
	    next;
	} else {
	    my $percent = '0';
	    if ( $totalenrol{$date} ) { # if non-zero
		$percent = round( $totalpresent{$date} / $totalenrol{$date} * 100, 1);
	    }
	    print qq{<td class="bcn" title="$totalpresent{$date} / $totalenrol{$date}">};
	    print qq{$totalpresent{$date}/$totalenrol{$date}<br>$percent%</td>};
	}
    }
    print qq{</tr>\n\n}; # end of Totals Line

    
    print qq{</table>\n};
    
    exit;
}



#----------------
sub showStartPage {
#----------------

    # Setup Year-Months.
    my @months;
    my %months;

    my ($cyear,$cmonth,$cday) = split('-',$currdate);

    my ($sy, $sm, $sd) = split('-', $schoolstart); # schoolstart is global var from config.
    my $yrmo = "$sy-$sm";
    push @months, $yrmo;
    $months{$yrmo} = "$s_month[$sm]-$sy";

    for my $i (1..10) {
	my $mo = $sm + $i;
	my $yr = $sy;
	if ( $mo > 12 ) {
	    $mo = $mo - 12;
	    $yr++;
	}

	if ( length $mo == 1 ) { $mo = '0'. $mo; }
	my $yrmo = "$yr-$mo";
	push @months, $yrmo;
	$months{$yrmo} = "$s_month[$mo]-$yr";

	if ( $yr == $cyear and $mo == $cmonth ) { # done
	    last;
	}
    }

    # Months
    print qq{<h3>$lex{Select} $lex{Month}</h3>};

    foreach my $mo ( @months ) {
	print qq{<form action="$self" method="post" style="margin:0.6em 1em;">\n};
	print qq{<input type="hidden" name="page" value="1">\n};
	print qq{<input type="hidden" name="month" value="$mo">\n};
	print qq{<input type="submit" value = "$months{$mo}"></form>\n};
    }
    print qq{</body></html>\n};

    exit;
}
