sum availibilty of user in minute - php

I want to calcul the total availability of an user:
I store availibilty like this :
And I have history of availibilty cause user can change their availibilty so I need to make the sum with this.
signupDate to first UpdateDATE and after
updateDate[i] to updateDate[i+1]
and at the end
updateDate[i+n] to now;
and get for each duration in minute :
endHours - startHours
I got json like this :
availibility object are per week
{
"2022-12-20" (date when user have signup ): [
{
dayNumber : 2,
startHours:08:00,
endHours :10:00;
},
{
dayNumber : 3,
startHours:11:00,
endHours :16:00;
}
],
"2022-12-28" (date when user have update his availibilties): [
{
dayNumber : 2,
startHours:08:00,
endHours :10:00;
},
{
dayNumber : 3,
startHours:11:00,
endHours :16:00;
}
],
"2023-01-01" (date when user have update his availibilties): [
{
dayNumber : 5,
startHours:05:00,
endHours :10:00;
},
{
dayNumber : 7,
startHours:19:00,
endHours :22:00;
}
]
}
Whats I have start for the moment :
I have count number of weeks beetwen signupDate and now :
$number_of_week = Carbon::parse($user->signupDate)->diffInWeeks(Carbon::now());
Finaly I want to get total availibilty of the user
Thanks

After our chat, I think I got the full picture of the problem, so lets see if we can solve this together:
I'm not sure where the json comes from, so let's just assign it to a variable for now:
$jsonString = '
{
"2022 - 12 - 20": [
{
"dayNumber": 2,
"startHours": "08:00",
"endHours": "10:00"
},
{
"dayNumber": 3,
"startHours": "11:00",
"endHours": "16:00"
}
],
"2022 - 12 - 28": [
{
"dayNumber": 2,
"startHours": "08:00",
"endHours": "10:00"
},
{
"dayNumber": 3,
"startHours": "11:00",
"endHours": "16:00"
}
],
"2023 - 01 - 01": [
{
"dayNumber": 5,
"startHours": "05:00",
"endHours": "10:00"
},
{
"dayNumber": 7,
"startHours": "19:00",
"endHours": "22:00"
}
]
}
';
Then, we can run the code like so:
//I'm assuming that the json only contains availabilities for 1 user
//This creates an associated array out of your json
$assocArray = json_decode($jsonString, true);
$totalAvailabilityInMinutes = 0;
foreach($assocArray as $updatedAvailabilityAt => $availabilityArray) {
$availabilityOfDayInMinutes = 0;
foreach($availabilityArray as $availability) {
$explodedStart = explode(':', $availability['startHours']);
$explodedEnd = explode(':', $availability['endHours']);
//Perform calculation from my comment
$availabilityOfDayInMinutes = ($explodedEnd[0] * 60 + $explodedEnd[1]) - ($explodedStart[0] * 60 + $explodedStart[1]);
dump("Availability of day {$availability['dayNumber']}: $availabilityOfDayInMinutes");
$totalAvailabilityInMinutes += $availabilityOfDayInMinutes;
}
}
dump($totalAvailabilityInMinutes);
Please note that I used 2 variables to store the minutes, one per day, and one accumulating the days. You can pick which one is most applicable to you.
I've tested the code locally, it should work and provide correct numbers ;)
Edit:
So since you already have an array, not a json, you could skip this step:
$assocArray = json_decode($jsonString, true);

Related

Sorting Minutes

