Skip to content

Commit f1fe7b4

Browse files
committed
impl scheduler
1 parent 95968c8 commit f1fe7b4

File tree

4 files changed

+447
-17
lines changed

4 files changed

+447
-17
lines changed

src/ProdScheduler/Scheduler.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ class Scheduler extends AbstractScheduler implements SchedulerInterface
88
public function __construct(array $config)
99
{
1010
$this->init($config);
11+
12+
$this->schedule();
1113
}
1214

1315
public function getSchedule(): array

src/ProdScheduler/SchedulerComputeTrait.php

Lines changed: 282 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,304 @@ trait SchedulerComputeTrait
1010

1111
public function compute()
1212
{
13+
foreach ($this->list as $k => $item) {
14+
$itemQty = $item['item_qty'];
15+
$itemPhaseMaxCostTime = $item['phase_max_cost'];
16+
$reverseComputePhases = $item['phases_reverse'];
17+
$forwardComputePhases = $item['phases_forward'];
18+
19+
$reverseComputePhasesCnt = count($reverseComputePhases);
20+
if (!empty($reverseComputePhasesCnt)) {
21+
$i = $reverseComputePhasesCnt - 1;
22+
23+
while ($i > -1) {
24+
$itemPhase = $reverseComputePhases[$i];
25+
$workerNum = $itemPhase['worker_num'];
26+
$costTime = $itemPhase['cost_time'];
27+
28+
list($singleCost, $totalCost) = $this->getPhaseCostTime($itemQty, $itemPhaseMaxCostTime, $costTime, $workerNum);
29+
30+
if ($i === count($reverseComputePhases) - 1) {
31+
if ($k === 0) {
32+
$originStart = $start = $this->ISTS;
33+
} else {
34+
$originStart = $start = $this->list[$k - 1]['phases_forward'][0]['start'];
35+
}
36+
} else {
37+
$nextPhase = $reverseComputePhases[$i + 1];
38+
$originStart = $start = $nextPhase['start'];
39+
$start -= ($itemPhase['dead_time'] + $itemPhase['ahead_time']);
40+
if ($itemPhase['out_time'] > 0) {
41+
$start -= $itemPhase['out_time'];
42+
} else {
43+
$start -= $singleCost;
44+
}
45+
}
46+
47+
$start = $this->phaseTimeWithCalendarCompute($originStart, $start, true);
48+
$start = $this->phaseTimeWithRestDayCompute($start);
49+
$this->list[$k]['phases_reverse'][$i]['start'] = $start;
50+
51+
if ($itemPhase['out_time'] > 0) {
52+
$end = $start + $itemPhase['out_time'];
53+
} else {
54+
$end = $start + $totalCost;
55+
$end = $this->phaseTimeWithCalendarCompute($start, $end);
56+
$end = $this->phaseTimeWithRestDayCompute($end);
57+
$this->list[$k]['phases_reverse'][$i]['end'] = $end;
58+
}
59+
60+
$i--;
61+
}
62+
}
63+
64+
$initialPhase = $reverseComputePhases[$reverseComputePhasesCnt - 1];
65+
if (isset($initialPhase)) {
66+
foreach ($forwardComputePhases as $i => $itemPhase) {
67+
$workerNum = $itemPhase['worker_num'];
68+
$costTime = $itemPhase['cost_time'];
69+
70+
list($singleCost, $totalCost) = $this->getPhaseCostTime($itemQty, $itemPhaseMaxCostTime, $costTime, $workerNum);
71+
if ($i === 0) {
72+
$originStart = $initialPhase['start'];
73+
$start = $originStart + $initialPhase['dead_time'] + $initialPhase['ahead_time'];
74+
} else {
75+
$prevItem = $forwardComputePhases[$i - 1];
76+
if ($prevItem['out_time'] > 0) {
77+
$originStart = $start = $prevItem['end'];
78+
} else {
79+
$originStart = $prevItem['start'];
80+
$start = $originStart + $prevItem['dead_time'] + $prevItem['ahead_time'];
81+
}
82+
}
83+
84+
$start = $this->phaseTimeWithCalendarCompute($originStart, $start);
85+
$start = $this->phaseTimeWithRestDayCompute($start);
86+
$this->list[$k]['phases_forward'][$i]['start'] = $start;
87+
88+
if ($itemPhase['out_time'] > 0) {
89+
$end = $start + $itemPhase['out_time'];
90+
} else {
91+
$end = $start + $totalCost;
92+
$end = $this->phaseTimeWithCalendarCompute($start, $end);
93+
$end = $this->phaseTimeWithRestDayCompute($end);
94+
$this->list[$k]['phases_forward'][$i]['end'] = $end;
95+
}
96+
}
97+
}
98+
}
99+
100+
$this->scheduledList = $this->list;
13101
}
14102

