Difference between revisions of "CSC111 Lab 7 Moodle 2015"

From dftwiki3
Jump to: navigation, search
Line 185: Line 185:
 
</source>
 
</source>
 
<br />
 
<br />
 +
</showafterdate>
 +
<!-- =================================================================== -->
 
<br />
 
<br />
 +
<onlydft>
 +
=VPL Module=
 +
 +
==vpl_run.sh==
 
<br />
 
<br />
 +
<source lang="bash">
 +
#! /bin/bash
 +
 +
cat > vpl_execution <<EOF
 +
#! /bin/bash
 +
 +
# --- Python ----
 +
if [[ `hostname -s` = "beowulf2" ]]; then
 +
  python=/usr/bin/python3.3
 +
else
 +
  python=/usr/local/bin/python3.4
 +
fi
 +
 +
prog=testLab7.py
 +
\$python \$prog
 +
 +
EOF
 +
 +
chmod +x vpl_execution
 +
 +
</source>
 
<br />
 
<br />
[[Category:Python]][[Category:CSC111]][[Category:Labs]]
+
==vpl_debug.sh==
 +
<br />
 +
<source lang="bash">
 +
</source>
 +
<br />
 +
==vpl_evaluate.sh==
 +
<br />
 +
<source lang="bash">
 +
#! /bin/bash
  
 +
cat  > vpl_execution <<EOF
 +
#! /bin/bash
  
 +
# --- Python ----
 +
if [[ `hostname -s` = "beowulf2" ]]; then
 +
  python=/usr/bin/python3.3
 +
else
 +
  python=/usr/local/bin/python3.4
 +
fi
  
  
  
</showafterdate>
+
\$python evaluate.py
 +
 
 +
EOF
 +
 
 +
chmod +x vpl_execution
 +
</source>
 +
<br />
 +
==vpl_evaluate.cases==
 +
<br />
 +
<source lang="text">
 +
</source>
 +
<br />
 +
==evaluate.py==
 +
<br />
 +
<source lang="python">
 +
# evaluate.py
 +
# D. Thiebaut
 +
# This program is used to test a student's python program on Moodle.
 +
 
 +
import sys
 +
import random
 +
import subprocess
 +
 
 +
#--- GLOBALS ---
 +
#--- define what the student program is called, and what the solution
 +
#--- program name is.
 +
 
 +
 
 +
module = "testLab7"
 +
solutionModule = module + "sol"
 +
userOutSplitPattern = ""      # pattern used to start recording the user
 +
                              # output.  Useful when program does several
 +
                              # input() statements, and user output starts
 +
                              # after that.
 +
stripOutputsBeforeCompare = True
 +
                              # set to True if extra spaces at beginning or
 +
                              # end of user output is ok
 +
 
 +
interpreter = sys.executable
 +
 
 +
def commentLong( line ):
 +
    print( "<|--\n" + line  + "\n --|>" )
 +
 
 +
def commentShort( text ):
 +
    print( "Comment :=>> " + text )
 +
 
 +
def printGrade( grade ):
 +
    print( "Grade :=>> ", grade )
 +
 
 +
# generateInputFileWithRandomInputs
 +
# generate a file with name "inputFileName" with some random input
 +
# for the program.
 +
# MAKE SURE TO EDIT THIS TO MATCH THE PROGRAM BEING TESTED
 +
def generateInputFileWithRandomInputs( inputFileName ):
 +
    #--- we don't need an input file for stdin, but we'll generate a
 +
    #--- dummy one nonetheless
 +
    open( inputFileName, "w" ).write( "\n\n\n\n\n\n\n" )
 +
 
 +
    #--- generate random inputs ---
 +
    return "\n"
 +
 
 +
# checkForFunctionPresence
 +
# checks that "functionName" is defined and called in the program.
 +
# MAKE SURE TO EDIT TO MATCH PROGRAM BEING TESTED
 +
def checkForFunctionPresence( module, functionName ):
 +
    foundDef = False
 +
    foundCall = False
 +
 
 +
    for line in open( module+".py", "r" ).readlines():
 +
        # remove comments
 +
        idx = line.find( "#" )
 +
        if ( idx >=0 ): line = line[0:idx]
 +
 
 +
        if line.startswith( "def " + functionName + "(" ):
 +
            foundDef = True
 +
            continue
 +
        if line.startswith( "def " + functionName + " (" ):
 +
            foundDef = True
 +
            continue
 +
        if line.find( functionName+"(" ) != -1:
 +
            foundCall = True
 +
            continue
 +
 
 +
    return (foundDef, foundCall)
 +
 
 +
 
 +
 
 +
