フランスの大学院で先生の仕事をしながら、生徒のためにいつも新たな教え方を探しています。僕はプログラミングのレッスンをしているので、課題として生徒は応用問題を解かなければいけません。
会社に仕事、学校の教育でも、先輩からもらった感謝が第一であるって僕は絶対に思います。今回は先生として、先輩になるからこそ、感謝の正しい伝え方を探しました。生徒の努力をちゃんと認めたら、自然に頑張ります。
生徒には得点を伝えなければならないけれど、応用問題がよくできたかどうかも伝えたい。でも結局、それは十分じゃないと思いました。最初は、応用問題に関して生徒の努力をはっきり感謝したい。そうしたら頑張らなかった生徒は悔しくてやる気になって、よく頑張った生徒はもっと頑張ります。
得点のかわりは、何?
勇気付けられる物を考えたら「音ゲー」、すなわちリズムゲームを思いだしました。一曲遊んだ後で、リザルト画面は文字スコアで評価を見せます。
あまりできなかったら「B」スコアになり、普通にクリアしたら「A」スコアがあって、もっと上手にできたら「S」スコアがあって、それに完璧だったら「SSS」スコアがあります。これなら評価はわかりやすいし、なら次回はもっと頑張りたい、と感じるようになります。
これを思い出したとたん、文字スコアの利用をすぐに決めました。
「チュウニズム」アケードゲームのリザルト画面(©SEGA)️
上の画像のように、文字スコアは一番大きいテキストですね。その他は、細かいことについてのデータが見れます。リザルト画面は基本的に明るくて、かっこよくて、そして前回からの伸びがわかります。
文字スコアだけじゃなく、応用問題についての細かい説明も表示するのがいいでしょう。例えばソースコードに関して評価をします。そして応用問題の目的がちゃんとできたかどうか、構文規則が悪いかどうか、バグが多いかどうかも表示します。
「maimai」アケードゲームのリザルト画面(©SEGA)️
その上maimaiの画面では、画面下にプレイした時間と場所が見れます。それでは、応用問題の名前と日付も書きましょうか。
リザルト画面のやり方
まずどこかのファイルに生徒の評価を書かなければなりません。簡単な記入のために、エクセルがいいと思いました。エクセルファイルは後でPythonで読みやすいし、そして余白イメージにデータを印刷するつもりです。
テンプレートのイメージ
さて、印刷されられるイメージを作りましょう。いつも通り僕はAffinity Designerを使いますが、別のソフトでも大丈夫です。
後でPythonでイメージにテキストを印刷するので、空欄が必要です。リズムゲームのような感じにしたいから、カラフルで読みやすいデザインにしました。このファイルはtemplate.png
という名前にしましょう。
例のために日本語に変えちゃった
テキストを印刷するために、空欄の座標を書いておきましょう。イメージ本体のサイズは2048px*1024pxで、応用問題の名前の空欄の座標は(1296,196)、日付の空欄の座標は(1298,902)、などなど。
そして、使用可能なすべての文字スコアは別のイメージでおいて置きましょう。
文字スコアのイメージ
エクセルファイルの用意
評価はあるエクセルファイルにまとめるつもりなので、準備しましょう。1行目には応用問題の名前、日付、レッスンの名前を書いておきます。以降、一行一人、生徒の評価を書いておきます。
エクセルファイルの例
Pythonを使うときのため、データがどこにあるかを覚えましょう。応用問題の名前は「B1」セル、日付は「D1」セル、レッスン名は「F1」セルです。そして3行目からは、生徒の評価です。一番目の生徒のランクは「C3」セル、構文規則ランクは「D3」セル、などなど。
このファイルはnotes.xslx
としましょう。
Pythonで読んで印刷
テンプレートイメージとエクセルファイルが完成したら、Pythonで生徒の結果のイメージが印刷できます。
import os
import argparse
from PIL import Image, ImageDraw, ImageFont
from openpyxl import load_workbook
#色んなサイズのフォントの準備
font_bold_60 = ImageFont.truetype("MPLUS1p-Bold.ttf", 60)
font_bold_52 = ImageFont.truetype("MPLUS1p-Bold.ttf", 52)
font_bold_28 = ImageFont.truetype("MPLUS1p-Bold.ttf", 28)
font_medium_32 = ImageFont.truetype("MPLUS1p-Medium.ttf", 28)
#argparseのおかげで使いやすくなります
parser = argparse.ArgumentParser(description="ある応用問題の結果を印刷差し上げます。")
parser.add_argument("spreadsheet", help="表計算ファイルの名前")
args = parser.parse_args()
#ファイルを開く
excel = load_workbook(args.spreadsheet)
#一番目の表計算を使う
sheet = excel.active
#データを読んでおきます
exercice_name = sheet["B1"].value
exercice_date = sheet["D1"].value
exercice_lesson = sheet["F1"].value
#3行目から表計算を読んで、10列目まで
for row in sheet.iter_rows(min_row=3, max_col=10, values_only=True):
#一つ行からデータを引き出す
lastname, firstname, rank, syntax_rank, syntax_note, objective_rank, objective_note, quality_rank, quality_note, notes = row
#ランクがない場合は多分、結果の打ち込みがまだ
if rank is None:
print(f"空きランク、スキップ...")
continue
print(f"--> {lastname} {firstname} ● ランク {rank}")
#テンプレートのイメージを開く
with Image.open("template.png") as im:
draw = ImageDraw.Draw(im)
# テキストの印刷
draw.text((92, 80), f"{lastname}\n{firstname}", font=font_bold_52, fill=(0,0,0))
#anchor="mm"の意味は、中央揃えで書く
draw.text((1296, 196), exercice_name, font=font_bold_60, anchor="mm", fill=(255,255,255))
draw.text((1298, 902), exercice_date.strftime("%d/%m/%Y"), font=font_bold_28, fill=(0,0,0))
draw.text((1610, 902), exercice_lesson, font=font_bold_28, fill=(0,0,0))
#ここからは複数行テキスト
draw.multiline_text((500, 384), syntax_note or "", font=font_medium_32, anchor="lm", fill=(0,0,0))
draw.multiline_text((500, 544), objective_note or "", font=font_medium_32, anchor="lm", fill=(0,0,0))
draw.multiline_text((500, 704), quality_note or "", font=font_medium_32, anchor="lm", fill=(0,0,0))
draw.multiline_text((280, 870), notes or "", font=font_medium_32, anchor="lm", fill=(255,255,255))
#文字ランクのイメージのサイズが違っているので、
#中央揃えのために、正しいx位置を書いておこう
ranks_x_position = {
"B": 1496,
"A": 1466,
"S": 1490,
"SS": 1384,
"SSS": 1278
}
#文字ランクのイメージの印刷
with Image.open(f"rank_{rank}.png") as im_rank:
im.paste(im_rank, (ranks_x_position[rank], 486), im_rank)
#構文規則ランクのイメージの印刷
with Image.open(f"rank_{syntax_rank}.png") as im_syntax_rank:
im_syntax_rank.thumbnail((94, 94))
im.paste(im_syntax_rank, (380 if syntax_rank != "A" else 375, 340), im_syntax_rank)
#目的ランクのイメージの印刷
with Image.open(f"rank_{objective_rank}.png") as im_objective_rank:
im_objective_rank.thumbnail((94, 94))
im.paste(im_objective_rank, (380 if objective_rank != "A" else 375, 500), im_objective_rank)
#コード質のイメージの印刷
with Image.open(f"rank_{quality_rank}.png") as im_quality_rank:
im_quality_rank.thumbnail((94, 94))
im.paste(im_quality_rank, (380 if quality_rank != "A" else 375, 660), im_quality_rank)
#最後はイメージを保存する
im.save(f"{firstname} {lastname} - {exercice_name}.png")
スクリプトを実行する前に、フォントのファイルをダウンロードしなきゃいけません。たとえばM+1フォントはGoogle Fontsからみつけます。そして、スクリプトはprinter.py
でnotes.xlsx
のエクセルファイルを使いたかったら、ターミナルで実行のはこのようになります。
$ python printer.py notes.xlsx
数秒後、一生徒一枚のイメージが保存されます。
できたイメージはこういうものです。
生徒たちへの影響
多分、一番知りたいことでしょうか。基本的に、生徒が自分の能力をちゃんとわかるように、そして後でどうしたらいいかわかるようにするために、役に立ったと思います。
それなのに、次の応用問題を提出してもらったときに、たまに同じミスや悪いやり方を見つけました。その原因はいろいろだと思います。おそらく僕の説明が明らでなかったとか、締め切りの前に生徒が忙し過ぎたとか。だからこそ責任は生徒だけじゃなく、学校や先生にもあると思います。
とりあえず、結果の新しい伝え方がみつけられてうれしいです。せめて生徒が応用問題の結果をもっと気になって、次の応用問題に役立ててくれればうれしいです。
読んでいただきありがとうございます。このトピックで話したいなら、ツイッターは@komanakun、Wantedlyはこちら、LinkedInプロフはこちらです。