-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathschedule.go
132 lines (110 loc) · 3.46 KB
/
schedule.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
* Shift Scheduler
* Copyright (C) 2018 Ritchie Borja
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package schedule
import (
"math"
)
// Shift is the structure for the Shift of the employee. Start is the
// starting time of the employee inclusively while the End is the
// ending shift of the employee exclusively. This struct is the node
// of a doubly-linked list. The next node must be the next shift
// accordingly by time.
type Shift struct {
Start int
End int
Employee
prev *Shift
next *Shift
}
// Employee is the struct for Employee having a name and an ID
type Employee struct {
Name string
Id int
}
// Add adds the new employee to the day's shift's linked list and
// automatically validates any overlapping schedules and inserts
// according to the order of time
func Add(first *Shift, employee *Shift) (*Shift, bool) {
if first == nil {
return employee, true
}
for i := first; i != nil; i = i.next {
if i.Add(employee) {
return employee, true
}
}
return employee, false
}
// Add validates the correctness of employee's schedule to the
// current shift's list of all employees' schedule and adds to
// the shift if the new employee doesn't overlap any schedule
// of all employees
func (shift *Shift) Add(employee *Shift) bool {
if l, r := Interval(employee)(); l > r {
return false
}
if shift.prev == nil && shift.Start > employee.Start && !shift.Overlaps(Interval(employee)) {
employee.next = shift
shift.prev = employee
return true
}
if shift.next == nil && shift.End <= employee.Start && !shift.Overlaps(Interval(employee)) {
employee.prev = shift
shift.next = employee
return true
}
if shift.Start < employee.Start && employee.Start < shift.next.Start &&
!shift.Overlaps(Interval(employee)) {
nextShift := shift.next
employee.prev = shift
shift.next = employee
nextShift.prev = employee
employee.next = nextShift
return true
}
return false
}
// Overlaps checks the interval whether it will not overlap
// to the current shifts schedule. Returns true if it overlaps.
// Returns otherwise.
func (shift *Shift) Overlaps(interval func() (int, int)) bool {
start, end := interval()
for i := shift; i != nil; i = i.next {
if math.Min(float64(i.End), float64(end)) > math.Max(float64(i.Start), float64(start)) {
return true
}
}
return false
}
// Interval is the wrapper function that extract's the employee's shift
// time information into interval
func Interval(shift *Shift) func() (start, end int) {
return func() (start, end int) {
return shift.Start, shift.End
}
}
// TimeToNumeric converts hour and minute into the equivalent
// integer representation that serves as the order or index
// of a 24-hour pattern
func TimeToNumeric(hour int, minute int) int {
if hour < 0 || hour >= 24 {
return -1
}
return hour*2 - ^(^minute&(minute+^0))>>31
}