15103
private function initialStartTimeCompute(): int
16104
{
17-
return 0;
105+
$dayCalendar = $this->getDayCalendar($this->ISTS);
106+
if (empty($dayCalendar)) {
107+
$dayCalendar = $this->getDefaultDayCalendar();
108+
}
109+
110+
$initialScheduleDate = date(self::SCHEDULER_DATE_FORMAT, $this->ISTS);
111+
if ($this->computeDirection === ComputeDirection::Forward) {
112+
foreach ($dayCalendar as $k => $day) {
113+
if ($initialScheduleDate === $day['date']) {
114+
if ($day['is_rest'] === 1) {
115+
if ($k !== count($dayCalendar)) {
116+
$nextDayCalendar = $dayCalendar[$k + 1];
117+
if ($nextDayCalendar['is_rest'] === 1) {
118+
continue;
119+
} else {
120+
$nextDayCalendarDate = $nextDayCalendar['date'];
121+
$nextDayCalendarStartTime = $this->getDayCalendarStartTime($nextDayCalendarDate);
122+
123+
$this->ISDT = $nextDayCalendarDate . " " . $nextDayCalendarStartTime;
124+
}
125+
}
126+
} else {
127+
$dayCalendarDate = $day['date'];
128+
$dayCalendarStartTime = $this->getDayCalendarStartTime($day);
129+
130+
$this->ISDT = $dayCalendarDate . " " . $dayCalendarStartTime;
131+
}
132+
}
133+
}
134+
}
135+
136+
$this->ISTS = strtotime($this->ISDT);
137+
138+
return $this->ISTS;
18139
}
19140

20-
private function adjustPhasePosition(bool $isAdjust = false)
141+
private function getPhaseCostTime(int $qty, int $maxCostTime, int $costTime, int $workerNum): array
21142
{
143+
$cost = 0;
144+
if ($costTime > 0) {
145+
if ($this->getMCTC()) {
146+
$cost = $maxCostTime / $workerNum;
147+
} else {
148+
$cost = $costTime / $workerNum;
149+
}
150+
}
151+
152+
$singleCost = $cost * $this->getEDQ();
153+
$totalCost = $qty * $this->getEDQ();
154+
155+
return [(int)$singleCost, (int)$totalCost];
22156
}
23157

