commit
ae827f13c6
4 changed files with 3154 additions and 0 deletions
@ -0,0 +1,63 @@ |
|||||||
|
import csv |
||||||
|
|
||||||
|
csv_file = open("output.csv", mode="w", encoding="UTF-8", newline='') |
||||||
|
writer = csv.writer(csv_file) |
||||||
|
src_file = open("drone.txt", mode="r", encoding="UTF-8") |
||||||
|
src_string = src_file.read() |
||||||
|
chap1_pos = src_string.find("第一章") |
||||||
|
chap2_pos = src_string.find("第二章", chap1_pos) |
||||||
|
chap3_pos = src_string.find("第三章", chap2_pos) |
||||||
|
chap4_pos = src_string.find("第四章", chap3_pos) |
||||||
|
chap1_ans_pos = src_string.find("第一章", chap4_pos) |
||||||
|
chap2_ans_pos = src_string.find("第二章", chap1_ans_pos) |
||||||
|
chap3_ans_pos = src_string.find("第三章", chap2_ans_pos) |
||||||
|
chap4_ans_pos = src_string.find("第四章", chap3_ans_pos) |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
data_list = [] |
||||||
|
|
||||||
|
def getBlock(current_pos, end_pos, current_ans_pos, end_ans_pos, label): |
||||||
|
question_number = 1 |
||||||
|
while(1): |
||||||
|
search_key = str(question_number) + ". " |
||||||
|
question_pos = src_string.find(search_key, current_pos, end_pos) |
||||||
|
if(question_pos == -1): |
||||||
|
break |
||||||
|
#print(src_string[question_pos:].split("\n")[0]) |
||||||
|
options1_pos = src_string.find("(A) ", question_pos, end_pos) |
||||||
|
options2_pos = src_string.find("(B) ", options1_pos, end_pos) |
||||||
|
options3_pos = src_string.find("(C) ", options2_pos, end_pos) |
||||||
|
options4_pos = src_string.find("(D) ", options3_pos, end_pos) |
||||||
|
|
||||||
|
question_str = src_string[question_pos:].split("\n")[0] |
||||||
|
options1_str = src_string[options1_pos:].split("\n")[0] |
||||||
|
options2_str = src_string[options2_pos:].split("\n")[0] |
||||||
|
options3_str = src_string[options3_pos:].split("\n")[0] |
||||||
|
options4_str = src_string[options4_pos:].split("\n")[0] |
||||||
|
|
||||||
|
#print(question_str) |
||||||
|
question = [] |
||||||
|
question.append(question_number) |
||||||
|
question.append(question_str.split(search_key)[1]) |
||||||
|
question.append(options1_str.split("(A)\t")[1]) |
||||||
|
question.append(options2_str.split("(B)\t")[1]) |
||||||
|
question.append(options3_str.split("(C)\t")[1]) |
||||||
|
question.append(options4_str.split("(D)\t")[1]) |
||||||
|
|
||||||
|
ans_pos = src_string.find(search_key, current_ans_pos, end_ans_pos) |
||||||
|
ans_str = src_string[ans_pos:].split(search_key)[1][0] |
||||||
|
|
||||||
|
question.append(ans_str) |
||||||
|
question.append(label+str(question_number)) |
||||||
|
data_list.append(question) |
||||||
|
#print(question) |
||||||
|
question_number += 1 |
||||||
|
|
||||||
|
|
||||||
|
getBlock(chap1_pos, chap2_pos, chap1_ans_pos, chap2_ans_pos, "第一章") |
||||||
|
getBlock(chap2_pos, chap3_pos, chap2_ans_pos, chap3_ans_pos, "第二章") |
||||||
|
getBlock(chap3_pos, chap4_pos, chap3_ans_pos, chap4_ans_pos, "第三章") |
||||||
|
getBlock(chap4_pos, chap1_ans_pos, chap4_ans_pos, -1, "第四章") |
||||||
|
writer.writerows(data_list) |
@ -0,0 +1,229 @@ |
|||||||
|
import tkinter as tk |
||||||
|
from tkinter import ttk |
||||||
|
import customtkinter as ctk |
||||||
|
import csv, random |
||||||
|
|
||||||
|
|
||||||
|
def updatePage(): |
||||||
|
question_from.configure(text= question_list[current_question-1][7]) |
||||||
|
question_label.configure(text= question_list[current_question-1][1], ) |
||||||
|
optionA.configure(text= "(A) " + question_list[current_question-1][2]) |
||||||
|
optionB.configure(text= "(B) " + question_list[current_question-1][3]) |
||||||
|
optionC.configure(text= "(C) " + question_list[current_question-1][4]) |
||||||
|
optionD.configure(text= "(D) " + question_list[current_question-1][5]) |
||||||
|
|
||||||
|
|
||||||
|
def nextPageCallback(): |
||||||
|
global current_question |
||||||
|
|
||||||
|
if(current_question < question_count): |
||||||
|
current_question += 1 |
||||||
|
select_question.set(current_question) |
||||||
|
option_var.set(ans[current_question-1]) |
||||||
|
checkAnswerFinish() |
||||||
|
setOptionColor() |
||||||
|
updatePage() |
||||||
|
|
||||||
|
|
||||||
|
def prevPageCallback(): |
||||||
|
global current_question |
||||||
|
|
||||||
|
if(current_question > 1): |
||||||
|
current_question -= 1 |
||||||
|
select_question.set(current_question) |
||||||
|
option_var.set(ans[current_question-1]) |
||||||
|
checkAnswerFinish() |
||||||
|
setOptionColor() |
||||||
|
updatePage() |
||||||
|
|
||||||
|
|
||||||
|
def selectQuestionCallback(choice): |
||||||
|
global current_question |
||||||
|
current_question = int(choice) |
||||||
|
option_var.set(ans[current_question-1]) |
||||||
|
checkAnswerFinish() |
||||||
|
setOptionColor() |
||||||
|
updatePage() |
||||||
|
|
||||||
|
|
||||||
|
def selectOptionCallback(): |
||||||
|
global current_question |
||||||
|
ans[current_question-1] = option_var.get() |
||||||
|
checkAnswerFinish() |
||||||
|
|
||||||
|
|
||||||
|
def checkAnswerFinish(): |
||||||
|
for i in ans: |
||||||
|
if(i == None): |
||||||
|
return False |
||||||
|
if(optionA.cget("state") != "disabled"): |
||||||
|
submit_btn.place(x= screen_width - 70, y= 25, anchor="center") |
||||||
|
return True |
||||||
|
|
||||||
|
|
||||||
|
def setOptionColor(): |
||||||
|
global current_question |
||||||
|
if(optionA.cget("state") == "disabled"): |
||||||
|
clearColor() |
||||||
|
if(correct[current_question-1] == True): |
||||||
|
#print("correct") |
||||||
|
match(ans[current_question-1]): |
||||||
|
case "A": |
||||||
|
optionA.configure(fg_color= "green", text_color= "green") |
||||||
|
case "B": |
||||||
|
optionB.configure(fg_color= "green", text_color= "green") |
||||||
|
case "C": |
||||||
|
optionC.configure(fg_color= "green", text_color= "green") |
||||||
|
case "D": |
||||||
|
optionD.configure(fg_color= "green", text_color= "green") |
||||||
|
else: |
||||||
|
#print("wrong") |
||||||
|
match(ans[current_question-1]): |
||||||
|
case "A": |
||||||
|
optionA.configure(fg_color= "red", text_color= "red") |
||||||
|
case "B": |
||||||
|
optionB.configure(fg_color= "red", text_color= "red") |
||||||
|
case "C": |
||||||
|
optionC.configure(fg_color= "red", text_color= "red") |
||||||
|
case "D": |
||||||
|
optionD.configure(fg_color= "red", text_color= "red") |
||||||
|
|
||||||
|
match(question_list[current_question-1][6]): |
||||||
|
case "A": |
||||||
|
option_mask.place(x= int(optionA.place_info()["x"]), y= int(optionA.place_info()["y"]), anchor="w") |
||||||
|
case "B": |
||||||
|
option_mask.place(x= int(optionB.place_info()["x"]), y= int(optionB.place_info()["y"]), anchor="w") |
||||||
|
case "C": |
||||||
|
option_mask.place(x= int(optionC.place_info()["x"]), y= int(optionC.place_info()["y"]), anchor="w") |
||||||
|
case "D": |
||||||
|
option_mask.place(x= int(optionD.place_info()["x"]), y= int(optionD.place_info()["y"]), anchor="w") |
||||||
|
|
||||||
|
|
||||||
|
def clearColor(): |
||||||
|
#print(optionA.cget("text_color")) |
||||||
|
option_mask.place_forget() |
||||||
|
optionA.configure(fg_color= ['#3B8ED0', '#1F6AA5'], text_color= ['gray10', '#DCE4EE']) |
||||||
|
optionB.configure(fg_color= ['#3B8ED0', '#1F6AA5'], text_color= ['gray10', '#DCE4EE']) |
||||||
|
optionC.configure(fg_color= ['#3B8ED0', '#1F6AA5'], text_color= ['gray10', '#DCE4EE']) |
||||||
|
optionD.configure(fg_color= ['#3B8ED0', '#1F6AA5'], text_color= ['gray10', '#DCE4EE']) |
||||||
|
|
||||||
|
|
||||||
|
def submitCallback(): |
||||||
|
global question_count |
||||||
|
submit_btn.place_forget() |
||||||
|
optionA.configure(state="disabled") |
||||||
|
optionB.configure(state="disabled") |
||||||
|
optionC.configure(state="disabled") |
||||||
|
optionD.configure(state="disabled") |
||||||
|
|
||||||
|
idx = 0 |
||||||
|
corrent_count = 0 |
||||||
|
for i in range(0, question_count): |
||||||
|
if(ans[i] != question_list[current_question-1][6]): |
||||||
|
correct[idx] = False |
||||||
|
#print("Wrong", idx) |
||||||
|
else: |
||||||
|
correct[idx] = True |
||||||
|
corrent_count += 1 |
||||||
|
idx += 1 |
||||||
|
print(correct) |
||||||
|
score.place(x= screen_width - 70, y= 25, anchor="center") |
||||||
|
score.configure(text= str(corrent_count)+ "/" +str(question_count)) |
||||||
|
setOptionColor() |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Config |
||||||
|
question_count = 20 |
||||||
|
|
||||||
|
screen_height = 500 |
||||||
|
screen_width = 600 |
||||||
|
|
||||||
|
|
||||||
|
# Variable |
||||||
|
current_question = 1 |
||||||
|
ans = [None] * question_count |
||||||
|
correct = [None] * question_count |
||||||
|
#print(ans) |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Read Data |
||||||
|
csv_file = open("output.csv", mode="r", encoding="UTF-8", newline='') |
||||||
|
data = list(csv.reader(csv_file)) |
||||||
|
question_list = random.sample(data, 20) |
||||||
|
|
||||||
|
|
||||||
|
# Init Window |
||||||
|
screen_height_str = str(screen_height) |
||||||
|
screen_width_str = str(screen_width) |
||||||
|
|
||||||
|
ctk.set_appearance_mode("System") |
||||||
|
ctk.set_default_color_theme("blue") |
||||||
|
window = ctk.CTk() |
||||||
|
window.title('GUI') |
||||||
|
window.resizable(False, False) |
||||||
|
window.geometry(screen_width_str + "x" + screen_height_str) |
||||||
|
|
||||||
|
|
||||||
|
# Font Settings |
||||||
|
title_font = ctk.CTkFont(family= "Microsoft JhengHei", size= 20, weight="bold") |
||||||
|
function_font = ctk.CTkFont(family= "Microsoft JhengHei", size= 18, weight="bold") |
||||||
|
option_font = ctk.CTkFont(family= "Microsoft JhengHei", size= 16, weight="bold") |
||||||
|
|
||||||
|
|
||||||
|
# Select Question |
||||||
|
next_question_btn = ctk.CTkButton(window, text="下一題", font= function_font, width= 100, command= nextPageCallback) |
||||||
|
next_question_btn.place(x= screen_width/2 + 150, y= screen_height - 50, anchor="center") |
||||||
|
|
||||||
|
prev_question_btn = ctk.CTkButton(window, text="上一題", font= function_font, width= 100, command= prevPageCallback) |
||||||
|
prev_question_btn.place(x= screen_width/2 - 150, y= screen_height - 50, anchor="center") |
||||||
|
|
||||||
|
question_num_list = str(list(range(1, question_count+1))).strip('][').split(', ') |
||||||
|
select_question = ctk.CTkOptionMenu(window, values= question_num_list, width= 100, font= function_font, dropdown_font = function_font, command= selectQuestionCallback) |
||||||
|
select_question.place(x= screen_width/2, y= screen_height - 50, anchor="center") |
||||||
|
|
||||||
|
|
||||||
|
# Question From |
||||||
|
question_from = ctk.CTkLabel(window, font= title_font) |
||||||
|
question_from.place(x= screen_width/2, y= 30, anchor="center") |
||||||
|
|
||||||
|
|
||||||
|
# Question |
||||||
|
question_label = ctk.CTkLabel(window, wraplength= screen_width - 100, font= title_font) |
||||||
|
question_label.place(x= screen_width/2, y= 80, anchor="center") |
||||||
|
|
||||||
|
|
||||||
|
# Options |
||||||
|
option_var = ctk.StringVar() |
||||||
|
optionA = ctk.CTkRadioButton(window, variable= option_var, value= "A", font= option_font, command= selectOptionCallback) |
||||||
|
optionA.place(x= 80, y= 200, anchor="w") |
||||||
|
optionB = ctk.CTkRadioButton(window, variable= option_var, value= "B", font= option_font, command= selectOptionCallback) |
||||||
|
optionB.place(x= 80, y= 250, anchor="w") |
||||||
|
optionC = ctk.CTkRadioButton(window, variable= option_var, value= "C", font= option_font, command= selectOptionCallback) |
||||||
|
optionC.place(x= 80, y= 300, anchor="w") |
||||||
|
optionD = ctk.CTkRadioButton(window, variable= option_var, value= "D", font= option_font, command= selectOptionCallback) |
||||||
|
optionD.place(x= 80, y= 350, anchor="w") |
||||||
|
|
||||||
|
|
||||||
|
# Submit |
||||||
|
submit_btn = ctk.CTkButton(window, text="完成", font= function_font, width= 100, command= submitCallback) |
||||||
|
#submit_btn.place(x= screen_width - 70, y= 25, anchor="center") |
||||||
|
|
||||||
|
score = ctk.CTkLabel(window, wraplength= screen_width - 100, font= title_font) |
||||||
|
#score.place(x= screen_width - 70, y= 25, anchor="center") |
||||||
|
|
||||||
|
|
||||||
|
# Correct Mask |
||||||
|
option_mask = ctk.CTkRadioButton(window, text= "", font= option_font, fg_color= "green", text_color= "green", state="disable", width= 0) |
||||||
|
option_mask.select() |
||||||
|
#option_mask.place(x= 150, y= 350, anchor="w") |
||||||
|
|
||||||
|
updatePage() |
||||||
|
#print(optionD.place_info()["x"]) |
||||||
|
|
||||||
|
|
||||||
|
window.mainloop() |
Loading…
Reference in new issue