'How to change the schedule work for a range of possible time combinations in R

This is my dataset dput()

timeset=structure(list(SAP = c("S412", "S412", "S412", "S412", "S412", 
"S412", "S412", "S412", "S412", "S412", "S412", "S412", "S412", 
"S412", "S412", "S412", "S412"), weekday = c(1L, 1L, 2L, 2L, 
3L, 3L, 4L, 4L, 4L, 5L, 5L, 5L, 6L, 6L, 6L, 7L, 7L), tab = c(1001L, 
1002L, 1001L, 1003L, 1001L, 1002L, 1001L, 1002L, 1003L, 1001L, 
1002L, 1003L, 1001L, 1002L, 1003L, 1001L, 1003L), date = c(20220411L, 
20220411L, 20220412L, 20220412L, 20220413L, 20220413L, 20220414L, 
20220414L, 20220414L, 20220415L, 20220415L, 20220415L, 20220416L, 
20220416L, 20220416L, 20220417L, 20220417L), stuff_code = c(801L, 
690L, 690L, 690L, 1180L, 690L, 1180L, 690L, 690L, 1180L, 690L, 
690L, 1180L, 690L, 690L, 1180L, 690L), TS = c(9L, 9L, 9L, 9L, 
9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L), TE = c(21L, 
21L, 21L, 21L, 21L, 21L, 21L, 21L, 21L, 21L, 21L, 21L, 21L, 21L, 
21L, 21L, 21L)), class = "data.frame", row.names = c(NA, -17L
))

I am having strong difficulties with two possible staff scheduling situations

The first situation

Sometimes it happens that on some days, for example, on weekday=4, work 2 people with stuff_code=690 and one person with stuff_code=1180 works with them. How to make it so that if on some day two people with stuff_code=690 work simultaneously and stuff_code=1180 with them and these two stuff_code=690 have the same start time TS and time end TE, then for these code=690 change the start and end time by 10 hour interval, for example the first stuff_code is 9-19, the second one is from 11-21, so both will work 10 hours to keep the store working range from 9-21, don't need to set both from 9-19. (stuff=1180 we do not touch.it is only an indication that a situation has occurred 2 people 690 and 1 person 1180)

the second situation

There are days when both stuff_code=690 work at the same time (weekday=2), for them need to similarly change hours according to the 10 hour range, the first from 9-19 the second from 11-21 well, or if the time from 10-22 is indicated, then one from 10-20 the second from 12-22.

We do the same if on some day like in weekend=1 only two people work, but one of them stuff_code=801 and the second stuff_code=690, they work at the same time, then we change the hour for them, where 801 should have the very first earliest date, for example, 801 from 9-19 ,a 690 from 11-21

What is the simplest way to change the graphs in such possible situations?

Desired output which I performed manually in excel

SAP weekday tab date    stuff_code  TS  TE
**S412  1   1001    20220411    801 9   19
S412    1   1002    20220411    690 11  21
S412    2   1001    20220412    690 9   19
S412    2   1003    20220412    690 11  21**
S412    3   1001    20220413    1180    9   21
S412    3   1002    20220413    690 9   21
**S412  4   1001    20220414    1180    9   21
S412    4   1002    20220414    690 9   19
S412    4   1003    20220414    690 11  21
S412    5   1001    20220415    1180    9   21
S412    5   1002    20220415    690 9   19
S412    5   1003    20220415    690 11  21
S412    6   1001    20220416    1180    9   21
S412    6   1002    20220416    690 9   19
S412    6   1003    20220416    690 11  21**
S412    7   1001    20220417    1180    9   21
S412    7   1003    20220417    690 9   21

** marked weekdays where I changed hour.



Solution 1:[1]

You can write a small function, f to handle the logic, and then apply the function to each date:

f <- function(cd,s,e) {
  
  new_hours <- function(cd,s,e) {
    s[cd!=1180] <- c(min(s),min(s)+2)
    e[cd!=1180] <- c(max(e)-2,max(e))
    list(s,e)
  }
  
  ## Situation 1 and 2
  if(sum(cd==690)==2 & length(unique(s[cd==690]))==1 & length(unique(e[cd==690]))==1) {
      newh = new_hours(cd,s,e)
      s = newh[[1]]
      e = newh[[2]]
  }
  ## Situation 3
  if(length(cd==2) & (690 %in% cd) & (801 %in% cd)) {
    if(length(unique(s))==1 & length(unique(e))==1) {
      newh = new_hours(cd,s,e)
      s = newh[[1]][order(cd, decreasing=T)]
      e = newh[[2]][order(cd, decreasing=T)]
    }
  }
  return(list(as.integer(cd),as.integer(s),as.integer(e)))
}

library(data.table)
setDT(timeset)
timeset[, c("stuff_code", "TS", "TE"):=f(stuff_code, TS, TE), by=date]

Output:

       SAP weekday   tab     date stuff_code    TS    TE
    <char>   <int> <int>    <int>      <int> <int> <int>
 1:   S412       1  1001 20220411        801     9    19
 2:   S412       1  1002 20220411        690    11    21
 3:   S412       2  1001 20220412        690     9    19
 4:   S412       2  1003 20220412        690    11    21
 5:   S412       3  1001 20220413       1180     9    21
 6:   S412       3  1002 20220413        690     9    21
 7:   S412       4  1001 20220414       1180     9    21
 8:   S412       4  1002 20220414        690     9    19
 9:   S412       4  1003 20220414        690    11    21
10:   S412       5  1001 20220415       1180     9    21
11:   S412       5  1002 20220415        690     9    19
12:   S412       5  1003 20220415        690    11    21
13:   S412       6  1001 20220416       1180     9    21
14:   S412       6  1002 20220416        690     9    19
15:   S412       6  1003 20220416        690    11    21
16:   S412       7  1001 20220417       1180     9    21
17:   S412       7  1003 20220417        690     9    21

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 langtang