Need a logic using foreach - php

I have a following table display
Task No. Person Company Project Task Date Tracked Total Time Comments
14.1 vaish, arpit ABC-TecHolding Relaunch Websitnalysis 2013-02-12 19:21:03
14.2 vaish, arpit Sugarion New Opensource Server 2013-02-12 19:21:03
14.6 vaish, arpit Sugarion New Opensource Server 2013-02-12 19:21:03
5.26 Projectmanager, Paul ABC-Tec Holding Relaunch Website 2010-03-13 03:40:16
5.27 Projectmanager, Paul ABC-Tec Holding Relaunch Website 2010-03-12 03:40:16
5.27 Projectmanager, Paul ABC-Tec Holding Relaunch Website 2010-03-13 03:40:16
8.2 Worker, Willi Customers ACME Hosting Data transfer 2010-03-13 00:21:18
14.2 Worker, Willi Sugarion New Opensource Server 2013-02-06 00:21:18 fyhbvghjukjjkhhlhh uuiuijujj jookljh
This is my foreach loop
foreach($result123 as $key=>$task) {
$time=$this->addtime($task['name'],$range['start'],$range['end']); //to calculate total time per user in time range
$diff = $task['estimated']+$task['tracked'];
$diffSign = $diff > 0 ? '-' : '+';
$table->addRow(array(
'number' => $task['tasknumber'].' '.$task['id_project'] ,
'person'=> $task['name'],
'customer' => $task['company'],
'project' => $task['project'],
'task' => $task['task'],
'date' => $task['date_tracked'],
'tracked' => $task['workload_tracked'],
'Total_Time' => $time,
'comment'=>$task['comment']
));
}
The column total time shows total of time tracked per person.
I want the total time should show only once per Person and not display again and again for each row.
Thanks in advance.