24-
private function phaseCostTime(): int
158+
private function phaseTimeWithCalendarCompute(int $originStart, int &$start, bool $isReverse = false): int
25159
{
26-
return 0;
160+
$originStartDate = date(self::SCHEDULER_DATE_FORMAT, $originStart);
161+
162+
$calendar = $this->getDayCalendar($originStart);
163+
$dayStart = $calendar['dayStart'];
164+
$dayEnd = $calendar['dayEnd'];
165+
$dayDuration = $calendar['dayDuration'];
166+
$diff = $start - $originStart;
167+
if ($diff >= $dayDuration) {
168+
while ($diff > 0) {
169+
$dayCalendar = $this->getDayCalendar($originStart);
170+
if ($dayCalendar['duration'] < $diff) {
171+
$diff -= $dayCalendar['duration'];
172+
if ($isReverse) {
173+
$originStart -= self::SCHEDULER_DAY_SECONDS;
174+
} else {
175+
$originStart += self::SCHEDULER_DAY_SECONDS;
176+
}
177+
} else {
178+
break;
179+
}
180+
}
181+
182+
if ($isReverse) {
183+
$start = $originStart - $diff;
184+
} else {
185+
$start = $originStart + $diff;
186+
}
187+
188+
$calendar = $this->getDayCalendar($start);
189+
$dayStart = $calendar['dayStart'];
190+
$dayEnd = $calendar['dayEnd'];
191+
$dayDuration = $calendar['dayDuration'];
192+
}
193+
194+
foreach ($calendar as $c) {
195+
if ($start >= $dayStart && $start <= $dayEnd) {
196+
$times = $c['rest'];
197+
foreach ($times as $t) {
198+
$restStart = strtotime("{$originStartDate} {$t['start']}");
199+
$restEnd = strtotime("{$originStartDate} {$t['end']}");
200+
201+
if ($start >= $restStart && $start < $restEnd) {
202+
if ($isReverse) {
203+
$start -= $t['duration'];
204+
} else {
205+
$start += $t['duration'];
206+
}
207+
} else {
208+
$cycle = 10 * 60;
209+
$cycleCount = ceil($diff / $cycle);
210+
$_start = $originStart;
211+
for ($i = 1; $i <= $cycleCount; $i++) {
212+
if ($isReverse) {
213+
$_start -= $cycle * $i;
214+
215+
if ($_start >= $restStart && $_start < $restEnd) {
216+
$start -= $t['duration'];
217+
break;
218+
}
219+
} else {
220+
$_start += $cycle * $i;
221+
222+
if ($_start >= $restStart && $_start < $restEnd) {
223+
$start += $t['duration'];
224+
break;
225+
}
226+
}
227+
}
228+
}
229+
}
230+
} else {
231+
break;
232+
}
233+
}
234+
235+
if ($start < $dayStart) {
236+
if ($isReverse) {
237+
$diff = $dayStart - $start;
238+
239+
$prevCalendar = $this->getDayCalendar($start - self::SCHEDULER_DAY_SECONDS);
240+
$prevDayStart = $prevCalendar['dayStart'];
241+
$prevDayEnd = $prevCalendar['dayEnd'];
242+
$prevStart = $prevDayEnd - $diff;
243+
244+
$start = $this->phaseTimeWithCalendarCompute($prevDayEnd, $prevStart, $isReverse);
245+
} else {
246+
$prevCalendar = $this->getDayCalendar($start - self::SCHEDULER_DAY_SECONDS);
247+
$diff = $start - $prevCalendar['dayEnd'];
248+
$dayStart = $calendar['dayStart'];
249+
$start = $dayStart + $diff;
250+
$start = $this->phaseTimeWithCalendarCompute($dayStart, $start, $isReverse);
251+
}
252+
}
253+
254+
if ($start > $dayEnd) {
255+
if ($isReverse) {
256+
$nextCalendar = $this->getDayCalendar($start + self::SCHEDULER_DAY_SECONDS);
257+
$nextDayStart = $nextCalendar['dayStart'];
258+
$diff = $start - $dayEnd;
259+
$start = $nextDayStart + $diff;
260+
261+
$start = $this->phaseTimeWithCalendarCompute($nextDayStart, $start, $isReverse);
262+
} else {
263+
$diff = $start - $dayEnd;
264+
265+
$nextCalendar = $this->getDayCalendar($start + self::SCHEDULER_DAY_SECONDS);
266+
$nextDayStart = $nextCalendar['dayStart'];
267+
$nextDayEnd = $nextCalendar['dayEnd'];
268+
$nextStart = $nextDayStart + $diff;
269+
270+
$start = $this->phaseTimeWithCalendarCompute($nextDayStart, $nextStart, $isReverse);
271+
}
272+
}
273+
274+
return $start;
27275
}
28276

29-
private function phaseStartedTimeCompute(bool $isReverse = false): int
277+
private function phaseTimeWithRestDayCompute(int &$time, bool $isReverse = false): int
30278
{
31-
return 0;
279+
$calendar = $this->getDayCalendar();
280+
281+
foreach ($calendar as $c) {
282+
if (strtotime($c['date']) < $time && $c['is_rest'] === 1) {
283+
if ($isReverse) {
284+
$time -= self::SCHEDULER_DAY_SECONDS;
285+
} else {
286+
$time += self::SCHEDULER_DAY_SECONDS;
287+
}
288+
}
289+
}
290+
291+
return $time;
32292
}
33293

34-
private function phaseCompletedTimeCompute(): int
294+
private function phaseCompleteTimeCompute(int $start, int $cost): int
35295
{
296+
while ($cost > 0) {
297+
$dayCalendar = $this->getDayCalendar();
298+
if ($dayCalendar['duration'] < $cost) {
299+
$cost -= $dayCalendar['duration'];
300+
$start += self::SCHEDULER_DAY_SECONDS;
301+
} else {
302+
break;
303+
}
304+
}
305+
306+
$originStart = $start;
307+
$end = $start + $cost;
308+
$dayCalendar = $this->getDayCalendar();
309+
310+
36311
return 0;
37312
}
38313
}

0 commit comments

Comments
 (0)