生徒の努力は得点じゃなく、「音ゲー」ようなリザルト画面で評しました!
フランスの大学院で先生の仕事を行いながら、生徒のためにいつも新たな教え方を探しています。僕はプログラミングのレッソンを差し上げるので、そのお返しに生徒は応用問題をしなきゃいけません。
会社に仕事でも、学校の教育でも、先輩からもらったの感謝は第一な事って僕が絶対に思います。今回は先生として、その先輩になるだからこそ、感謝の正しい伝え方を探しに行きました。生徒の努力がちゃんと認めたら、自然に頑張ります。
生徒は得点を持ったなければならなくても、その先、応用問題がよくできたかどうかは伝えたい。でも結局、それは十分じゃないだと思いました。最初は、応用問題に関して生徒の努力をはっきり感謝したい。そうしたら頑張らなかった生徒は悔しいくて盛り上がって、よく頑張った生徒はもっと頑張ります。
得点のかわりは、何?
勇気付けられる物を考えたら「音ゲー」を思いだした、すなわち、リズムゲームです。一曲を遊んだ後で、リザルト画面は文字スコアで性能を見せます。
あまりできなくたら「B」スコアを当たって、普通にクリアしたら「A」スコアがあって、もっと上手なできたら「S」スコアがあって、それに完璧だったら「SSS」スコアもあります。これで性能はわかりやすいし、なら次回はもっと頑張りたいの感じがします。
これを思い出したとたん、文字スコアの利用をすぐに決めました。
上のイメージ通り、文字スコアは一番大きいテキストですね。その他は、細かいことについてのデータが見せます。そのリザルト画面は基本的に明るくて、かっこくて、そして前回からの伸びがわかります。
文字スコアだけじゃなく、応用問題についての細かい説明がいいでしょう。例えばソースコードに関して評価が差し上げますね。応用問題の目的がちゃんとできたかどうか、構文規則が悪くかどうか、バグが多いかどうか。
その上maimaiの画面は、プレイの時間と場所が見えます。じゃあ、応用問題の名前と日付も書きましょうか。
リザルト画面のやり方
最初はどこかで生徒の評価を書きなければなりません。簡単な記入のために、エクセル表計算のほうがいいだっと思った。その表計算は後でPythonで読みやすいし、そして余白イメージにデータを印刷するつもりです。
テンプレートのイメージ
さって、その印刷されられるイメージを作りましょう。いつも通り僕はAffinity Designerを使いますが、別のソフトでも大丈夫です。
後でPythonはイメージにテキストを印刷するので、空欄は必要でしょう。なんかリズムゲームのように感じがしたいから、カラフルと読みやすいのデザインでやりました。このファイルはtemplate.pngというにしましょう。
テキストを印刷ために、空欄の座標を書いておきましょう。イメージ本体のサイズは2048px*1024pxで、応用問題の名前の空欄は1296*196から始まるし、日付の空欄は1298*902から始まるし、などなど。
そして、全部の可能の文字スコアは別のイメージでおいて置きましょう。
表計算の用意
評価はある表計算にまとめるつもりので、準備しましょう。上側には応用問題の名前、日付、関してレッソンの名前を書いておきます。次は、一行一人で生徒の評価が書いておきます。
Pythonを使うときのため、データはどこに置いたを覚えましょう。応用問題の名前は「B1」セル、日付は「D1」セル、レッソンは「F1」セルで置いておきました。そして二番の列のあとは、生徒の評価。一番目の生徒のランクは「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はこちらです。