#!/usr/bin/perl -w
use strict;
#
# cl2ww [-c|-s] [crs-sxn [crs-sxn.. ]]
#
# process classlist files for class-sections indicated, creating
# corresponding webwork userlist files, classnum.lst
# -s : assume the webwork roster has section & recitation # = section num
# (e.g., 115-103 has sxn=103, rct=103)
# -c : assume the webwork roster has the section # = course # and
# recitation # = section # (e.g., 115-103 has sxn=115, rct=103)
# otherwise, assume that section # = section # rounded down, recitation #
# = section number (e.g., 215-021 has sxn=020, rct=021)
#
# by Gavin LaRose
# version 1.34
# changes: 1.34: add -s flag
# 1.33: add -c flag
# 1.32: correct handling of csv files generated by python
# 1.31: bugfix; chomp newlines from file names, avoid double
# counting students in 215, 216 if -all is used, make
# instructors show up with section number and 000 for
# recitation
# 1.3 : update to get rid of passwords, add instructor
# 1.2 : revised recitation number support
# 1.1 : added support for recitation number
# 5 jan 2010
#
# (c)2013 Gavin LaRose/Regents of the University of Michigan
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#------------------------------------------------------------------------------
# variables
#
my $dataDir = '/home/glarose/IFS-Home/LSA-Files/Private/classlists/data';
my @instrFiles = ('instr_pw.csv', 'instr.csv');
select STDERR; $|=1;
select STDOUT; $|=1;
#------------------------------------------------------------------------------
# main
#
my $cflag = 0;
if ( @ARGV && $ARGV[0] eq '-c' ) {
$cflag = 1;
shift( @ARGV );
}
if ( @ARGV && $ARGV[0] eq '-s' ) {
$cflag = 2;
shift( @ARGV );
}
if ( ! @ARGV ) {
my $fname = "none";
print "course-section to process (e.g., 115-all, 216-102)? ";
chomp( $fname = <STDIN> );
push( @ARGV, $fname );
}
# we make $classes{crs-num} = [ list of webwork roster lines ]
my %classes = ();
# webwork lines are
# studentID, lName, fmName, status, comment, section, recitation, \
# email, loginName
foreach my $course ( @ARGV ) {
my @fileList = ();
my ( $crs, $sxn ) = ( $course =~ /(\d+)-((\d+)|(all))/ );
die("* error: course identifier $course is not in the form CRS-SXN\n")
if ( ! defined($crs) || ! defined($sxn) || ! $crs || ! $sxn );
if ( $sxn eq 'all' ) {
if ( $crs =~ /^21[56]/ ) {
@fileList = `/bin/ls ${crs}_??[1-4].csv 2> /dev/null`;
@fileList = `/bin/ls $dataDir/${crs}_??[1-4].csv 2> /dev/null`
if ( ! @fileList );
} else {
@fileList = `/bin/ls ${crs}_*.csv 2> /dev/null`;
@fileList = `/bin/ls $dataDir/${crs}_*.csv 2> /dev/null`
if ( ! @fileList );
}
} else {
push(@fileList, "${crs}_${sxn}.csv");
}
for ( my $i=0; $i<@fileList; $i++ ) {
chomp($fileList[$i]);
if ( ! -f $fileList[$i] && ! -f "$dataDir/$fileList[$i]" ) {
@fileList = ();
last;
} elsif ( ! -f $fileList[$i] ) {
$fileList[$i] = "$dataDir/$fileList[$i]";
}
}
die("* error: missing class roster file(s)\n") if ( ! @fileList );
print "reading course file: ";
foreach my $f ( @fileList ) {
my ( $c, $s ) = ($f =~ /(\d{3})_(\d{3})/);
print "$c-$s.. ";
open( IF, $f ) or die("* error: cannot open $f for reading\n");
while ( <IF> ) {
# first line is a header; skip it
if ( /^[0-9]/ ) {
s/\s*$//;
s/\"//g;
my @entry = csvSplit( $_ );
my $cnum = $entry[0] . "_" . $entry[1];
# update section and recitation if needed
my ( $snum, $rcn );
if ( $cflag == 1 ) {
$snum = $entry[0];
$rcn = $entry[1];
} elsif ( $cflag == 2 ) {
$rcn = $entry[1];
$snum = $rcn;
} else {
$rcn = $entry[1];
$snum = substr($entry[1],0,2) . '0';
}
$classes{"$crs-$sxn"} = [ ]
if ( ! defined( $classes{"$crs-$sxn"} ) );
# generate webwork user data line
push( @{$classes{"$crs-$sxn"}},
"$entry[-1], $entry[3], $entry[4], C, , $snum, " .
"$rcn, $entry[2]\@umich.edu, $entry[2]" );
}
}
}
print "done\n";
}
# where can we find instructor data?
my $instrFile = ;
foreach my $iFile ( @instrFiles ) {
if ( -f "$dataDir/$iFile" ) {
$instrFile = $iFile;
last;
}
}
my @instrList = ();
@instrList = `/bin/cat $dataDir/$instrFile 2> /dev/null` if ( $instrFile );
foreach ( keys %classes ) {
my $fn = $_ . ".lst";
while ( -f "$fn" ) {
print "file $fn exists: [cr] to overwrite or newname: ";
chomp( $fn = <STDIN> );
}
$fn = ( $fn eq "" ) ? $_ . ".lst" : $fn;
open ( FN, ">$fn") or die ("* error: cannot open file $fn for writing\n");
# get instructor data, if possible
my @instrLines = ();
if ( @instrList ) {
my ( $crs, $sxn ) = ( $_ =~ /(\d+)-((\d+)|(all))/ );
if ( $sxn eq 'all' ) {
@instrLines = grep {/^$crs,/} @instrList;
} else {
@instrLines = grep {/^$crs,$sxn,/} @instrList;
}
}
foreach my $iLine ( @instrLines ) {
$iLine =~ s/\s*$//;
my @vals = csvSplit(/,/, $iLine);
my ( $sxn, $rcn );
if ( $cflag ) {
$sxn = $vals[0];
$rcn = $vals[1];
} else {
$rcn = $vals[1]; $rcn =~ s/\d$/0/;
$sxn = '000';
}
print FN "$vals[5], $vals[3], $vals[4], C, , $sxn, " .
"$rcn, $vals[2]\@umich.edu, $vals[2]\n";
}
foreach my $ent ( @{$classes{$_}} ) {
print FN "$ent\n";
}
close FN;
if ( @instrLines ) {
print "wrote userdata to file $fn, including instructor(s)\n";
} else {
print "wrote userdata to file $fn; could not add instructor(s)\n";
}
}
#
#------------------------------------------------------------------------------
# subroutines
#
# sub getpass {
#
# generate a random password of the form wordNword2, with word being
# four letters long, N being a random digit, and word2 being three
# letters long. this uses the arrays @threes and @fours loaded by
# loadDict
#
# my $rand1 = int(rand()*(@fours));
# my $rand2 = int(rand()*(@threes));
# my $randd = int(rand()*10);
# return $fours[$rand1] . $randd . $threes[$rand2];
# }
# sub loadDict {
# my ( $df3, $df4 ) = @_;
#
# returns arrays of 'nice' three and four letter words from the dictionary
# files $df3 and $df4
#
# @threes = ();
# @fours = ();
# open(DF, $df3) or die("** can't open dictionary file $df3 **\n");
# while ( <DF> ) {
# chomp;
# push @threes, $_;
# }
# close(DF);
# open(DF, $df4) or die("** can't open dictionary file $df4 **\n");
# while ( <DF> ) {
# chomp;
# push @fours, $_;
# }
# close(DF);
# }
sub csvSplit {
my $line = shift();
my @fields = ();
while ( $line ) {
my $term = ;
if ( $line =~ /^"/ ) { #"
$line = substr( $line, 1 ); # bite off quote
my $ind = index( $line, '"' ); # "
$term = substr( $line, 0, $ind );
$line = ( $term =~ /$line,?$/ ) ? : substr( $line, $ind+1 );
# get rid of any trailing comma
$line =~ s/^,//;
} else {
my $ind = index( $line, ',' );
$term = ($ind == -1) ? $line : substr( $line, 0, $ind );
$line = ( $term =~ /$line,?$/ ) ? : substr( $line, $ind );
# get rid of any trailing comma
$line =~ s/^,//;
}
push( @fields, $term );
}
return @fields;
}
#
# end script
#------------------------------------------------------------------------------