# ==================================================================
 +
# NO EDITS NEEDED BELOW!
 +
# ==================================================================
 +
 
 +
def clearLog():
 +
    open( "log.txt", "w" ).write( "" )
 +
 
 +
def log( message ):
 +
    file = open( "log.txt", "a" )
 +
    file.write( message + "\n" )
 +
    file.flush()
 +
    file.close()
 +
 
 +
 
 +
# checkModuleRunsOK: runs the module as a shell subprocess and
 +
# look for errors in the output.  This is required, because otherwise
 +
# importing the module in this program will make this program crash.
 +
# It's not possible (as far as I can tell0 to catch exceptions from
 +
# the import or __module__ statements.
 +
# returns True, none if no errors, otherwise False, string if there's
 +
# an exception, and the error message (string) is in the returned 2nd
 +
# arg.
 +
# The module name is assumed to not include ".py"
 +
def checkModuleRunsOk( module, inputFileName ):
 +
    global interpreter
 +
    p = subprocess.Popen( [ interpreter, module+".py" ],
 +
                          stdout=subprocess.PIPE,
 +
                          stderr=subprocess.PIPE,
 +
                          stdin=subprocess.PIPE)
 +
 
 +
    #print( "inputFileName = ", inputFileName )
 +
    #print( "open( inputFileName, r).read() = ", open( inputFileName, "r" ).read() )
 +
 
 +
    p.stdin.write( bytes( open( inputFileName, "r" ).read(), 'UTF-8' ) )
 +
    data = p.communicate( )
 +
    p.stdin.close()
 +
 
 +
    error = data[1].decode( 'UTF-8' )
 +
    if len( error ) > 1:
 +
        return False, error
 +
    return True, None
 +
 
 +
 
 +
# extractTextFromErrorMessage( sys_exc_info ):
 +
def extractTextFromErrorMessage( sys_exc_info ):
 +
    print( "sys_exec_info = ", sys_exc_info )
 +
    text = ""
 +
    for field in sys_exc_info:
 +
        if type( field )==type( " " ):
 +
            text += field + "\n"
 +
    return text
 +
 
 +
# runModule:
 +
# runs the module, passes it data from the input file on its stdin
 +
# and get its output on stdout captured in outputFileName.
 +
# We assume the module will not crash, because we already tested
 +
# it with checkModuleRunsOk().
 +
def runModule( module, inputFileName, outputFileName ):
 +
    global userOutSplitPattern
 +
 
 +
    error = False
 +
 
 +
    #--- make stdin read information from the text file
 +
    sys.stdin = open( inputFileName, "r" )
 +
 
 +
    #--- capture the stdout of the program to test into a file
 +
    saveStdOut = sys.stdout
 +
    saveStdErr = sys.stderr
 +
 
 +
    sys.stdout = open( outputFileName, "w" )
 +
    sys.stderr = open( "errorOut", "w" )
 +
 
 +
    #--- run the student program ---
 +
    try:
 +
        _module = __import__(  module  )
 +
    except:
 +
        error = True
 +
        sys.stderr.close()
 +
        sys.stderr = saveStdErr
 +
        sys.stdout.close()
 +
        sys.stdout = saveStdOut
 +
        text = sys.exc_info()[0]
 +
        text = extractTextFromErrorMessage( text )
 +
        #print( "*** sys.exc_info() = ", text )
 +
        text = open( outputFileName, "r" ).read() + "\n" + text
 +
        return error, text
 +
 
 +
    #--- filter out junk from output of program ---
 +
    sys.stdout.close()
 +
    sys.stdout = saveStdOut
 +
    sys.stderr.close()
 +
    sys.stderr = saveStdErr
 +
 
 +
    file = open( outputFileName, "r" )
 +
    text = file.read()
 +
    score = 0
 +
    for line in text.split( "\n" ):
 +
        if line.find( "out" ) != -1:
 +
            words = line.split( " " )
 +
            for i in range( len( words ) ):
 +
                if words[i]=="out":
 +
                    #print( "words[i-1] =|%s|" % words[i-1] )
 +
                    try:
 +
                        score += int( words[i-1] )
 +
                    except:
 +
                        pass
 +
 
 +
    #print( text, end="" )
 +
    file.close()
 +
    return False, text, score
 +
 
 +
