#!/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) }