EVA_duty_arrange_tool/utils.py

145 lines
6.0 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
from random import choice
# 对于表格每一列:
col_timestamp = 1 # i = 1 -> 时间戳
col_name = 6 # i = 6 -> 姓名
col_department = 7 # i = 7 -> 部门编号
col_member = 8 # i = 8 -> 老人 / 小朋友
col_dutystart = 9 # i = 9 -> 值班开始时间
col_dutyend = 28 # i = 28 -> 值班结束时间
col_dutyfreq = 29 # i = 29 -> 想要值班的次数
index_to_departments = { # 部门编号和部门名称的对应关系
1: "电脑部",
2: "电器部",
3: "人资部",
4: "财外部",
5: "文宣部"
}
index_to_type = { # 老人 / 小朋友和对应的编号
1: "老人",
2: "小朋友"
}
def read_excel(file_path):
df = pd.read_excel(file_path)
# 待返回的所有信息。N 为学生人数M 为班次数
index_to_name_dict = {} # 长度为 N 的字典,包含数组下标和学生姓名的对应关系
preference_mat = [] # N x M 的二维数组,表示每位学生对每个班次的满意度
depart_mat = [] # N x D 的二维数组表示每位学生所属的部门D 为部门数量)
want_num_array = [] # 长度为 N 的数组,表示每位学生想要值班的次数
is_new_array = [] # 长度为 N 的数组,表示每位学生是否是小朋友
'''
考虑到原始填表信息中可能有某位同学多次提交的记录,先过滤一下冗余信息
'''
all_data = {} # 储存过滤后的数据
time_format = "%Y/%m/%d %H:%M:%S"
for index, row in df.iterrows():
name = row.iloc[col_name]
time_this = datetime.strptime(row.iloc[col_timestamp], time_format)
if name not in all_data or time_this > datetime.strptime(all_data[name][col_timestamp], time_format):
all_data[name] = row.tolist()
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])
depart_mat.append([1 if info_list[col_department] == i else 0 for i in range(1, 6)])
want_num_array.append(info_list[col_dutyfreq])
is_new_array.append(index_to_type[info_list[col_member]] == "小朋友")
return all_data, index_to_name_dict, preference_mat, depart_mat, want_num_array, is_new_array
def save_to_excel(variables, all_data, index_to_name_dict, file_path):
# 收集每个班次的值班人员信息
all_result = []
max_single_class_num = 0
for j in range(len(variables[0])):
on_duty_list = []
hr_new_index = []
none_tech_new_index = []
new_index = []
all_index = []
for i in range(len(variables)):
if variables[i][j] == 1:
name = index_to_name_dict[i]
department = index_to_departments[all_data[name][col_department]]
member_type = index_to_type[all_data[name][col_member]]
single_stu_info = {
"name": name,
"department": department,
"type": member_type,
"duty_monitor": False
}
on_duty_list.append(single_stu_info)
idx = len(all_index)
all_index.append(idx)
if member_type == "小朋友":
new_index.append(idx)
if department in ["人资部", "财外部", "文宣部"]:
none_tech_new_index.append(idx)
if department == "人资部":
hr_new_index.append(idx)
# 选择值班组长(优先级:人资部小朋友 > 非技术部小朋友 > 小朋友 > 所有人)
# 无人值班的班次跳过组长选择
if all_index:
if hr_new_index:
duty_monitor_index = choice(hr_new_index)
elif none_tech_new_index:
duty_monitor_index = choice(none_tech_new_index)
elif new_index:
duty_monitor_index = choice(new_index)
else:
duty_monitor_index = choice(all_index)
on_duty_list[duty_monitor_index]["duty_monitor"] = True
on_duty_list.sort(key=lambda x: x["department"])
all_result.append(on_duty_list)
max_single_class_num = max(max_single_class_num, len(on_duty_list))
from openpyxl import Workbook
from openpyxl.styles import PatternFill
wb = Workbook()
ws = wb.active if wb.active else wb.create_sheet(title="Sheet1")
# 设置表头
weekdays = ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"]
for idx, day in enumerate(weekdays, start=2):
col = chr(ord('A') + idx - 1)
ws[f'{col}1'] = day
ws.column_dimensions[col].width = 25
# 设置班次标题和起始行
shift_names = ["第一班", "第二班", "第三班"]
start_index = []
for shift_idx, shift_name in enumerate(shift_names):
start_row = 2 + shift_idx * (max_single_class_num + 1)
end_row = start_row + max_single_class_num
ws.merge_cells(f'A{start_row}:A{end_row}')
ws[f'A{start_row}'] = shift_name
start_index.append(start_row)
# 填写值班人员信息
yellow_fill = PatternFill(fill_type='solid', start_color='FFFF00', end_color='FFFF00')
for duty_index, duty in enumerate(all_result):
col = chr(ord('B') + duty_index // 3)
for stu_index, stu in enumerate(duty):
row = start_index[duty_index % 3] + stu_index
cell = ws[f'{col}{row}']
cell.value = f"{stu['name']} {stu['department']} {stu['type']}"
if stu['duty_monitor']:
cell.fill = yellow_fill
wb.save(file_path)