2 天以前 a962579b636b055bb70ae2233787d42483eb4b3b
src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java
@@ -6,6 +6,10 @@
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.device.mapper.DeviceAreaMapper;
import com.ruoyi.device.mapper.DeviceLedgerMapper;
import com.ruoyi.device.pojo.DeviceArea;
import com.ruoyi.device.pojo.DeviceLedger;
import com.ruoyi.inspectiontask.dto.TimingTaskDto;
import com.ruoyi.inspectiontask.mapper.InspectionTaskMapper;
import com.ruoyi.inspectiontask.mapper.TimingTaskMapper;
@@ -19,9 +23,23 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.*;
import java.time.DayOfWeek;
import java.time.DateTimeException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Year;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
/**
@@ -44,35 +62,34 @@
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private DeviceLedgerMapper deviceLedgerMapper;
    @Autowired
    private DeviceAreaMapper deviceAreaMapper;
    @Override
    public IPage<TimingTaskDto> selectTimingTaskList(Page<TimingTask> page, TimingTask timingTask) {
        // 1. 先分页查询定时任务数据
        // 构建查询条件
        LambdaQueryWrapper<TimingTask> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(timingTask.getTaskName())) {
            queryWrapper.like(TimingTask::getTaskName, timingTask.getTaskName());
        }
        if (timingTask.getAreaId() != null) {
            queryWrapper.eq(TimingTask::getAreaId, timingTask.getAreaId());
        }
        IPage<TimingTask> taskPage = timingTaskMapper.selectPage(page, queryWrapper);
        // 2. 如果没有数据,直接返回空分页
        if (taskPage.getRecords().isEmpty()) {
            return new Page<>(taskPage.getCurrent(), taskPage.getSize(), taskPage.getTotal());
        }
        // 3. 收集所有需要查询的用户ID
        Set<Long> userIds = new HashSet<>();
        // 收集登记人ID
        taskPage.getRecords().forEach(task -> {
            if (task.getRegistrantId() != null) {
                userIds.add(task.getRegistrantId());
            }
        });
        // 收集巡检人ID(多个ID以逗号分隔)
        taskPage.getRecords().forEach(task -> {
            task.setDateStr(task.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            if (task.getCreateTime() != null) {
                task.setDateStr(task.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            }
            if (StringUtils.isNotBlank(task.getInspectorIds())) {
                Arrays.stream(task.getInspectorIds().split(","))
                        .filter(StringUtils::isNotBlank)
@@ -81,25 +98,27 @@
            }
        });
        // 4. 批量查询用户信息
        Map<Long, String> userNickNameMap = new HashMap<>();
        if (!userIds.isEmpty()) {
            List<SysUser> users = sysUserMapper.selectUserByIds((new ArrayList<>(userIds)));
            List<SysUser> users = sysUserMapper.selectUserByIds(new ArrayList<>(userIds));
            users.forEach(user -> userNickNameMap.put(user.getUserId(), user.getNickName()));
        }
        // 5. 转换为DTO
        Map<Long, String> areaNameMap = deviceAreaMapper.selectBatchIds(taskPage.getRecords().stream()
                        .map(TimingTask::getAreaId)
                        .filter(Objects::nonNull)
                        .distinct()
                        .collect(Collectors.toList()))
                .stream()
                .collect(Collectors.toMap(DeviceArea::getId, DeviceArea::getAreaName, (left, right) -> left, HashMap::new));
        List<TimingTaskDto> dtoList = taskPage.getRecords().stream().map(task -> {
            TimingTaskDto dto = new TimingTaskDto();
            // 复制基本属性
            BeanUtils.copyProperties(task, dto);
            // 设置登记人昵称
            if (task.getRegistrantId() != null) {
                dto.setRegistrant(userNickNameMap.getOrDefault(task.getRegistrantId(), "未知用户"));
            }
            // 设置巡检人昵称列表
            dto.setAreaName(areaNameMap.get(task.getAreaId()));
            if (StringUtils.isNotBlank(task.getInspectorIds())) {
                List<String> inspectorNickNames = new ArrayList<>();
                for (String idStr : task.getInspectorIds().split(",")) {
@@ -110,11 +129,9 @@
                }
                dto.setInspector(inspectorNickNames);
            }
            return dto;
        }).collect(Collectors.toList());
        // 6. 构建返回的分页对象
        Page<TimingTaskDto> resultPage = new Page<>(taskPage.getCurrent(), taskPage.getSize(), taskPage.getTotal());
        resultPage.setRecords(dtoList);
        return resultPage;
@@ -125,58 +142,92 @@
    public int addOrEditTimingTask(TimingTaskDto timingTaskDto) throws SchedulerException {
        TimingTask timingTask = new TimingTask();
        BeanUtils.copyProperties(timingTaskDto, timingTask);
        // 1. 解析字符串为 LocalDate(只包含年月日)
        prepareTimingTask(timingTask);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate localDate = LocalDate.now();
        if(StringUtils.isNotEmpty(timingTaskDto.getDateStr())){
        if (StringUtils.isNotEmpty(timingTaskDto.getDateStr())) {
            localDate = LocalDate.parse(timingTaskDto.getDateStr(), formatter);
        }
        // 2. 获取当前系统的 LocalTime(包含时分秒)
        LocalTime currentTime = LocalTime.now();
        timingTask.setCreateTime(LocalDateTime.of(localDate, currentTime));
        // 3. 合并 LocalDate 和当前 LocalTime 为 LocalDateTime
        LocalDateTime localDateTime = LocalDateTime.of(localDate, currentTime);
        timingTask.setCreateTime(localDateTime);
        // 设置创建人信息和默认值
        if (Objects.isNull(timingTaskDto.getId())) {
            timingTask.setRegistrationDate(LocalDate.now());
            timingTask.setActive(true);
            // 计算首次执行时间
            LocalDateTime firstExecutionTime = calculateFirstExecutionTime(timingTask);
            timingTask.setNextExecutionTime(firstExecutionTime);
            timingTask.setNextExecutionTime(calculateFirstExecutionTime(timingTask));
            int result = timingTaskMapper.insert(timingTask);
            if (result > 0) {
                // 新增成功后添加到调度器
                timingTaskScheduler.scheduleTimingTask(timingTask);
            }
            return result;
        } else {
            int result = timingTaskMapper.updateById(timingTask);
            if (result > 0) {
                // 更新成功后重新调度任务
                timingTaskScheduler.rescheduleTimingTask(timingTask);
            }
            return result;
        }
        int result = timingTaskMapper.updateById(timingTask);
        if (result > 0) {
            timingTaskScheduler.rescheduleTimingTask(timingTask);
        }
        return result;
    }
    private void prepareTimingTask(TimingTask timingTask) {
        Long[] selectedTaskIds = timingTask.getTaskIds();
        if ((selectedTaskIds == null || selectedTaskIds.length == 0) && timingTask.getTaskId() != null) {
            selectedTaskIds = new Long[]{timingTask.getTaskId().longValue()};
        }
        if (selectedTaskIds == null || selectedTaskIds.length == 0) {
            timingTask.setTaskIdsStr(null);
            return;
        }
        List<Long> deviceIds = Arrays.stream(selectedTaskIds)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        if (deviceIds.isEmpty()) {
            timingTask.setTaskIdsStr(null);
            return;
        }
        List<DeviceLedger> devices = deviceLedgerMapper.selectBatchIds(deviceIds);
        Map<Long, DeviceLedger> deviceMap = devices.stream()
                .collect(Collectors.toMap(DeviceLedger::getId, device -> device, (left, right) -> left, LinkedHashMap::new));
        List<Long> validDeviceIds = deviceIds.stream()
                .filter(deviceMap::containsKey)
                .collect(Collectors.toList());
        if (validDeviceIds.isEmpty()) {
            throw new IllegalArgumentException("所选设备不存在");
        }
        timingTask.setTaskIds(validDeviceIds.toArray(new Long[0]));
        timingTask.setTaskIdsStr(validDeviceIds.stream().map(String::valueOf).collect(Collectors.joining(",")));
        timingTask.setTaskId(validDeviceIds.get(0).intValue());
        if (timingTask.getAreaId() == null) {
            DeviceLedger firstDevice = deviceMap.get(validDeviceIds.get(0));
            if (firstDevice != null) {
                timingTask.setAreaId(firstDevice.getAreaId());
            }
        }
        timingTask.setTaskName(validDeviceIds.stream()
                .map(deviceMap::get)
                .filter(Objects::nonNull)
                .map(DeviceLedger::getDeviceName)
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.joining(",")));
    }
    public LocalDateTime calculateFirstExecutionTime(TimingTask task) {
        // 根据频率类型和详情计算首次执行时间
        String frequencyType = task.getFrequencyType();
        if ("DAILY".equals(frequencyType)) {
            // 如果是每天执行,计算今天或明天的具体时间
            return calculateDailyFirstExecution(task.getFrequencyDetail());
        } else if ("WEEKLY".equals(frequencyType)) {
            // 如果是每周执行,计算下周的具体星期几
            return calculateWeeklyFirstExecution(task.getFrequencyDetail());
        } else if ("MONTHLY".equals(frequencyType)) {
            // 如果是每月执行,计算下个月的具体日期
            return calculateMonthlyFirstExecution(task.getFrequencyDetail());
        } else if ("YEARLY".equals(frequencyType)) {
            return calculateYearlyFirstExecution(task.getFrequencyDetail());
        } else if ("QUARTERLY".equals(frequencyType)) {
            // 自定义频率,如每小时、每30分钟等
            return calculateCustomFirstExecution(task.getFrequencyDetail());
        } else {
            throw new IllegalArgumentException("不支持的频率类型: " + task.getFrequencyType());
@@ -184,17 +235,14 @@
    }
    private LocalDateTime calculateDailyFirstExecution(String frequencyDetail) {
        // frequencyDetail可能是具体时间,如 "14:30"
        LocalTime executionTime = LocalTime.parse(frequencyDetail);
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime todayExecution = LocalDateTime.of(now.toLocalDate(), executionTime);
        // 如果今天的时间已过,则安排明天执行
        return now.isBefore(todayExecution) ? todayExecution : todayExecution.plusDays(1);
    }
    // 映射星期简写与DayOfWeek
    private static final Map<String, DayOfWeek> WEEK_DAY_MAP = new HashMap<>();
    static {
        WEEK_DAY_MAP.put("MON", DayOfWeek.MONDAY);
        WEEK_DAY_MAP.put("TUE", DayOfWeek.TUESDAY);
@@ -206,47 +254,36 @@
    }
    private LocalDateTime calculateWeeklyFirstExecution(String frequencyDetail) {
        // 解析输入参数
        String[] parts = frequencyDetail.split(",");
        if (parts.length != 2) {
            throw new IllegalArgumentException("参数格式错误,应为'MON,13:43'格式");
            throw new IllegalArgumentException("参数格式错误,应为 MON,13:43");
        }
        String weekDayStr = parts[0].trim();
        String timeStr = parts[1].trim();
        // 获取对应的星期几
        DayOfWeek targetDay = WEEK_DAY_MAP.get(weekDayStr);
        if (targetDay == null) {
            throw new IllegalArgumentException("无效的星期简写: " + weekDayStr);
            throw new IllegalArgumentException("无效的星期: " + weekDayStr);
        }
        // 解析时间
        LocalTime targetTime = LocalTime.parse(timeStr, DateTimeFormatter.ofPattern("HH:mm"));
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime targetDateTime = now.with(targetDay).with(targetTime);
        // 如果计算出的时间在当前时间之前,则加一周
        if (targetDateTime.isBefore(now)) {
            targetDateTime = targetDateTime.plusWeeks(1);
        }
        return targetDateTime;
    }
    private LocalDateTime calculateMonthlyFirstExecution(String frequencyDetail) {
        // 解析输入参数
        String[] parts = frequencyDetail.split(",");
        if (parts.length != 2) {
            throw new IllegalArgumentException("参数格式错误,应为'03,17:00'格式");
            throw new IllegalArgumentException("参数格式错误,应为 03,17:00");
        }
        String dayStr = parts[0].trim();
        String timeStr = parts[1].trim();
        // 解析日期
        int dayOfMonth;
        try {
            dayOfMonth = Integer.parseInt(dayStr);
@@ -254,12 +291,10 @@
            throw new IllegalArgumentException("无效的日期格式: " + dayStr, e);
        }
        // 验证日期有效性(1-31之间)
        if (dayOfMonth < 1 || dayOfMonth > 31) {
            throw new IllegalArgumentException("日期必须在1-31之间: " + dayOfMonth);
            throw new IllegalArgumentException("日期必须在 1-31 之间: " + dayOfMonth);
        }
        // 解析时间
        LocalTime targetTime;
        try {
            targetTime = LocalTime.parse(timeStr, DateTimeFormatter.ofPattern("HH:mm"));
@@ -267,32 +302,40 @@
            throw new IllegalArgumentException("无效的时间格式: " + timeStr, e);
        }
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime targetDateTime = now.withDayOfMonth(dayOfMonth).with(targetTime);
        // 检查日期是否被自动调整(如31日在小月会被调整)
        boolean isDateAdjusted = targetDateTime.getDayOfMonth() != dayOfMonth;
        // 如果目标时间在当前时间之前,或者日期被系统自动调整了
        if (targetDateTime.isBefore(now) || isDateAdjusted) {
            // 计算下个月的日期
            LocalDateTime nextMonth = now.plusMonths(1);
            // 尝试设置下个月的目标日期
            LocalDateTime nextMonthTarget = nextMonth.withDayOfMonth(dayOfMonth).with(targetTime);
            // 如果下个月的日期也被调整了,就用下个月的最后一天
            if (nextMonthTarget.getDayOfMonth() != dayOfMonth) {
                // 正确获取下个月的最后一天(修复isLeapYear调用问题)
                int lastDayOfMonth = nextMonth.getMonth().length(
                        Year.of(nextMonth.getYear()).isLeap()
                );
                int lastDayOfMonth = nextMonth.getMonth().length(Year.of(nextMonth.getYear()).isLeap());
                nextMonthTarget = nextMonth.withDayOfMonth(lastDayOfMonth).with(targetTime);
            }
            targetDateTime = nextMonthTarget;
        }
        return targetDateTime;
    }
    private LocalDateTime calculateYearlyFirstExecution(String frequencyDetail) {
        String[] parts = frequencyDetail.split(",");
        if (parts.length != 3) {
            throw new IllegalArgumentException("参数格式错误,应为 03,15,17:00");
        }
        int month = Integer.parseInt(parts[0].trim());
        int dayOfMonth = Integer.parseInt(parts[1].trim());
        LocalTime targetTime = LocalTime.parse(parts[2].trim(), DateTimeFormatter.ofPattern("HH:mm"));
        LocalDateTime now = LocalDateTime.now();
        YearMonth currentYearMonth = YearMonth.of(now.getYear(), month);
        int adjustedDay = Math.min(dayOfMonth, currentYearMonth.lengthOfMonth());
        LocalDateTime targetDateTime = LocalDateTime.of(now.getYear(), month, adjustedDay, targetTime.getHour(), targetTime.getMinute());
        if (!targetDateTime.isAfter(now)) {
            YearMonth nextYearMonth = YearMonth.of(now.getYear() + 1, month);
            adjustedDay = Math.min(dayOfMonth, nextYearMonth.lengthOfMonth());
            targetDateTime = LocalDateTime.of(now.getYear() + 1, month, adjustedDay, targetTime.getHour(), targetTime.getMinute());
        }
        return targetDateTime;
    }
@@ -308,24 +351,16 @@
            throw new RuntimeException("定时任务不存在,ID: " + taskId);
        }
        // 更新最后执行时间为当前时间
        task.setLastExecutionTime(LocalDateTime.now());
        // 计算下次执行时间
        LocalDateTime nextExecutionTime = calculateNextExecutionTime(
                task.getFrequencyType(),
                task.getFrequencyDetail(),
                LocalDateTime.now()
        );
        task.setNextExecutionTime(nextExecutionTime);
        // 更新数据库
        timingTaskMapper.updateById(task);
    }
    /**
     * 计算下次执行时间
     */
    private LocalDateTime calculateNextExecutionTime(String frequencyType,
                                                     String frequencyDetail,
                                                     LocalDateTime currentTime) {
@@ -339,6 +374,8 @@
                    return calculateMonthlyNextTime(frequencyDetail, currentTime);
                case "QUARTERLY":
                    return calculateQuarterlyNextTime(frequencyDetail, currentTime);
                case "YEARLY":
                    return calculateYearlyNextTime(frequencyDetail, currentTime);
                default:
                    throw new IllegalArgumentException("不支持的频率类型: " + frequencyType);
            }