def removeBlankLines( lines ):
 +
    newLines = []
 +
    log( "removeBlankLines: lines = " + str( lines ) )
 +
    for line in lines.split( "\n" ):
 +
        if len( line )==0:
 +
            continue
 +
        newLines.append( line )
 +
 
 +
    return ( "\n".join( newLines ) ) + "\n"
 +
 
 +
def compareUserExpected( inputLines, userOutText, expectedOutText ):
 +
    global stripOutputsBeforeCompare
 +
 
 +
    log( "userOutText = " + userOutText )
 +
    log( "expectedOutText = " + expectedOutText )
 +
 
 +
    userOutText = removeBlankLines( userOutText )
 +
    expectedOutText = removeBlankLines( expectedOutText )
 +
    misMatchLineNumbers = []
 +
    userTextOutLines = userOutText.split( "\n" )
 +
    expectedOutTextLines = expectedOutText.split( "\n" )
 +
 
 +
    log( "-" * 60 )
 +
    log( "userTextOutLines = " + str( userTextOutLines ) )
 +
    log( "expectedOutTextLines = " + str( expectedOutTextLines ) )
 +
    log( "-" * 60 )
 +
 
 +
    for i in range( len( userTextOutLines ) ):
 +
        lineNo = i+1
 +
        userLine = userTextOutLines[i]
 +
        if i >= len( expectedOutTextLines ):
 +
            misMatchLineNumbers.append( lineNo )
 +
            break
 +
        expectedLine = expectedOutTextLines[i]
 +
        log( "comparing:\n  "+userLine+"\n  "+expectedLine )
 +
        if stripOutputsBeforeCompare:
 +
            userLine = userLine.strip()
 +
            expectedLine = expectedLine.strip()
 +
        if userLine != expectedLine:
 +
            log( "\ndifference: user    >" + userTextOutLines[i] + "<" )
 +
            log( "expected >" + expectedOutTextLines[i] + "<" )
 +
            misMatchLineNumbers.append( lineNo )
 +
 
 +
    return misMatchLineNumbers
 +
 
 +
 
 +
 
 +
def main():
 +
    global module
 +
    global solutionModule
 +
 
 +
    #--- clear debug log ---
 +
    clearLog()
 +
 
 +
    #--- check that the main module uses a main() function
 +
    foundDef, foundCall = checkForFunctionPresence( module, "main" )
 +
    """
 +
    if (not foundDef) or (not foundCall):
 +
        commentShort( "-Missing main() program" )
 +
        commentShort( "Your program must use a main() function." )
 +
        commentShort( "(make sure you spell it exactly \"main()\"!" )
 +
        printGrade( 40 )
 +
        return
 +
    """
 +
 
 +
    #--- generate input file with random data ---
 +
    inputLines = generateInputFileWithRandomInputs( "input" )
 +
 
 +
 
 +
    Ok, errorMessage = checkModuleRunsOk( module, "input" )
 +
    if not Ok:
 +
        commentLong( "- Your program crashed...\n"
 +
                    + "Error message:\n"
 +
                    + errorMessage + "\n" )
 +
        printGrade( 50 )
 +
        return
 +
 
 +
 
 +
    error, userOutText, score  = runModule( module, "input", "userOut" )
 +
    if error:
 +
        commentLong( "- Your program crashed...\n"
 +
                    + "Your program was tested with files containing:\n"
 +
                    + inputLines  + "\n"
 +
                    + "Error message:\n"
 +
                    + userOutText + "\n" )
 +
        printGrade( 53 + score)
 +
        return
 +
 
 +
    commentLong( "- Output of the test program:\n" + userOutText )
 +
    printGrade( (100-24*2) + score*2 )
 +
 
 +
main()
 +
 
 +
 
 +
 
 +
</source>
 +
<br />
 +
==testLab7.py==
 +
<br />
 +
<source lang="python">
 +
# testLab7.py
 +
# D. Thiebaut
 +
# This program tests all the functions for Lab 7.
 +
# To use this program, simply write a program called lab7.py and
 +
# store your functions in it.  The functions are expected to be
 +
# named isLeftSide(), isUpperHalf(), and getColor().
 +
