From 65dea9bce2c211126114386768ed6940fbbaee9f Mon Sep 17 00:00:00 2001 From: ASH Date: Mon, 6 May 2019 22:39:08 +0400 Subject: [PATCH] #79 adding task planer generation --- .../ru/ulstu/students/model/Scheduler.java | 49 +++++++++ .../repository/SchedulerRepository.java | 8 ++ .../students/repository/TaskRepository.java | 2 + .../students/service/SchedulerService.java | 99 +++++++++++++++++++ .../service/TaskGenerationService.java | 19 +++- .../ulstu/students/service/TaskService.java | 81 +++++++++++++-- src/main/java/ru/ulstu/tags/model/Tag.java | 14 +++ .../db/changelog-20190505_000000-schema.xml | 24 +++++ src/main/resources/db/changelog-master.xml | 1 + src/main/resources/public/js/tasks.js | 2 +- 10 files changed, 285 insertions(+), 14 deletions(-) create mode 100644 src/main/java/ru/ulstu/students/model/Scheduler.java create mode 100644 src/main/java/ru/ulstu/students/repository/SchedulerRepository.java create mode 100644 src/main/java/ru/ulstu/students/service/SchedulerService.java create mode 100644 src/main/resources/db/changelog-20190505_000000-schema.xml diff --git a/src/main/java/ru/ulstu/students/model/Scheduler.java b/src/main/java/ru/ulstu/students/model/Scheduler.java new file mode 100644 index 0000000..67005b1 --- /dev/null +++ b/src/main/java/ru/ulstu/students/model/Scheduler.java @@ -0,0 +1,49 @@ +package ru.ulstu.students.model; + +import org.springframework.format.annotation.DateTimeFormat; +import ru.ulstu.core.model.BaseEntity; + +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.OneToOne; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import java.util.Date; + +@Entity +@Table(name = "scheduler") +public class Scheduler extends BaseEntity { + + @OneToOne(optional = false) + @JoinColumn(name = "task_id") + private Task task; + + @Temporal(value = TemporalType.TIMESTAMP) + @DateTimeFormat(pattern = "yyyy-MM-dd") + private Date date; + + public Scheduler() { + } + + public Scheduler(Task task, Date date) { + this.task = task; + this.date = date; + } + + public Task getTask() { + return task; + } + + public void setTask(Task task) { + this.task = task; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } +} diff --git a/src/main/java/ru/ulstu/students/repository/SchedulerRepository.java b/src/main/java/ru/ulstu/students/repository/SchedulerRepository.java new file mode 100644 index 0000000..ff25e98 --- /dev/null +++ b/src/main/java/ru/ulstu/students/repository/SchedulerRepository.java @@ -0,0 +1,8 @@ +package ru.ulstu.students.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import ru.ulstu.students.model.Scheduler; + +public interface SchedulerRepository extends JpaRepository { + +} diff --git a/src/main/java/ru/ulstu/students/repository/TaskRepository.java b/src/main/java/ru/ulstu/students/repository/TaskRepository.java index 0b17691..adcc43a 100644 --- a/src/main/java/ru/ulstu/students/repository/TaskRepository.java +++ b/src/main/java/ru/ulstu/students/repository/TaskRepository.java @@ -20,4 +20,6 @@ public interface TaskRepository extends JpaRepository { "(YEAR FROM t.createDate) = :year)") List findToGenerate(@Param("day") Integer day, @Param("month") Integer month, @Param("year") Integer year); + @Query("SELECT t FROM Task t WHERE(:tag IS NULL OR :tag MEMBER OF t.tags) ORDER BY create_date DESC") + List findByTag(@Param("tag") Tag tag); } diff --git a/src/main/java/ru/ulstu/students/service/SchedulerService.java b/src/main/java/ru/ulstu/students/service/SchedulerService.java new file mode 100644 index 0000000..09fbce7 --- /dev/null +++ b/src/main/java/ru/ulstu/students/service/SchedulerService.java @@ -0,0 +1,99 @@ +package ru.ulstu.students.service; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import ru.ulstu.students.model.Scheduler; +import ru.ulstu.students.model.Task; +import ru.ulstu.students.repository.SchedulerRepository; +import ru.ulstu.tags.model.Tag; + +import java.util.Date; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +@Service +public class SchedulerService { + + private final TaskService taskService; + private final SchedulerRepository schedulerRepository; + + public SchedulerService(TaskService taskService, SchedulerRepository schedulerRepository) { + this.taskService = taskService; + this.schedulerRepository = schedulerRepository; + } + + private void save(Tag tag) { + List taskList = taskService.findTasksByTag(tag); + create(taskList.get(0)); + } + + + @Transactional + private Scheduler create(Task task) { + Scheduler scheduler = new Scheduler(task, task.getDeadlines().get(task.getDeadlines().size() - 1).getDate()); + return schedulerRepository.save(scheduler); + } + + @Transactional + private void delete(Integer schedulerId) { + if (schedulerRepository.exists(schedulerId)) { + schedulerRepository.delete(schedulerId); + } + } + + public void checkPlanToday() { + List schedulerList = schedulerRepository.findAll(); + if (!schedulerList.isEmpty()) { + doTodayPlanIfNeed(schedulerList); + schedulerList = schedulerRepository.findAll(); + } + checkNewPlan(schedulerList); + } + + private void checkNewPlan(List schedulerList) { + Set tags = taskService.checkRepeatingTags(); + Tag newTag = null; + if (!schedulerList.isEmpty()) { + newTag = checkNewTag(tags, schedulerList); + } else { + if (!tags.isEmpty()) { + newTag = tags.iterator().next(); + } + } + if (newTag != null) { + save(newTag); + } + } + + private Tag checkNewTag(Set tags, List schedulerList) { + Set newTags = tags + .stream() + .filter(tag -> schedulerList + .stream() + .anyMatch(scheduler -> + !scheduler.getTask().getTags().contains(tag))) + .collect(Collectors.toSet()); + if (!newTags.isEmpty()) { + return newTags.iterator().next(); + } + return null; + } + + private void doTodayPlanIfNeed(List schedulerList) { + List plan = schedulerList + .stream() + .filter(scheduler -> scheduler.getDate().before(new Date())) + .collect(Collectors.toList()); + doToday(plan); + } + + private void doToday(List plan) { + plan.forEach(scheduler -> { + taskService.createPeriodTask(scheduler); + delete(scheduler.getId()); + }); + } + + +} diff --git a/src/main/java/ru/ulstu/students/service/TaskGenerationService.java b/src/main/java/ru/ulstu/students/service/TaskGenerationService.java index d347140..57060d5 100644 --- a/src/main/java/ru/ulstu/students/service/TaskGenerationService.java +++ b/src/main/java/ru/ulstu/students/service/TaskGenerationService.java @@ -10,16 +10,25 @@ public class TaskGenerationService { private final Logger log = LoggerFactory.getLogger(TaskGenerationService.class); private final TaskService taskService; + private final SchedulerService schedulerService; - public TaskGenerationService(TaskService taskService) { + public TaskGenerationService(TaskService taskService, SchedulerService schedulerService) { this.taskService = taskService; + this.schedulerService = schedulerService; } +// @Scheduled(cron = "0 * * ? * *", zone = "Europe/Samara") +// public void generateYearTasks() { +// log.debug("TaskService.generateYearTasks started"); +// taskService.generateYearTasks(); +// log.debug("TaskService.generateYearTasks finished"); +// } + @Scheduled(cron = "0 * * ? * *", zone = "Europe/Samara") - public void generateYearTasks() { - log.debug("TaskService.generateYearTasks started"); - taskService.generateYearTasks(); - log.debug("TaskService.generateYearTasks finished"); + public void checkPlanToday() { + log.debug("SchedulerService.checkPlanToday started"); + schedulerService.checkPlanToday(); + log.debug("SchedulerService.checkPlanToday finished"); } } diff --git a/src/main/java/ru/ulstu/students/service/TaskService.java b/src/main/java/ru/ulstu/students/service/TaskService.java index 0fab0be..c7f750c 100644 --- a/src/main/java/ru/ulstu/students/service/TaskService.java +++ b/src/main/java/ru/ulstu/students/service/TaskService.java @@ -4,8 +4,10 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import ru.ulstu.core.util.DateUtils; import ru.ulstu.deadline.model.Deadline; import ru.ulstu.deadline.service.DeadlineService; +import ru.ulstu.students.model.Scheduler; import ru.ulstu.students.model.Task; import ru.ulstu.students.model.TaskDto; import ru.ulstu.students.model.TaskFilterDto; @@ -18,6 +20,10 @@ import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TimeZone; +import java.util.TreeMap; import java.util.stream.Collectors; import static org.springframework.util.ObjectUtils.isEmpty; @@ -108,14 +114,46 @@ public class TaskService { } } - public Task copyYearTask(Task task) { - - Task newTask = new Task(); + public void copyMainPart(Task newTask, Task task) { newTask.setTitle(task.getTitle()); newTask.setTags(tagService.saveOrCreate(task.getTags())); newTask.setCreateDate(new Date()); newTask.setStatus(Task.TaskStatus.LOADED_FROM_KIAS); - newTask.setDeadlines(task.getDeadlines() + } + + public Task copyTaskWithNewDates(Task task) { + Task newTask = new Task(); + copyMainPart(newTask, task); + Calendar cal1 = Calendar.getInstance(TimeZone.getTimeZone("Europe/Paris")); + cal1.setTime(newTask.getCreateDate()); + Calendar cal2 = Calendar.getInstance(TimeZone.getTimeZone("Europe/Paris")); + cal2.setTime(task.getCreateDate()); + Integer interval = cal1.get(Calendar.DAY_OF_YEAR) - cal2.get(Calendar.DAY_OF_YEAR); + newTask.setDeadlines(newDatesDeadlines(task.getDeadlines(), interval)); + return newTask; + } + + private List newDatesDeadlines(List deadlines, Integer interval) { + return deadlines + .stream() + .map(deadline -> { + Deadline newDeadline = new Deadline(); + Date newDate = DateUtils.addDays(deadline.getDate(), interval); + newDeadline.setDescription(deadline.getDescription()); + newDeadline.setDate(newDate); + return deadlineService.create(newDeadline); + }).collect(Collectors.toList()); + } + + public Task copyTaskWithNewYear(Task task) { + Task newTask = new Task(); + copyMainPart(newTask, task); + newTask.setDeadlines(newYearDeadlines(task.getDeadlines())); + return newTask; + } + + private List newYearDeadlines(List deadlines) { + return deadlines .stream() .map(deadline -> { Deadline newDeadline = new Deadline(); @@ -125,22 +163,40 @@ public class TaskService { newDeadline.setDescription(deadline.getDescription()); newDeadline.setDate(cal.getTime()); return deadlineService.create(newDeadline); - }).collect(Collectors.toList())); - - return newTask; + }).collect(Collectors.toList()); } + @Transactional public void generateYearTasks() { Calendar cal = Calendar.getInstance(); cal.setTime(new Date()); List tasks = taskRepository.findToGenerate(cal.get(Calendar.DAY_OF_MONTH), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.YEAR) - 1); tasks.forEach(task -> { - Task newTask = copyYearTask(task); + Task newTask = copyTaskWithNewYear(task); taskRepository.save(newTask); }); } + @Transactional + public Set checkRepeatingTags() { + Map tagsCount = new TreeMap<>(); + List tags = tagService.getTags(); + List tasks = taskRepository.findAll(); + tags.forEach(tag -> + tagsCount.put(tag, tasks + .stream() + .filter(task -> task.getTags().contains(tag)) + .count())); + + return tagsCount + .entrySet() + .stream() + .filter(tagLongEntry -> tagLongEntry.getValue() >= 2) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)) + .keySet(); + } + public List getTaskStatuses() { return Arrays.asList(Task.TaskStatus.values()); } @@ -149,4 +205,13 @@ public class TaskService { return tagService.getTags(); } + public List findTasksByTag(Tag tag) { + return taskRepository.findByTag(tag); + } + + @Transactional + public void createPeriodTask(Scheduler scheduler) { + Task newTask = copyTaskWithNewDates(scheduler.getTask()); + taskRepository.save(newTask); + } } diff --git a/src/main/java/ru/ulstu/tags/model/Tag.java b/src/main/java/ru/ulstu/tags/model/Tag.java index aed000f..933b3ef 100644 --- a/src/main/java/ru/ulstu/tags/model/Tag.java +++ b/src/main/java/ru/ulstu/tags/model/Tag.java @@ -9,6 +9,7 @@ import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; import javax.validation.constraints.Size; +import java.util.Objects; @Entity @Table(name = "tag") @@ -41,4 +42,17 @@ public class Tag extends BaseEntity { public void setTagName(String tagName) { this.tagName = tagName; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Tag tag = (Tag) o; + return tagName.equals(tag.tagName); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), tagName); + } } diff --git a/src/main/resources/db/changelog-20190505_000000-schema.xml b/src/main/resources/db/changelog-20190505_000000-schema.xml new file mode 100644 index 0000000..a47476e --- /dev/null +++ b/src/main/resources/db/changelog-20190505_000000-schema.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/db/changelog-master.xml b/src/main/resources/db/changelog-master.xml index 68b294a..a28952a 100644 --- a/src/main/resources/db/changelog-master.xml +++ b/src/main/resources/db/changelog-master.xml @@ -34,4 +34,5 @@ + \ No newline at end of file diff --git a/src/main/resources/public/js/tasks.js b/src/main/resources/public/js/tasks.js index 0eb2da6..be24d5b 100644 --- a/src/main/resources/public/js/tasks.js +++ b/src/main/resources/public/js/tasks.js @@ -21,7 +21,7 @@ $(document).ready(function () { $("#input-tag").keyup(function (event) { if(event.keyCode == 13 || event.keyCode == 188) { var tagNumber = $("#tags .tag").length; - if(length != 0) { + if(tagNumber > 0) { tagNumber = $("#tags .tag").last() .children('input') .attr("name")