Of course if you would like the ability to tailor the level you could paste the following into a file called, math_quiz.py:
#!/usr/bin/env python
#coding:utf-8
"""
Author: Steve Barnes
Purpose: Provide some maths practice
Created: 11/07/2015
This module should allow some maths practice against the clock.
Set the level of difficulty by adding a number 0-9 to the command line.
"""
from __future__ import print_function
import sys
import random
import datetime
import os
import pickle
# Note that other operands such as dev, modulo, int dev, etc could be added but
# the check for correct would need to use floats and to specify a limit to the
# number of characters and rounding level of result to avoid irrational numbers
LOD2Options = { # Dictionary of the level of difficulty v. range and operations
0:(5, ['+',], 1, 5),
1:(10, ['+', '-'], 1, 5),
2:(100, ['+', '-'], 1, 4),
3:(1000, ['+', '-'], 2, 3),
4:(20, ['+', '-', '*'], 2, 2),
5:(200, ['+', '-', '*'], 2, 2),
6:(250, ['+', '-', '*'], 3, 2),
7:(1000, ['+', '-', '*'], 3, 1),
8:(3000, ['+', '-', '*'], 3, 1),
9:(6000, ['+', '-', '*'], 4, 1),
}
def CreateProblem(MaxNum, Ops, Parts):
""" Generate the problem."""
Steps = [str(random.randint(0, MaxNum))] # First number
for n in range(Parts):
Steps.append(random.choice(Ops)) # Add an operand
Steps.append(str(random.randint(0, MaxNum))) # Next Number
Problem = ' '.join(Steps) # Generate the string
Solution = str(eval(Problem)) # and the answer
return (Problem, Solution)
def DoQuiz(LoD):
""" Actually perform the quiz - return the score the and time taken."""
(MaxNum, Ops, Parts, Tries) = LOD2Options.get(LoD)
NoQuestions = 10
QnAs = [CreateProblem(MaxNum, Ops, Parts) for n in range(NoQuestions)]
Score = 0
Started = datetime.datetime.now()
for n in range(NoQuestions):
Correct = False
(Quest, Ans) = QnAs[n]
for trys in range(Tries):
response = raw_input(Quest+' = ')
Correct = response == Ans
if Correct:
Score += 1
break
print(Correct and "Correct" or " = ".join([Quest, Ans]))
Finished = datetime.datetime.now()
return (Score, Finished-Started)
def GetLod(arg):
""" Get the level of difficulty."""
LoD = arg
while LoD not in [str(x) for x in range(10)]:
LoD = raw_input('Please enter diffulty level [0..9]:')
return int(LoD)
def ShowSaveStats(LoD, Score, Time):
""" Show the scores, including cumative, and save for future."""
score_filename = os.path.join(os.path.expanduser('~'), 'MathQuiz.scores')
scores = None
if os.path.exists(score_filename):
with open(score_filename) as scorefile:
scores = pickle.load(scorefile)
if not scores:
scores = {}
for n in range(10):
scores[n] = (0, 0, None, None, 0, None)
(Runs, MaxScore, BestTimeForScore, WhenBest, LatestScore,
LatestTime) = scores[LoD]
print('Results form this run: %s/10 in %s at level %s' % (Score, Time, LoD))
print('Last Run at %s: %s/10 in %s' % (LoD, LatestScore,
LatestTime))
print('Best %s/10 Level %s was %s on %s' % (MaxScore, LoD,
BestTimeForScore,
WhenBest))
NewBest = False
if Score > MaxScore:
print('%s/10 is a new best score for level %s' % (Score, LoD))
NewBest = True
if Score == MaxScore and Time < BestTimeForScore:
print('Fastest time for %s/10 at level %s' % (Score, LoD))
if not BestTimeForScore or Time < BestTimeForScore:
print('NEW BEST TIME FOR %s/10 AT THIS LEVEL %s vs %s' % (
Score, Time, BestTimeForScore))
NewBest = True
if NewBest:
newentry = (Runs+1, Score, Time,
datetime.datetime.now(), Score, Time)
else:
newentry = (Runs + 1, MaxScore,
BestTimeForScore, WhenBest,
Score, Time)
scores[LoD] = newentry
try:
with open(score_filename, 'w') as scorefile:
pickle.dump(scores, scorefile)
except (IOError), e:
print('Error writing to %s' % score_filename)
print(e)
if __name__ == '__main__':
if len(sys.argv) > 1 and sys.argv[1].lower() in ['-h', '?', '--help']:
print(__doc__)
else:
sys.argv.append(' ')
LoD = GetLod(sys.argv[1])
Score, Time = DoQuiz(LoD)
ShowSaveStats(LoD, Score, Time)
And then either run it with:
python math_quiz.py
or change the file type to executable.
You can then consider modifying the levels and/or enhancing the code to add more operators, time limits, etc.