# To test the the function, simply make sure that testLab7.py and
 +
# lab7.py are in the same directory, and run testLab7.py.  It will
 +
# automatically import lab7.py and call the different functions,
 +
# passing them parameters and checking the values returned by
 +
# the functions.
 +
 
 +
import sys
 +
import random      # that's the module that allows us to pick random quantities
 +
import lab7        # that's your hw6.py module.  We don't add ".py" to modules,
 +
                  # but the file containing the program must have ".py" at the end.
 +
 
 +
 
 +
# ---------------------------------------------------------------------
 +
def testIsLeftSide():
 +
    try:
 +
      score, total = testIsLeftSideb()
 +
      return score, total
 +
    except:
 +
      e = sys.exc_info()[0]
 +
      print( e )
 +
      print( "isLeftSide does not exist or crashed. 0 out of 8 points." )
 +
      return 0, 8
 +
 
 +
def testIsLeftSideb():
 +
    xyw      = [ (0, 100, 20, True), (9, 100, 20, True), (11, 100, 20, False), (20, 100, 20, False ),
 +
                  (0, 100, 100, True), (49, 100, 100, True), (51, 100, 100, False), (100, 100, 100, False ) ]
 +
    noTests    = len( xyw )
 +
 
 +
    numberGood = 0
 +
    for i in range( noTests ):
 +
        x, y, w, expected    = xyw[i]
 +
        try:
 +
            userOut =  lab7.isLeftSide( x, y, w )
 +
        except:
 +
            e = sys.exc_info()[0]
 +
            print( "isLeftSide crashed:", e )
 +
            return numberGood, noTests
 +
 
 +
        if type( userOut ) != type( expected ):
 +
            print( "isLeftSide does not return a boolean.  0 out of", noTests )
 +
            return 0, noTests
 +
        if expected == userOut:
 +
            numberGood = numberGood + 1
 +
        else:
 +
            print( ("isLeftSide( %d, %d, %d ) returns" % (x,y,w)), userOut, "instead of", expected  )
 +
 
 +
    print( "isLeftSide passes", numberGood, "out of", noTests, "tests." )
 +
    return numberGood, noTests
 +
 
 +
# ---------------------------------------------------------------------
 +
def testIsUpperHalf():
 +
    try:
 +
      score, total = testIsUpperHalfb()
 +
      return score, total
 +
    except:
 +
      e = sys.exc_info()[0]
 +
      print( e )
 +
      print( "isUpperHalf does not exist or crashed. 0 out of 8 points." )
 +
      return 0, 8
 +
 
 +
def testIsUpperHalfb():
 +
    xyw      = [ (100, 0, 20, True), (100,9, 20, True), (100, 11, 20, False), (100,20, 20, False ),
 +
                  (100, 0, 100, True), (100, 49, 100, True), (100, 51, 100, False), (100, 100, 100, False ) ]
 +
    noTests    = len( xyw )
 +
 
 +
    numberGood = 0
 +
    for i in range( noTests ):
 +
        x, y, w, expected    = xyw[i]
 +
        try:
 +
            userOut =  lab7.isUpperHalf( x, y, w )
 +
        except:
 +
            e = sys.exc_info()[0]
 +
            print( "isUpperHalf crashed:", e )
 +
            return numberGood, noTests
 +
 
 +
        if type( userOut ) != type( expected ):
 +
            print( "isUpperHalf does not return a boolean.  0 out of", noTests )
 +
            return 0, noTests
 +
        if expected == userOut:
 +
            numberGood = numberGood + 1
 +
        else:
 +
            print( ("isUpperHalf( %d, %d, %d ) returns" % (x,y,w)), userOut, "instead of", expected  )
 +
 
 +
    print( "isUpperHalf passes", numberGood, "out of", noTests, "tests." )
 +
    return numberGood, noTests
 +
 
 +
# ---------------------------------------------------------------------
 +
def testGetColor():
 +
    if True: #try:
 +
      score, total = testGetColorb()
 +
      return score, total
 +
    else: #except:
 +
      e = sys.exc_info()[0]
 +
      print( e )
 +
      print( "getColor does not exist or crashed. 0 out of 8 points." )
 +
      return 0, 8
 +
 
 +
def testGetColorb():
 +
    xywl      = [ (20, 20, 100, 100), (80, 20, 100, 100), (20, 80, 100, 100), (80, 80, 100, 100 ),
 +
                  (20, 20, 200, 200), (180, 20, 200, 200), (20, 180, 200, 200), (180, 180, 200, 200) ]
 +
 
 +
    noTests    = len( xywl )
 +
 
 +
    numberGood = 0
 +
    colors    = []
 +
    for i in range( noTests ):
 +
        if i%4 == 0:
 +
            colors = []
 +
        x, y, w, h  = xywl[i]
 +
        try:
 +
            userOut =  lab7.getColor( x, y, w, h )
 +
        except:
 +
            e = sys.exc_info()[0]
 +
            print( "getColor crashed:", e )
 +
            return numberGood, noTests
 +
 
 +
        if type( userOut ) != type( " " ):
 +
            print( ("getColor does not return a string when passed %d, %d, %d, %d." %
 +
                  (x, y, w, h)), ("%d out of %d" % ( numberGood, noTests ) ) )
 +
            return numberGood, noTests
 +
 
 +
 
 +
        if not userOut in colors:
 +
            colors.append( userOut )
 +
            numberGood = numberGood + 1
 +
        else:
 +
            print( ("getColor( %d, %d, %d, %d ) returns" % (x,y,w,h)),
 +
                  userOut, "which was already returned for another corner.\n",
 +
                  "There should be 4 distinct colors for the 4 corners." )
 +
 
 +
    print( "getColor passes", numberGood, "out of", noTests, "tests." )
 +
    return numberGood, noTests
 +
 
 +
 
 +
def main():
 +
    score  = 0
 +
    total  = 0
 +
 
 +
    numberGood, maxGood = testIsLeftSide()
 +
    score = score + numberGood
 +
    total = total + maxGood
 +
 
 +
 
 +
    numberGood, maxGood = testIsUpperHalf()
 +
    score = score + numberGood
 +
    total = total + maxGood
 +
 
 +
    numberGood, maxGood = testGetColor()
 +
    score = score + numberGood
 +
    total = total + maxGood
 +
 
 +
    print( "\nYour functions pass {0:1} tests out of {1:1}."
 +
          .format( score, total ) )
 +
 
 +
 
 +
main()
 +
 
 +
</source>
 +
<br />
 +
 
 +
 
 +
</onlydft>
 +
<br />
 +
<br />
 +
[[Category:Python]][[Category:CSC111]][[Category:Labs]]

Revision as of 19:05, 8 March 2015

--D. Thiebaut (talk) 17:49, 8 March 2015 (EDT)


<showafterdate after="20150311 12:00" before="20150601 00:00">

This page contains the information regarding the Moodle submission for CSC 111 Lab #7. You have until 3/13 11:00 a.m. to submit your program.

Moodle Submission


  • Write python program called lab7.py that contains only the following functions you wrote for the last challenges of Lab 7:
  • isLeftSide()
  • isUpperHalf()
  • getColor()
  • Your function will contain only these 3 functions. No main function. No graphics required. Your program will be called from a test program that will test your three functions separately.


Test Program


  • If you want to test your lab7.py using a similar test used by Moodle, simply create the program below in the same directory where you have stored lab7.py, and run it. It will test your lab7.py functions for you.


# testLab7.py
# D. Thiebaut
# This program tests all the functions for Lab 7.
# To use this program, simply write a program called lab7.py and
# store your functions in it.  The functions are expected to be
# named isLeftSide(), isUpperHalf(), and getColor().
# To test the the function, simply make sure that testLab7.py and 
# lab7.py are in the same directory, and run testLab7.py.  It will 
# automatically import lab7.py and call the different functions,
# passing them parameters and checking the values returned by
# the functions.

import sys
import random      # that's the module that allows us to pick random quantities
import lab7        # that's your hw6.py module.  We don't add ".py" to modules,
                   # but the file containing the program must have ".py" at the end.


# ---------------------------------------------------------------------
def testIsLeftSide():
    try:
       score, total = testIsLeftSideb()
       return score, total
    except:
       e = sys.exc_info()[0]
       print( e )
       print( "isLeftSide does not exist or crashed. 0 out of 8 points." )
       return 0, 8
    
