AnyLogic中如何计算资源池每日加班时长及日均加班时长
资源池加班时长自动统计实现方案
问题说明
当前需要统计各resourcePool(资源池)的加班时长,原有手动统计方案耗时高、重复工作量大,需要可直接在模型内自动输出每日加班时长、日均加班时长的实现方法。
原有手动统计流程
- 以药剂师资源池为例,先将资源池拆分为常规工时池、加班池两个独立单元,用于后续班次数据统计与排班优化
- 在药剂师资源池的
onExit release回调中添加日志打印代码:
traceln(date()); traceln(agent.OrderID);
- 模型运行后,将控制台输出的所有流经agent的时间、订单ID日志复制到Excel中
- 按公式
当日加班时长 = 对应日期的最后一条日志记录时间 - 加班班次开始时间手动计算单日加班时长,逐天重复操作完成统计 - 该方案需要逐天手动处理数据,且需要覆盖多个资源池,执行效率极低
自动统计实现步骤
1. 预置统计用数据结构
无需导出日志到外部工具,直接在模型内定义存储容器完成数据累计:
- 在Main或资源池所属的Agent中,创建
Map<Date, Double> dailyOvertime变量,键为截断到天的自然日期,值为对应日期的累计加班时长,初始化为空HashMap - 为加班专用资源池添加两个跟踪变量:
Date currentDay用于记录当前统计日期,double shiftStartTime用于记录当日加班班次的开始时间
2. 替换原有回调逻辑
将加班资源池onExit release回调中原有的traceln打印代码,替换为自动统计逻辑:
// 将当前仿真时间截断到自然日维度,作为统计标签 Date today = truncateToDay(time()); // 跨天时重置当日统计基准值 if (!today.equals(currentDay)) { currentDay = today; // 替换为自身业务对应的当日加班班次开始时间计算逻辑,可直接对接资源池班次日历接口 shiftStartTime = getTodayOvertimeShiftStart(today); } // 累计当前任务产生的加班时长,非加班时段产生的时长自动剔除 double taskOvertime = max(0, time() - shiftStartTime); dailyOvertime.put(today, dailyOvertime.getOrDefault(today, 0.0) + taskOvertime);
若使用独立的加班资源池,可直接调用资源池内置的班次日历接口获取当日加班班次开始时间,无需手动硬编码固定时间值
3. 指标直接读取
- 每日加班时长:仿真运行过程中可随时读取
dailyOvertime中对应日期的value值,无需二次计算 - 日均加班时长:仿真运行结束后,直接对
dailyOvertime中存储的所有日度加班时长求平均值即可,参考代码:
double avgDailyOvertime = dailyOvertime.values().stream() .mapToDouble(Double::doubleValue) .average() .orElse(0.0);
4. 多资源池适配
对所有需要统计加班数据的资源池,复用上述逻辑即可;也可将统计逻辑封装为通用自定义资源池组件,一次配置后全量资源池复用,避免重复编码。
内容的提问来源于stack exchange,提问作者Majed Hadid
相关产品推荐
相关产品推荐

