how to get interval overlap between time and given multiple time? - php

i have below array
Array
(
[0] => Array
(
[from_time] => 15:00
[to_time] => 17:15
)
[1] => Array
(
[from_time] => 10:00
[to_time] => 12:15
)
[2] => Array
(
[from_time] => 09:00
[to_time] => 11:15
)
[3] => Array
(
[from_time] => 09:00
[to_time] => 11:15
)
[4] => Array
(
[from_time] => 14:00
[to_time] => 16:15
)
[5] => Array
(
[from_time] => 15:00
[to_time] => 17:15
)
)
i want to get common time in this array.
If i Find common time in this array my expected result should be
Array
(
[0] => Array
(
[from_time] => 10:00
[to_time] => 11:15
)
[1] => Array
(
[from_time] => 15:00
[to_time] => 16:15
)
)
I have try with below code but not getting accurate result.
foreach ($booking_time as $time1) {
foreach ($booking_time as $time2) {
{
if(($time1['from_time'] > $time2['from_time'] && $time1['from_time'] < $time2['to_time'])|| ( $time1['to_time'] > $time2['from_time'] && $time1['to_time'] < $time2['to_time'])){
echo $time1['from_time'];
echo $time1['to_time'];
}
}
}
}

Quick example (I think it can be shorter, but for quick understanding it is ok) :
$intervals = [
['from_time' => '15:00', 'to_time' => '17:15'],
['from_time' => '10:00', 'to_time' => '12:15'],
['from_time' => '09:00', 'to_time' => '11:15'],
['from_time' => '09:00', 'to_time' => '11:15'],
['from_time' => '14:00', 'to_time' => '16:15'],
['from_time' => '15:00', 'to_time' => '17:15'],
];
$overlaps = [];
foreach ($intervals as $interval) {
$key = null;
foreach ($overlaps as $_key => $_intervals) {
foreach ($_intervals as $_interval) {
if (
($_interval['from_time'] <= $interval['from_time'] && $interval['from_time'] <= $_interval['to_time'])
||
($_interval['from_time'] <= $interval['to_time'] && $interval['to_time'] <= $_interval['to_time'])
) {
$key = $_key;
break 2;
}
}
}
if (is_null($key)) {
$key = count($overlaps);
}
$overlaps[$key][] = $interval;
}
foreach ($overlaps as &$overlap) {
$from = '00:00';
$to = '23:59';
foreach ($overlap as $_interval) {
$from = max($from, $_interval['from_time']);
$to = min($to, $_interval['to_time']);
}
$overlap = ['from_time' => $from, 'to_time' => $to];
}
unset($overlap);
print_r($overlaps);
Output :
Array
(
[0] => Array
(
[from_time] => 15:00
[to_time] => 16:15
)
[1] => Array
(
[from_time] => 10:00
[to_time] => 11:15
)
)

General Overlay for comparing A and B
X) A(start) < B(start) < A(end) < B(end)
Y) B(start) < A(start) < B(end) < A(end)
(and usually full inclusions are required as well)
B(start) <= A(start) < A(end) <= B(end)
A(start) <= B(start) < B(end) <= A(end)
You actually wrote that down, but you overlooked that A and B are switching places in your source (A will be B and B A at another run -> you only need to check X or Y) and depending on which case you check you have to adjust your variable/key selection.
Additionally you are not handling inclusions well (exluding them or appropriately including them).
Simple example:
a = 10-20
b = 15-25
you would expect 15-20 as result
lets assume the run: time1 a, time2 b
$time1['to_time'] > $time2['from_time'] &&
$time1['to_time'] < $time2['to_time']
matches and prints
10-20 (time1 (a) from and to -- you wanted to print time2 from and time1 to)
another run will assign: time2 a and time1 b
$time1['from_time'] > $time2['from_time'] &&
$time1['from_time'] < $time2['to_time'])
matches and prints
15-25 (time1 (b) from and to -- you wanted to print time1 from and time2 to)
Here a working example
foreach($array as $key => $time1) {
foreach($array as $key2 => $time2) {
if (($time1["from_time"] < $time2["from_time"]) && ($time2["from_time"] < $time1["to_time"]) && ($time2["to_time"] > $time1["to_time"])) {
$overlap[] = array("from_key" => $time2["from_time"], "to_time" => $time1["to_time"]);
}
//inclusion
if (($time1["from_time"] >= $time2["from_time"]) && ($time2["to_time"] >= $time1["to_time"]) && ($key !== $key2)) {
$overlap[] = array("from_time" => $time1["from_time"], "to_time" => $time1["to_time"]);
}
}
}
Disclaimer: There are no checks for double entries. If you dont want inclusions you need a way to handle A(start) < B(start) < A(end) == B(end) etc.