def testIsLeftSideb():
    xyw       = [ (0, 100, 20, True), (9, 100, 20, True), (11, 100, 20, False), (20, 100, 20, False ),
                  (0, 100, 100, True), (49, 100, 100, True), (51, 100, 100, False), (100, 100, 100, False ) ]
    noTests    = len( xyw )
    
    numberGood = 0
    for i in range( noTests ):
        x, y, w, expected    = xyw[i]
        try:
            userOut =  lab7.isLeftSide( x, y, w )
        except:
            e = sys.exc_info()[0]
            print( "isLeftSide crashed:", e )
            return numberGood, noTests

        if type( userOut ) != type( expected ):
            print( "isLeftSide does not return a boolean.  0 out of", noTests )
            return 0, noTests
        if expected == userOut:
            numberGood = numberGood + 1
        else:
            print( ("isLeftSide( %d, %d, %d ) returns" % (x,y,w)), userOut, "instead of", expected  )

    print( "isLeftSide passes", numberGood, "out of", noTests, "tests." )        
    return numberGood, noTests

# ---------------------------------------------------------------------
def testIsUpperHalf():
    try:
       score, total = testIsUpperHalfb()
       return score, total
    except:
       e = sys.exc_info()[0]
       print( e )
       print( "isUpperHalf does not exist or crashed. 0 out of 8 points." )
       return 0, 8
    
def testIsUpperHalfb():
    xyw       = [ (100, 0, 20, True), (100,9, 20, True), (100, 11, 20, False), (100,20, 20, False ),
                  (100, 0, 100, True), (100, 49, 100, True), (100, 51, 100, False), (100, 100, 100, False ) ]
    noTests    = len( xyw )
    
    numberGood = 0
    for i in range( noTests ):
        x, y, w, expected    = xyw[i]
        try:
            userOut =  lab7.isUpperHalf( x, y, w )
        except:
            e = sys.exc_info()[0]
            print( "isUpperHalf crashed:", e )
            return numberGood, noTests

        if type( userOut ) != type( expected ):
            print( "isUpperHalf does not return a boolean.  0 out of", noTests )
            return 0, noTests
        if expected == userOut:
            numberGood = numberGood + 1
        else:
            print( ("isUpperHalf( %d, %d, %d ) returns" % (x,y,w)), userOut, "instead of", expected  )

    print( "isUpperHalf passes", numberGood, "out of", noTests, "tests." )        
    return numberGood, noTests

# ---------------------------------------------------------------------
def testGetColor():
    if True: #try:
       score, total = testGetColorb()
       return score, total
    else: #except:
       e = sys.exc_info()[0]
       print( e )
       print( "getColor does not exist or crashed. 0 out of 8 points." )
       return 0, 8
    
def testGetColorb():
    xywl       = [ (20, 20, 100, 100), (80, 20, 100, 100), (20, 80, 100, 100), (80, 80, 100, 100 ),
                   (20, 20, 200, 200), (180, 20, 200, 200), (20, 180, 200, 200), (180, 180, 200, 200) ]
 
    noTests    = len( xywl )
    
    numberGood = 0
    colors     = []
    for i in range( noTests ):
        if i%4 == 0:
            colors = []
        x, y, w, h   = xywl[i]
        try:
            userOut =  lab7.getColor( x, y, w, h )
        except:
            e = sys.exc_info()[0]
            print( "getColor crashed:", e )
            return numberGood, noTests

        if type( userOut ) != type( " " ):
            print( ("getColor does not return a string when passed %d, %d, %d, %d." %
                   (x, y, w, h)), ("%d out of %d" % ( numberGood, noTests ) ) )
            return numberGood, noTests


        if not userOut in colors:
            colors.append( userOut )
            numberGood = numberGood + 1
        else:
            print( ("getColor( %d, %d, %d, %d ) returns" % (x,y,w,h)), 
                   userOut, "which was already returned for another corner.\n",
                   "There should be 4 distinct colors for the 4 corners." )

    print( "getColor passes", numberGood, "out of", noTests, "tests." )        
    return numberGood, noTests

    
def main():
    score  = 0
    total  = 0

    numberGood, maxGood = testIsLeftSide()
    score = score + numberGood
    total = total + maxGood


    numberGood, maxGood = testIsUpperHalf()
    score = score + numberGood
    total = total + maxGood

    numberGood, maxGood = testGetColor()
    score = score + numberGood
    total = total + maxGood

    print( "\nYour functions pass {0:1} tests out of {1:1}."
           .format( score, total ) )


main()


</showafterdate>


...