To Manage Schedule in PHP foreach loop - php

I am having table like below
So there are priority and sqft, i want to start manufacturing schedule (from current date) that every day 1700 SQFT will be processed, like below image
but as you can see its not working
I have tried below code
foreach($priorityArraySum as $key=>$val)
{
$totalDays=ceil($val/1700);
$cutSQFT=$val;
for($j=1;$j<=$totalDays;$j++)
{
if($cutSQFT>1700)
{
echo '1700';
$cutDate=date('Y-m-d', strtotime($cutDate. ' + 1 days'));
$cutSQFT=$cutSQFT-1700;
}
else
{
echo $cutSQFT;
$cutSQFT=$cutSQFT-$cutSQFT;
}
}
}
#Nigel, to Make this dynamic, I have changed code to below, but its not working.
$pln_qry=mysql_query("select * from tbl_mfg_schedule where ms_date='".$today."'") or die(mysql_error());
$pln_data=mysql_fetch_array($pln_qry);
$max = $pln_data['ms_po_sqft'];
$dailyLeft = $max;
$current = reset($priorityArraySum);
$output = [];
//$day = date('Y-m-d');
$day = date('Y-m-d');
while (true) {
$pln_qry=mysql_query("select * from tbl_mfg_schedule where ms_date='".$today."'") or die(mysql_error());
$pln_data=mysql_fetch_array($pln_qry);
$max = $pln_data['ms_po_sqft'];
if ( $current >= $dailyLeft ) {
//$day=date('Y-m-d', strtotime($day. ' + 1 days'));
$output[] = ["priority" => key($priorityArraySum),
"amount" => $dailyLeft,
"day" => $day
];
$day=date('Y-m-d', strtotime($day. ' + 1 days'));
$current -= $dailyLeft;
$dailyLeft = $max;
}
else {
$output[] = ["priority" => key($priorityArraySum),
"amount" => $current,
"day" => $day
];
$dailyLeft -= $current;
if ( ($current = next($priorityArraySum)) === false ) {
break;
}
}
}

This code uses a while() loop to create an output array of the days work. It uses $current to keep track of each item and how much is left to allocate. It also uses $dailyLeft to keep track of how much capacity is left on a particular day. It checks the two and if the current is less than the daily capacity left, it allocates a full day to that item and resets the daily capacity. If there is extra capacity for that day it allocates this item to the day and gets the next item.
The day is only incremented (using $day++) when the capacity for that day is filled...
$max = 1700;
$dailyLeft = $max;
$current = reset($priorityArraySum);
$output = [];
$day = 1;
while (true) {
// echo $current."/".$dailyLeft."=".$day.PHP_EOL;
if ( $current >= $dailyLeft ) {
$output[] = ["priority" => key($priorityArraySum),
"amount" => $dailyLeft,
"day" => $day++
];
$current -= $dailyLeft;
$dailyLeft = $max;
}
else {
$output[] = ["priority" => key($priorityArraySum),
"amount" => $current,
"day" => $day
];
$dailyLeft -= $current;
if ( ($current = next($priorityArraySum)) === false ) {
break;
}
}
}
print_r($output);

Related

Counting tickets by hour in Laravel

I'm trying to create hourly counting groups of tickets. I have to count three tickets for each hour and insert them as a bonus while inserting the remaining ones as a malus; every hour perform this count on a table where tickets are generated. I should calculate based on two time periods, one from 7 in the morning to 15 in the afternoon and one from 15 in the afternoon to 7 in the morning. I was taking a cue from this post, but I can't see the ticket number and time, while I can see the down, up, total and uptime columns. Can anyone help me perform this? I would also like to insert the count of time between the opening and closing of each intervention
Laravel group data by odd amount of hours throughout days
$uptimeData = Ticket::whereYear('created_at', '>=', Carbon::now()->year)
->whereYear('created_at', '<=', Carbon::now()->year)
->orderBy('created_at', 'asc')
->select('ticket_Id', 'created_at')
->get();
$intervals = \Carbon\CarbonInterval::hours(1)->toPeriod('2023/01/01 07:00:00', '2023/01/01 15:00:00');
$uptimeDataTimeline = $uptimeData->groupBy(function ($item, $key) use ($intervals) {
$date = Carbon::parse($item->created_at);
foreach ($intervals as $key => $interval) {
if ($date->hour == Carbon::parse($interval)->addHours(1)->hour) {
$actualHour1 = Carbon::parse($interval)->hour;
if (strlen($actualHour1) == 1) {
$actualHour1 = "0$actualHour1";
}
return $date->format("Y-m-d $actualHour1:00:00");
} else {
if ($date->hour == Carbon::parse($interval)->addHours(1)->hour) {
$actualHour2 = Carbon::parse($interval)->subHours(1)->hour;
if (strlen($actualHour2) == 1) {
$actualHour2 = "0$actualHour2";
}
return $date->format("Y-m-d $actualHour2:00:00");
}
}
}
return $date->format('Y-m-d H:00:00');
});
$uptimeDataTimeline = $uptimeDataTimeline->map(function ($checksInPeriod, $key) {
$down = 0;
$up = 0;
$total = 0;
$uptime = 0;
$fill = '#1fc777';
foreach ($checksInPeriod as $key => $value) {
$total++;
if ($total <= 3) {
$up++;
} else {
$down++;
}
}
$uptime = floatval(number_format(round($up / $total, 5) * 100, 2, '.', ','));
if ($uptime < 100) {
$fill = '#9deab8';
}
if ($uptime < 99) {
$fill = '#fbaa49';
}
if ($uptime < 98) {
$fill = '#e0465e';
}
return [
'total_ticket_Id' => $total,
'down_ticket_Id' => $down,
'up_ticket_Id' => $up,
'uptime' => $uptime,
'fill' => $fill,
];
});

Find records between two time slots in php

i have time slots like
$timeslot = ['09:00-10:00', .... '23:00-00:00', '00:00-01:00'];
I have records with updated time as 23:15:00, 23:30:00, 00:15:00, 09:15:00 etc.
What i'm trying to find is the sum of records between each of the $timeslot. I'm not considering what day got updated, only time i'm looking for.
i tried with:-
$data = ['23:15:00', '23:30:00', '00:15:00', '09:15:00'];
foreach($data as $val) {
$cnt = 0;
foreach($timeslot as $slots) {
$slot = explode("-", $slots);
if( (strtotime($val) > strtotime($slot[0])) && (strtotime($val) <= strtotime($slot[1])) ) {
$up_time[$slot[0] . '-' . $slot[1]] = $cnt++;
}
}
}
echo '<pre>';print_r($up_time);echo '</pre>';
The expected output is:-
09:00-10:00 = 1
23:00-00:00 = 2
00:00-01:00 = 1
Strtotime is not required since your time can be compared as strings.
This code works as you expected.
$data = ['23:15:00', '23:30:00', '00:15:00', '09:15:00'];
$timeslot = ['09:00-10:00', '23:00-00:00', '00:00-01:00'];
$up_time = array();
foreach ($data as $val) {
$myTime = substr($val, 0, 5);
foreach ($timeslot as $slot) {
$times = explode("-", $slot);
if (substr($times[1], 0, 3) == "00:") {
$times[1] = "24:" . substr($times[1], 3);
}
if ($myTime >= $times[0] && $myTime <= $times[1]) {
if (!isset($up_time[$slot])) {
$up_time[$slot] = 1;
} else {
$up_time[$slot]++;
}
}
}
}
echo '<pre>';
print_r($up_time);
echo '</pre>';
The if with 'substr' is needed because for midnight you have '00' and not '24' so the computer thinks is an empty set (such as hours bigger then 23 and smaller then 0).
Comparison is made between string because bigger time is also a bigger string since you use 2 digits for hours.
You need to count equal slots so you need an array with an element for each slot and increment if duplicate or create an element if not found (the condition '!isset').
Update for modification request
$data = ['23:15:00', '23:30:00', '00:15:00', '09:15:00'];
// added unused slot 8:00-9:00
$timeslot = ['08:00-09:00','09:00-10:00', '23:00-00:00', '00:00-01:00'];
$up_time = array();
// new initialization
foreach ($timeslot as $slot) {
$up_time[$slot] = 0;
}
foreach ($data as $val) {
$myTime = substr($val, 0, 5);
foreach ($timeslot as $slot) {
$times = explode("-", $slot);
if (substr($times[1], 0, 3) == "00:") {
$times[1] = "24:" . substr($times[1], 3);
}
if ($myTime >= $times[0] && $myTime <= $times[1]) {
$up_time[$slot]++; // simplified
}
}
}