you wanna increment or += [any number]
$latest = aray_pop($booking_time); // this will grab the last element from the array
for($i = 0; $i < $latest; $i += 15 // this is the number you want to increment by) {
$booking_time[$key] = $i;
}

Related

Apply a function on value multidimentionnal array PHP

I have an array with the hours of production like this (the number of array is not fixed, somethimes we can have production in January, not in february, and restart in March etc...) :
Array
(
[0] => Array
(
[Month] => 8
[HoursProd] => 181.37
)
[1] => Array
(
[Month] => 9
[HoursProd] => 699.35
)
[2] => Array
(
[Month] => 10
[HoursProd] => 500.25
)
[3] => Array
(
[Month] => 11
[HoursProd] => 350.61
)
)
I want to divide the hours in my array by the number of hours in the month. Get the month key (number of th month), calculate the number of hours in this month, and divide my Hours value by this number.
For the number of hours, i write this code for try to have the total of hours in a month.:
$m = 1;
$a = date('m');
$y = date("y");
$result2 = array();
for($m; $m <= 12; $m++){
$d=cal_days_in_month(CAL_GREGORIAN,$m,$y);
$result2[]["HoursTotalMonth"] = $d * 24;
$result2[]["Month"] = $m;
$t = $d * 24;
//To simplify the problem, i try to convert Hours of the month in the same array of production, and wheen the value of month is the same, divise value hours prod by value of hours total month
$test[] = array("Month" => $m, "HoursTotalMonth" => $t);
};
I try lot of things whithout success. The goal being at the end to be able to create a Json file to create a chart with ChartJS, The goal being at the end to be able to create a Json file to create a graph with ChartJS, with the production hour / hour ratio of the month in percentage. I succeed with a simple array but not with an associative multidimentional array.
Ex : [Month] => 8
[RatioHoursProdOnHoursTotalMonth] => 24.37 // (181.37 / (31j*24h))
I want this array :
Array
(
[0] => Array
(
[Month] => 8
[RatioHoursProdOnHoursTotalMonth] => 24.37
)
[1] => Array
(
[Month] => 9
[RatioHoursProdOnHoursTotalMonth] => 97.13
)
[2] => Array
(
[Month] => 10
[RatioHoursProdOnHoursTotalMonth] => 67.23
)
[3] => Array
(
[Month] => 11
[RatioHoursProdOnHoursTotalMonth] => 48.69
)
)
To be able to use the Json encoder, like this one:
[{"Month":8,"RatioHoursProdOnHoursTotalMonth":24.37},{"Month":9,"RatioHoursProdOnHoursTotalMonth":97.13},{"Month":10,"RatioHoursProdOnHoursTotalMonth":67.23},{"Month":11,"RatioHoursProdOnHoursTotalMonth":48.69}]
Is it what you expect as output ?
$a = date('m');
$y = date("y");
$result = array();
$data = array(100,60,75,90,58,98,105,85,74,685,700,550);
for ($m = 1; $m <= 12; $m++){
$d = cal_days_in_month(CAL_GREGORIAN, $m, $y);
$result[] = [
"Heure" => $d * 24,
"Mois" => $m,
"ratio" => $data[$m - 1] * 100 / ($d * 24),
];
};
print_r($result);
With the help of #Melvyn Marigny, the code below make the output i want.
$m = 1;
$a = date('m');
$y = date("y");
$nb = count($result);
for ($m = 1; $m <= $nb; $m++){
$d = cal_days_in_month(CAL_GREGORIAN, $m, $y);
$result3[] = [
"Mois" => $result[$m - 1]["Mois"],
"HeureProd" => $result[$m - 1]["Heure"],
"HeureMois" => $d * 24,
"ratio" => $result[$m - 1]["Heure"] / ($d * 24),
];
}
print_r($result3);
Array
(
[0] => Array
(
[Mois] => 8
[HeureProd] => 181.37
[HeureMois] => 744
[ratio] => 0.24377688172043
)
[1] => Array
(
[Mois] => 9
[HeureProd] => 753.39
[HeureMois] => 696
[ratio] => 1.0824568965517
)
[2] => Array
(
[Mois] => 10
[HeureProd] => 1292.25
[HeureMois] => 744
[ratio] => 1.7368951612903
)
[3] => Array
(
[Mois] => 11
[HeureProd] => 376.11
[HeureMois] => 720
[ratio] => 0.522375
)

Determining overlapping time ranges based on day of the week

I have an array of time ranges like this:-
$events = array(
array("Monday", '19:00:00', '19:30:00', 0),
array("Monday", '19:10:00', '19:40:00', 0),
array("Tuesday", '19:10:00', '19:40:00', 0),
array("Wednesday", '19:10:00', '19:40:00', 0),
array("Monday", '19:30:00', '19:50:00', 0),
);
I am using bubble sort on the array:-
for($i = 0; $i < (count($events) - 1); $i++)
{
for($j = 1; $j < (count($events) - i - 1); $j++)
{
if($events[$i][0] < $events[$j][0])
{
if ($events[$j] > $events[($j + 1)])
{
$swap = $events[$j];
$events[$j] = $events[($j + 1)];
$events[($j + 1)] = $swap;
}
}
}
}
The result comes like this:-
Array (
[0] => Array (
[0] => Monday
[1] => 19:00:00
[2] => 19:30:00
[3] => 0)
[1] => Array (
[0] => Monday
[1] => 19:10:00
[2] => 19:40:00
[3] => 0)
[2] => Array (
[0] => Monday
[1] => 19:30:00
[2] => 19:50:00
[3] => 0)
[3] => Array (
[0] => Tuesday
[1] => 19:10:00
[2] => 19:40:00
[3] => 0)
[4] => Array (
[0] => Wednesday
[1] => 19:10:00
[2] => 19:40:00
[3] => 0)
)
Now I need to strike out those time ranges which overlap on a specific day.
Like this:
Array (
[0] => Array (
[0] => Monday
[1] => 19:00:00
[2] => 19:30:00
[3] => 1)
[1] => Array (
[0] => Monday
[1] => 19:10:00
[2] => 19:40:00
[3] => 1)
[2] => Array (
[0] => Monday
[1] => 19:30:00
[2] => 19:50:00
[3] => 1)
[3] => Array (
[0] => Tuesday
[1] => 19:10:00
[2] => 19:40:00
[3] => 0)
[4] => Array (
[0] => Wednesday
[1] => 19:10:00
[2] => 19:40:00
[3] => 0)
)
The ones which are [3] => 1, denote there is a time overlap conflict.
How can I proceed?
I tried to use this solution, but got no luck. Besides, mine has a day of week.
I had a little play and this is what I came up with. It preserves the original order of the $events array as textual days don't sort well (Friday would come before Wednesday etc). A bit brute force, not optimised or properly tested, but hope it's useful for ideas.
foreach ($events as $event_id=>$event) {
$days[$event[0]][]=[$event_id,$event[1],$event[2]];
}
foreach ($days as $dayevents) {
if (count($dayevents)>1) {
foreach ($dayevents as $dayevent1) {
foreach ($dayevents as $dayevent2) {
if ((($dayevent1[1]>$dayevent2[1]) and ($dayevent1[1]<$dayevent2[2])) or
(($dayevent1[2]>$dayevent2[1]) and ($dayevent1[2]<$dayevent2[2]))) {
$events[$dayevent1[0]][3]=1;
$events[$dayevent2[0]][3]=1;
}
}
}
}
}
$events = array(
array("Monday", '19:00:00', '19:30:00', 0),
array("Monday", '19:10:00', '19:40:00', 0),
array("Tuesday", '19:10:00', '19:40:00', 0),
array("Wednesday", '19:10:00', '19:40:00', 0),
array("Monday", '19:30:00', '19:50:00', 0),
);
$combined = array();
// first we collect all intervals for the given day
foreach($events as $record)
{
$combined[$record[0]][] = array(
$record[1], $record[2], 0
);
}
// then for each day we look if there are overlaps
foreach($combined as $day => &$intervals)
{
$len = count($intervals);
// we compare each interval with each of the rest intervals for the same day
foreach($intervals as $i => &$interval_1)
{
// we convert the start/end times of the interval A to an integer
$begin_1 = str_replace(':','',$interval_1[0]);
$end_1 = str_replace(':','',$interval_1[1]);
for($k = $i + 1; $k < $len; $k++)
{
// we convert the start/end times of the interval B to an integer
$begin_2 = str_replace(':','',$intervals[$k][0]);
$end_2 = str_replace(':','',$intervals[$k][1]);
// we compute the overlap of the 2 intervals
$overlap = max(0,$end_1 - $begin_1 - max(0,$end_1 - $end_2) - max(0,$begin_2 - $begin_1));
if($overlap)
{
$interval_1[2]++; // we increase the counter of interval A
$intervals[$k][2]++; // we increase the counter of interval B
}
}
}
}
<?php
$events = array(
array("Monday", '19:00:00', '19:10:00'),
array("Monday", '19:05:00', '19:20:00'),
array("Tuesday", '19:10:00', '19:40:00'),
array("Wednesday", '19:10:00', '19:40:00'),
array("Monday", '19:15:00', '19:30:00'),
);
function convertToSeconds($time){
$time = explode(":",$time);
return intval($time[0]) * 3600 + intval($time[1]) * 60 + intval($time[2]);
}
$time_ranges = [];
$hold_dates = [];
for($i=0;$i<=86401;++$i){
$time_ranges[] = 0;
$hold_dates[$i] = [];
}
$time_range_for_week = [];
$week_days = ['monday' ,'tuesday','wednesday','thursday','friday','saturday','sunday'];
foreach($week_days as $day){
$time_range_for_week[$day] = [
'hold_dates' => $hold_dates,
'time_range' => $time_ranges
];
}
foreach($events as &$data){
$start_time = convertToSeconds($data[1]);
$end_time = convertToSeconds($data[2]);
$time_range_for_week[strtolower($data[0])]['hold_dates'][$start_time][] = &$data;
$time_range_for_week[strtolower($data[0])]['hold_dates'][$end_time][] = &$data;
$time_range_for_week[strtolower($data[0])]['time_range'][$start_time] += 1;
$time_range_for_week[strtolower($data[0])]['time_range'][$end_time + 1] -= 1;
}
foreach($time_range_for_week as $day_name => &$day_data){
$sum = 0;
foreach($day_data['time_range'] as $time => $value){
$sum += $value;
if($sum > 1 && count($day_data['hold_dates'][$time]) > 0){
foreach($day_data['hold_dates'][$time] as &$each_event){
$each_event[3] = 1;
}
}
}
}
print_r($events);
Demo: https://3v4l.org/JeGdR
Algorithm:
This is rather simple and efficient than basic brute force.
To find out collisions between times, we first make an array of size 86400 for each day. 86400 because it is no. of seconds(24*60*60) for a day(like Monday or Tuesday etc).
The array looks like this for a particular day(like Monday or Tuesday etc):
Structure:
Array
(
[monday] => Array
(
[hold_dates] => Array
(
[],[],[],... till 86400
),
[time_range] => Array
(
[],[],[],... till 86400
),
),
[tuesday] => Array(
...
),
...
)
In the hold_dates key for a day, we are just going to have our array values at the start time and end times positions. Here start time is the 1st position(0-based indexing) in array("Monday", '19:10:00', '19:40:00', 0) and end time is 2nd position in array("Monday", '19:10:00', '19:40:00', 0). In the code, the lines look like:
Code:
$time_range_for_week[strtolower($data[0])]['hold_dates'][$start_time][] = &$data;
$time_range_for_week[strtolower($data[0])]['hold_dates'][$end_time][] = &$data;
The & is used for syncing updates with actual $events array, so it's a pass by reference.
The time_range will just hold integer values and those integer values as explained below.
Let's consider intervals like below:
[2,7],
[4,9],
[6,10]
We have a timeline like below:
1 2 3 4 5 6 7 8 9 10 11 // these are seconds from 1 to 11
+1 -1
+1 -1
+1 -1
1 1 2 2 3 3 2 2 1 0
In the above diagram, for each date's start time, we add +1, and -1 to it's end time + 1. This means that, when we iterate from 1 to 11 and keep summing values, if we find any date's start time or end time having a sum > 1, we found there is a collision and we need to set it's value to 1.
We do the same in the above code. Here, the space used for this code is 86400 * 7 = 604800, which is constant space O(1) since this does not depend upon size of $events.
Time complexity is again the constant iterations 86400 * 7 = 604800 + looping twice through each element in $events, which makes it O(n) where n is size of $events.

How to determine if integers are within a range and store into two arrays?

I have an array called $grades which contains grades ranging from negative numbers to numbers over 100.
I need to put the negative grades and the grades over 100 into their own array and all the other numbers into their own array.
for($i = 0; $i < count($grades); $i++) {
if ($grades[$i] < 0 || $grades[$i] > 100) {
$invalidGrades[] = $i;
} else if ($grades[$i] >= 0 && $grades[$i] <= 100) {
$validGrades[] = $i;
}
}
This is the code I have so far. It appears to only be returning the numbers in the count instead of the values.
could be you want assign the grades using same index you can try this way
for($i = 0; $i < count($grades); $i++) {
if ($grades[$i] < 0 || $grades[$i] > 100) {
$invalidGrades[$i] = $grades[$i];
} else if ($grades[$i] >= 0 && $grades[$i] <= 100) {
$validGrades[$i] = $grades[$i];
}
}
or if you want push the value
for($i = 0; $i < count($grades); $i++) {
if ($grades[$i] < 0 || $grades[$i] > 100) {
$invalidGrades[] = $grades[$i];
} else if ($grades[$i] >= 0 && $grades[$i] <= 100) {
$validGrades[] = $grades[$i];
}
}
Try This
$grades = array(88,86,90,78,95,101,78,105,79,110);
$invalidGrades = array();
$validGrades = array();
foreach($grades as $grade) {
if ($grade > 100 || $grade < 0) {
array_push($invalidGrades, $grade);
} else {
array_push($validGrades, $grade);
}
}
print "Grades";
print_r($grades);
print "invalidGrades";
print_r($invalidGrades);
print "validGrades";
print_r($validGrades);
You should get the following.
php54s test.php
Content-type: text/html
GradesArray
(
[0] => -1
[1] => -4
[2] => -10
[3] => 88
[4] => 86
[5] => 90
[6] => 78
[7] => 95
[8] => 101
[9] => 78
[10] => 105
[11] => 79
[12] => 110
)
invalidGradesArray
(
[0] => -1
[1] => -4
[2] => -10
[3] => 101
[4] => 105
[5] => 110
)
validGradesArray
(
[0] => 88
[1] => 86
[2] => 90
[3] => 78
[4] => 95
[5] => 78
[6] => 79
)
foreach is your best option here, try this:
//Some random grades
$grades = [1, -10, 90, 30, -3, 200, 300, 44];
$validGrades = array();
$inValidGrades = array();
foreach($grades as $grade){
if($grade < 0 || $grade > 100){
$inValidGrades[] = $grade;
}else{
$validGrades[] = $grade;
}
}
//Test the output
echo "<pre>";
print_r($grades);
echo "<br>";
print_r($validGrades);
echo "<br>";
print_r($inValidGrades);
The output will be:
Array
(
[0] => 1
[1] => -10
[2] => 90
[3] => 30
[4] => -3
[5] => 200
[6] => 300
[7] => 44
)
Array
(
[0] => 1
[1] => 90
[2] => 30
[3] => 44
)
Array
(
[0] => -10
[1] => -3
[2] => 200
[3] => 300
)
This can be done with a simple if-else block. The only choice about how to construct it comes down to if you want to use one condition or two in the if expression.
Method #1: (Output Demo) (Calculation Demo) "Single Condition"
$grades=array(-4,-1,0,1,6,10,70,99,100,101,105,110);
foreach($grades as $grade){
if( ($grade+1)*(101-$grade) > 0 ){ // ($grade minus negative [lower limit])*([upper limit] plus $grad)
$validGrades[] = $grade;
}else{
$invalidGrades[] = $grade;
}
}
var_export($validGrades);
echo "\n---\n";
var_export($invalidGrades);
Method #2: (Output Demo) "Double Condition"
$grades=array(-4,-1,0,1,6,10,70,99,100,101,105,110);
foreach($grades as $grade){
if( $grade<0 || $grade>100 ){
$validGrades[] = $grade;
}else{
$invalidGrades[] = $grade;
}
}
var_export($validGrades);
echo "\n---\n";
var_export($invalidGrades);
Output (from either method)
array (
0 => -4,
1 => -1,
2 => 101,
3 => 105,
4 => 110,
)
---
array (
0 => 0,
1 => 1,
2 => 6,
3 => 10,
4 => 70,
5 => 99,
6 => 100,
)
*Notes:
There will be an unnoticeable difference in efficiency between the two methods; this is purely demonstrative.
The "Double Condition" can also be written with the "And" logical operator (&&) as if( $grade<=100 && $grade>=0 ){ with the same effect.
Because the pass/fail comparison is determined in the if expression, there is no need to use an elseif expression -- this would be redundant.
foreach() is a more appropriate construct to loop with versus for because calling the count() function is avoided. This also prevents your coding error while trying to access the grades via their index.
Calling array_push() (as some other answers do) is unnecessary overhead -- not that it is actually going to impact your application. I like to avoid function calls when possible. Using [] syntax is the function-free alternative to array_push().

Check PHP array for consecutive indexes

Sorry if the title of the question is unclear, I couldn't sum it up more precisely.
This is the issue:
To begin with, I have an array in this format:
Array (
[0] => 09:00
[1] => 10:00
[2] => 11:00
[3] => 12:00
[4] => 13:00
[5] => 14:00
[6] => 15:00
[7] => 16:00
[8] => 17:00
[9] => 18:00
)
Then some of the members are unset, so after that we're left with something like:
Array (
[0] => 09:00
[1] => 10:00
[6] => 15:00
[7] => 16:00
[8] => 17:00
[9] => 18:00
)
As you see, the array represents time slots. Now, what I need to do is eliminate all time slots shorter than 3 hours. So I need to go through the array and, wherever there are less than 3 members of the original array present, take them out too. So in the example above, since 09:00 and 10:00 are not followed by 11:00, I need to take them out and be left with:
Array (
[6] => 15:00
[7] => 16:00
[8] => 17:00
[9] => 18:00
)
How do I accomplish this? Logically, I think it might be easiest to check for 3 consecutive indexes, rather then checking the actual times but I'm open to any suggestions.
I've solved the problem on my own, and I made it generic so it would work for any duration, not just 3 hours.
$dur=3; //could be anything
foreach($work_times as $member){
$key=array_search($member,$work_times);
$a_ok=0;
for($options=0;$options<$dur;$options++){
$thisone=1;
for($try=$key-$options;$try<$key-$options+$dur;$try++){
if(!array_key_exists($try,$work_times))
$thisone=0;
}
if($thisone==1)
$a_ok=1;
}
if($a_ok==0)
unset($work_times[$key]);
}
$arr = array(
0 => '09:00',
1 => '10:00',
6 => '15:00',
7 => '16:00',
8 => '17:00',
9 => '18:00'
);
// for some testing
$arr += array(12 => '19:00', 13 => '20:00', 14 => '21:00');
$arr += array(16 => '22:00', 17 => '23:00');
$dontRemove = array();
foreach($arr as $key => $val) {
// if the next 2 keys are set
if (isset($arr[$key+1]) && isset($arr[$key+2])) {
$dontRemove[] = $key;
$dontRemove[] = $key+1;
$dontRemove[] = $key+2;
}
}
// combine and diff the keys to get the keys which should be actually removed
$remove = array_diff(array_keys($arr), array_unique($dontRemove));
foreach($remove as $key) {
unset($arr[$key]);
}
print_r($arr);
Try this:
<?php
function check() {
global $array;
$tmpArr = array_keys( $array );
$val1 = $tmpArr[0];
$val2 = $tmpArr[1];
$val3 = $tmpArr[2];
if( ( ++$val1 == $val2 ) && ( ++$val2 == $val3 ) ) {
// continuous
} else {
// not continuous, remove it
unset( $array[$tmpArr[0]] );
}
}
$array = array(
'0' => '09:00',
'1'=> '10:00',
'6' => '15:00',
'7'=> '16:00',
'8' => '17:00',
'9' => '18:00'
);
$total = count( $array );
$ctotal = 0;
while( $ctotal < $total ) {
if( count( $array ) <= 2 ) {
// this array has 2 elements left, which obviously
// nullifies the 3 continuous element check
$array = array();
break;
} else {
//check the array backwards
check();
$total--;
}
}
?>
Hope this helps
$a = Array(
0 => "09:00",
1 => "10:00",
6 => "15:00",
7 => "16:00",
8 => "17:00",
9 => "18:00",
11 => "20:00",
);
foreach ($a as $k => $v) {
// previous or next two time slots exist
$consecutive = (isset($a[$k-1]) or
(isset($a[$k+1]) and isset($a[$k+2])));
if (!$consecutive)
unset($a[$k]);
}

Trying to generate a week-timeline with PHP

I'm coding some kind of schedule and get stuck itterating trough the the dates.
I have a timeline generated for 5 work-days starting at 6:00h till 18:30h this is no problem.
I have a table with users and a table with dates. The users can have multiple tasks during the week.
This is the array:
Array
(
[0] => Array
(
[dateStart] => 2011-09-14 13:00:00
[dateEnd] => 2011-09-15 11:00:00
[eventType] => 1
[data] => test
[taskDescription] => Vakantieverlof
[taskColor] => ff6600
)
[1] => Array
(
[dateStart] => 2011-09-14 15:00:00
[dateEnd] => 2011-09-14 18:00:00
[eventType] => 3
[data] =>
[taskDescription] => ADV
[taskColor] => 336600
)
[2] => Array
(
[dateStart] => 2011-09-15 16:00:00
[dateEnd] => 2011-09-16 10:00:00
[eventType] => 2
[data] =>
[taskDescription] => Ziek
[taskColor] => ff0000
)
)
And this is the loop trough the array:
$dat=0;
while($dat<count($row->dates))
{
$color = "cccccc";
if(!empty($row->dates[$dat]['taskColor'])) {
$color = $row->dates[$dat]['taskColor'];
$desc = $row->dates[$dat]['taskDescription'];
} else {
$color = "cccccc";
}
$datNext = $dat+1;
if($datNext >= count($row->dates)) $datNext = $dat;
if($row->dates[$datNext]['dateStart'] >= $hourCons AND $dat >= count($row->dates))
{
$dat++;
} else {
if( $row->dates[$dat]['dateStart'] < $hourConsEnd AND $row->dates[$dat]['dateEnd'] > $hourCons )
{
$wpcal .= "<div class=\"fullCell\" style=\"".$transparent." background-color: #".$color.";\"></div>";
} else {
$wpcal .= "<div class=\"emptyCell\" style=\"\"></div>";
}
}
$dat++;
}
Now I get 3 timelines representing each planned task. like this:
Screenshot
But I want 1 timeline containing each of these tasks... the green task in this case may overlap the orange.
Please help I'm strungling with it for a couple of days now...
Instead of looping through the array of appointments, loop through hours of the day for each day. Inside that loop, check if any of the appointments overlap that time, and draw filled if so.
$filled_flag = false;
foreach ($row->dates as $appt) {
if ($appt['dateStart'] < $hourConsEnd && $appt['dateEnd'] > $hourCons) {
$filled_flag = true;
break;
}
}
if ($filled_flag) {
$wpcal .= "<div class=\"fullCell\" style=\"".$transparent." background-color: #".$color.";\"></div>";
} else {
$wpcal .= "<div class=\"emptyCell\" style=\"\"></div>";
}
You need to merge the arrays into one array first, before you loop through them generating the <div>s. For example you can precreate an array with all the 'slots', and then fill them with the most applicable task. In the foreach where you do the merge, you can apply some business logic, like if the task is completely overlapped by another one, overwrite its slots etc.
Eventually my Array is part of an object per user:
stdClass Object
(
[id] => 2
[username] => Emminet
[user_level] => 100
[dates] => Array
(
[0] => Array
(
[dateStart] => 2011-09-07 07:00:00
[dateEnd] => 2011-09-14 15:29:59
[eventType] => 3
[data] => Dit is dan veld 2...
[taskDescription] => ADV
[taskColor] => 336600
)
[1] => Array
(
[dateStart] => 2011-09-14 09:00:00
[dateEnd] => 2011-09-14 16:29:59
[eventType] => 3
[data] => dit is veld 1
[taskDescription] => ADV
[taskColor] => 336600
)
[2] => Array
(
[dateStart] => 2011-09-15 12:30:00
[dateEnd] => 2011-09-15 16:29:59
[eventType] => 3
[data] =>
[taskDescription] => ADV
[taskColor] => 336600
)
)
)
So I loop through the users and for every user I loop trough the week like this:
for($day=1; $day<=7; $day++){
// Timeframing settings
$startDayAt = "06:00";
$frameAmount = 26;
$timeFrame = 30; // minutes
// Timeframing output
for($i=0,$eTime = strtotime($startDayAt); $i < $frameAmount; $i++, $eTime = strtotime("+$timeFrame minutes", $eTime)) {
$dat=0;
while($dat<count($row->dates))
{
$color = "cccccc";
if(!empty($row->dates[$dat]['taskColor'])) {
$color = $row->dates[$dat]['taskColor'];
$desc = $row->dates[$dat]['taskDescription'];
} else {
$color = "cccccc";
}
$datNext = $dat+1;
if($datNext >= count($row->dates)) $datNext = $dat;
if($row->dates[$datNext]['dateStart'] >= $hourCons AND $dat >= count($row->dates))
{
$dat++;
} else {
if( $row->dates[$dat]['dateStart'] < $hourConsEnd AND $row->dates[$dat]['dateEnd'] > $hourCons )
{
$wpcal .= "<div class=\"fullCell\" style=\"".$transparent." background-color: #".$color.";\"></div>";
} else {
$wpcal .= "<div class=\"emptyCell\" style=\"\"></div>";
}
}
$dat++;
}
}
}
So that's my actual loop, trough the days and then the hours and later the users...

Categories