That's how I'd do it (Pseudocode) :
Set an array of "checked" people
Foreach record :
Is person in the "checked" array?
If yes, go on.
If no, display total AND add person to "checked" people.
And in PHP : (if I got it right)
$checked = array();
foreach($result123 as $key=>&$task) {
$time=$this->addtime($task['name'],$range['start'],$range['end']); //to calculate total time per user in time range
$diff = $task['estimated']+$task['tracked'];
$diffSign = $diff > 0 ? '-' : '+';
if (in_array($task['name'],$checked) $time =0;
else {
$checked[] = $task['name'];
}
$table->addRow(array(
'number' => $task['tasknumber'].' '.$task['id_project'] ,
'person'=> $task['name'],
'customer' => $task['company'],
'project' => $task['project'],
'task' => $task['task'],
'date' => $task['date_tracked'],
'tracked' => $task['workload_tracked'],
'Total_Time' => $time,
'comment'=>$task['comment']
));
}

$name = '';
foreach($result123 as $key=>$task) {
if ($name == $task['name']) {
$time = '';
}
elseif ($name != $task['name']) {
$time=$this->addtime($task['name'],$range['start'],$range['end']);
$name = $task['name'];
}
$diff= $task['estimated']+$task['tracked'];
$diffSign= $diff > 0 ? '-' : '+';
$table->addRow(array(
'number' => $task['tasknumber'].' '.$task['id_project'] ,
'person'=> $task['name'],
'customer' => $task['company'],
'project' => $task['project'],
'task' => $task['task'],
'date' => $task['date_tracked'],
'tracked' => $task['workload_tracked'],
'Total_Time' => $time,
'comment'=>$task['comment']
));
}
That should do it, I think.

Related

Laravel calendar scheduler

I'm trying to make an calendar scheduler for student teacher for their future lessons together.
I'm trying to add day, time and DATE(most important). Right now I added day and time in each of their following meetings. For ex. every Monday at 08:00 and every Wednesday at 10:00. But what I cannot add is Date . Here is some of my coding.
$student = Auth::user()->student;
$teacher = Teacher::where('id',$id)->first();
$lessons = $request->lessons_booked;
$times = $request->times;
$timesArrLength = count($times);
$stuTeachArr = array();
for($i = 1;$i<= $lessons;$i++){
$studentTeacher = StudentTeacher::create([
'student_id' => $student->id,
'teacher_id' => $teacher->id,
'subject_id' => $request->subject_id,
'place_of_tutoring_id' => $request->place_of_tutoring_id,
'lessons_booked' => $lessons,
'lesson_nr' => $i,
'time_id' => $times[($i-1) % $timesArrLength]['id'],
'day' => $times[($i-1) % $timesArrLength]['day'],
'date' => '2021-01-01', // add date here
'lessons_left' => $request->lessons_booked - $i,
'status' => 'active'
]);
array_push($stuTeachArr,$studentTeacher);
}
// $stuTeachArr['booked_teacher'] = $studentTeacher;
return $stuTeachArr;
What I want is to add DATE for every lesson that will happen from now until they finish with their lessons(For ex. every Monday and every Wednesday as mentioned before).
Any suggestion to change the way I'm doing would be welcomed.

Importancy algorithm based on time

I have an array of users, as follows;
<?php
$users = array(
array(
"id" => 1,
"last_updated" => 1398933140,
"weight" => 2.0
),
array(
"id" => 2,
"last_updated" => 1398933130,
"weight" => 0
),
array(
"id" => 3,
"last_updated" => 1398933120,
"weight" => 1.0
),
array(
"id" => 4,
"last_updated" => 1398933110,
"weight" => 0
)
);
?>
I want to (asynchronously) refresh some stats on users (for which I'm using a crobjob) ordered on last_updated, in essence the user with the most stale stats.
However, I want to add weights to users and calculate that into the equation. Is it good enough to just convert the weight to some amount of seconds and substract that from the last_updated timestamp?
I know my example array has time differences of 10 seconds, but I only want to start adding the weight criteria after 3600 seconds.
// Start substracting weight
if ($timediff > 3600) {
// The longer the timediff, the heavier the weight becomes
$weight_severity = (($timediff/1000) * $weight) * SOME_CONSTANT;
// Putting the 'last_updated' back farther in the past
$substract = $timestamp - $weight_severity;
}
Is this a good 'algorithm' or will this go horribly wrong when the differences become pretty large?
At the moment I have nearly 2000 users (expected will become 10.000), so theoretically a full loop takes 2000 minutes. My concern is, will a user with a weight of 2.0 be buried under 500 'insignificant' users?
Update: I have enhanced my code a bit.
<?php
$users = array(
array(
"id" => 1,
"last_updated" => 1399281955,
"weight" => 2.0
),
array(
"id" => 2,
"last_updated" => 1399281955 - 15000,
"weight" => 0
),
array(
"id" => 3,
"last_updated" => 1399281955 - 30000,
"weight" => 1.0
),
array(
"id" => 4,
"last_updated" => 1399281955 - 45000,
"weight" => 0
)
);
$results = array();
foreach ($users as $index => $user) {
$factor = 3;
$timestamp = $user['last_updated'];
$substract = $timestamp;
// Start substracting weight
$timediff = time() - $timestamp;
if ($timediff > 3600) {
// The longer the timediff, the heavier the weight becomes
$weight_severity = pow((($timediff/1000) * $user['weight']), $factor);
// Putting the 'last_updated' back farther in the past
$substract = $timestamp - $weight_severity;
}
$users[$index]['weight_updated'] = floor($substract);
$users[$index]['timediff'] = $timediff;
$users[$index]['diff'] = $users[$index]['last_updated'] -
$users[$index]['weight_updated'];
}
echo '<pre>';
print_r($users);
usort($users, function($a, $b) {
return (($a['weight_updated'] == $b['weight_updated'])) ?
0 : ($a['weight_updated'] < $b['weight_updated']) ? -1 : 1;
});
print_r($users);
So without weights, the user IDs would be: 4,3,2,1. But with my 'algorithm' it's now 3,4,2,1. User ID 3 because of it's weight, is getting done before 4. This is with a time difference of 15000 seconds (a little over 4 hours).

Indeed API XML feed always returns only 25 results

I'm trying to use the Indeed.com XML Feed API's in a PHP website. I use this script https://github.com/indeedlabs/indeed-php, see how it works on the Github page (very good script, thanks to the author).
It works but Indeed always returns only 25 results for jobs, even when I set the 'limit', 'start' and 'end' parameters.
Here are the parameters I send :
$aParams = array(
"q" => "php",
"l" => "paris",
"co" => "FR",
"limit" => 10000,
"sort" => "date",
"start" => 0,
"end" => 100,
"userip" => $_SERVER["REMOTE_ADDR"],
"useragent" => $_SERVER["HTTP_USER_AGENT"],
"v" => 2,
"format" => "json",
"publisher" => "123456789"
);
An array is returned and contains :
[version] = 2
[query] = 'php'
[location] = 'paris'
[dupefilter] = 'true'
[highlight] = 'true'
[start] = 1
[end] = 25
[totalResults] = 2068
[pageNumber] = 0
[results] = an array which contains the jobs informations
As we can see, totalResults is equal to 2058 but real the jobs results array always contains only 25 entries.
It seems to be a pagination issue (read here : http://forums.appthemes.com/report-jobroller-bugs/indeed-integration-api-37420) but I don't understand the goal : why proceed like this and not more simply ? So I have to do many requests : one to know first the 'totalResults' and save it (in session for example) and other requests to paginate the results 25 by 25 until the last?
Are there any developers who use this API and how do you proceed?
Thanks
Right Indeed limits the feed to 25 at a time. I have written script to get round this. In the Indeed $params you can specify a 'start' which as default is 0.
I have created a script which using the job count creates a foreach loop and loops the API changing the 'start' to keep getting different results until theres no more left. Then it puts it all into a single PHP array.
Single API request just so we can get totalResults (count of total jobs)
$client = new Indeed("YOUR_ID");
$args_count = array(
"q" => "YOUR SEARCH QUERY",
"l" => "",
"co" => "GB",
"userip" => "1.2.3.4",
"limit" => 10000,
"useragent" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2)"
);
Once we have the total job count we divide it by 25 and round the result up. This is so we know how many times we need to run our foreach
$totalResults = $client->search($args_count);
$totalCount = $totalResults['totalResults'] / 25;
$loop_to_count = ceil($totalCount);
We create a array starting with 0 and going up in 25s to as many as you require. My below will return 150 results.
$counter = 0;
$loop_options = array('0', '25', '50', '75', '100', '125', '150');
Then we start the main foreach:
$results = '';
foreach ($loop_options as $options) {
$params = array(
"q" => "YOUR SEARCH QUERY",
"l" => "",
"co" => "GB",
"userip" => "1.2.3.4",
"limit" => 10000,
"start" => $options,
"useragent" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2)"
);
$getResults = $client->search($params);
foreach ($getResults['results'] as $rawResults) {
$Subresults[] = array(
'jobtitle' => $rawResults['jobtitle'],
'company' => $rawResults['company'],
'city' => $rawResults['city'],
'state' => $rawResults['state'],
'country' => $rawResults['country'],
'language' => $rawResults['language'],
'formattedLocation' => $rawResults['formattedLocation'],
'source' => $rawResults['source'],
'date' => $rawResults['date'],
'snippet' => $rawResults['snippet'],
'url' => $rawResults['url'],
'onmousedown' => $rawResults['onmousedown'],
'jobkey' => $rawResults['jobkey'],
'sponsored' => $rawResults['sponsored'],
'expired' => $rawResults['expired'],
'indeedApply' => $rawResults['indeedApply'],
'formattedLocationFull' => $rawResults['formattedLocationFull'],
'formattedRelativeTime' => $rawResults['formattedRelativeTime'],
'stations' => $rawResults['stations']
);
}
$counter++;
if ($counter == $loop_to_count) { break; }
}
Finally all our results are inside this array:
$results = array ('results' => $Subresults);
$results will contains all the jobs you have posted on Indeed
please give limit attribute i gave 50 eg :
http://api.indeed.com/ads/apisearch?publisher=1772xxxxxxxxx&q=java&l=austin%2C%20tx&sort=&radius=&st=&jt=&start=&limit=50&fromage=&filter=&latlong=1&co=us&chnl=&userip=1.2.3.4&useragent=Mozilla/%2F4.0%28Firefox%29&v=2
Here you are using a library so you have to modify library function process_request() , in that function add a line $args["limit"] = 50; . here i just gave 50 you can initialize whatever number you want.

How can I manipulate my array, so if there is a scan within 60min with the same

This is really hard to explain, but i will do my best.
I have a array called arrayoftransationcs which contains 4 strings. *SCAN, MEMBER_ID, RESTAURANT, TIME, PAID. If a scan is paid, it will defined as 1, and if not it will have 0.
So the main question to my problem is, how can I get scan that contain paid = 0 which has not have paid = 1 within 60 min. I will give an example.
Example A In this example, there is 3 scan which comes from the same cafe x within 20 min. The first 2 has been defined as paid = 0, and the last has been defined as paid = 1. Because there is paid = 1 within 60min with the same member_id and restaurant, i dont want any of the scan
Scan A 1635752 Cafe X 17-11-2013 21:00 Paid 1
Scan B 1635752 Cafe X 17-11-2013 20:50 Paid 0
Scan C 1635752 Cafe X 17-11-2013 20:40 Paid 0
Example B In this example, there is also 3 scan from the same member, same restaurant, within 60min, but all of them has been defined as paid = 0. Because there is no paid = 1 in this example, i want these in a array. This is the goal. But there is a twist here, because there is more than 1 scan to use, i only want the latest scan in this example, which will mean only scan A can be used
Scan A 1635752 Cafe X 17-11-2013 21:00 Paid 0
Scan B 1635752 Cafe X 17-11-2013 20:50 Paid 0
Scan C 1635752 Cafe X 17-11-2013 20:40 Paid 0
So I hope you understand the my question. I need paid = 0 scan if there is not a paid = 1 scan subsequently with the same member_id, restaurant within 60min
This is how i tried.
I am looping my array 2 times, and then checking for it the same member_id (cardid) and restaurants are equals together, if yes, then check time. If it is whitin 60min, mark the scan as double
foreach($arrayoftransationcs as $key => $array)
{
$time=$arrayoftransationcs[$key]['created'];
$cardid = $arrayoftransationcs[$key]['cardid'];
$restaurant_id = $arrayoftransationcs[$key]['restaurant_id'];
if(isset($arrayoftransationcs[$key]))
{
foreach($arrayoftransationcs as $k1=>$v1)
{
$time2=$arrayoftransationcs[$k1]['created'];
if($key<$k1)
{
if($arrayoftransationcs[$k1]['cardid']==$cardid && $arrayoftransationcs[$k1]['restaurant_id']==$restaurant_id)
{
if(compare($time,$time2))
{
$arrayoftransationcs[$key]['error'] = 'double';
$arrayoftransationcs[$k1]['error'] = 'double';
}
}
}
}
}
}
checking the time here.
function compare($firsttime, $secondtime)
{
$interval = $firsttime-$secondtime;
$dif=round(abs($interval) / 60);
if ($dif < 60 || $dif < -60 )
{
if ($dif!==0)
{
return true;
}
else
{
return false;
}
}
}
This is the place, where i filter after paid = 0 and does not contain anything in the error field.
foreach ($arrayoftransationcs as $key)
{
if($key['paid'] == 0 && empty($key['error']))
{
$ids[] = $key['transactionid'];
}
}
But I am not sure it is the right approach, I did it with the code. For technically, I select all scan which has the same membership number, restaurant with "double" in the field error, if it is paid = 1 or 0, does not matter .. this is not right, i think.
So I'm missing something here, checking if there is paid = 0 scan here if yes, check if there is a paid = 1 scan within the next 60min having the same medlem_id and restaurant. If so, then mark them as doubles.
This is how you do it:
<?php
// Data Source
$arrayoftransationcs = array(
array(
'transactionid' => 16148,
'cardid' => 10010234,
'created' => 1380650784,
'restaurant_id' => 32089,
'paid' => 1
),
array(
'transactionid' => 16552,
'cardid' => 10010241,
'created' => 1381522288,
'restaurant_id' => 41149,
'paid' => 1
),
array(
'transactionid' => 16936,
'cardid' => 10010440,
'created' => 1386247655,
'restaurant_id' => 47897,
'paid' => 0
),
array(
'transactionid' => 16808,
'cardid' => 10010557,
'created' => 1382361447,
'restaurant_id' => 43175,
'paid' => 0
),
array(
'transactionid' => 18932,
'cardid' => 10010440,
'created' => 1386247655,
'restaurant_id' => 47897,
'paid' => 1
)
);
// Helper Function
function getUnpaidWithinHour($transactions) {
$unpaid_transactions = array();
$time_now = time();
foreach ($transactions as $transaction) {
if ($transaction['paid']) continue;
if (($time_now - $transaction['created']) < 3600 && !$transaction['paid']) {
$unpaid_transactions[] = $transaction;
}
}
return $unpaid_transactions;
}
// Test
$unpaid_transactions = getUnpaidWithinHour($arrayoftransationcs);
echo "<pre>";
print_r($unpaid_transactions);
echo "<pre>";
?>
Outputs:
Array
(
[0] => Array
(
[transactionid] => 16936
[cardid] => 10010440
[created] => 1386247655
[restaurant_id] => 47897
[paid] => 0
)
)
To test if this is working, I edited the transaction 16936 to have a timestamp of 5 minutes ago and ran the function. The code correctly detected that transaction.
Try it yourself and with your own datasource.
Let's make things simple, your question is: Find paid = 0 scan if there is not paid = 1 with same member_id within 60min, since lack of test data, so i'll describe below with nature language in php style:
make an empty arrayPaid
foreach (all data) {
if time passed greater than 60min, continue;
if paid
add member_id in arrayPaid: arrayPaid[member_id] = something
continue;
if unpaid and arrayPaid[member_id] is not set
this is the data you want
}
The logic is clear, easy to write your real code. And one important thing is, your data need to be order by time in desc.
I found the answer by doing this.
foreach ($results->result_array() as $filterofresults)
{
if($filterofresults['paid'] == 1)
{
$arrayoftransationcs1[]=$filterofresults;
}
if($filterofresults['paid'] == 0)
{
$arrayoftransationcs[]=$filterofresults;
}
}
foreach($arrayoftransationcs as $key => $array)
{
$time=$arrayoftransationcs[$key]['created'];
$cardid = $arrayoftransationcs[$key]['cardid'];
$restaurant_id = $arrayoftransationcs[$key]['restaurant_id'];
if(isset($arrayoftransationcs[$key]))
{
foreach($arrayoftransationcs1 as $k1=>$v1)
{
$time2=$arrayoftransationcs1[$k1]['created'];
if($key<$k1)
{
if($arrayoftransationcs1[$k1]['cardid']==$cardid && $arrayoftransationcs1[$k1]['restaurant_id']==$restaurant_id)
{
if(compare($time,$time2))
{
$arrayoftransationcs[$key]['error'] = 'Dobbelt';
$arrayoftransationcs1[$k1]['error'] = 'Dobbelt';
}
}
}
}
}
}
foreach ($arrayoftransationcs as $key)
{
if($key['paid'] == 0 && empty($key['error']))
{
$samlet[] = get_all_data($key['transactionid']);
}
}

Code loops optimization in PHP

Is there any way to optimize this piece of code to work faster? I'd appreciate any suggestions!
This piece of code processes the transferring of edges during graph creation.
foreach($times_arrival as $city_id => $time_points) {
// if city is not prohibited for transfers and there is and exists any departure times for this city
if (isset($times_departure[$city_id]) && isset($cities[$city_id]))
{
foreach($times_arrival[$city_id] as $t1_info)
{
foreach($times_departure[$city_id] as $t2_info)
{
if ($t1_info[0] != $t2_info[0]) //transfers are allowed only for different passages
{
$t1 = $t1_info[1];
$t2 = $t2_info[1];
$vertex_key = new Vertex($city_id, $t1, 1);
$vertex_key = $vertex_key->toString();
//minimum transfer time is 10 min.
if (date('H:i', strtotime($t2)) > date('H:i', strtotime('+ 10 minutes', strtotime($t1))))
{
$this->graph[$vertex_key][] = new Edge(
NULL,
$vertex_key,
new Vertex($city_id, $t2, 0),
(float) 0,
$f((strtotime($t2) - strtotime($t1)) / 60, 0, 1) //edge weight
);
}
//if transfer is on the bound of the twenty-four hours
else if (date('H:i', strtotime('+ 24 hours', strtotime($t2))) > date('H:i', strtotime('+ 10 minutes', strtotime($t1))))
{
$this->graph[$vertex_key][] = new Edge(
NULL,
$vertex_key,
new Vertex($city_id, $t2, 0),
(float) 0,
$f(strtotime('+ 24 hours', strtotime($t2)) - strtotime($t1) / 60, 0, 1) //edge weight
);
}
}
}
}
}
}
example of variables:
var_dump($times_arrival); //$times_departure have the same structure
array
3 =>
array
0 =>
array
0 => string '1' (length=1)
1 => string '08:12' (length=5)
1 =>
array
0 => string '2' (length=1)
1 => string '08:40' (length=5)
41 =>
array
0 =>
array
0 => string '21' (length=2)
1 => string '12:40' (length=5)
Thank you all!
The reason of slow speed was coz of using functions strtotime() and date().
In that case only you can say whether you chose a good or bad algorithm. In my point of view your code not has no extra computations.
Only one recommendation - use Xdebug to profile your code and find out where the bottleneck is, if possible.

Categories