How to get the label in the result of an array

The following code works as expected to get the number of patients per age group.
It also gets the highest (or most common) age group.
$count_0_19 = 0;
$count_20_29 = 0;
$count_30_39 = 0;
$count_40_49 = 0;
$count_50_59 = 0;
$count_above_60 = 0;
$curr_year = date('Y');
$sql= "SELECT pt_dob FROM ptlist WHERE mid=$userID";
$stmt = $pdo->query($sql);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$result = $pdo->query($sql);
$pt_dob = $row[ 'pt_dob' ];
while($row = $result->fetch(PDO::FETCH_ASSOC)) {
$pt_dob = explode('-', $row['pt_dob']);
$year = $pt_dob[0];
$month = $pt_dob[1];
$day = $pt_dob
$temp = abs($curr_year - $year);
if($temp >= 0 && $temp <= 19) {
$count_0_19++;
}
elseif($temp >= 20 && $temp <= 29) {
$count_20_29++;
}
elseif($temp >= 30 && $temp <= 39) {
$count_30_39++;
}
elseif($temp >= 40 && $temp <= 49) {
$count_40_49++;
}
elseif($temp >= 50 && $temp <= 59) {
$count_50_59++;
}
else {
$count_above_60++;
}
}
echo '0-19: '.$count_0_19.'<br>';
echo '20-29: '.$count_20_29.'<br>';
echo '30-39: '.$count_30_39.'<br>';
echo '40-49: '.$count_40_49.'<br>'; // example output is > 40-49: 7 (i.e. 7 patients in age group 40-49)
echo '50-59: '.$count_50_59.'<br>';
echo '60+: '.$count_above_60.'<br>';
// getting highest value
$a = array($count_0_19, $count_20_29, $count_30_39, $count_40_49, $count_50_59, $count_above_60);
$res = 0;
foreach($a as $v) {
if($res < $v)
$res = $v;
}
echo $res;
^^ This tells me that e.g. 9 patients are in the 30-39 age group - i.e. the highest number of patients are in this age group.
But $res gives me only the number (e.g. 9).
What I am asking your help with is to get $res to give me the text(or label) "30-39", instead of the number 9.
Please help.
continue from comment... you need to store $key into a variable.
$a = array('0-19'=>$count_0_19, '20-29'=>$count_20_29, '30-39'=>$count_30_39, '40-49'=>$count_40_49, '50-59'=>$count_50_59, '60+'=>$count_above_60);
$res = 0;
$label = '';
foreach($a as $key => $v) {
if($res < $v){
$res = $v;
$label = $key; //get label from key and store in a variable
}
}
echo 'label = '.$label . ' , Number = '.$res;
You can archived this by creating the array of labels and then incrementing it according and then find the greatest value form the $label array to get the key.
$label = [
"0_19" => 0,
"20_29" => 0,
"30_39" => 0,
"40_49" => 0,
"50_59" => 0,
"above_60" => 0,
];
while ($row4 = $result4->fetch(PDO::FETCH_ASSOC)) {
$pt_dob = explode('-', $row4['pt_dob']);
$year = $pt_dob[0];
$month = $pt_dob[1];
$day = $pt_dob$temp = abs($curr_year - $year);
if ($temp >= 0 && $temp <= 19) {
$label['0_19'] = $label['0_19'] +1;
}
elseif ($temp >= 20 && $temp <= 29) {
$label['20_29'] = $label['20_29'] +1;
}
elseif ($temp >= 30 && $temp <= 39) {
$label['30_39'] = $label['30_39']+1;
}
elseif ($temp >= 40 && $temp <= 49) {
$label['40_49'] = $label['40_49'] +1;
}
elseif ($temp >= 50 && $temp <= 59) {
$label['50_59'] = $label['50_59']+1;
}
else {
$label['above_60']= $label['above_60']+1;
}
}
echo $maxs = array_keys($label, max($label));
echo "<br/>";
foreach($label as $k => $v);
echo "key $k count $v <br/>";

PHP For Loop, Compare Incrementing Value to Incrementing Array

