http://qs321.pair.com?node_id=390743
Category: Utility Scripts
Author/Contact Info hossman
Description:

This script parses a data file containing students votes for when Discussion Sections (or office hours) should be held, and generates an Excel spreedsheet containing stats on how useful each trio of sections would be (along with a complete roster of everyone who's info is in the data file)

People who aren't enrolled or waitlisted are included in roster, but their prefrences are not counted.

See Also: the CGI to generate the DATA

#!/usr/local/bin/perl

# $Id: class-schedule.pl,v 1.4 2004/08/20 05:25:28 hossman Exp $
# $Source: /home/hossman/cvs_archive/code/perl/class-scheduler/class-s
+chedule.pl
,v $
#

use warnings;
use strict;
use Set::Scalar;

use Spreadsheet::WriteExcel;

# name all of the time slots (0-N)
my @names = qw(
               Mon-10-11
               Mon-2-3
               Mon-3-4
               Mon-4-5
               Tue-12-1
               Tue-1-2
               Tue-4-5
               Wed-9-10
               Wed-10-11
               Thur-12-1
               Thur-1-2
               );

# keep a set of all known users who are enrolled/waitlisted
my $users = new Set::Scalar();

# for each time slot, create a set in which we'll put all the people
# that can make it who are enrolled/waitlisted.
my @slots = map { new Set::Scalar() } (0 .. @names-1);

# we use these hashs to try and find possible duplicate entries
my %dup_sid;
my %dup_name;
my %dup_email;
    
# start our Excel Workbook
binmode STDOUT;
my $wb = new Spreadsheet::WriteExcel('-');

# make a sheet to record the stats
my $stats = $wb->add_worksheet('Stats');
$stats->keep_leading_zeros();
$stats->write_row(0,0,
                  [qw(session1 session2 session3 1ok 2ok 3ok happy scr
+ewed)]);

# make a sheet that to list the full details of who can make what
my $details = $wb->add_worksheet("Details");
$details->keep_leading_zeros();
$details->write_row
    (0,0, [ 'SID', 'Last Name', 'First Name', 'Email', 'Status', 'Tota
+l',
            @names ]);

## now loop over our input

# input lines should be a user id, and a list of slot numbers the user
# prefers, seperated by whitespace
while (<>) {
    my ($sid, $lname, $fname, $email, $status, $p) = split /:/;
    my @prefs = split /\s/, $p;

    # detect dups
    warn "Duplicate SID Found: $sid" if exists $dup_sid{$sid};
    warn "Duplicate Email Found: $email" if exists $dup_email{$email};
    warn "Duplicate Name Found: $lname, fname"
        if exists $dup_name{"$lname, $fname"};
    $dup_name{"$lname, $fname"} = $dup_sid{$sid} = $dup_email{$email} 
+= undef;
    
    # if they are probably in the class, then record the info for stat
+s
    if ('N' ne $status) {
        $users->insert($sid);
        $slots[$_]->insert($sid) foreach (@prefs);
    }

    # add all raw data to our details screen
    my $ok = new Set::Scalar(@prefs);
    $details->write_row($., 0,
                        [ $sid, $lname, $fname, $email, $status, $ok->
+size(),
                          map { $ok->contains($_) ? 1 : 0 } (0..@names
+-1) ]);
    
}

my $row = 1; # where are we in the current sheet ?

# loop over all the 3 way combinations of slots, and report stats...
for (my $i = 0; $i < @slots; $i++) {
    for (my $j = $i+1; $j < @slots; $j++) {
        for (my $k = $j+1; $k < @slots; $k++) {

            my ($is, $js, $ks) = ($slots[$i], $slots[$j], $slots[$k]);
            
            my $iorj = $is->union($js);
            my $iork = $is->union($ks);
            my $jork = $js->union($ks);

            my $any = $iorj->union($ks);

            my $screwed = $users->difference($any);

            $stats->write_row($row++, 0,
                              [ ((map { $names[$_] } ($i, $j, $k)),
                                 (map { $_->size() }
                                  ($is, $js, $ks, $any, $screwed))) ])
+;
            
        }
    }
}    

# we're done
$stats->activate();
$stats->select();
$stats->set_first_sheet();
$wb->close();

__DATA__
2:Burnquest:Bob:hossman@asf:E:1 2 5 8
3:Hawk:Tony:hossman@asf:E:
99:Blo:Joe:joe@blow.com:E:0 5