143 lines
5.9 KiB
Python
143 lines
5.9 KiB
Python
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 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) |