im trying to sort soccer minutes, but is not sorting right, for example in soccer is very normal minutes be like "1,2,3,40+5...". Basically is saying 40 minutes + 5 minutes (45 minutes).
So in my records i a colllection like:
[
{
"id": 9876,
"minute": "90+30",
},
{
"id": 9874,
"minute": "90+10",
},
{
"id": 9873,
"minute": "105",
},
{
"id": 9873,
"minute": "90",
},
...
]
So to make it order the minutes right, i need to use explode on the string "minute", than make a array_sum, but in my code, it still doesnt order right, still in the 105 is above of "90+10".
Here is my code:
$timelines = SoccerTime::where('match_id',$id)
->orderBy('minute', 'desc')
->get();
$collection = collect($timelines);
$sorted = $collection->sortByDesc('minute');
$test = $sorted->values()->all();
//Here i begin the new Sort
$newSort = collect($test)->sort(function ($a, $b) {
return array_sum(explode("+",$a->minute)) - array_sum(explode("+",$b->minute));
});
return $newSort;
I think you should change a couple of field in your model. I'd use a minute field to store the actual minute (100 in cases like your "90+10" example) and another integer field period to indicate the "period", where:
- 1 for 1T
- 2 for 2T
- 3 for 1ET
- 4 for 2ET.
So your new way of sorting should be:
First by period (solving your problem of getting 90'+4' of 2T before 93' of 1ET) and then by minute (the actual sort).
It would be so much easier and it could also help you to do some other reporting queries.

I want to sort arrays, but I can't?

I have a JSON file that I created, and I want to sort from the biggest price value.
JSON is like this:
[
{
"username": "elbugato",
"sold": 19,
"qmimi": 38.5
},
{
"username": "Pablo",
"sold": 12,
"qmimi": 42
},
{
"username": "Hqstuff",
"sold": 0,
"qmimi": "0"
},
{
"username": "matchspamm3rs",
"sold": 0,
"qmimi": "0"
},
{
"username": "Pachenko",
"sold": 1,
"qmimi": 1.1
},
I want to sort qmimi from the highest value
My php code is this.
$sellertop8json = json_decode(get_html('link'));
$i = 1;
sort($sellertop8json->qmimi, SORT_NUMERIC);
foreach($sellertop8json as $top8){
max($top8);
if (++$i == 8) break;
echo '<tr>
<td>'.$top8->username.'</td>
<td># '.$top8->sold.'</td>
<td>$ '.$top8->qmimi.'</td>
</tr>
';
}
but they aren't sorting from the biggest value
The results I get :
Look at "Pachenko", he is after a seller that has "0" Earned.
Thank You
Sorry for my bad English
P.S : JSON ISN'T RAW, I copied from some extension I am using on google chrome, so JSON it's not the problem.
You need to use usort and provide custom function comparing the field of the element:
usort($sellertop8json, function($a, $b) {
return $a->qmimi == $b->qmimi ? 0 :
$a->qmimi < $b->qmimi ? 1 : -1;
}
);
The comparison function must return 0 if the elements are equal, less than 0 if the first element is lower and greater than 0 if the second element is higher.
This may be a bit confusing as you're sorting from highest and therefore the swap of the sign in comparison - see the last part of comparison.

How can I query in laravel from a column in the db that has single values and arrays?

I am doing a complex query that looks at data in the database from a column that has single and multiple values depending on whats added. Here is a snippet of what might be sent out:
[
{
"id": 1,
"offer_title": "",
"offer headline": "",
"offer_subheader": "small subheader",
"image": "2015-08-10-09-2.png",
"thumbnail": "2015-08-10-09-1.png",
"offer_terms": "the terms",
"venue_name": "the venue number 2",
"venue_headline": "the headline",
"venue_description": "the venue is awesome",
"venue_phone_number": "00445676833",
"venue_website": "site.co.uk",
"venue_latitude": 999999.99,
"venue_longitude": -999999.99,
"offer_when": "tomorrow",
"days": "tuesday",
"featured_date": "",
"offer_end_time": "08:50",
"offer_start_time": "08:50",
"created_at": "2015-08-10 09:50:50",
"updated_at": "2015-08-11 07:50:59",
"deleted_at": null,
"offer_headline": "large header",
"venue_address": "55 road",
"offer_start_date": "08/11/2015",
"offer_end_date": "08/11/2015"
},
{
"id": 2,
"offer_title": "",
"offer headline": "",
"offer_subheader": "the subheader",
"image": "2015-08-11-09-logotype.png",
"thumbnail": "2015-08-11-09-logotype.png",
"offer_terms": "terms",
"venue_name": "a name",
"venue_headline": "this headline",
"venue_description": "the venue is cool",
"venue_phone_number": "00445676833",
"venue_website": "anothersite.co.uk",
"venue_latitude": 999999.99,
"venue_longitude": -999999.99,
"offer_when": "tomorrow",
"days": "monday,tuesday,wednesday",
"featured_date": "",
"offer_end_time": "20:29",
"offer_start_time": "15:29",
"created_at": "2015-08-11 09:31:12",
"updated_at": "2015-08-11 09:31:12",
"deleted_at": null,
"offer_headline": "the header",
"venue_address": "55 road",
"offer_start_date": "08/11/2015",
"offer_end_date": "08/11/2015"
}
]
As you can see in each object there is a column called days each one has either a list or a single value. What I am trying to achieve is by getting the current day today query the db and show up items in here that match the current day today so for example, its tuesday so all offers with either 'tuesday' or 'tuesday,wednesday,friday' should show up as it's tuesday today, if they don't they would show up another day. Here is what I have tried so far which only ever gives me the single valued days as the result not the one with the array in it:
public function getOffers(Offer $offer)
{
$mytime = Carbon::now();
$today = $mytime->format('m/d/Y');
$day = $mytime->format('l');
$thisDay = strtolower($day);
$offerWhen = $offer['offer_when'];
foreach(Offer::all() as $offerObject){
$offerObject->update(['offer_when' => 'tomorrow']);
$the_days = $offerObject['days'];
$offersAll = $offerObject::whereIn('days', array($the_days) )->orWhere('days', '=', array($the_days))->get();
return $offersAll;
}
}
The above query only returns one object with just 'tuesday' in it and not the one with an array that still has 'tuesday' in it.
The ideal scenario would be that it only ever shows results with the current day in the 'days' column. The current day is created with Carbon::now()->format('l');
I don't really understand everything in your code, but best approach here is to try with LIKE condition.
Try something like that:
->where('days', 'LIKE', '%' . $dayName . '%')
This will work here well because all day names are pretty different and none of them contains the other (like with big, bigger which would cause problems here).

JSON response returns 2 out of 3 date results as Objects, not as strings

I have a strange problem with a JSON response where I am retrieving 3 dates. Two are relating to a subscription start and end date from one table, and another date is the members date of birth.
In the JSON output, these three dates are retrieved. However, the date of birth and the end subscription date are displayed as objects, while the start subscription date is returned as a string. All 3 dates come from fields in the database that are set to DATE and not DATETIME or equivalent.
So my JSON output is:
{
"dob": {
"date": "1999-09-28 00:00:00",
"timezone_type": 3,
"timezone": "Europe/London"
},
"msuStart": "2014-04-17",
"msuEnd": {
"date": "2014-04-30 00:00:00",
"timezone_type": 3,
"timezone": "Europe/London"
}
}
What I need to do is get the date of birth and subscription end date to be formatted in the same way as the start subscription date. So I want the dates to be output like 2014-05-01 instead of 2014-05-01 00:00:00. It's confusing me as to why only one date is being output correctly while the other two aren't.
The JQuery code is here:
var searchCentres = $('#centreSearchForm');
searchCentres.submit(function () {
$('.memberContainer').show();
$.ajax({
type: searchCentres.attr('method'),
url: searchCentres.attr('action'),
data: searchCentres.serialize(),
success: function (data) {
var CentreName = (data.centreName);
var ActiveMembers = (data.actMem);
var ExpiringMembers = (data.expMem);
var NewMembers = (data.newMem);
var RenewalMembers = (data.renMem);
var ActiveMemberList = (data.actMemList)
$('.searchedCentre').text(CentreName);
$('.centreActive').text(ActiveMembers);
$('.centreExpiring').text(ExpiringMembers);
$('.centreSuccess').text(NewMembers);
$('.centreRenewing').text(RenewalMembers);
$('#searchedCentreMembers > tbody:last').empty();
$.each(ActiveMemberList, function(i, item) {
alert(ActiveMemberList[i].dob.date);
$('#searchedCentreMembers > tbody:last').append('<tr><td>' + ActiveMemberList[i].id + '</td><td>' + ActiveMemberList[i].firstName + ' ' + ActiveMemberList[i].surname + '</td><td>' + age + '</td><td>' + ActiveMemberList[i].msuStart + '</td><td>' + ActiveMemberList[i].msuEnd + '</td></tr>');
});
}
});
return false;
});
My PHP code (which uses Symfony) is here:
$activeMemberList = $dm->createQuery('
SELECT mc.id, mc.surname, mc.firstName, mc.gender, mc.dob, max(msu.startDate) AS msuStart, msu.endDate as msuEnd, msu.renewal, COUNT(mc.id) AS counting
FROM InstructorBundle:MapCentreSubscriptions msu
LEFT JOIN InstructorBundle:MapCentreContacts mc WHERE msu.contact = mc.id
LEFT JOIN InstructorBundle:MapMemberCategories mmc WHERE mc.category = mmc.id
LEFT JOIN InstructorBundle:MapBranches mb WHERE msu.branchId = mb.id
WHERE msu.branchId = :searched
AND msu.startDate BETWEEN :lastyear AND :today
AND msu.noLongerSubscribing = :nls
AND mb.entryType = :centre'
)->setParameters(array(
'today' => $dateToday,
'lastyear' => $date1Year,
'nls' => '0',
'centre' => 'Centre',
'searched' => $centreID
));
$actMemList = $activeMemberList->getResult();
$response = array(
"centreName" => $centre,
"actMem" => $actMem,
"expMem" => $expMem,
"newMem" => $newMem,
"renMem" => $renMem,
"actMemList" => $actMemList
);
return new JsonResponse($response);
You need to access the date string, split it at " " and select the 0th item.
You can access the date like this:
alert(output.dob.date);
After that you just need to split it at " " and select the 0th item.
alert(output.dob.date.split(" ")[0]);
VIEW DEMO
var output = {
"dob": {
"date": "1999-09-28 00:00:00",
"timezone_type": 3,
"timezone": "Europe/London"
},
"msuStart": "2014-04-17",
"msuEnd": {
"date": "2014-04-30 00:00:00",
"timezone_type": 3,
"timezone": "Europe/London"
}
};
alert(output.dob.date.split(" ")[0]);
"msuEnd": {
"date": "2014-04-30 00:00:00",
"timezone_type": 3,
"timezone": "Europe/London"
}
Is a correct representation of DateTime object in JSON.
If you want to represent your field as a string with special format, then the best way to do this is to implement a custom field type, e.g. my_date
<?php
# src/My/Bundle/Type/MyDate.php
namespace My\Bundle\Type;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\ConversionException;
use Doctrine\DBAL\Types\VarDateTimeType;
use Doctrine\DBAL\Types\Type;
class MyDate extends VarDateTimeType
{
public function getName() {
return 'my_date';
}
public function convertToPHPValue($value, AbstractPlatform $platform) {
$date = parent::convertToPHPValue($value, $platform);
if ($date instanceof \DateTime)
return $date->format('Y-m-d');
return $date;
}
}
Then register it
# app/config/config.yml
doctrine:
dbal:
types:
my_date: My\Bundle\Type\MyDate
And use it for your entity
/**
* #ORM\Column(type="my_date", name="startDate", nullable=true)
*/
protected $startDate;

How would I convert this array to usable javascript array?

I have php code that returns this from a database,
[
{
"Time": "2012-11-27 16:10:35",
"NumPlayers": "1"
},
{
"Time": "2012-11-27 16:24:55",
"NumPlayers": "1"
},
{
"Time": "2012-11-27 16:25:37",
"NumPlayers": "2"
},
{
"Time": "2012-11-27 16:29:33",
"NumPlayers": "2"
The times are MySQL timestamps. I need to get it into this format to use with Highcharts javascript charting.
data: [
[Date.UTC(1970, 9, 9), 0 ],
[Date.UTC(1970, 9, 14), 0.15],
[Date.UTC(1970, 10, 28), 0.35],
[Date.UTC(1970, 11, 12), 0.46],
I'm having trouble figuring out how to loop through the MySQL results and convert the timestamps to javascript Date.UTC objects. I need to place the NumPlayers value after the Date.UTC objects, and output it in the format below. I'm a PHP and javascript noob :\
It should look something like this:
data: [
[Date.UTC(2012, 11, 27, 16, 10, 35), 1],
[Date.UTC(2012, 11, 27, 16, 24, 55), 1],
[Date.UTC(2012, 11, 27, 16, 25, 37), 2],
[Date.UTC(2012, 11, 27, 16, 29, 33), 2],
You should realize that Date.UTC(2012, 11, 27, 16, 10, 35) simply returns the number of milliseconds since the epoch (1356624635000). Therefore, you can just convert your object into UNIX timestamps (times a 1000 since JS works with millisecond timestamps, but PHP works with seconds).
Sample Code
$data = '[{"Time": "2012-11-27 16:10:35", "NumPlayers": "1"}, {"Time": "2012-11-27 16:24:55", "NumPlayers": "1"}]';
// Make sure date is parsed as UTC
date_default_timezone_set("UTC");
// Convert items into the desired format
$mapper = function($item) {
return array(strtotime($item->Time)*1000, $item->NumPlayers);
}
echo json_encode(array_map($mapper, json_decode($data)));
Output
[[1354032635000,"1"],[1354033495000,"1"]]
You seem to be getting straight JSON from your database, which you can always convert into an array:
$data = '[{"Time": "2012-11-27 16:10:35", "NumPlayers": "1"}, {"Time": "2012-11-27 16:24:55", "NumPlayers": "1"}]';
$arrayData = json_decode($data, true);
After which you can simply iterate through the array and print out the contents of the array in the JS format you need. Something like that:
echo 'data: [' . PHP_EOL;
foreach ($arrayData as $item) {
echo '[Date.UTC(';
$tmp = preg_split( '/(-| |\:)/', $item['Time'] );
echo implode(', ', $tmp);
echo '), ' . $item['NumPlayers'] . '],';
echo PHP_EOL;
}
echo PHP_EOL . '];';
You can split the time string into sections using /[^\d]+/g:
var finalData = [], numbers=/[^\d]+/g, item, dateParts, newDate;
for (var i=0, l=data.length; i<l; i++) {
item = data[i];
dateParts = item.Time.split(numbers);
newDate = Date.UTC.apply(Date, dateParts);
finalData.push([newDate, item.NumPlayers]);
}
See also: MDN's documentation on JavaScript regular expressions (/[^\d]/g is a regex).
The best way to provide data to Highcharts is getting data formated from database, so that you don't have to do it on client side.
To do it you just have to change your query to something like the following.
Backend
$query = "SELECT UNIX_TIMESTAMP(date) * 1000 AS 'date', value FROM ...";
Then to send the result to frontend:
echo json_encode($result);
Frontend
To get the result on frontend, this case using jQuery and assuming that url is your url:
$.getJSON(url, function(json) {
// decode json
var data = $.parseJSON(json);
// Then you just have to pass it to your series
});
Or better, store date values in UTC.
var php_data = [
{
"Time": "2012-11-27 16:10:35",
"NumPlayers": "1"
},
{
"Time": "2012-11-27 16:24:55",
"NumPlayers": "1"
}
];
var length = php_data.length;
hc_data = [];
for(var i = 0; i< length; i++){
php_date = new Date(php_data[i]["Time"]);
hc_data.push(
[
Date.UTC(
php_date.getFullYear(),
php_date.getMonth() + 1,
php_date.getDate()
),
php_data[i]["NumPlayers"]
]
);
}
// hc_data is your Array

Categories