Date

In my classes, I often assign students to random teams. I use a simple notebook to do this. From the roster, I prepare a list of strings of student names. I then randomize the list and partition it into groups. I render this in an HTML table to make it easy to read and project it on the screen.

This semester, I'm adding a few widgets to make it easier to use and configure quickly during class. The widget framework supplied by IPython makes it straightforward to create lightweight applications.

I make a class with a HTML representation method that allows it to be displayed by IPython's display functions. I also make a small function to randomize a list of strings representing student names.

To make the application, I set up widgets for the sizes of the teams and whether or not to shuffle the list. I have a function that outputs random groups of teams based on the list of students, the size of teams, and whether or not to shuffle the list. Finally, a button executes this function when pressed and creates a new table of teams.

In [1]:
class ListTable(list):
    """ Overridden list class which takes a 2-dimensional list of 
        the form [[1,2,3],[4,5,6]], and renders an HTML Table in 
        IPython Notebook. """
    
    def _repr_html_(self):
        html = ["<table>"]
        for i, row in enumerate(self, start=1):
            html.append("<tr>")
            # create row index
            html.append("<td>{0}</td>".format(i))
            # add elements in row
            for col in row:
                html.append("<td>{0}</td>".format(col))
            # close row
            html.append("</tr>")
        html.append("</table>")
        return ''.join(html)
    
def group_students(students, groupsize, randomize=True):
    ''' Shuffle a list of strings and partition into groups.
        Returns a 2-d list of strings.'''
    templist = [s for s in students]
    if randomize:
        import random
        random.shuffle(templist)
    table = []
    for i in range(0, len(templist), groupsize):
        table.append(templist[i:i+groupsize])
    return table

students = [
'Amory Lovins',
'Art Rosenfeld',
'Daniel Yergin',
'Ernest Moniz',
'Gavin Schmidt',
'Henry Ford',
'James Watt',
'Judith Curry',
'Michael Mann',
'Stephen Schneider',
'Svante Arrhenius',
'Vaclav Smil',
]
In [2]:
import ipywidgets
from IPython.display import display, clear_output

# set up widgets
button = ipywidgets.Button(description="Create Teams")
team_size = ipywidgets.IntSlider(min=2, max=5, value=3, 
                                 description="Team Size")
randomize = ipywidgets.Checkbox(value=True, 
                                description='Randomize')

# define function called on button click
def on_button_clicked(b):
    clear_output()
    display(ListTable(group_students(students,
                                     team_size.value,
                                     randomize=randomize.value)))

# render and run widgets
display(randomize)
display(team_size)
display(button)
button.on_click(on_button_clicked)
1Judith CurryVaclav SmilErnest Moniz
2James WattMichael MannAmory Lovins
3Stephen SchneiderSvante ArrheniusDaniel Yergin
4Henry FordArt RosenfeldGavin Schmidt

Unfortunately, the widgets don't render in this static blog post, but there is a slider for the size of the teams and a button to create a new random draw.

I have a link to an app using the Binder service where you can run this.

In [ ]: