EVA_duty_arrange_tool/utils.py

171 lines
6.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import pandas as pd
from datetime import datetime
import random
# 对于表格每一列:
# i = 1 -> 时间戳
# i = 6 -> 姓名
# i = 7 -> 部门编号
# i = 8 -> 老人 / 小朋友
# i = 9~28 -> 共 20 个班次,每个班次的意愿度
# i = 29 -> 想要值班的次数
col_timestamp = 1
col_name = 6
col_department = 7
col_member = 8
col_dutystart = 9
col_dutyend = 28
col_dutyfreq = 29
index_to_departments = { # 部门编号和部门名称的对应关系
1: "电脑部",
2: "电器部",
3: "人资部",
4: "财外部",
5: "文宣部"
}
index_to_type = { # 老人 / 小朋友和对应的编号
1: "老人",
2: "小朋友"
}
def read_excel(file_path):
# 读取 Excel 文件
df = pd.read_excel(file_path)
# 待返回的所有信息。N 为学生人数M 为班次数
index_to_name_dict = {} # 长度为 N 的字典,包含数组下标和学生姓名的对应关系
preference_mat = [] # N x M 的二维数组,表示每位学生对每个班次的满意度
want_num_array = [] # 长度为 N 的数组,表示每位学生想要值班的次数
is_new_array = [] # 长度为 N 的数组,表示每位学生是否是小朋友
is_tech_array = [] # 长度为 N 的数组,表示每位学生是否是电脑部或电器部成员
is_hr_array = [] # 长度为 N 的数组,表示每位学生是否是人资部成员
'''
考虑到原始填表信息中可能有某位同学多次提交的记录,先过滤一下冗余信息
'''
all_data = {} # 储存过滤后的数据
format = "%Y/%m/%d %H:%M:%S"
for index, row in df.iterrows():
# 读取学生姓名,比较时间戳
name = row[col_name]
time_this = datetime.strptime(row[col_timestamp], format)
if (name not in all_data) or (time_this > datetime.strptime(all_data[name][col_timestamp], format)):
info_list = row.tolist()
all_data[name] = info_list
# 遍历过滤后的数据,组建待返回的信息
for index, (name, info_list) in enumerate(all_data.items()):
# 学生姓名
index_to_name_dict[index] = name
# 意愿度
preference_mat.append(info_list[col_dutystart:col_dutyend + 1])
# 想要值班的次数
want_num_array.append(info_list[col_dutyfreq])
# 是否是小朋友
is_new_array.append(index_to_type[info_list[col_member]] == "小朋友")
# 是否是电脑部或电器部成员
is_tech_array.append(index_to_departments[info_list[col_department]] in ["电脑部", "电器部"])
# 是否是人资部成员
is_hr_array.append(index_to_departments[info_list[col_department]] == "人资部")
return all_data, index_to_name_dict, preference_mat, want_num_array, is_new_array, is_tech_array, is_hr_array
def save_to_excel(variables, all_data, index_to_name_dict, file_path):
# 用一个 list 储存每一班的值班人员,该 list 中每个元素是一个存有若干 dict 的 list每个 dict 表示某一班的某一值班人员信息
all_result = []
max_single_class_num = 0 # 用于记录最大的班次人数,以便后写入 excel
for j in range(len(variables[0])):
on_duty_list = []
single_class_num = 0
hr_new_index = []
none_tech_new_index = []
new_index = []
all_index = []
_cnt = 0
for i in range(len(variables)):
if variables[i][j] == 1:
single_stu_info = {}
single_stu_info["name"] = index_to_name_dict[i]
single_stu_info["department"] = index_to_departments[all_data[index_to_name_dict[i]][col_department]]
single_stu_info["type"] = index_to_type[all_data[index_to_name_dict[i]][col_member]]
single_stu_info["duty_monitor"] = False
on_duty_list.append(single_stu_info)
single_class_num += 1
all_index.append(_cnt)
if single_stu_info["type"] == "小朋友":
new_index.append(_cnt)
if single_stu_info["department"] in ["人资部", "财外部", "文宣部"]:
none_tech_new_index.append(_cnt)
if single_stu_info["department"] == 3:
hr_new_index.append(_cnt)
_cnt += 1
# 为每一班的值班组长打上标记
duty_monitor_index = -1
if hr_new_index:
duty_monitor_index = random.choice(hr_new_index)
elif none_tech_new_index:
duty_monitor_index = random.choice(none_tech_new_index)
elif new_index:
duty_monitor_index = random.choice(new_index)
else:
duty_monitor_index = random.choice(all_index)
on_duty_list[duty_monitor_index]["duty_monitor"] = True
on_duty_list = sorted(on_duty_list, key=lambda x: x["department"]) # 按部门编号升序排序
all_result.append(on_duty_list)
max_single_class_num = max(max_single_class_num, single_class_num)
from openpyxl import Workbook
from openpyxl.styles import PatternFill
# 创建一个新的工作簿
wb = Workbook()
ws = wb.active
if ws is None:
ws = wb.create_sheet(title="Sheet1")
# 写入表头
width = 25
ws['B1'] = "星期一"
ws.column_dimensions['B'].width = width
ws['C1'] = "星期二"
ws.column_dimensions['C'].width = width
ws['D1'] = "星期三"
ws.column_dimensions['D'].width = width
ws['E1'] = "星期四"
ws.column_dimensions['E'].width = width
ws['F1'] = "星期五"
ws.column_dimensions['F'].width = width
ws['G1'] = "星期六"
ws.column_dimensions['G'].width = width
ws['H1'] = "星期日"
ws.column_dimensions['H'].width = width
start_index = []
ws.merge_cells(f'A2:A{2 + max_single_class_num}')
ws['A2'] = "第一班"
start_index.append(2)
ws.merge_cells(f'A{2 + max_single_class_num + 1}:A{2 + 2 * max_single_class_num + 1}')
ws[f'A{2 + max_single_class_num + 1}'] = "第二班"
start_index.append(2 + max_single_class_num + 1)
ws.merge_cells(f'A{2 + 2 * max_single_class_num + 2}:A{2 + 3 * max_single_class_num + 2}')
ws[f'A{2 + 2 * max_single_class_num + 2}'] = "第三班"
start_index.append(2 + 2 * max_single_class_num + 2)
for duty_index, duty in enumerate(all_result):
for stu_index, stu in enumerate(duty):
col = chr(ord('B') + duty_index // 3)
row = start_index[duty_index % 3] + stu_index
str_info = f"{stu['name']} {stu['department']} {stu['type']}"
if stu['duty_monitor']:
ws[col + str(row)].fill = PatternFill(fill_type='solid', start_color='FFFF00', end_color='FFFF00')
ws[col + str(row)] = str_info
# 保存文件
wb.save(file_path)