@@ -347,86 +384,54 @@
        }
    }
    /**
     * 计算每日任务的下次执行时间
     */
    private LocalDateTime calculateDailyNextTime(String timeStr, LocalDateTime current) {
        LocalTime executionTime = LocalTime.parse(timeStr); // 解析格式 "HH:mm"
        LocalTime executionTime = LocalTime.parse(timeStr);
        LocalDateTime nextTime = LocalDateTime.of(current.toLocalDate(), executionTime);
        // 如果今天的时间已过,则安排明天
        return current.isBefore(nextTime) ? nextTime : nextTime.plusDays(1);
    }
    /**
     * 计算每周任务的下次执行时间
     */
    private LocalDateTime calculateWeeklyNextTime(String detail, LocalDateTime current) {
        String[] parts = detail.split(",");
        String dayOfWeekStr = parts[0];  // 如 "MON" 或 "MON|WED|FRI"
        LocalTime time = LocalTime.parse(parts[1]); // 时间部分
        // 解析星期几(支持多个星期)
        String dayOfWeekStr = parts[0];
        LocalTime time = LocalTime.parse(parts[1]);
        Set<DayOfWeek> targetDays = parseDayOfWeeks(dayOfWeekStr);
        // 从当前时间开始找下一个符合条件的星期几
        LocalDateTime nextTime = current;
        while (true) {
            nextTime = nextTime.plusDays(1);
            if (targetDays.contains(nextTime.getDayOfWeek())) {
                return LocalDateTime.of(nextTime.toLocalDate(), time);
            }
            // 防止无限循环(理论上不会发生)
            if (nextTime.isAfter(current.plusYears(1))) {
                throw new RuntimeException("无法找到下次执行时间");
            }
        }
    }
    /**
     * 计算每月任务的下次执行时间
     */
    private LocalDateTime calculateMonthlyNextTime(String detail, LocalDateTime current) {
        String[] parts = detail.split(",");
        int dayOfMonth = Integer.parseInt(parts[0]);
        LocalTime time = LocalTime.parse(parts[1]);
        // 从下个月开始计算
        LocalDateTime nextTime = current.plusMonths(1)
        return current.plusMonths(1)
                .withDayOfMonth(Math.min(dayOfMonth, current.plusMonths(1).toLocalDate().lengthOfMonth()))
                .with(time);
        return nextTime;
    }
    /**
     * 计算每季度任务的下次执行时间
     */
    private LocalDateTime calculateQuarterlyNextTime(String detail, LocalDateTime current) {
        String[] parts = detail.split(",");
        int quarterMonth = Integer.parseInt(parts[0]); // 1=第1个月,2=第2个月,3=第3个月
        int quarterMonth = Integer.parseInt(parts[0]);
        int dayOfMonth = Integer.parseInt(parts[1]);
        LocalTime time = LocalTime.parse(parts[2]);
        // 计算当前季度
        int currentQuarter = (current.getMonthValue() - 1) / 3 + 1;
        int currentMonthInQuarter = (current.getMonthValue() - 1) % 3 + 1;
        YearMonth targetYearMonth;
        if (currentMonthInQuarter < quarterMonth) {
            // 本季度内还有执行机会
            targetYearMonth = YearMonth.from(current)
                    .plusMonths(quarterMonth - currentMonthInQuarter);
            targetYearMonth = YearMonth.from(current).plusMonths(quarterMonth - currentMonthInQuarter);
        } else {
            // 需要到下个季度
            targetYearMonth = YearMonth.from(current)
                    .plusMonths(3 - currentMonthInQuarter + quarterMonth);
            targetYearMonth = YearMonth.from(current).plusMonths(3 - currentMonthInQuarter + quarterMonth);
        }
        // 处理月末日期
        int adjustedDay = Math.min(dayOfMonth, targetYearMonth.lengthOfMonth());
        return LocalDateTime.of(
                targetYearMonth.getYear(),
                targetYearMonth.getMonthValue(),
@@ -436,40 +441,64 @@
        );
    }
    /**
     * 解析星期几字符串
     */
    private LocalDateTime calculateYearlyNextTime(String detail, LocalDateTime current) {
        String[] parts = detail.split(",");
        int month = Integer.parseInt(parts[0]);
        int dayOfMonth = Integer.parseInt(parts[1]);
        LocalTime time = LocalTime.parse(parts[2]);
        YearMonth targetYearMonth = YearMonth.of(current.getYear(), month);
        int adjustedDay = Math.min(dayOfMonth, targetYearMonth.lengthOfMonth());
        LocalDateTime target = LocalDateTime.of(current.getYear(), month, adjustedDay, time.getHour(), time.getMinute());
        if (!target.isAfter(current)) {
            targetYearMonth = YearMonth.of(current.getYear() + 1, month);
            adjustedDay = Math.min(dayOfMonth, targetYearMonth.lengthOfMonth());
            target = LocalDateTime.of(current.getYear() + 1, month, adjustedDay, time.getHour(), time.getMinute());
        }
        return target;
    }
    private Set<DayOfWeek> parseDayOfWeeks(String dayOfWeekStr) {
        Set<DayOfWeek> days = new HashSet<>();
        String[] dayStrs = dayOfWeekStr.split("\\|");
        for (String dayStr : dayStrs) {
            switch (dayStr) {
                case "MON": days.add(DayOfWeek.MONDAY); break;
                case "TUE": days.add(DayOfWeek.TUESDAY); break;
                case "WED": days.add(DayOfWeek.WEDNESDAY); break;
                case "THU": days.add(DayOfWeek.THURSDAY); break;
                case "FRI": days.add(DayOfWeek.FRIDAY); break;
                case "SAT": days.add(DayOfWeek.SATURDAY); break;
                case "SUN": days.add(DayOfWeek.SUNDAY); break;
                default: throw new IllegalArgumentException("无效的星期几: " + dayStr);
                case "MON":
                    days.add(DayOfWeek.MONDAY);
                    break;
                case "TUE":
                    days.add(DayOfWeek.TUESDAY);
                    break;
                case "WED":
                    days.add(DayOfWeek.WEDNESDAY);
                    break;
                case "THU":
                    days.add(DayOfWeek.THURSDAY);
                    break;
                case "FRI":
                    days.add(DayOfWeek.FRIDAY);
                    break;
                case "SAT":
                    days.add(DayOfWeek.SATURDAY);
                    break;
                case "SUN":
                    days.add(DayOfWeek.SUNDAY);
                    break;
                default:
                    throw new IllegalArgumentException("无效的星期: " + dayStr);
            }
        }
        return days;
    }
    @Override
    public int delByIds(Long[] ids) {
        int i = timingTaskMapper.deleteBatchIds(Arrays.asList(ids));
        if(i > 0){
        if (i > 0) {
            for (Long id : ids) {
                timingTaskScheduler.unscheduleTimingTask(id);
            }
        }
        return i;
    }
}