Short question: I am trying to see if a variable ($y) is between multiple array values from a database ($ending[0] && $starting[0], $ending[1] && $starting[1], etc...). "If" $y is between any of those, echo "statement".
I'm using a for loop to increment a drop down in 30 minute intervals from 9am - 7pm.
If any of those times = a time saved within my database, it echoes "not available" instead.
Now I need to see "if" the dropdown time is "between" the start and end times in the database and make those "not available" as well.
Everything works if I manually identify which array keys to compare...but my question is: can I check the drop down value against all of the values in the arrays?
Example:
Start Dropdown: 09:00am 09:30am 10:00am etc up until 07:30pm. End Dropdown: 09:30am 10:00am 10:30am etc. up until 08:00pm. If there is a start and end time of 09:00am(start) 10:00am(end) saved in the database for an appointment, the dropdown will show "Not available" for the corresponding starting and end times, so a user cannot double book an appointment. What I am asking about, is how to identify all of the "in between" values...09:30am for example, cannot be a start or an end time, if the 09:00am-10:00am slot is already booked.
$sql_slots = "SELECT * FROM XXXXX WHERE date = '$query_date' ORDER BY XXXXX ASC";
$result_slots = mysqli_query($connection, $sql_slots);
$open = strtotime("9:00am");
$close = strtotime("9:30am");
$starting = array();
$ending = array();
while($row_result_slots = mysqli_fetch_assoc($result_slots)){
$starting[] = $row_result_slots['start_time'];
$ending[] = $row_result_slots['end_time'];
}
echo'
<select name="start_time">';
for($b = 0; $b <= 20; $b++){
$y = strtotime(($b*30) . " Minutes", $open);
$the_time = date("h:ia", $y);
// Here, instead of only comparing the first values in the array, I need to match it up against $ending[1] & $starting[1], $ending[2] & $starting[2], etc...
if(in_array($the_time, $starting) || ($y <= strtotime($ending[0]) && $y >= strtotime($starting[0]))){
echo "<option>Not Available<br></option>";
} else {
echo "<option>" . $the_time . "<br></option>";
}
}
echo'</select>';
How about that?
$sql_slots = "SELECT * FROM XXXXX WHERE date = '$query_date' ORDER BY XXXXX ASC";
$result_slots = mysqli_query($connection, $sql_slots);
$open = strtotime("9:00am");
$close = strtotime("9:30am");
$reserved = array();
while($row_result_slots = mysqli_fetch_assoc($result_slots)){
$start = $row_result_slots['start_time'];
while ($start <= $row_result_slots['end_time']) {
$reserved[$start] = true;
$start = date("Y/m/d h:i:s", strtotime($start . "+30 minutes"));
}
}
echo '<select name="start_time">';
for($b = 0; $b <= 20; $b++){
$y = strtotime(($b*30) . " Minutes", $open);
$the_time = date("h:ia", $y);
if(isset($reserved[$the_time]){
echo "<option>Not Available<br></option>";
} else {
echo "<option>" . $the_time . "<br></option>";
}
}
echo'</select>';
Below is what I came up with. This uses a do while loop and creates a reserved array that will fill all time between what is given in the appointment.
I updated the data to use my own array but updated your mysqli work with what should be correct. If not I left in my testing code for you to view if needed. I also used the disabled attribute on an option over outputting some text.
<?php
$sql_slots = "SELECT * FROM XXXXX WHERE date = '$query_date' ORDER BY XXXXX ASC";
$result_slots = mysqli_query($connection, $sql_slots);
$open = strtotime("9:00am");
$close = strtotime("7:00pm");
$space = 900; //15min * 60 seconds space between?
//This seems more normal for people to see.
//Simulate these appoinments
/*
$query_results = array(
array(
"start_time" => "9:00am",
"end_time" => "9:30am"
),
array(
"start_time" => "10:30am",
"end_time" => "11:30am"
),
array(
"start_time" => "11:45am",
"end_time" => "12:30pm"
)
);
*/
$reserved = array();
while($row_result_slots = mysqli_fetch_assoc($result_slots)){
//**NOTE**: Make sure these are times or use strtotime()
$next_slot = $reserved[] = strtotime($row_result_slots['start_time']);
$end_time = strtotime($row_result_slots['end_time']);
while($next_slot < $end_time){
$next_slot += $space;
$reserved[] = $next_slot;
}
}
/*
foreach($query_results as $appoinment) {
$next_slot = $reserved[] = strtotime($appoinment['start_time']);
$end_time = strtotime($appoinment['end_time']);
while($next_slot < $end_time){
$next_slot += $space;
$reserved[] = $next_slot;
}
}
*/
echo'<select name="start_time">';
$current = $open;
do {
$disabled = in_array($current, $reserved) ? 'disabled' : '';
echo '<option ' . $disabled . '>' . date("h:ia", $current) . '</option>';
$current += $space;
} while($current <= $close);
echo'</select>';

For loop Logic Problems with PHP

This is my new code, its almost working, but I think my while loop is wrong some where?
Same as before, gets users taken sick puts it into a var. Then get users entitlement based on years of service, then work out what they have taken and see if the user has used all the full entitlement, then to see if they have used all there half pay entitlement.
Please Help?
if($this->CURRENT_USER['User']['role_id'] > 3) { //locks out user types
//Get Holidaytypes
$types = $this->Holiday->find(
'all',
array(
'conditions' => array(
'Holiday.holidaystype_id' => 3,
'Holiday.user_id' => $id
)));
//Get starting date
$contracts = $this->Holiday->User->Contract->find(
'all',
array(
'conditions' => array(
'Contract.user_id' => $id//$data['user_id']),
'order' => array('Contract.startson' => 'ASC')
)
);
//Get How Many sick days
foreach ($types as $key => $value) {
global $SickTotal;
$typesDataEnds = strftime ("%u-%d-%Y", $types[$key]['Holiday']['endson']);
$typesDataStarts = strftime ("%u-%d-%Y", $types[$key]['Holiday']['startson']);
$SickTotal = count($typesDataEnds - $typesDataStarts);
//echo $SickTotal;
//Get Contract Start & End Dates
$start = array_shift($contracts);
$end = array_pop($contracts);
$endDate = $end['Contract']['endson'];
$startDate = $start['Contract']['startson'];
if (empty($endDate)) {
$endDate = time('now');
}
if (!empty($startDate)) {
$SortEnd = strftime("%Y", $endDate);
$SortStart = strftime("%Y", $startDate);
$YearsService = $SortEnd - $SortStart;
if ($YearsService <= 1) {
$SetFullEntitlement = 5;
$SetHalfEntitlement = 5;
//echo 'one year';
} elseif ($YearsService >= 2) {
$SetFullEntitlement = 10;
$SetHalfEntitlement = 10;
//echo 'two years';
} elseif ($YearsService >= 5) {
$SetFullEntitlement = 20;
$SetHalfEntitlement = 20;
//echo 'up to five years';
} elseif ($YearsService > 5) {
$SetFullEntitlement = 30;
$SetHalfEntitlement = 30;
//echo 'five years or more';
} else {
$SetFullEntitlement = 0;
$SetHalfEntitlement = 0;
//echo 'no sick pay';
}
} else {
$YearsService = 0;
//echo 'Sorry No Start Date For You Found!';
}
while ($SickTotal > 0) {
if ($SetFullEntitlement != 0) {
$SetFullEntitlement--;
} elseif ($SetHalfEntitlement != 0) {
$SetHalfEntitlement--;
}
}
echo 'FullPay:';
echo $SetFullEntitlement;
echo '<br/><br/>Halpay:';
echo $SetHalfEntitlement;
echo $SickTotal;
}
debug($types);
die();
//$this->render('/artists/holidayslist');
}
}
If ($startdate <= 1 year) {
If that's literally what you've typed, it's not going to work. Maybe strtotime might make some sense of it?
In any case,
For ($i = $Totalsick, $i >= $Fulldays, $i--) {
For ($i = $Totalsick, $>= $Halfdays, $i--) {
you're missing an $i in there - you're evaluating nothing against $Halfdays. You're also using $i for two seperate loops, so they're both on the same counter. switch your second loop to use a different variable.
I'm not quite sure I follow exactly what you are trying to do here but you could tidy up your code a bit and save on lines of code. I assume that $startdate is how many years ago the user started.
$sickdays= array( 0=>5, 1=>10, 2=>20, 5=>30 );
$userdays= 0;
foreach ( array_keys( $sickdays ) as $years_service )
{
if ( $years_service <= $startdate )
$userdays=$sickdays[$years_service];
}
Now $userdays should be the correct number of paid sick days and half days ( the two are always the same in your example ) for this user. A simple comparison should be sufficient to check whether they have taken less or more than their allotted number of days and half days.
I haven't tried this as I'm not working with PHP today, so I'm sure someone will shoot me down directly, but by setting your variables once and writing fewer lines you should find your code gets easier to maintain.

Categories