#!/usr/bin/awk -f
# coldcall.awk
# (c) 2011 Stephen E. Sachs, sachs@law.duke.edu
# revised Dec. 4, 2011
# current version available at http://www.stevesachs.com/code
# Released under GNU Lesser General Public License, v.3 or (at your option)
# any successor version. See http://www.gnu.org/copyleft/lgpl.html .
# Requires:
# awk
# python
# xlrd, by John Machin
# xls2csv, by Stephane Jeannenot
# This program is designed to aid professors in randomly choosing
# students for cold-calling, as in traditional Socratic law school
# classes.
# It assigns each student a relative probability of being called on.
# The student who has been called on the most is assigned the number 1.
# Someone who has been called on n fewer times than that is assigned
# (prob_factor^n), where prob_factor is some number larger than 1.
# The manner of choosing students is as follows. All of the students are
# arranged in a line. Those with larger relative probabilities take up
# more space on the line. A random integer is then chosen between 1 and
# the end point (inclusive); the student that it lands on is the one who
# will be picked. That student's share of the line is then deleted, and
# the process is repeated for the remaining students, until enough have
# been chosen.
# Names and data on the previous calls should be stored in an Excel
# file, with the first four columns formatted as:
# FirstName MI LastName #ofPrevCalls
# To run, change the parameters in the set_parameters() function to
# match your desired values (such as the location of the Excel file,
# etc.).
# To debug, run with the option "-v debug=1".
BEGIN {
srand()
set_parameters()
set_up_data()
pickthem(listsize)
}
function set_parameters( f,x,y) {
# Exports as parameters the following global variables:
# listsize, prob_factor, xls_cmd
# Number of students on each day's list:
listsize = 15
# Discounting factor for students who have been called on more often:
prob_factor = 8
# Location of previous-call data:
f = "Classroom_Participation.xls"
# Version of xls2csv used:
x = "xls2csv.0.4.py"
"which "x | getline y ; close("which "x)
xls_cmd = y" -q -i "f" -o /dev/stdout"
}
function set_up_data( c,i,maxcalls) {
# imports xls_cmd, prob_factor, debug
# exports three arrays: Name, PrevCalls, and Prob
FS = ";"
c = 0
maxcalls = 0
while ((xls_cmd | getline) > 0) {
c++
Name[c] = $1" "$2" "$3
PrevCalls[c] = $4 + 0
maxcalls = max(maxcalls, PrevCalls[c])
}
close(xls_cmd)
for (i=1;i<=c;i++) {
Prob[i] = prob_factor ^ (maxcalls - PrevCalls[i])
if (debug) { print i, Name[i], PrevCalls[i], Prob[i] }
}
if (debug) {
print "\nTotal number of students is "c"."
print "Maximum number of calls is "maxcalls".\n"
}
}
function max(a,b) { if (a > b) { return a } else { return b } }
function pickthem(remaining, i, sum, r, c) {
# imports Name, PrevCalls, Prob
# modifies Prob
if (remaining <= 0) return ""
if (debug) print "Now choosing "remaining" students."
sum = 0 ; for (i in Prob) { sum += Prob[i] }
if (debug) print "Sum of all relative probabilities = "sum
r = int(rand() * sum) + 1
if (debug) print "random number = "r
c = 0
while (r > 0) {
c++
r -= Prob[c]
if (debug) {
print "\nCounter is now "c
print "Now subtracting "(Prob[c] + 0)
print "Random is now "r
}
}
if (debug) print "\nThe final count was "c"."
print Name[c], PrevCalls[c], Prob[c]
delete Prob[c]
remaining--
pickthem(remaining)
}