Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
januschung authored Sep 20, 2020
1 parent e08097e commit 4c0a12b
Show file tree
Hide file tree
Showing 4 changed files with 206 additions and 0 deletions.
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Maths Worksheet Generator

![sample worksheet](sample.png)

## Background
One of my best friends is training his 5 years old with basic addition questions from store-bought material. Good for one time usage as kid is smart enough to memorize the answers. He wants to give him more practice.

Two solutions:
1. keep buying more one time usage materials (less beer budget); or
2. make question sets with the number pairs and calculate the answer for each question manually (less beer time)

Not ideal.

That's the reason for me to look into an automate way to get the job done.

## Benefit of the Maths Worksheet Generator
You can generate as many non duplicated questions as you need with the answer sheet in a fraction of second.

There are four choices:
1. Addition
2. Subtraction
3. Multiplication
4. Mixed

## Requirements
1. [python3](https://www.python.org/downloads/)
2. [fpdf](https://pypi.org/project/fpdf/)

## How to Use
1. Generate the worksheet in pdf format with the following command:
```
python3 run.py --type [+|-|x|mix]
```
For example, for addition only worksheet, use the following command:
```
python3 run.py --type +
```
3. Print out the generated file `worksheet.pdf`

## Sample
[sample worksheet](sample-worksheet.pdf)

## Code Overview
Everything is written in python in `run.py`. You can play with the font and gird size with the variables under the `# Basic settings` section.

## Contributing
Any suggestion will be appreciated. You can simply create a pull request with your idea. Feel free to fork the project too.

## Special Thanks
My long time friend San for the inspiration of this project and lovely sons Tim and Hin.
156 changes: 156 additions & 0 deletions run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import argparse
import random
from fpdf import FPDF


class maths_worksheet_generator():
pdf = FPDF()
# Basic settings
small_font_size = 10
middle_font_size = 15
large_font_size = 30
size = 21
tiny_pad_size = 2
pad_size = 10
large_pad_size = 30
num_x_cell = 4
num_y_cell = 2
total_question = 80 # Must be a multiple of 40
font_1 = 'Times'
font_2 = 'Arial'

def generate_question(self, type):
# Generate each question and calculate the answer depending on the type in a list
# To keep it simple, number is generated randomly within the range of 0 to 100
num_1 = random.randint(0, 100)
num_2 = random.randint(0, 100)
if type == 'mix':
type = random.choice(['+', '-', 'x'])
if type == '+':
answer = num_1 + num_2
elif type == '-':
answer = num_1 - num_2
elif type == 'x':
answer = num_1 * num_2
else:
raise RuntimeError('Question type {} not supported'.format(type))
return [num_1, type, num_2, answer]

def get_list_of_questions(self, type):
# Generate all the questions for the worksheet in a list
questions = []
while len(questions) < self.total_question:
new_question = self.generate_question(type)
if new_question not in questions:
questions.append(new_question)
return questions

def make_question_page(self, data):
# Prepare a single page of question
total_page = int(self.total_question / (self.num_x_cell * self.num_y_cell))
for page in range(0, total_page):
self.pdf.add_page(orientation='L')
self.print_question_row(data, (page) * (2 * self.num_x_cell))
self.print_horizontal_seperator()
self.print_question_row(data, (page) * (2 * self.num_x_cell) + self.num_x_cell)

def print_top_row(self, question_num):
# Helper function to print first row of a question
self.pdf.set_font(self.font_1, size=self.middle_font_size)
self.pdf.cell(self.pad_size, self.pad_size, txt=question_num, border='LT', ln=0, align='C')
self.pdf.cell(self.size, self.pad_size, border='T', ln=0, align='C')
self.pdf.cell(self.size, self.pad_size, border='T', ln=0, align='C')
self.pdf.cell(self.pad_size, self.pad_size, border='TR', ln=0, align='C')

def print_second_row(self, num):
# Helper function to print second row of a question
self.pdf.set_font(self.font_2, size=self.large_font_size)
self.pdf.cell(self.pad_size, self.size, border='L', ln=0, align='C')
self.pdf.cell(self.size, self.size, border=0, ln=0, align='C')
self.pdf.cell(self.size, self.size, txt=str(num), border=0, ln=0, align='R')
self.pdf.cell(self.pad_size, self.size, border='R', ln=0, align='C')

def print_third_row(self, num, type):
# Helper function to print third row of a question
self.pdf.set_font(self.font_2, size=self.large_font_size)
self.pdf.cell(self.pad_size, self.size, border='L', ln=0, align='C')
self.pdf.cell(self.size, self.size, txt=type, border=0, ln=0, align='L')
self.pdf.cell(self.size, self.size, txt=str(num), border=0, ln=0, align='R')
self.pdf.cell(self.pad_size, self.size, border='R', ln=0, align='C')

def print_bottom_row(self):
# Helper function to print bottom row of question
self.pdf.set_font(self.font_2, size=self.large_font_size)
self.pdf.cell(self.pad_size, self.size, border='LB', ln=0, align='C')
self.pdf.cell(self.size, self.size, border='TB', ln=0, align='C')
self.pdf.cell(self.size, self.size, border='TB', ln=0, align='R')
self.pdf.cell(self.pad_size, self.size, border='BR', ln=0, align='C')

def print_edge_vertical_seperator(self):
# Print space between question for the top or bottom row
self.pdf.cell(self.pad_size, self.pad_size, border=0, ln=0)

def print_middle_vertical_seperator(self):
# Print space betwen question for the second or third row
self.pdf.cell(self.pad_size, self.size, border=0, ln=0)

def print_horizontal_seperator(self):
# Print line breaker between two rows of questions
self.pdf.cell(self.size, self.size, border=0, ln=0, align='C')
self.pdf.ln()

def print_question_row(self, data, offset):
# Print a single row of questions (total question in a row is set by num_x_cell)
for x in range(0, self.num_x_cell):
self.print_top_row(str(x + 1 + offset))
self.print_edge_vertical_seperator()
self.pdf.ln()
for x in range(0, self.num_x_cell):
self.print_second_row(data[x + offset][0])
self.print_middle_vertical_seperator()
self.pdf.ln()
for x in range(0, self.num_x_cell):
self.print_third_row(data[x + offset][2], data[x + offset][1])
self.print_middle_vertical_seperator()
self.pdf.ln()
for _ in range(0, self.num_x_cell):
self.print_bottom_row()
self.print_edge_vertical_seperator()
self.pdf.ln()

def make_answer_page(self, data):
# Print answer sheet
self.pdf.add_page(orientation='L')
self.pdf.set_font(self.font_1, size=self.large_font_size)
self.pdf.cell(self.large_pad_size, self.large_pad_size, txt='Answers', border=0, ln=1, align='C')

for i in range(len(data)):
self.pdf.set_font(self.font_1, size=self.small_font_size)
self.pdf.cell(self.pad_size, self.pad_size, txt='{}:'.format(i+1), border='TLB', ln=0, align='R')
self.pdf.set_font(self.font_2, size=self.small_font_size)
self.pdf.cell(self.pad_size, self.pad_size, txt=str(data[i][3]), border='TB', ln=0, align='R')
self.pdf.cell(self.tiny_pad_size, self.pad_size, border='TRB', ln=0, align='R')
self.pdf.cell(self.tiny_pad_size, self.pad_size, border=0, ln=0, align='C')
if (i+1) >= 10 and (i+1) % 10 == 0:
self.pdf.ln()


def main(type):
new_pdf = maths_worksheet_generator()
seed_question = new_pdf.get_list_of_questions(type)
new_pdf.make_question_page(seed_question)
new_pdf.make_answer_page(seed_question)
new_pdf.pdf.output("worksheet.pdf")


if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Generate Maths Addition/Subtraction/Multiplication Exercise Worksheet')
parser.add_argument('--type', default='+', choices=['+', '-', 'x', 'mix'],
help='type of calculation: '
'+: Addition; '
'-: Substration; '
'x: Multipication; '
'mix: Mixed; '
'(default: +)')
args = parser.parse_args()
main(args.type)
Binary file added sample-worksheet.pdf
Binary file not shown.
Binary file added sample.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 4c0a12b

Please sign in to comment.