8 Commits

Author SHA1 Message Date
HCha
bbff63bbe5 ui小修正,字体更改为黑体 2023-02-16 00:22:52 +08:00
HCha
6d7f241d3e 紧急更新--v2.0.0.5 修复滚动条GUI严重BUG,更正版本号错误 2023-02-16 00:00:10 +08:00
HCha
61869f7247 更新LICENCE 2023-02-14 21:50:33 +08:00
HCha
a10e51f8e9 更新README 2023-02-14 21:40:04 +08:00
HCha
f7d165a7ec 更新README 2023-02-14 21:14:08 +08:00
HCha
dae64f1d0f 点名器 v1.2.3 版本更新 更新gitignore 2023-02-14 21:03:57 +08:00
13632530821
c20ea289ff 修复README缩进错误 2022-11-22 23:10:19 +08:00
13632530821
c7930bc7ff 更新报错信息 2022-11-22 18:07:03 +08:00
5 changed files with 399 additions and 183 deletions

11
.gitignore vendored
View File

@@ -1,10 +1,5 @@
.history/
Build64.bat
Build32.bat
BuildAll.bat
bin/
bin32/
data/
*.spec
.vscode/
Release/
log/
specs/
*.bat

View File

@@ -1,6 +1,6 @@
# 随机点名器 README
> 当前`README.md`以 `点名器 v1.2.2` 为最新版,会与最新版本持续更新。
> 当前`README.md`以 `点名器 v2.0.0.5` 为最新版,会与最新版本持续更新。
## 基本结构
@@ -16,8 +16,11 @@
| sel.wav
| 点名器.ico
|
+---log
| *.log
|
\---data
* config.data
* config.data
names.xls
```
@@ -45,6 +48,12 @@
+ 虽然应用程序图标软件左上角图标与Windows底部的任务栏图标一致但是该点名器.ico仅影响软件左上角图标。
+ 欲更改软件左上角图标,请将目标图标转化为`*.ico`格式,并重命名为`点名器.ico`,将老图标文件覆盖
+ 本文件的删除、重命名、更改格式等操作将会导致程序在启动时提示`资源文件错误`,继续进入软件会在应用左上角加载默认图标
* log文件夹
+ 内部存放软件生成的所有日志文件
+ 日志命名方式YYYY-MM-DD [HH:MM:SS],时间以应用运行时的系统本地时间为准。
+ 可以通过传入 `--log-level-**DEBUG/INFO/WARN/ERROR/FATAL/SILENT**` 更改日志等级
+ `DEBUG`日志等级仅供排障使用不在log文件内提示。
+ 可以通过传入 `--disable-logging` 关闭日志记录。
* data文件夹
- 存放软件使用所需的数据库文件
- 删除其中的`names.xls`文件,会导致软件**报错并退出**
@@ -75,12 +84,7 @@
+ 这个概率的上限是30%当人数大于6人时所有人共享30%的概率
+ 由于以上机制被随机抽到的情况,将不受适用于一般人的`防反复抽取机制`的影响,即有可能出现连续两次都是标记为概率增加的序号的情况
+ 通过编辑`config.data`文件来执行修改概率功能
- `config.data`文件由`N`行组成,`N`为需要修改概率的总人数
- 每一行由`X,P`组成,`X`为需要修改概率的序号,`P``+`/`-`/`0`中的任意一个
+ 当`P``+`该行对应的X序号将被列入概率增加的列表中
+ 当`P``-`该行对应的X序号将被列入概率减少的列表中
+ 当`P``0`该行对应的X序号将被列入移除列表中
- 全程请务必使用**英文符号**,并严格按照语法编写
- 请使用[gitee仓库](https://gitee.com/hchazzy/random_picker/releases)下载最新Release的`b64Writer.exe`密文生成软件,并根据软件提示操作。
- 如果出现语法不合法的情况,预期的软件反应是拒绝读取`config.data`文件但由于概率修改是隐藏功能如果出现任何bug没有任何日志可以记录也不保证软件一定按期望进行操作请在编辑该文件的时候谨慎操作
## 软件使用方法
@@ -152,13 +156,16 @@
- 检查`names.xls`文件是否有多余的数据干扰软件,如果存在,请人工排除(可以查看错误信息中的软件访问的行列数据辅助排查)
- 其他错误/可能的解决方案无效
+ 请在[gitee仓库](https://gitee.com/hchazzy/random_picker)中检查是否有新版本,如果有,请删除本软件,并重新安装最新版本
+ 如果仍未解决问题,请联系作者<peter13632530821@163.com>
+ 如果仍未解决问题,请`/log`目录打包并发送至作者邮箱<peter13632530821@163.com>
## 可选的传参
* --help 查看帮助对话框
* --licence 查看许可证信息
* --version 查看版本信息
* --path 查看程序运行路径
* --top-most 使用置顶运行方式
* --disable-logging 关闭日志记录
* --log-level-*INFO/WARN/ERROR/FATAL/SILENT* 调整日志等级为`INFO/WARN/ERROR/FATAL/SILENT`
## 关于本软件
本软件受`GNU General Public License v3.0`开源协议保护,任何人均可在遵守[本协议](https://www.gnu.org/licenses/)的前提下随意使用/修改本软件,任何对本软件的分发需随附源码与许可证,如果对本软件进行了修改并二次分发,请注明修改部分及修改时间,详细内容请参阅[GPL v3协议](https://www.gnu.org/licenses/)。

30
b64writer.py Normal file
View File

@@ -0,0 +1,30 @@
import base64
def encode(str):
return base64.b64encode(bytes(str,"utf-8"))
def main():
flag = True
while flag:
id = input("输入需要更改的id:")
method = input("输入需要进行的操作:('-'代表加入概率减少人员组,'+'代表加入概率增加人员组,'0'代表删除该人员)")
command = ""
if method == "-" or method == "——":
command = id + ",-"
elif method == "+":
command = id + ",+"
elif method == "0":
command = id + ",0"
else:
print("指令语法错误,请检查输入指令是否满足要求")
continue
print("密文已生成:" + encode(command).decode("utf-8"))
with open("config.data",mode = "a",encoding="utf-8") as config:
config.write(encode(command).decode("utf-8") + "\n")
print("密文已写入./config.data文件中")
command = input("是否继续录入?(Y/N)")
if not (command == "Y" or command == "y"):
flag = False
if __name__ == "__main__":
main()

BIN
点名器.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@@ -18,20 +18,29 @@
import xlrd as excel
from tkinter import *
from tkinter.ttk import *
import tkinter.messagebox as msgbox
import random
import sys
import winsound
import webbrowser
import time
import requests
import os
import base64
version = "v1.2.2"
version = "v2.0.0.5"
filename = "./data/names.xls"
configname = "./data/config.data"
selname = "./assets/sel.wav"
procname = "./assets/proc.wav"
iconname = "./assets/点名器.ico"
gui_size = "650x200"
gui_size = "550x140"
appname = '点名器'
author = "海Cha"
copyright = appname + ' ' + version + ' Copyright (C) 2022 ' + author
protection_override = False
up_percent = 30
@@ -55,51 +64,16 @@ last_choice = ""
gui = Tk()
gui.withdraw()
gui.title("点名器")
gui.title(appname)
gui.geometry(gui_size)
gui.resizable(0,0)
gui.configure(bg = "white")
topmost = False
if_exit = False
try:
if len(sys.argv) > 1:
for arg in sys.argv[1:]:
if arg == "--licence":
if msgbox.askokcancel('许可证信息', '点名器 ' + version + ' Copyright (C) 2022 海Cha\n本程序是开源程序,受开源协议 GNU General Public Licence v3.0 (GPL v3) 保护\n基于GPL v3协议本程序没有任何质量保证。\n这是一个自由软件,欢迎再次分发。\n点击「确认」将会由系统默认浏览器打开LICENCE文件\n出现此对话框的原因是由于您在运行本软件时传入了 --licence 参数,欲启动主程序,请移除该参数。'):
webbrowser.open_new_tab('https://www.gnu.org/licenses/gpl-3.0.html')
assert False
if arg == "--version":
msgbox.showinfo('版本信息', '点名器 ' + version + ' Copyright (C) 2022 海Cha\n出现此对话框的原因是由于您在运行本软件时传入了 --version 参数,欲启动主程序,请移除该参数。')
assert False
if arg == "--help":
msgbox.showinfo('帮助信息','----- 点名器 ' + version + ' -----\n--licence 显示许可证信息\n--version 显示版本信息\n--path 显示程序运行路径\n--help 显示此信息\n欲打开主程序GUI则无需传参\n出现此对话框的原因是由于您在运行本软件时传入了 --help 参数,欲启动主程序,请移除该参数。')
assert False
if arg == "--path":
msgbox.showinfo('路径信息','点名器 ' + version + ' Copyright (C) 2022 海Cha\n当前程序运行在 ' + sys.argv[0] + ' 路径上\n出现此对话框的原因是由于您在运行本软件时传入了 --path 参数,欲启动主程序,请移除该参数。')
assert False
if arg.find("--") != -1:
msgbox.showerror('传参错误','无法识别参数 ' + arg + ' 请调整您的启动参数\n传入 --help以查看帮助信息\n出现此对话框的原因是由于您在运行本软件时传入了 ' + arg + ' 参数,欲启动主程序,请移除该参数。')
assert False
except AssertionError:
sys.exit()
try:
file = open(iconname)
file.close()
gui.iconbitmap(iconname)
except IOError:
if not msgbox.askokcancel('资源文件错误', '在 ./assets目录下未能找到 点名器.ico 文件,点击「确定」将加载默认图标,点击「取消」以关闭程序'):
sys.exit()
try:
file = open(selname)
file.close()
file = open(procname)
file.close()
except IOError:
if msgbox.askokcancel('资源文件错误', '在 ./assets目录下未能找到音频文件,点击「确定」将关闭声音,点击「取消」以关闭程序'):
sound = False
else:
sys.exit()
logging = True
log_level = "INFO"
log_file = ""
class Student(object):
name = ""
@@ -113,148 +87,358 @@ class Student(object):
self.subject = subject
self.name = name
try:
with excel.open_workbook(filename) as excel_data:
table = excel_data.sheets()[0]
# win32api.SetFileAttributes(filename,win32con.FILE_ATTRIBUTE_HIDDEN)
except FileNotFoundError:
msgbox.showerror('找不到数据库文件', '在相同目录下未能找到 names.xls 文件,请确认您的文件存在')
sys.exit()
def Decode(str):
decode = base64.b64decode(str).decode("utf-8")
logs("DEBUG","获得base64解码:" + decode)
return decode
def newlog(type = "INFO"):
global log_file
if logging:
if not os.path.exists(".\\log\\"):
os.makedirs(".\\log\\")
curtime = time.strftime('%Y-%m-%d [%H-%M-%S]', time.localtime())
log_file = ".\\log\\" + curtime + ".log"
with open(log_file,mode = "w",encoding="utf-8") as log:
log.write("点名器日志文件 " + log_file + "\n")
log.write(copyright + '\n')
log.write("若点名器软件出现预期外行为或崩溃,请将此文件发送给作者。\n")
log.write("若需发布该日志文件到公开网络平台,请注意屏蔽日志文件中涉及的计算机敏感信息。\n")
log.write("当前日志等级:" + type + "\n")
log.write("若需改变日志记录等级,请在启动主程序时传入 --log-level-**INFO/WARN/ERROR/FATAL/SILENT**\n")
log.write("若需关闭日志记录,请在启动主程序时传入 --disable-logging。\n")
def logtype_to_int(type):
if type == "DEBUG":
return 0
elif type == "INFO":
return 1
elif type == "WARN":
return 2
elif type == "ERROR":
return 3
elif type == "FATAL":
return 4
elif type == "SILENT":
return 5
elif type == "SYSTEM":
return 6
def logs(type, message):
if logging:
curtime = time.strftime('%Y-%m-%d [%H-%M-%S]', time.localtime())
logline = ""
if logtype_to_int(type) >= logtype_to_int(log_level):
logline = "\n[" + type + "] " + curtime + " " + message
with open(log_file,mode = 'a',encoding="utf-8") as log:
log.write(logline)
try:
cols = table.ncols
rows = table.nrows
assert cols == 4
assert rows > 1
except AssertionError:
msgbox.showerror('数据库文件格式不正确', '数据库文件内行/列数不合法,请确认数据库文件拥有超过1的行数和等于4的列数,当前行数:' + str(rows) + ' 当前列数:' + str(cols))
sys.exit()
try:
with open(configname,'r') as file:
# win32api.SetFileAttributes(configname,win32con.FILE_ATTRIBUTE_HIDDEN)
config = file.read().splitlines()
for unit in config:
temp = unit.split(",")
if temp[1] == '0':
elim_id.append(int(temp[0]))
elif temp[1] == '+':
up_id.append(int(temp[0]))
elif temp[1] == "-":
down_id.append(int(temp[0]))
else:
pass
if len(sys.argv) > 1:
for arg in sys.argv[1:]:
if arg == "--licence":
if msgbox.askokcancel('许可证信息', copyright + '\n本程序是开源程序,受开源协议 GNU General Public Licence v3.0 (GPL v3) 保护\n基于GPL v3协议本程序没有任何质量保证。\n这是一个自由软件,欢迎再次分发。\n点击「确认」将会由系统默认浏览器打开LICENCE文件\n出现此对话框的原因是由于您在运行本软件时传入了 --licence 参数,欲启动主程序,请移除该参数。'):
webbrowser.open_new_tab('https://www.gnu.org/licenses/gpl-3.0.html')
if_exit = True
elif arg == "--version":
msgbox.showinfo('版本信息', copyright + '\n出现此对话框的原因是由于您在运行本软件时传入了 --version 参数,欲启动主程序,请移除该参数。')
if_exit = True
elif arg == "--help":
msgbox.showinfo('帮助信息','----- 点名器 ' + version + ' -----\n--licence 显示许可证信息\n--version 显示版本信息\n--path 显示程序运行路径\n--help 显示此信息\n欲打开主程序GUI则无需传参\n出现此对话框的原因是由于您在运行本软件时传入了 --help 参数,欲启动主程序,请移除该参数。')
if_exit = True
elif arg == "--path":
msgbox.showinfo('路径信息',copyright + '\n当前程序运行在 ' + sys.argv[0] + ' 路径上\n出现此对话框的原因是由于您在运行本软件时传入了 --path 参数,欲启动主程序,请移除该参数。')
if_exit = True
elif arg == "--top-most":
msgbox.showinfo('设置成功',copyright + '\n点名器将会置顶运行。\n出现此对话框的原因是由于您在运行本软件时传入了 --top-most 参数,欲关闭置顶运行,请移除该参数。')
elif arg == "--disable-logging":
msgbox.showinfo('设置成功',copyright + '\n调试日志已关闭。程序出现预期外动作或崩溃时,请移除此参数以获得日志。\n出现此对话框的原因是由于您在运行本软件时传入了 --disable-logging 参数,欲重启日志记录,请移除该参数。')
logging = False
elif arg == "--log-level-DEBUG":
msgbox.showinfo('设置成功',copyright + '\n调试日志等级更改为 DEBUG\n该模式仅供程序运行出现问题排障使用,请勿在常规使用中调用此参数\n出现此对话框的原因是由于您在运行本软件时传入了 ' + arg + ' 参数。')
log_level = "DEBUG"
elif arg == "--log-level-INFO":
# msgbox.showinfo('设置成功',copyright + '\n调试日志等级更改为 INFO\n出现此对话框的原因是由于您在运行本软件时传入了 ' + arg + ' 参数。')
log_level = "INFO"
elif arg == "--log-level-WARN":
# msgbox.showinfo('设置成功',copyright + '\n调试日志等级更改为 WARN\n出现此对话框的原因是由于您在运行本软件时传入了 ' + arg + ' 参数。')
log_level = "WARN"
elif arg == "--log-level-ERROR":
# msgbox.showinfo('设置成功',copyright + '\n调试日志等级更改为 ERROR\n出现此对话框的原因是由于您在运行本软件时传入了 ' + arg + ' 参数。')
log_level = "ERROR"
elif arg == "--log-level-FATAL":
# msgbox.showinfo('设置成功',copyright + '\n调试日志等级更改为 FATAL\n出现此对话框的原因是由于您在运行本软件时传入了 ' + arg + ' 参数。')
log_level = "FATAL"
elif arg == "--log-level-SILENT":
# msgbox.showinfo('设置成功',copyright + '\n调试日志等级更改为 SILENT\n出现此对话框的原因是由于您在运行本软件时传入了 ' + arg + ' 参数。')
log_level = "SILENT"
elif arg.find("--") != -1:
msgbox.showerror('传参错误','无法识别参数 ' + arg + ' 请调整您的启动参数\n传入 --help以查看帮助信息\n出现此对话框的原因是由于您在运行本软件时传入了 ' + arg + ' 参数,欲启动主程序,请移除该参数。')
if_exit = True
except:
percent_override = False
if_exit = False
finally:
if if_exit:
sys.exit(0)
up_percent = len(up_id) * 5 if len(up_id) <= 6 else 30
down_percent = len(down_id) * 8 if len(down_id) <= 5 else 40
newlog(log_level)
gui.deiconify()
if logtype_to_int(log_level) != logtype_to_int("INFO"):
logs("SYSTEM","日志等级调整为" + log_level)
for i in range(elim_rows,rows):
tmp_list = [str(table.cell_value(i,j)) for j in range(0,cols)]
if (int(float(tmp_list[0])) not in elim_id):
student = Student(tmp_list[0],tmp_list[1],tmp_list[2],tmp_list[3])
students.append(student)
logs("SYSTEM","日志记录已激活")
cur_stu = students[:]
try:
if logtype_to_int(log_level) <= logtype_to_int("DEBUG"):
try:
ip = requests.get('http://myip.ipip.net',timeout=5).text.replace('\n', '').replace('\r', '')
except:
ip = "当前IP无公网IP"
logs("DEBUG","-----系统基本信息-----")
logs("DEBUG",ip)
logs("DEBUG","运行平台:" + sys.platform)
logs("DEBUG","当前运行目录:" + sys.argv[0] + '\n')
for student in students:
if student.class_name not in classes:
classes.append(student.class_name)
if student.subject not in subjects:
subjects.append(student.subject)
try:
logs("DEBUG","加载图片文件 " + iconname)
file = open(iconname)
file.close()
gui.iconbitmap(iconname)
except IOError:
logs("ERROR","资源加载错误:在 ./assets目录下未能找到 点名器.ico 文件")
if not msgbox.askokcancel('资源文件错误', '在 ./assets目录下未能找到 点名器.ico 文件,点击「确定」将加载默认图标,点击「取消」以关闭程序'):
sys.exit()
logs("WARN","图标加载错误,回滚到默认图标")
cur_name = StringVar()
try:
logs("DEBUG","加载音频资源文件 " + selname)
file = open(selname)
file.close()
file = open(procname)
logs("DEBUG","加载音频资源文件 " + procname)
file.close()
except IOError:
logs("ERROR","资源加载错误:在 ./assets目录下未能找到音频文件")
if msgbox.askokcancel('资源文件错误', '在 ./assets目录下未能找到音频文件,点击「确定」将关闭声音,点击「取消」以关闭程序'):
logs("WARN","声音已关闭")
sound = False
else:
sys.exit()
def upd_name(name):
cur_name.set(name)
try:
logs("DEBUG","加载数据库文件 " + filename)
with excel.open_workbook(filename) as excel_data:
table = excel_data.sheets()[0]
# win32api.SetFileAttributes(filename,win32con.FILE_ATTRIBUTE_HIDDEN)
except FileNotFoundError:
logs("FATAL","数据库加载错误:在 ./data下未能找到 names.xls 文件")
msgbox.showerror('找不到数据库文件', '在 ./data下未能找到 names.xls 文件,请确认您的文件存在')
sys.exit()
upd_name("")
try:
cols = table.ncols
rows = table.nrows
logs("DEBUG","读取数据库行数:" + str(cols) + " 列数:" + str(rows))
assert cols == 4
assert rows > 1
except AssertionError:
logs("FATAL","数据库加载错误:数据库文件内行/列数不合法,当前行数:" + str(rows) + ' 当前列数:' + str(cols))
msgbox.showerror('数据库文件格式不正确', '数据库文件内行/列数不合法,请确认数据库文件拥有超过1的行数和等于4的列数,当前行数:' + str(rows) + ' 当前列数:' + str(cols))
sys.exit()
listbox = Listbox(gui, selectmode = MULTIPLE, height = 5)
try:
logs("DEBUG","加载概率修正配置文件 " + configname)
with open(configname,'r') as file:
config = file.read().splitlines()
for unit in config:
logs("DEBUG","读取到概率修正密文:" + unit)
unit = Decode(unit)
temp = unit.split(",")
assert temp[1] == '0' or temp[1] == '+' or temp[1] == '-'
if temp[1] == '0':
logs("DEBUG","应用概率修正:移除ID " + temp[0])
elim_id.append(int(temp[0]))
elif temp[1] == '+':
logs("DEBUG","应用概率修正:标记ID为提升 " + temp[0])
up_id.append(int(temp[0]))
elif temp[1] == "-":
logs("DEBUG","应用概率修正:标记ID为降低 " + temp[0])
down_id.append(int(temp[0]))
else:
pass
except Exception as e:
logs("DEBUG","加载概率修正出现错误:" + str(e))
percent_override = False
for tmp_class in classes:
listbox.insert("end",tmp_class)
up_percent = len(up_id) * 5 if len(up_id) <= 6 else 30
down_percent = len(down_id) * 8 if len(down_id) <= 5 else 40
logs("DEBUG","应用概率修正组概率:概率提升组:" + str(up_percent) + "% 概率降低组:" + str(down_percent) + "%")
def sel_class(flag = 1):
global filter, listbox, classes, cur_stu, students, percent_override
filter.clear()
for selection in listbox.curselection():
# print(selection)
filter.append(classes[selection])
# print(filter)
if filter:
if flag:
msgbox.showinfo('班级选择已应用', '已应用当前班级选择', parent=gui)
percent_override = False
cur_stu.clear()
for student in students:
if student.class_name in filter:
# print(student.name)
cur_stu.append(student)
else:
if flag:
msgbox.showwarning('班级选择已应用', '当前设置会选择所有班级的名单,这样对吗?', parent=gui)
percent_override = False
filter = classes[:]
cur_stu = students[:]
gui.deiconify()
def choose():
global last_choice, cur_stu
sel_class(0)
# 触发30%概率,从up中挑选
if (random.randint(1,100) < up_percent and percent_override):
protection_override = True;
temp = []
for student in cur_stu:
if int(float(student.id)) in up_id:
temp.append(student)
cur_stu = temp[:]
elif (random.randint(1,100) < down_persent and percent_override):
protection_override = True;
temp = [];
for student in cur_stu:
if int(float(student.id)) not in down_id:
temp.append(student)
cur_stu = temp[:]
else:
protection_override = False
if not cur_stu:
protection_override = False
logs("DEBUG","数据库内容写入内存")
for i in range(elim_rows,rows):
tmp_list = [str(table.cell_value(i,j)) for j in range(0,cols)]
if (int(float(tmp_list[0])) not in elim_id):
student = Student(tmp_list[0],tmp_list[1],tmp_list[2],tmp_list[3])
logs("DEBUG","更新数据库内容到内存:" + str(student.id))
students.append(student)
logs("DEBUG","创建数据库备份cur_stu")
cur_stu = students[:]
logs("DEBUG","创建班级列表")
for student in students:
if student.class_name not in classes:
classes.append(student.class_name)
if student.subject not in subjects:
subjects.append(student.subject)
cur_name = StringVar()
def upd_name(name):
logs("DEBUG","更新cur_name显示" + name)
cur_name.set(name)
upd_name("")
listbox = Listbox(gui, selectmode = MULTIPLE, height = 5)
for tmp_class in classes:
listbox.insert("end",tmp_class)
def sel_class(flag = 1):
global filter, listbox, classes, cur_stu, students, percent_override
filter.clear()
for selection in listbox.curselection():
# print(selection)
logs("DEBUG","添加班级筛选:" + classes[selection])
filter.append(classes[selection])
logs("DEBUG","班级筛选名单:" + str(filter))
# print(filter)
if filter:
logs("INFO","已应用班级选择")
if flag:
msgbox.showinfo('班级选择已应用', '已应用当前班级选择', parent=gui)
logs("DEBUG","概率修正已禁用")
percent_override = False
cur_stu.clear()
for student in students:
if student.class_name in filter:
# print(student.name)
cur_stu.append(student)
else:
logs("INFO","未选择任何班级,默认选择所有班级")
if flag:
msgbox.showwarning('班级选择已应用', '当前设置会选择所有班级的名单,这样对吗?', parent=gui)
logs("DEBUG","概率修正已禁用")
percent_override = False
filter = classes[:]
cur_stu = students[:]
def choose():
global last_choice, cur_stu
logs("INFO","开始新一轮随机挑选")
logs("DEBUG","上一轮的选择:" + str(last_choice))
logs("DEBUG","重新应用班级筛选(静默)")
sel_class(0)
choice = random.choice(cur_stu)
# print(choice.name)
counter = 0;
while (last_choice == choice.name and (not protection_override) and (len(cur_stu) > 1)) or choice.id in elim_id:
# 触发30%概率,从up中挑选
if (random.randint(1,100) < up_percent and percent_override):
logs("DEBUG","从概率提升组中挑选")
logs("DEBUG","防重选保护关闭")
protection_override = True;
temp = []
for student in cur_stu:
if int(float(student.id)) in up_id:
logs("DEBUG","学生id:" + str(student.id) + "学生姓名:" + str(student.name) + "加入至当前挑选名单")
temp.append(student)
logs("DEBUG","挑选名单重筛完毕")
cur_stu = temp[:]
elif (random.randint(1,100) < down_persent and percent_override):
logs("DEBUG","概率降低组人员排除")
logs("DEBUG","防重选保护关闭")
protection_override = True;
temp = [];
for student in cur_stu:
if int(float(student.id)) not in down_id:
logs("DEBUG","学生id:" + str(student.id) + "学生姓名:" + str(student.name) + "加入至当前挑选名单")
temp.append(student)
logs("DEBUG","挑选名单重筛完毕")
cur_stu = temp[:]
else:
protection_override = False
if not cur_stu:
protection_override = False
sel_class(0)
logs("DEBUG","开始随机挑选")
choice = random.choice(cur_stu)
counter = counter + 1
if counter >= 100:
break
logs("DEBUG","随机选中人员 id:" + choice.id + " 姓名:" + choice.name + " 学科:" + choice.subject)
# print(choice.name)
upd_name(choice.name)
class_label.config(text = choice.class_name)
subject_label.config(text = choice.subject)
last_choice = choice.name
if sound:
winsound.PlaySound(selname, winsound.SND_ASYNC | winsound.SND_FILENAME)
counter = 0
while (last_choice == choice.name and (not protection_override) and (len(cur_stu) > 1)) or choice.id in elim_id:
logs("DEBUG","防重选保护激活:重选人员")
choice = random.choice(cur_stu)
logs("DEBUG","随机选中人员 id:" + choice.id + " 姓名:" + choice.name + " 学科:" + choice.subject)
counter = counter + 1
if counter >= 100:
logs("DEBUG","防重选保护关闭:重选次数过多")
break
logs("DEBUG","重选保护重筛完毕,应用选择人员")
logs("SILENT","选中人员 id:" + choice.id + " 姓名:" + choice.name + " 学科:" + choice.subject)
upd_name(choice.name)
logs("DEBUG","更新班级Label显示" + choice.class_name)
class_label.config(text = choice.class_name)
logs("DEBUG","更新学科Label显示" + choice.subject)
subject_label.config(text = choice.subject)
logs("DEBUG","更新防重选保护人员记录:" + choice.name)
last_choice = choice.name
if sound:
logs("DEBUG","播放 " + selname + " 选中音频文件")
winsound.PlaySound(selname, winsound.SND_ASYNC | winsound.SND_FILENAME)
startrandom = Button(gui, text = "立刻摇人!", font = ("宋体", 17, "bold"), height = 2, fg = "red", command = choose, bg = "white")
setclass = Button(gui, text = "应用班级选用", font = ("宋体", 17), height = 2, command = sel_class, bg = "white")
scrool = Scrollbar(gui, command = listbox.yview)
listbox.config(yscrollcommand=scrool.set)
logs("DEBUG","设置GUI控件样式")
startramdonStyle=Style()
startramdonStyle.configure("SR.TButton", font = ("黑体", 17, "bold"), foreground = "red", background = "white",width=29,relief="flat",highlightthickness = 0, bd = 0,pady=0, padx=0)
setclassStyle=Style()
setclassStyle.configure("SC.TButton", font = ("黑体", 15), background = "white",relief="flat",highlightthickness = 0, bd = 0,pady=0, padx=0)
namelabelStyle=Style()
namelabelStyle.configure("NL.TLabel", font = ("黑体", 30, "bold"), background = "white", foreground = "blue",width=15,anchor="center")
classlabelStyle=Style()
classlabelStyle.configure("CL.TLabel", font = ("黑体", 15), background = "white",width=20,anchor="center")
subjectlabelStyle=Style()
subjectlabelStyle.configure("SL.TLabel", font = ("黑体", 15), background = "white",width=20,anchor="center")
name_label = Label(gui, textvariable = cur_name, font = ("宋体", 30, "bold"), width = 20, bg = "white", fg = "blue")
class_label = Label(gui, text = "", font = ("宋体", 15), width = 20, bg = "white")
subject_label = Label(gui, text = "", font = ("宋体", 15), width = 20, bg = "white")
logs("DEBUG","设置控件变量连接")
startrandom = Button(gui, text = "立刻摇人!", command = choose, style="SR.TButton")
setclass = Button(gui, text = "应用班级选用", command = sel_class, style="SC.TButton")
scrool = Scrollbar(gui, command = listbox.yview)
listbox.config(yscrollcommand=scrool.set)
class_label.grid(row = 2, column = 1, sticky = N+S+E+W)
subject_label.grid(row = 2, column = 2, sticky = N+S+E+W)
name_label.grid(row = 1, column = 1, sticky = N+S)
listbox.grid(row = 1, column = 2, sticky = N+S)
startrandom.grid(row = 3, column = 1, sticky = N+S+E+W)
setclass.grid(row = 3, column = 2, sticky = N+S+E+W)
scrool.grid(row = 1, column = 3, sticky = N+S)
name_label = Label(gui, textvariable = cur_name, style="NL.TLabel")
class_label = Label(gui, text = "", style="CL.TLabel")
subject_label = Label(gui, text = "", style="SL.TLabel")
gui.mainloop()
# class_label.grid(row = 2, column = 1, sticky = N+S+E+W)
# subject_label.grid(row = 2, column = 2, sticky = N+S+E+W)
# name_label.grid(row = 1, column = 1, sticky = N+S)
# listbox.grid(row = 1, column = 2, sticky = N+S)
# startrandom.grid(row = 3, column = 1, sticky = N+S+E+W)
# setclass.grid(row = 3, column = 2, sticky = N+S+E+W)
# scrool.grid(row = 1, column = 3, sticky = N+S)
logs("DEBUG","绘制GUI")
class_label.place(relx=0.3,rely=0.5)
subject_label.place(relx=0,rely=0.5)
name_label.place(relx=0.05,rely=0.05)
listbox.place(relx=0.7,rely=0,width=150,height=104)
startrandom.place(relx=0,rely=0.7375,height=37)
setclass.place(relx=0.7,rely=0.7375,height=37,width=164.5)
scrool.place(relx=0.965,rely=0,height=104)
if topmost:
logs("INFO","应用在置顶模式下运行")
gui.wm_attributes("-topmost", 1)
gui.mainloop()
except Exception as e:
logs("FATAL","运行发生了错误:" + str(e))