How can i show how many times a sence was shown while looping?
$i = 0;
foreach ($parts as $new[$i]) {
$abouttoexpire = strpos($new[$i], 'Your Airbnb question is about to expire');
$anairbnbexpert = strpos($new[$i], 'An Airbnb expert is waiting on feedback from you regarding');
$requesttoalter = strpos($new[$i], 'Your request to alter reservation');
//when the message was made
preg_match('/<div class="timestamp"[\s\S]*?>(.*)*?\+0000<\/div>/', $new[$i], $dateofmsg);
//between 9am and 6pm
$hour = date('H', strtotime(#$dateofmsg[1]));
if ($hour >= 9 && $hour <= 18) {
//if we found this sentence
if ($abouttoexpire !== FALSE) {
//how i show here how many times we catch the sentence #abouttoexpire??
}
}
}
$i++;
Inside the condition: if ($abouttoexpire !== FALSE)
How do i print the times this sence (#abouttoexpire) was accured during the loop?
Try this...
$i = 0;
$j = 0;
$k = 0;
foreach ($parts as $new[$i]) {
if ($hour >= 9 && $hour <= 18) {
$j++;
if ($abouttoexpire !== FALSE) {
$k++;
}
}
$i++;
}
echo "foreach loop=".$i;
echo "if loop =".$j;
echo "within if loop =".$k;
$i = 0;$j=0;
foreach ($parts as $new[$i]) {
$abouttoexpire = strpos($new[$i], 'Your Airbnb question is about to expire');
$anairbnbexpert = strpos($new[$i], 'An Airbnb expert is waiting on feedback from you regarding');
$requesttoalter = strpos($new[$i], 'Your request to alter reservation');
//when the message was made
preg_match('/<div class="timestamp"[\s\S]*?>(.*)*?\+0000<\/div>/', $new[$i], $dateofmsg);
//between 9am and 6pm
$hour = date('H', strtotime(#$dateofmsg[1]));
if ($hour >= 9 && $hour <= 18) {
//if we found this sentence
if ($abouttoexpire !== FALSE) {
$j++;
}
}
}
$i++;
echo 'no_of_times:'.$j;
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 months ago.
Improve this question
Hi i am working on a docker microservices grade checker application. I am getting user input from an HttpRequest. I am lacking some basic knowledge on arrays and how to work with them in php, its a weak point for me. I currently have the below code.
<?php
function getIndividualClassification($input_text)
{
$grades = null;
$lines = explode('newline', $input_text);
foreach ($lines as $line){
if ($line >= 70 && $line <= 100){
$grades = 'Distinction';
}elseif ($line >= 60 && $line <= 69){
$grades = 'Commendation';
}elseif ( $line >= 50 && $line <= 59){
$grades = 'Pass';
}elseif ($line >= 40 && $line <= 49){
$grades = 'Marginal Fail';
}elseif ($line >= 30 && $line <= 39){
$grades = 'Fail';
}elseif ($line >= 0 && $line <= 29){
$grades = 'Low Fail';
}else{
$grades = 'Error - Check input';
}
return $grades;
}
what i am trying to do is take the input which will be any number of modules and marks in the form (module1,60) and classify each one into the above grade bands.
Input is like:
module1,60newlinemodule2,80
so i will have an output like
module1 = Pass
module2 = fail
Any help or pointers is very much apricated :)
Collect the results in an associative array, and return that after the loop is done.
function getIndividualClassification($input_text)
{
$grades = [];
$lines = explode('newline', $input_text);
foreach ($lines as $line){
[$module, $grade] = explode(',', $line);
if ($grade > 100 || $grade < 0) {
$grades[$module] = 'Error - Check input';
} elseif ($grade >= 70) {
$grades[$module] = 'Distinction';
} elseif ($grade >= 60) {
$grades[$module] = 'Commendation';
} elseif ( $grade >= 50) {
$grades[$module] = 'Pass';
} elseif ($grade >= 40) {
$grades[$module] = 'Marginal Fail';
} elseif ($grade >= 30) {
$grades[$module] = 'Fail';
} else {
$grades[$module] = 'Low Fail';
}
}
return $grades;
}
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
}
}
}
I'm trying to create a simple attendance application with Laravel. I'm just a little stuck with the logic side.
What I'm trying to do is to match up the time logs of users to the correct schedule.
So in our office, we could have from 2 to 3 breaks, so a typical work shift will look like this:
Time In - 06:00 AM
Break Out 1 - 07:15 AM
Break In 1 - 07:30 AM
Break Out 2 - 11:30 AM
Break In 2 - 12:00 PM
Time Out - 03:00 PM
Now a user typically just uses the biometric device and selects "in" or "out".
My problem is given something like this:
05:58 AM, in
07:17 AM, out
07:31 AM, in
05:58 AM, out
How can the system tell which time log (07:17 AM) belongs to which time slot (Break Out 1)?
Thank you so much for the help, and if my question is unclear, I'm sorry.
Here's a sample code of what I've done so far. It works but I think it's really messy:
$day_shift = [
"time_in" => date('H:i:s', strtotime("06:00 AM")),
"break_out_1" => date('H:i:s', strtotime("07:15 AM")),
"break_in_1" => date('H:i:s', strtotime("07:30 AM")),
"break_out_2" => date('H:i:s', strtotime("11:30 AM")),
"break_in_2" => date('H:i:s', strtotime("12:00 PM")),
"break_out_3" => '',
"break_in_3" => '',
"time_out" => date('H:i:s', strtotime("03:00 pM")),
];
foreach ($day_shift as $key => $userScheduleTime) {
if ($userScheduleTime !== "") {
$time = $logDate->date." ".$userScheduleTime;
} else {
$time = "";
}
$schedules[] = array('time' => $time, 'type' => $types[$i%2],'name'=>$key);
$i++;
}
// logTimes is a collection of time logs
foreach ($logTimes as $logTime) {
$logs[] = $logTime->toArray();
}
$cloneLogs = $logs;
$lastlog = end($cloneLogs);
if ($lastlog["log_type"] == "login") {
$dayOut = "";
} else {
$dayOut = $lastlog["log_time"];
}
$lastout = null;
$size = count($logs);
do {
if ($logs[$size-1]['log_type'] == 'logout') {
$lastout = $logs[$size-1];
break;
}
$size--;
} while ($size > 0);
$lastlog = null;
for ($i = 0; $i < count($schedules); $i++) {
$logTime = current($logs);
if ($lastlog == $logTime['log_type']) {
next($logs);
}
// checks the first log, calculates how late the person is
if ($i == 0) {
if ($logTime['log_type'] == "login") {
$timein = $schedules[0]['time'];
if (strtotime(date("Y-m-d H:i", strtotime($logTime['log_time']))) >
strtotime(date("Y-m-d H:i", strtotime($timein)))) {
$lates[$logTime['log_time']] = true;
$lates["totallate"] += getDifferenceInMinutes($logTime['log_time'], $timein);
}
$lastlog = $logTime["log_type"];
next($logs);
}
}
if ($schedules[$i]['type']==$logTime['log_type'] && $i!=0 && $lastlog !== $logTime["log_type"]) {
$nextSched = isset($schedules[$i+1])?$schedules[$i+1]:$schedules[$i];
$j = 1;
while ($nextSched['time']=="" && ($i+$j)<=count($schedules)) {
$nextSched = $schedules[$i+$j];
$j++;
}
if (strtotime($nextSched['time'])>strtotime($logTime['log_time']) && $logTime["log_time"] != $dayOut) {
// checks and calculates if the user has undertime
if (strtotime($nextSched['time']) > strtotime($logTime['log_time']) && $nextSched['type']=='login') {
if (strtotime($logTime['log_time']) < strtotime($schedules[$i]['time'])) {
$lates[$logTime['log_time']] = true;
$lates["totalunder"] += getDifferenceInMinutes($logTime['log_time'], $schedules[$i]['time']);
}
}
// checks and calculates if the user has overbreaks
if (date('H:i', strtotime($schedules[$i]['time'])) <
date('H:i', strtotime($logTime['log_time'])) &&
$logTime['log_type'] == 'login') {
$lates[$logTime['log_time']] = true;
$lates["totalover"] += getDifferenceInMinutes($schedules[$i]['time'], $logTime['log_time']);
}
$lastlog = $logTime["log_type"];
next($logs);
}
if ($i+1==count($schedules)) {
next($logs);
}
if ($logTime["log_time"] == $dayOut && $dayOut !== null) {
$timeOut = $schedules[count($schedules)-1]["time"];
if (strtotime(date("Y-m-d H:i", strtotime($logTime["log_time"]))) <
strtotime(date("Y-m-d H:i", strtotime($timeOut)))) {
$lates[$logTime["log_time"]] = true;
$lates["totalunder"] += getDifferenceInMinutes($logTime['log_time'], $timeOut);
$lastlog = $logTime["log_type"];
}
break;
}
}
}
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.
I'm having an asbolute nightmare dealing with an array of numbers which has the following structure :
Odd numbers in the array : NumberRepresenting Week
Even numbers in the array : NumberRepresenting Time
So for example in the array :
index : value
0 : 9
1 : 1
2 : 10
3 : 1
Would mean 9 + 10 on Day 1 (Monday).
The problem is, I have a an unpredictable number of these and I need to work out how many "sessions" there are per day. The rules of a session are that if they are on a different day they are automatically different sessions. If they are next to each other like in the example 9 + 10 that would count as a single session. The maximum number than can be directly next to eachother is 3. After this there needs to be a minimum of a 1 session break in between to count as a new session.
Unfortunately, we cannot also assume that the data will be sorted. It will always follow the even / odd pattern BUT could potentially not have sessions stored next to each other logically in the array.
I need to work out how many sessions there are.
My code so far is the following :
for($i = 0; $i < (count($TimesReq)-1); $i++){
$Done = false;
if($odd = $i % 2 )
{
//ODD WeekComp
if(($TimesReq[$i] != $TimesReq[$i + 2])&&($TimesReq[$i + 2] != $TimesReq[$i + 4])){
$WeeksNotSame = true;
}
}
else
{
//Even TimeComp
if(($TimesReq[$i] != ($TimesReq[$i + 2] - 1))&& ($TimesReq[$i + 2] != ($TimesReq[$i + 4] - 1)))
$TimesNotSame = true;
}
if($TimesNotSame == true && $Done == false){
$HowMany++;
$Done = true;
}
if($WeeksNotSame == true && $Done == false){
$HowMany++;
$Done = true;
}
$TimesNotSame = false;
$WeeksNotSame = false;
}
However this isn't working perfectly. for example it does not work if you have a single session and then a break and then a double session. It is counting this as one session.
This is, probably as you guessed, a coursework problem, but this is not a question out of a textbook, it is part of a timetabling system I am implementing and is required to get it working. So please don't think i'm just copy and pasting my homework to you guys!
Thank you so much!
New Code being used :
if (count($TimesReq) % 2 !== 0) {
//throw new InvalidArgumentException();
}
for ($i = 0; $i < count($TimesReq); $i += 2) {
$time = $TimesReq[$i];
$week = $TimesReq[$i + 1];
if (!isset($TimesReq[$i - 2])) {
// First element has to be a new session
$sessions += 1;
$StartTime[] = $TimesReq[$i];
$Days[] = $TimesReq[$i + 1];
continue;
}
$lastTime = $TimesReq[$i - 2];
$lastWeek = $TimesReq[$i - 1];
$sameWeek = ($week === $lastWeek);
$adjacentTime = ($time - $lastTime === 1);
if (!$sameWeek || ($sameWeek && !$adjacentTime)) {
if(!$sameWeek){//Time
$Days[] = $TimesReq[$i + 1];
$StartTime[] = $TimesReq[$i];
$looking = true;
}
if($sameWeek && !$adjacentTime){
}
if($looking && !$adjacentTime){
$EndTime[] = $TimesReq[$i];
$looking = false;
}
//Week
$sessions += 1;
}
}
If you want a single total number of sessions represented in the data, where each session is separated by a space (either a non-contiguous time, or a separate day). I think this function will get you your result:
function countSessions($data)
{
if (count($data) % 2 !== 0) throw new InvalidArgumentException();
$sessions = 0;
for ($i = 0; $i < count($data); $i += 2) {
$time = $data[$i];
$week = $data[$i + 1];
if (!isset($data[$i - 2])) {
// First element has to be a new session
$sessions += 1;
continue;
}
$lastTime = $data[$i - 2];
$lastWeek = $data[$i - 1];
$sameWeek = ($week === $lastWeek);
$adjacentTime = ($time - $lastTime === 1);
if (!$sameWeek || ($sameWeek && !$adjacentTime)) {
$sessions += 1;
}
}
return $sessions;
}
$totalSessions = countSessions(array(
9, 1,
10, 1,
));
This of course assumes the data is sorted. If it is not, you will need to sort it first. Here is an alternate implementation that includes support for unsorted data.
function countSessions($data)
{
if (count($data) % 2 !== 0) throw new InvalidArgumentException();
$slots = array();
foreach ($data as $i => $value) {
if ($i % 2 === 0) $slots[$i / 2]['time'] = $value;
else $slots[$i / 2]['week'] = $value;
}
usort($slots, function($a, $b) {
if ($a['week'] == $b['week']) {
if ($a['time'] == $b['time']) return 0;
return ($a['time'] < $b['time']) ? -1 : 1;
} else {
return ($a['week'] < $b['week']) ? -1 : 1;
}
});
$sessions = 0;
for ($i = 0; $i < count($slots); $i++) {
if (!isset($slots[$i - 1])) { // First element has to be a new session
$sessions += 1;
continue;
}
$sameWeek = ($slots[$i - 1]['week'] === $slots[$i]['week']);
$adjacentTime = ($slots[$i]['time'] - $slots[$i - 1]['time'] === 1);
if (!$sameWeek || ($sameWeek && !$adjacentTime)) {
$sessions += 1;
}
}
return $sessions;
}
Here is my little attempt at solving your problem. Hopefully I understand what you want:
$TimesReq = array(9,4,11,4,13,4,8,4,7,2,12,4,16,4,18,4,20,4,17,4);
// First just create weeks with all times lumped together
$weeks = array();
for($tri=0; $tri<count($TimesReq); $tri+=2){
$time = $TimesReq[$tri];
$week = $TimesReq[$tri+1];
$match_found = false;
foreach($weeks as $wi=>&$w){
if($wi==$week){
$w[0] = array_merge($w[0], array($time));
$match_found = true;
break;
}
}
if(!$match_found) $weeks[$week][] = array($time);
}
// Now order the times in the sessions in the weeks
foreach($weeks as &$w){
foreach($w as &$s) sort($s);
}
// Now break up sessions by gaps/breaks
$breaking = true;
while($breaking){
$breaking = false;
foreach($weeks as &$w){
foreach($w as &$s){
foreach($s as $ti=>&$t){
if($ti>0 && $t!=$s[$ti-1]+1){
// A break was found
$new_times = array_splice($s, $ti);
$s = array_splice($s, 0, $ti);
$w[] = $new_times;
$breaking = true;
break;
}
}
}
}
}
//print_r($weeks);
foreach($weeks as $wi=>&$w){
echo 'Week '.$wi.' has '.count($w)." session(s):\n";
foreach($w as $si=>&$s)
{
echo "\tSession ".($si+1).":\n";
echo "\t\tStart Time: ".$s[0]."\n";
echo "\t\tEnd Time: ".((int)($s[count($s)-1])+1)."\n";
}
}
Given $TimesReq = array(9,4,11,4,13,4,8,4,7,2,12,4,16,4,18,4,20,4,17,4); the code will produce as output:
Week 4 has 4 session(s):
Session 1:
Start Time: 8
End Time: 10
Session 2:
Start Time: 11
End Time: 14
Session 3:
Start Time: 16
End Time: 19
Session 4:
Start Time: 20
End Time: 21
Week 2 has 1 session(s):
Session 1:
Start Time: 7
End Time: 8
Hope that helps.