객관식 문제 채점 프로그램 (python)
- 목차
용도 : 시험 대비 등을 위하여 같은 문제를 여러 번 반복해서 풀어보기 위해 책 대신 다른 곳에 답을 적을 때 이 프로그램에 답을 입력, (답안 텍스트 파일을 설정 시) 채점까지 대신해준다.
기능
1. 프로그램 내 타이머가 있어 시간 제한을 둘 수 있다.
2. 답안 텍스트 파일을 통해 채점을 대신하여 합불합 여부를 알려준다. (과락인지 종합 점수 부족인지 또한 알려준다.)
3. 성적이 향상했는지 확인할 수 있도록 결과를 저장할 수 있다.
주의사항 : 답안 텍스트 파일 작성시 한 줄에 10문제씩 입력해야한다. (연습문제 한정, 모의고사는 관계 없음)
사용법 예시1 - 연습문제
연습문제 버튼을 클릭하여 문항수와 시간을 설정하고 확인을 누르면 아래와 같은 시험창이 뜬다.
띄어쓰기 없이 답을 입력한다.
코드를 대충 짜서 한 줄에 답을 열개 이상 입력해도 입력은 된다. 그래도 채점에는 들어가지 않는다.
이후 제출하기를 클릭하면 답안 텍스트 파일을 선택해야한다.
위 그림처럼 한 줄에 10문제의 답을 적어 텍스트 파일을 만들어 이 파일을 선택해주면 아래와 같은 결과창이 뜬다.
사용법 예시2 - 모의고사
실제 시험처럼 과목 수, 과목별 점수컷, 전체 점수컷을 입력해준다.
이후 과목별 문항수와 시간을 입력하고 확인을 누르면 아래와 같은 시험창이 뜬다.
(1과목 5문제, 2과목 5문제, 3과목 10문제로 설정)
오른쪽의 < , > 버튼으로 과목을 바꿔가며 답을 입력해준다.
시간이 다 되거나 제출하기를 클릭하고 답안 파일을 선택하면 아래와 같은 결과창이 뜬다.
마찬가지로 오른쪽의 < , > 버튼으로 과목을 변경할 수 있다.
결과 저장을 누르고 저장할 파일의 이름을 입력해주면
이같은 텍스트 파일을 생성한다.
전체 코드
from tkinter import *
import tkinter.font as font
import os
import tkinter.messagebox as msgbox
import time
from tkinter import filedialog
root = Tk()
root.title("채점 프로그램")
root.geometry("200x280")
root.resizable(False,False)
root.focus_set()
frame_button = Frame(root)
frame_button.pack(fill='both', expand=True)
# 연습문제
def practice():
root_practice = Tk()
root_practice.title("연습문제")
root_practice.focus_force()
root_practice.resizable(False, False)
frame_practice = Frame(root_practice)
frame_practice.pack(fill='both', expand=True)
# 연습문제 정보 입력 (문항, 시간)
label_prac_num = Label(frame_practice, text='문항 수', font=font.Font(size=12))
label_prac_num.grid(row=0, column=0, padx=5, pady=5, sticky=N+E+W+S)
entry_prac_num = Entry(frame_practice, font=font.Font(size=12))
entry_prac_num.grid(row=0, column=1, columnspan=5, padx=5, pady=5, sticky=N+E+W+S)
label_prac_time = Label(frame_practice, text='시간(시:분:초)', font=font.Font(size=12))
label_prac_time.grid(row=1, column=0, padx=3, pady=3, sticky=N+E+W+S)
entry_prac_time_h = Entry(frame_practice, font=font.Font(size=12), width=2)
entry_prac_time_h.grid(row=1, column=1, padx=3, pady=3, sticky=N+E+W+S)
label_prac_time_c1 = Label(frame_practice, text=':', font=font.Font(size=12))
label_prac_time_c1.grid(row=1, column=2, sticky=N+E+W+S)
entry_prac_time_m = Entry(frame_practice, font=font.Font(size=12), width=2)
entry_prac_time_m.grid(row=1, column=3, padx=1, pady=3, sticky=N+E+W+S)
label_prac_time_c2 = Label(frame_practice, text=':', font=font.Font(size=12))
label_prac_time_c2.grid(row=1, column=4, sticky=N+E+W+S)
entry_prac_time_s = Entry(frame_practice, font=font.Font(size=12), width=2)
entry_prac_time_s.grid(row=1, column=5, padx=3, pady=3, sticky=N+E+W+S)
label_prac_time_c = Label(frame_practice,
text='문항수는 최대 200개입니다.'
+'\n시간을 0으로 설정하면 시간제한 없이 진행합니다.')
label_prac_time_c.grid(row=2, column=0, columnspan=6, padx=5, pady=5, sticky=N+E+W+S)
frame_practice2 = Frame(root_practice)
frame_practice2.pack(fill='both', expand=True)
# 정보 입력 완료
def prac_ok():
global now_str, now, isgrading
isgrading = False
prac_num = entry_prac_num.get()
prac_time_h = entry_prac_time_h.get()
prac_time_m = entry_prac_time_m.get()
prac_time_s = entry_prac_time_s.get()
try :
prac_num = int(prac_num)
prac_time_h = int(prac_time_h)
prac_time_m = int(prac_time_m)
prac_time_s = int(prac_time_s)
except :
msgbox.showerror("오류", "알맞은 숫자를 입력해 주세요")
root_practice.focus_force()
return
if prac_num <= 0 or prac_num > 200 or prac_time_h < 0 or prac_time_m > 60 or prac_time_m < 0 or prac_time_s > 60 or prac_time_s < 0:
msgbox.showerror("오류", "알맞은 숫자를 입력해 주세요")
root_practice.focus_force()
return
root_practice.destroy()
# 시험 시작
root_practice_start = Tk()
root_practice_start.geometry("1100x450")
root_practice_start.title("연습문제")
root_practice_start.resizable(False, False)
root_practice_start.focus_force()
frame_prac_sl = Frame(root_practice_start)
frame_prac_sl.pack(side='left', fill='both', expand=True)
def prac_closing():
res_prac_close = msgbox.askokcancel("경고", "정말 시험을 종료하시겠습니까?")
if res_prac_close :
root_practice_start.destroy()
else :
root_practice_start.focus_force()
root_practice_start.protocol("WM_DELETE_WINDOW", prac_closing)
label_prac_list = []
entry_prac_list = []
for i in range(20):
label_prac_tmp = Label(frame_prac_sl, font=font.Font(size=12), text='{:03d}~{:03d}'.format(i*10+1, (i+1)*10))
entry_prac_tmp = Entry(frame_prac_sl, font=font.Font(size=12))
label_prac_list.append(label_prac_tmp)
entry_prac_list.append(entry_prac_tmp)
for i in range((prac_num-1)//10+1):
label_prac_list[i].grid(row=(i%10)+1, column=0+(i//10)*2, padx=5, pady=5, sticky=N+E+W+S)
entry_prac_list[i].grid(row=(i%10)+1, column=1+(i//10)*2, padx=5, pady=5, sticky=N+E+W+S)
if i == (prac_num-1)//10 and (prac_num % 10 != 0):
label_prac_list[i].configure(text='{:03d}~{:03d}'.format(i*10+1, i*10+(prac_num)%10))
time_limit = time.time() + prac_time_h * 3600 + prac_time_m * 60 + prac_time_s
now = time_limit - time.time() + 1
def time_to_str(time):
h = int(now // 3600)
r = now - h * 3600
m = int(r // 60)
s = int(r - m * 60)
return '{:02d}:{:02d}:{:02d}'.format(h,m,s)
now_str = time_to_str(now)
if prac_time_h == 0 and prac_time_m == 0 and prac_time_s == 0 :
now_str = '시간 제한 없음'
frame_prac_sr = Frame(root_practice_start)
frame_prac_sr.pack(side='right', fill='both', expand=True)
label_remain_text = Label(frame_prac_sr, text='남은 시간', font=font.Font(size=12))
label_remain_text.pack(fill='both')
label_remain_time = Label(frame_prac_sr, text=now_str, font=font.Font(size=20))
label_remain_time.pack(fill='both')
def update_timer():
global now_str, now, prac_file, isgrading
if isgrading :
return
if now_str != '시간 제한 없음' :
now = time_limit - time.time() + 1
now_str = time_to_str(now)
if now <= 1 :
now_str = '시간 종료'
label_remain_time.configure(text=now_str, font=font.Font(size=15))
prac_file = False
while not prac_file :
prac_grading()
return
label_remain_time.configure(text=now_str, font=font.Font(size=15))
root_practice_start.update()
root_practice_start.after(1000, update_timer)
else :
return
# 채점
def prac_grading():
global prac_file
aslist = []
for i in range(20):
aslist.append(entry_prac_list[i].get())
entry_prac_list[i].configure(state='disabled')
prac_file = filedialog.askopenfilename(title='정답 파일을 선택하세요',
filetypes=(("텍스트 파일", "*.txt"), ("모든 파일", "*.*")),
initialdir=os.path.abspath("."))
if prac_file :
root_practice_start.destroy()
root_practice_grade = Tk()
root_practice_grade.title("결과")
root_practice_grade.focus_force()
root_practice_grade.geometry('+0+5')
calist = []
with open(prac_file, 'r', encoding='utf8') as f:
for line in f:
calist.append(line.rstrip())
nca = 0
nq = 0
d_total = []
for i in range((prac_num-1)//10+1):
tmpframe = Frame(root_practice_grade, relief = 'solid', bd=1)
tmpframe.grid(row=(i%10), column=(i//10)*2, sticky=N+E+W+S)
Label(tmpframe, text='', font=font.Font(size=15)).pack()
if i == (prac_num-1)//10 and (prac_num % 10 != 0):
Label(tmpframe, text='{:03d}~{:03d}'.format(i*10+1, i*10+(prac_num)%10), font=font.Font(size=15)).pack()
else :
Label(tmpframe, text='{:03d}~{:03d}'.format(i*10+1, (i+1)*10), font=font.Font(size=15)).pack()
Label(tmpframe, text='', font=font.Font(size=15)).pack()
for i in range((prac_num-1)//10+1):
if len(calist) <= i :
tmpframe2 = Frame(root_practice_grade, relief='solid', bd=1)
tmpframe2.grid(row=(i%10), column=(i//10)*2+1, sticky=N+E+W+S)
Label(tmpframe2, text=' ', font=font.Font(size=15)).pack(fill='both', expand=True)
Label(tmpframe2, text='', font=font.Font(size=15)).pack(fill='both', expand=True)
Label(tmpframe2, text='', font=font.Font(size=8)).pack(fill='both', expand=True)
else :
d = ''
for j in range(len(calist[i])):
if j >= len(aslist[i]) :
d += 'X'
nq += 1
elif aslist[i][j] == calist[i][j] :
d += 'O'
nca += 1
nq += 1
else :
d += 'X'
nq += 1
d_total.append(d)
tmpframe2 = Frame(root_practice_grade, relief='solid', bd=1)
tmpframe2.grid(row=(i%10), column=(i//10)*2+1, sticky=N+E+W+S)
Label(tmpframe2, text=aslist[i], font=font.Font(size=15)).pack(fill='both', expand=True)
Label(tmpframe2, text=calist[i], font=font.Font(size=15)).pack(fill='both', expand=True)
Label(tmpframe2, text=d, font=font.Font(size=8)).pack(fill='both', expand=True)
frame_tmp = Frame(root_practice_grade)
frame_tmp.grid(row=9, column=4, sticky=N+E+W+S)
Label(frame_tmp, text=' ').pack()
# 결과 저장
def prac_save():
f = filedialog.asksaveasfile(filetypes=[("텍스트 파일", "*.txt")])
if f is None:
return
f.write('* 제출한 답안 / 정답 / 정오(O/X) 순입니다.\n\n')
for i in range(len(d_total)):
f.write(aslist[i])
f.write('\n')
f.write(calist[i])
f.write('\n')
f.write(d_total[i])
f.write('\n')
f.write('맞은 개수 : '+str(nca)+'/'+str(nq)+', 정답률 : {:.2f}%'.format(nca/nq*100))
f.close()
frame_practice_save = Frame(root_practice_grade)
frame_practice_save.grid(row=8, column=5, sticky=N+E+W+S)
Button(frame_practice_save, text='\n결과 저장\n', font=font.Font(size=10), command=prac_save).pack()
frame_grade = Frame(root_practice_grade, relief='solid', bd=1)
frame_grade.grid(row=9, column=5, sticky=N+E+W+S)
Label(frame_grade, text='맞은 개수\n'+str(nca)+'/'+str(nq)+'\n{:.2f}%'.format(nca/nq*100),
font=font.Font(size=10)).pack(fill='both', expand=True)
frame_prac_description = Frame(root_practice_grade, relief='solid', bd=1)
frame_prac_description.grid(row=0, column=5, sticky=N+E+W+S)
Label(frame_prac_description, text='제출한 답안', font=font.Font(size=15)).pack()
Label(frame_prac_description, text='정답', font=font.Font(size=15)).pack()
Label(frame_prac_description, text='정오(O/X)', font=font.Font(size=15)).pack()
# 답안 제출
def prac_submit():
global isgrading
response = msgbox.askyesno("답안 제출", "답안을 제출하시겠습니까?\n예를 누르면 답안 수정이 불가능합니다.")
if response :
isgrading = True
prac_grading()
else :
root_practice_start.focus_force()
button_submit = Button(frame_prac_sr, text = '\n제출하기\n',font=font.Font(size=12), command=prac_submit)
button_submit.pack(side='bottom', fill='x')
update_timer()
root_practice_start.mainloop()
def prac_cancel():
root_practice.destroy()
button_prac_ok = Button(frame_practice2, text='확인', command=prac_ok)
button_prac_ok.pack(side='left', fill='both', expand=True, padx=5, pady=5)
button_prac_cancel = Button(frame_practice2, text='취소', command=prac_cancel)
button_prac_cancel.pack(side='right', fill='both', expand=True, padx=5, pady=5)
root_practice.mainloop()
# 모의고사
def test():
global entry_test_list, isgrading
isgrading = False
sub_num = entry_num_subject.get()
each_percent = entry_each.get()
total_percent = entry_total.get()
try :
sub_num = int(sub_num)
each_percent = int(each_percent)
total_percent = int(total_percent)
except :
msgbox.showerror("오류", "알맞은 숫자를 입력해 주세요")
root.focus_force()
return
if sub_num <= 0 or sub_num > 10 or each_percent < 0 or each_percent > 100 or total_percent < 0 or total_percent > 100 :
msgbox.showerror("오류", "알맞은 숫자를 입력해 주세요")
root.focus_force()
return
root_test = Tk()
root_test.title("모의고사")
root_test.focus_force()
root_test.resizable(False, False)
frame_test = Frame(root_test)
frame_test.pack(fill='both', expand=True)
label_test_list = []
entry_test_list = []
for i in range(sub_num):
label_test_tmp = Label(frame_test, text='제{}과목 문항 수'.format(i+1), font=font.Font(size=12))
label_test_tmp.grid(row=i, column=0, padx=5, pady=5, sticky=N+E+W+S)
label_test_list.append(label_test_tmp)
entry_test_tmp = Entry(frame_test, font=font.Font(size=12))
entry_test_tmp.grid(row=i, column=1, columnspan=5, padx=5, pady=5, sticky=N+E+W+S)
entry_test_list.append(entry_test_tmp)
label_test_time = Label(frame_test, text='시간(시:분:초)', font=font.Font(size=12))
label_test_time.grid(row=i+2, column=0, padx=3, pady=3, sticky=N+E+W+S)
entry_test_time_h = Entry(frame_test, font=font.Font(size=12), width=2)
entry_test_time_h.grid(row=i+2, column=1, padx=3, pady=3, sticky=N+E+W+S)
label_test_time_c1 = Label(frame_test, text=':', font=font.Font(size=12))
label_test_time_c1.grid(row=i+2, column=2, sticky=N+E+W+S)
entry_test_time_m = Entry(frame_test, font=font.Font(size=12), width=2)
entry_test_time_m.grid(row=i+2, column=3, padx=1, pady=3, sticky=N+E+W+S)
label_test_time_c2 = Label(frame_test, text=':', font=font.Font(size=12))
label_test_time_c2.grid(row=i+2, column=4, sticky=N+E+W+S)
entry_test_time_s = Entry(frame_test, font=font.Font(size=12), width=2)
entry_test_time_s.grid(row=i+2, column=5, padx=3, pady=3, sticky=N+E+W+S)
label_test_time_c = Label(frame_test,
text='문항수는 과목 당 최대 200개입니다.'
+'\n시간을 0으로 설정하면 시간제한 없이 진행합니다.')
label_test_time_c.grid(row=i+1, column=0, columnspan=6, padx=5, pady=5, sticky=N+E+W+S)
frame_test2 = Frame(root_test)
frame_test2.pack(fill='both', expand=True)
def test_ok():
global now_str, now, entry_test_list, numofsubject, numofsubject2
test_num_list = []
for x in range(sub_num):
test_num_list.append(entry_test_list[x].get())
test_time_h = entry_test_time_h.get()
test_time_m = entry_test_time_m.get()
test_time_s = entry_test_time_s.get()
try :
for x in range(sub_num) :
test_num_list[x] = int(test_num_list[x])
test_time_h = int(test_time_h)
test_time_m = int(test_time_m)
test_time_s = int(test_time_s)
except :
msgbox.showerror("오류", "알맞은 숫자를 입력해 주세요")
root_test.focus_force()
return
if min(test_num_list) <= 0 or max(test_num_list) > 200 or test_time_h < 0 or test_time_m > 60 or test_time_m < 0 or test_time_s > 60 or test_time_s < 0:
msgbox.showerror("오류", "알맞은 숫자를 입력해 주세요")
root_test.focus_force()
return
root_test.destroy()
# 시험 시작
root_test_start = Tk()
root_test_start.geometry("1000x450")
root_test_start.title("모의고사")
root_test_start.resizable(False, False)
root_test_start.focus_force()
def test_closing():
res_test_close = msgbox.askokcancel("경고", "정말 시험을 종료하시겠습니까?")
if res_test_close :
root_test_start.destroy()
else :
root_test_start.focus_force()
root_test_start.protocol("WM_DELETE_WINDOW", test_closing)
frame_test_left_list = []
label_test_list_list = []
entry_test_list_list = []
for i in range(sub_num):
frame_test_sl = Frame(root_test_start)
frame_test_left_list.append(frame_test_sl)
label_test_list = []
entry_test_list = []
for j in range((test_num_list[i]-1)//10+1):
if i == 0 :
label_test_tmp = Label(frame_test_sl, font=font.Font(size=12), text='{:03d}~{:03d}'.format(j*10+1, (j+1)*10))
else :
label_test_tmp = Label(frame_test_sl, font=font.Font(size=12), text='{:03d}~{:03d}'.format(j*10+1+sum(test_num_list[:i]), (j+1)*10+sum(test_num_list[:i])))
entry_test_tmp = Entry(frame_test_sl, font=font.Font(size=12))
label_test_list.append(label_test_tmp)
entry_test_list.append(entry_test_tmp)
for j in range((test_num_list[i]-1)//10+1):
label_test_list[j].grid(row=(j%10)+1, column=0+(j//10)*2, padx=5, pady=5, sticky=N+E+W+S)
entry_test_list[j].grid(row=(j%10)+1, column=1+(j//10)*2, padx=5, pady=5, sticky=N+E+W+S)
if j == (test_num_list[i]-1)//10 and (test_num_list[i] % 10 != 0):
label_test_list[j].configure(text='{:03d}~{:03d}'.format(j*10+1+sum(test_num_list[:i]), j*10+(test_num_list[i])%10+sum(test_num_list[:i])))
label_test_list_list.append(label_test_list)
entry_test_list_list.append(entry_test_list)
frame_test_left_list[0].pack(side='left', fill='both', expand=True)
time_limit = time.time() + test_time_h * 3600 + test_time_m * 60 + test_time_s
now = time_limit - time.time() + 1
def time_to_str(time):
h = int(now // 3600)
r = now - h * 3600
m = int(r // 60)
s = int(r - m * 60)
return '{:02d}:{:02d}:{:02d}'.format(h,m,s)
now_str = time_to_str(now)
if test_time_h == 0 and test_time_m == 0 and test_time_s == 0 :
now_str = '시간 제한 없음'
frame_test_sr = Frame(root_test_start)
frame_test_sr.pack(side='right', fill='both')
label_remain_text = Label(frame_test_sr, text='남은 시간', font=font.Font(size=12))
label_remain_text.pack(fill='both')
label_remain_time = Label(frame_test_sr, text=now_str, font=font.Font(size=20))
label_remain_time.pack(fill='both')
numofsubject = 1
label_subject_name = Label(frame_test_sr, text='\n제{}과목\n'.format(numofsubject), font=font.Font(size=12))
label_subject_name.pack(fill='both')
def left_button():
global numofsubject
numofsubject -= 1
if numofsubject == 1 :
button_left.configure(state='disabled')
if numofsubject == sub_num-1 :
button_right.configure(state='normal')
frame_test_left_list[numofsubject].pack_forget()
frame_test_left_list[numofsubject-1].pack(side='left', fill='both', expand=True)
label_subject_name.configure(text='\n제{}과목\n'.format(numofsubject))
def right_button():
global numofsubject
numofsubject += 1
if numofsubject == sub_num :
button_right.configure(state='disabled')
if numofsubject == 2 :
button_left.configure(state='normal')
frame_test_left_list[numofsubject-2].pack_forget()
frame_test_left_list[numofsubject-1].pack(side='left', fill='both', expand=True)
label_subject_name.configure(text='\n제{}과목\n'.format(numofsubject))
button_left = Button(frame_test_sr, text='<', font=font.Font(size=15), command=left_button)
button_right = Button(frame_test_sr, text='>', font=font.Font(size=15), command=right_button)
button_left.pack(side='left')
button_right.pack(side='right')
button_left.configure(state='disabled')
if sub_num == 1 :
button_right.configure(state='disabled')
def update_timer():
global now_str, now, file, isgrading
if isgrading :
return
if now_str != '시간 제한 없음' :
now = time_limit - time.time() + 1
now_str = time_to_str(now)
if now <= 1 :
now_str = '시간 종료'
label_remain_time.configure(text=now_str, font=font.Font(size=15))
file = False
while not file :
grading()
return
label_remain_time.configure(text=now_str, font=font.Font(size=15))
root_test_start.update()
root_test_start.after(1000, update_timer)
else :
return
def grading():
global file, numofsubject2
aslist = []
for i in range(sub_num):
aslist_tmp = []
for j in range((test_num_list[i]-1)//10+1):
aslist_tmp.append(entry_test_list_list[i][j].get())
entry_test_list_list[i][j].configure(state='disabled')
aslist.append(aslist_tmp)
file = filedialog.askopenfilename(title='정답 파일을 선택하세요',
filetypes=(("텍스트 파일", "*.txt"), ("모든 파일", "*.*")),
initialdir=os.path.abspath("."))
if file :
root_test_start.destroy()
root_test_grade = Tk()
root_test_grade.title("시험 결과")
root_test_grade.geometry("825x925+0+5")
root_test_grade.resizable(False,False)
root_test_grade.focus_force()
calist = []
ca = ''
with open(file, 'r', encoding='utf8') as f:
for line in f:
ca += line.rstrip()
for i in range(sub_num):
ca_tmp_list = []
if i == 0 :
ca_tmp = ca[:test_num_list[i]]
else :
ca_tmp = ca[sum(test_num_list[:i]):sum(test_num_list[:i+1])]
while len(ca_tmp) > 10 :
ca_tmp_list.append(ca_tmp[:10])
ca_tmp = ca_tmp[10:]
ca_tmp_list.append(ca_tmp)
calist.append(ca_tmp_list)
nca_list = []
d_total_list = []
frame_result_list = []
for i in range(sub_num):
frame_result = Frame(root_test_grade)
frame_result_list.append(frame_result)
for j in range((test_num_list[i]-1)//10+1):
tmpframe = Frame(frame_result, relief = 'solid', bd=1)
tmpframe.grid(row=(j%10), column=(j//10)*2, sticky=N+E+W+S)
Label(tmpframe, text='', font=font.Font(size=15)).pack()
if i == 0 and j == (test_num_list[i]-1)//10 and (test_num_list[i] % 10 != 0):
Label(tmpframe, text='{:03d}~{:03d}'.format(j*10+1, j*10+(test_num_list[i])%10), font=font.Font(size=15)).pack()
elif i == 0 :
Label(tmpframe, text='{:03d}~{:03d}'.format(j*10+1, (j+1)*10), font=font.Font(size=15)).pack()
elif j == (test_num_list[i]-1)//10 and (test_num_list[i] % 10 != 0):
Label(tmpframe, text='{:03d}~{:03d}'.format(j*10+1+sum(test_num_list[:i]), j*10+(test_num_list[i])%10+sum(test_num_list[:i])), font=font.Font(size=15)).pack()
else :
Label(tmpframe, text='{:03d}~{:03d}'.format(j*10+1+sum(test_num_list[:i]), (j+1)*10+sum(test_num_list[:i])), font=font.Font(size=15)).pack()
Label(tmpframe, text='', font=font.Font(size=15)).pack()
nca = 0
d_total = []
for j in range((test_num_list[i]-1)//10+1):
if len(calist[i]) <= j :
tmpframe2 = Frame(frame_result, relief='solid', bd=1)
tmpframe2.grid(row=(j%10), column=(j//10)*2+1, sticky=N+E+W+S)
Label(tmpframe2, text=' ', font=font.Font(size=15)).pack(fill='both', expand=True)
Label(tmpframe2, text='', font=font.Font(size=15)).pack(fill='both', expand=True)
Label(tmpframe2, text='', font=font.Font(size=15)).pack(fill='both', expand=True)
else :
d = ''
for k in range(len(calist[i][j])):
if k >= len(aslist[i][j]) :
d += 'X'
elif aslist[i][j][k] == calist[i][j][k] :
d += 'O'
nca += 1
else :
d += 'X'
d_total.append(d)
tmpframe2 = Frame(frame_result, relief='solid', bd=1)
tmpframe2.grid(row=(j%10), column=(j//10)*2+1, sticky=N+E+W+S)
Label(tmpframe2, text=aslist[i][j], font=font.Font(size=15)).pack(fill='both', expand=True)
Label(tmpframe2, text=calist[i][j], font=font.Font(size=15)).pack(fill='both', expand=True)
Label(tmpframe2, text=d, font=font.Font(size=15)).pack(fill='both', expand=True)
nca_list.append(nca)
d_total_list.append(d_total)
result_str = '합격'
nca_total = sum(nca_list)
qn = sum(test_num_list)
for i in range(sub_num):
if ((nca_list[i] / test_num_list[i]) * 100 < each_percent) :
result_str = '불합격\n(제{}과목 과락)'.format(i+1)
break
if (nca_total / qn * 100 < total_percent) :
result_str = '불합격\n(종합 점수 부족)'
frame_result_list[0].pack(side='left', fill='both', expand=True)
frame_result_right = Frame(root_test_grade)
frame_result_right.pack(side='right', fill='both')
label_result = Label(frame_result_right, text=result_str, font=font.Font(size=20), relief='solid', bd=1)
label_result.pack(side='bottom', fill='x', padx=10, pady=10)
if result_str != '합격' :
label_result.configure(fg='red')
else :
label_result.configure(fg='blue')
label_total_result = Label(frame_result_right, text='전체\n맞은 개수\n{}/{}\n정답률\n{:.2f}%'.format(nca_total, qn, nca_total/qn*100), font=font.Font(size=15), relief='solid', bd=1)
label_total_result.pack(side='bottom', fill='x', padx=10, pady=10)
numofsubject2 = 1
label_subject_result = Label(frame_result_right, text='제{}과목\n맞은 개수\n{}/{}\n정답률\n{:.2f}%'.format(numofsubject2, nca_list[0], test_num_list[0], nca_list[0]/test_num_list[0]*100),
font=font.Font(size=15), relief='solid', bd=1)
label_subject_result.pack(side='bottom', fill='x', padx=10, pady=10)
def lb():
global numofsubject2
numofsubject2 -= 1
if numofsubject2 == 1 :
bl.configure(state='disabled')
if numofsubject2 == sub_num-1 :
br.configure(state='normal')
frame_result_list[numofsubject2].pack_forget()
frame_result_list[numofsubject2-1].pack(side='left', fill='both', expand=True)
label_subject_result.configure(text='제{}과목\n맞은 개수\n{}/{}\n정답률\n{:.2f}%'.format(numofsubject2, nca_list[numofsubject2-1], test_num_list[numofsubject2-1], nca_list[numofsubject2-1]/test_num_list[numofsubject2-1]*100))
def rb():
global numofsubject2
numofsubject2 += 1
if numofsubject2 == sub_num :
br.configure(state='disabled')
if numofsubject2 == 2 :
bl.configure(state='normal')
frame_result_list[numofsubject2-2].pack_forget()
frame_result_list[numofsubject2-1].pack(side='left', fill='both', expand=True)
label_subject_result.configure(text='제{}과목\n맞은 개수\n{}/{}\n정답률\n{:.2f}%'.format(numofsubject2, nca_list[numofsubject2-1], test_num_list[numofsubject2-1], nca_list[numofsubject2-1]/test_num_list[numofsubject2-1]*100))
bl = Button(frame_result_right, text='<', font=font.Font(size=15), command=lb)
br = Button(frame_result_right, text='>', font=font.Font(size=15), command=rb)
bl.pack(side='left')
br.pack(side='right')
bl.configure(state='disabled')
if sub_num == 1 :
br.configure(state='disabled')
frame_description = Frame(frame_result_right, relief='solid', bd=1)
frame_description.pack(side='top', fill='x')
Label(frame_description, text=' 제출한 답안 ', font=font.Font(size=15)).pack(fill='both', expand=True)
Label(frame_description, text='정답', font=font.Font(size=15)).pack(fill='both', expand=True)
Label(frame_description, text='정오(O/X)', font=font.Font(size=15)).pack(fill='both', expand=True)
def save():
f = filedialog.asksaveasfile(filetypes=[("텍스트 파일", "*.txt")], defaultextension="*.txt")
if f is None:
return
f.write('* 제출한 답안 / 정답 / 정오(O/X) 순입니다.\n\n')
for i in range(sub_num):
f.write('제{}과목\n'.format(i+1))
for j in range(len(d_total_list[i])) :
f.write(aslist[i][j])
f.write('\n')
f.write(calist[i][j])
f.write('\n')
f.write(d_total_list[i][j])
f.write('\n')
f.write('맞은 개수 : {}/{}, 정답률 : {:.2f}%\n\n'.format(nca_list[i], test_num_list[i], nca_list[i]/test_num_list[i]*100))
f.write('전체 맞은 개수 : {}/{}, 정답률 : {:.2f}%\n'.format(nca_total, qn, nca_total/qn*100))
f.write(result_str)
f.close()
Button(frame_result_right, text='\n결과 저장\n', font=font.Font(size=10), command=save).pack(side='bottom', fill='x')
def submit():
global isgrading
response = msgbox.askyesno("답안 제출", "답안을 제출하시겠습니까?\n예를 누르면 답안 수정이 불가능합니다.")
if response :
isgrading = True
grading()
else :
root_test_start.focus_force()
button_submit = Button(frame_test_sr, text = '\n제출하기\n',font=font.Font(size=12), command=submit)
button_submit.pack(side='bottom', fill='x')
update_timer()
root_test_start.mainloop()
def test_cancel():
root_test.destroy()
button_test_ok = Button(frame_test2, text='확인', command=test_ok)
button_test_ok.pack(side='left', fill='both', expand=True, padx=5, pady=5)
button_test_cancel = Button(frame_test2, text='취소', command=test_cancel)
button_test_cancel.pack(side='right', fill='both', expand=True, padx=5, pady=5)
root_test.mainloop()
button_practice = Button(frame_button, text='\n연습문제\n', command=practice, relief='groove', font=font.Font(size=12))
button_test = Button(frame_button, text='\n모의고사\n', command=test, relief='groove', font=font.Font(size=12))
button_practice.pack(fill='both', expand=True, padx=10, pady=10)
button_test.pack(fill='both', expand=True, padx=10, pady=5)
frame_option = LabelFrame(root, text='모의고사 옵션')
frame_option.pack(fill='both', expand=True, padx=10, pady=5)
Label(frame_option, text = '').grid(row=0, column=0)
label_num_subject = Label(frame_option, text='과목 수', font=font.Font(size=11))
label_num_subject.grid(row=0, column=1, sticky=N+E+W+S)
entry_num_subject = Entry(frame_option, width=3, font=font.Font(size=11))
entry_num_subject.grid(row=0, column=2, sticky=N+E+W+S)
label_caut_subject = Label(frame_option, text='※ 최대 10과목까지 설정 가능')
label_caut_subject.grid(row=1, column=1, columnspan=4, sticky=N+E+W+S)
label_each = Label(frame_option, text='과목별 정답률컷', font=font.Font(size=11))
label_each.grid(row=2, column=1, sticky=N+E+W+S)
entry_each = Entry(frame_option, width=3, font=font.Font(size=11))
entry_each.grid(row=2, column=2, sticky=N+E+W+S)
label_each_2 = Label(frame_option, text='%', font=font.Font(size=11))
label_each_2.grid(row=2, column=3, sticky=N+E+W+S)
label_total = Label(frame_option, text='전체 정답률컷', font=font.Font(size=11))
label_total.grid(row=3, column=1, sticky=N+E+W+S)
entry_total = Entry(frame_option, width=3, font=font.Font(size=11))
entry_total.grid(row=3, column=2, sticky=N+E+W+S)
label_total_2 = Label(frame_option, text='%', font=font.Font(size=11))
label_total_2.grid(row=3, column=3, sticky=N+E+W+S)
root.mainloop()
'파이썬 Python' 카테고리의 다른 글
wtf python 알아두면 좋은 내용 정리 (0) | 2024.01.31 |
---|---|
Python 모르고 놓치고 있는 유용한 기능 (0) | 2024.01.30 |
파이썬 Tesseract를 이용한 OCR 프로그램 만들기 (2) | 2020.12.05 |
클립보드 번역기(Clipboard Translator) & 화면 / 게임 번역기 v2.081 (61) | 2020.06.30 |
클립보드 복사 후 번역하는 프로그램 (exe파일) (4) | 2020.03.12 |