メインコンテンツまでスキップ

ケース1. 入出力に基づく採点

基本設定されたファイル構造の中で、以下のフォルダ&ファイルを追加します。

  • inputフォルダ / outputフォルダ : 採点のためのテストケースを定義します。
  • testcases.pyファイル : 各テストケースごとに部分点数および正誤メッセージを設定します。

  • inputフォルダ
    • テストケースごとに入力値をtxtファイルとして保存します。
    • 各ケースごとに1つの入力値を保存します。
  • outputフォルダ
    • テストケースごとに出力値をtxtファイルとして保存します。
    • inputフォルダに書き込んだ各入力値に応じた出力値を保存します。

2. 採点メッセージの作成

テストケースで設定した各項目ごとに正誤メッセージを定義します。
また、各テストケースごとに部分点数を設定します。

# testcaseごとの正答メッセージ
correct_messages = [
"テストケース1. 正解です!",
"テストケース2. 正解です!"
]

# testcaseごとの誤答メッセージ
wrong_message = [
"テストケース1. 不正解です!",
"テストケース2. 不正解です!"
]

# testcaseごとの部分点数
scores = [50, 50]

3. grader.py 採点コードの作成

テストケースの数だけ学生が書いたコードを実行し、学生が作成したコードの出力結果を確認します。その後、予測した正解出力値(outputファイル)と一致するかどうかを比較し、実習の正誤を判断します。

各テストケースごとに部分点数を提供することができ、最終採点結果は elice_utils.secure_send_score(total_score) を通じてプラットフォーム(LXP)内に送信します。

例示コードは以下の通りです。

import os
import subprocess
import sys
from testcases import *
sys.path.append(os.getcwd())
from grader_elice_utils import EliceUtils # isort:skip

elice_utils = EliceUtils()
elice_utils.secure_init()

SUM_TESTCASE_SCORES = 100
INPUT_DIR = '.elice/input/'
OUTPUT_DIR = '.elice/output/'

try:
total_score = 0

# 0. input, outputファイルを読み込む
input_data = [x for x in os.listdir(INPUT_DIR) if x.endswith('.txt')]
output_data = [x for x in os.listdir(OUTPUT_DIR) if x.endswith('.txt')]

# 1. テストケースの数を確認する
if len(input_data) != len(output_data):
sys.exit(1)
NUM_TESTCASES = len(input_data)

# 2. ファイル名を確認する
matching = True
for i in range(1, NUM_TESTCASES + 1):
input_file = '%d.txt' % i
output_file = '%d.txt' % i

if input_file not in input_data:
matching = False
if output_file not in output_data:
matching = False
if not matching:
sys.exit(1)

# 3. テストケースごとの採点を進める
for i in range(0, NUM_TESTCASES):
testcase_score = scores[i]
input_file = '%d.txt' % (i+1)

input_text = subprocess.run(['cat', '%s%s' % (INPUT_DIR, input_file)],
stdout=subprocess.PIPE).stdout
result = subprocess.run(['/bin/bash', '.elice/runner.sh'],
input=input_text,
stdout=subprocess.PIPE)
student_result = result.stdout.decode('utf-8')

answer = ''.join(open('%s%s' % (OUTPUT_DIR, input_file)).readlines())

student_result = student_result.strip()
answer = answer.strip()

# テストケースごとの正誤判断
if answer == student_result:
total_score += testcase_score # テストケース部分点数追加
elice_utils.secure_send_grader('✅ {} \n'.format(correct_messages[i]))

else:
elice_utils.secure_send_grader('❌ {} \n'.format(wrong_message[i]))

# 5. 実習最終得点計算
total_score = int(total_score)
elice_utils.secure_send_score(total_score)

except Exception as err:
elice_utils.secure_send_grader('採点中にエラーが発生しました。コードが正常に実行されているか確認してください。\n')
elice_utils.secure_send_score(0)
sys.exit(1)