I am creating a small game program in which there are two types of games. Single and Double.
For each game there is a fixed chart set.
Single Chart
'128', '129', '120', '130', '140', '123', '124', '125', '126', '127',
'137', '138', '139', '149', '159', '150', '160', '134', '135', '136',
'146', '147', '148', '158', '168', '169', '179', '170', '180', '145',
'236', '156', '157', '167', '230', '178', '250', '189', '234', '190',
'245', '237', '238', '239', '249', '240', '269', '260', '270', '235',
'290', '246', '247', '248', '258', '259', '278', '279', '289', '280',
'380', '345', '256', '257', '267', '268', '340', '350', '360', '370',
'470', '390', '346', '347', '348', '358', '359', '369', '379', '389',
'489', '480', '490', '356', '357', '349', '368', '378', '450', '460',
'579', '570', '580', '590', '456', '367', '458', '459', '469', '479',
'560', '589', '670', '680', '690', '457', '467', '468', '478', '569',
'678', '679', '689', '789', '780', '790', '890', '567', '568', '578',
Double Chart
'100', '110', '166', '112', '113', '114', '115', '116', '117', '118',
'119', '200', '229', '220', '122', '277', '133', '224', '144', '226',
'155', '228', '300', '266', '177', '330', '188', '233', '199', '244',
'227', '255', '337', '338', '339', '448', '223', '288', '225', '299',
'335', '336', '355', '400', '366', '466', '377', '440', '388', '334',
'344', '499', '445', '446', '447', '556', '449', '477', '559', '488',
'399', '660', '599', '455', '500', '600', '557', '558', '577', '550',
'588', '688', '779', '699', '799', '880', '566', '800', '667', '668',
'669', '778', '788', '770', '889', '899', '700', '990', '900', '677',
When I select a Single and entered number digit 0123456789 (any sequence(sorted & unsorted), min 4 digits & max 10 digits from 0-9, repeated), it returns the entire set which is related to Single Chart.
For this case it returns 120 sets.
If I select double and entered same digit 0123456789 it returns all the set which is related to Double Chart ONLY.
Currently I am using one solutions for Single game which is given here permutations-all-possible-sets-of-numbers but in some set it is returned like 001 but it has to be 100
Also I am not able to find the solutions for Double game.
What I try :
public function insertSingleGameData($motorGameData)
{
$chartvalidation = config('chartValidation');
$tempMotorSet = str_split($motorGameData->Playgame->cane);
$motorSet = $this->arrayCombination(3, $tempMotorSet); // Get All Sets
$motorRange = array_unique($motorSet);
foreach($motorRange as $cane)
{
if(in_array($cane, $chartvalidation['single'])){
$tempGameData[] = ([
'playgame_id' => $motorGameData->Playgame->id,
'user_id' => $motorGameData->Playgame->user_id,
'cane' => $cane,
'amount' => $motorGameData->Playgame->amount,
'gamemaster_id' => $motorGameData->Playgame->gamemaster_id,
"created_at" => \Carbon\Carbon::now(),
"updated_at" => \Carbon\Carbon::now(),
]);
}
}
Tempgame::insert($tempGameData);
}
function arrayCombination($le, $set){
$lk = $this->combination_number($le, count($set));
$ret = array_fill(0, $lk, array_fill(0, $le, '') );
$temp = array();
for ($i = 0 ; $i < $le ; $i++)
$temp[$i] = $i;
$ret[0] = $temp;
for ($i = 1 ; $i < $lk ; $i++){
if ($temp[$le-1] != count($set)-1){
$temp[$le-1]++;
} else {
$od = -1;
for ($j = $le-2 ; $j >= 0 ; $j--)
if ($temp[$j]+1 != $temp[$j+1]){
$od = $j;
break;
}
if ($od == -1){
break;
}
$temp[$od]++;
for ($j = $od+1 ; $j < $le ; $j++) {
$temp[$j] = $temp[$od]+$j-$od;
}
}
$ret[$i] = $temp;
}
for ($i = 0 ; $i < $lk ; $i++) {
for ($j = 0 ; $j < $le ; $j++){
$ret[$i][$j] = $set[$ret[$i][$j]];
}
}
$tempSet = array();
foreach ($ret as $key => $value) {
$tempSet[] = implode('', $value);
}
return $tempSet;
//print("<pre>".print_r($ret,true)."</pre>");
}
function combination_number($k,$n){
$n = intval($n);
$k = intval($k);
if ($k > $n){
return 0;
} elseif ($n == $k) {
return 1;
} else {
if ($k >= $n - $k){
$l = $k+1;
for ($i = $l+1 ; $i <= $n ; $i++)
$l *= $i;
$m = 1;
for ($i = 2 ; $i <= $n-$k ; $i++)
$m *= $i;
} else {
$l = ($n-$k) + 1;
for ($i = $l+1 ; $i <= $n ; $i++)
$l *= $i;
$m = 1;
for ($i = 2 ; $i <= $k ; $i++)
$m *= $i;
}
}
return $l/$m;
}
How can I achieve this both Single and Double game in a one function?
You can do a preg_match on numbers by creating regular expression such as:
/^[235046]+$/
This means we are trying to match a string which has digits 235046(meaning, 2 or 3 or 5 and so on) right from start (^ caret symbol) till end ($ dollar symbol). If we find a match, we collect them in another array.
Snippet:
<?php
$digits = '235046';
$single_chart_filtered = [];
foreach($single_chart as $chart_value){
if(preg_match("/^[$digits]+$/",$chart_value) === 1){
$single_chart_filtered[] = $chart_value;
}
}
print_r($single_chart_filtered);
$double_chart_filtered = [];
foreach($double_chart as $chart_value){
if(preg_match("/^[$digits]+$/",$chart_value) === 1){
$double_chart_filtered[] = $chart_value;
}
}
Demo: https://3v4l.org/jChvm
001 IS a valid combination of 0123456789. You need to filter your array for the possible set:
// simple artificial setup
$single = [111,222,333,444,555];
function generatePossibleSet($input) { return [000,001,010,100,011,101,110,111]; }
$possibleSet = generatePossibleSet("01");
$set = $single;
// just interscet the picked set with the possible set
$set = array_intersect($set, $possibleSet);
This example will give [111] - the only valid combination of 0 and 1 that was in the set-list.
We are looking to create a list of comma separated dates that tell us when a reservation is full. There are 7 units to rent so we want to know which dates are present >= 7
This Stackoverflow thread is close as it identifies intersections but I am looking for the specific dates where they intersect x amount of times.
<?php
// 2019-2-21 is present 8 times in the following array
$ranges = array(
array('id' =>'59','start' => new DateTime('2019-02-19'), 'end' => new DateTime('2019-02-21')),
array('id' =>'58','start' => new DateTime('2019-02-19'), 'end' => new DateTime('2019-02-21')),
array('id' =>'55','start' => new DateTime('2019-02-19'), 'end' => new DateTime('2019-02-21')),
array('id' =>'57','start' => new DateTime('2019-02-19'), 'end' => new DateTime('2019-02-21')),
array('id' =>'108','start' => new DateTime('2019-02-21'), 'end' => new DateTime('2019-02-28')),
array('id' =>'109','start' => new DateTime('2019-02-19'), 'end' => new DateTime('2019-02-24')),
array('id' =>'110','start' => new DateTime('2019-02-21'), 'end' => new DateTime('2019-02-23')),
array('id' =>'111','start' => new DateTime('2019-02-21'), 'end' => new DateTime('2019-02-25')),
);
function intersects($lhs, $rhs) {
return !($lhs['start'] > $rhs['end'] || $lhs['end'] < $rhs['start']);
}
function checkDates($ranges) {
// Comparison loop
for($i = 0; $i < sizeof($ranges); $i++) {
for($j = $i+1; $j < sizeof($ranges); $j++) {
if(intersects($ranges[$i], $ranges[$j])) {
echo "Date {$i} intersects with date {$j}<br>";
}
}
}
}
checkDates($ranges);
?>
I'm able to identify on a known specific date when we are over the limit
SELECT COUNT(*) FROM reservations
WHERE reservations.`date` <= '$date' AND reservations.`dateLast` >= '$date'
This gives us a count that we can compare to our qty of units but I'm not sure how to create a list of dates that intersect >= x so we can know in advance if we are sold out.
UPDATE to confirm solution:
foreach ($ranges as $range) {
while ($range['start'] <= $range['end']) {
$date = $range['start']->format('Y-m-d');
$dates[$date] = (isset($dates[$date]) ? $dates[$date] : 0) + 1; 1;//define new $dates array
$range['start']->modify('+1 day');
}
}
echo $sold_out = array_filter($dates, function($n) { return $n >= 7; });
echo '<pre>';
print_r($range);
echo '</pre>';
I think you don't need to intersect the ranges. You just need to know how many times each date appears in your list of ranges, so you can just iterate each range in ranges and count the dates.
foreach ($ranges as $range) {
while ($range['start'] <= $range['end']) {
$date = $range['start']->format('Y-m-d');
$dates[$date] = ($dates[$date] ?? 0) + 1;
// or $dates[$date] = (isset($dates[$date]) ? $dates[$date] : 0) + 1;
$range['start']->modify('+1 day');
}
}
/* Result:
array (size=10)
'2019-02-19' => int 5
'2019-02-20' => int 5
'2019-02-21' => int 8
'2019-02-22' => int 4 ...
*/
Then you can filter that to find any sold out dates.
$sold_out = array_filter($dates, function($n) { return $n >= 7; });
I think you can probably also do this in SQL by creating a temporary table with all dates in the date range you're interested in and joining it to your count query.
I want to print a different image every season of the year. Based on a date from my database. I want to print it in php/html5.
Found some things on the internet but none of them worked with my database date.
Just need to format the values o match yours
$someDay = "2018-12-01";
$spring = (new DateTime('March 20'))->format("Y-m-d");
$summer = (new DateTime('June 20'))->format("Y-m-d");
$fall = (new DateTime('September 22'))->format("Y-m-d");
$winter = (new DateTime('December 21'))->format("Y-m-d");
switch(true) {
case $someDay >= $spring && $someDay < $summer:
echo 'It\'s Spring!';
break;
case $someDay >= $summer && $someDay < $fall:
echo 'It\'s Summer!';
break;
case $someDay >= $fall && $someDay < $winter:
echo 'It\'s Fall!';
break;
default:
echo 'It must be Winter!';
}
Try it online!
Based on year of defined date and some leap year logic
$current_date = new DateTimeImmutable();
# $current_date = $current_date->setDate(2023,3,1); // test
$seasons = [
(object) ['name' => 'winter', 'date' => $current_date->setDate($current_date->format('Y'),1,1)],
(object) ['name' => 'spring', 'date' => $current_date->setDate($current_date->format('Y'),2,($current_date->format('Y') % 4 === 0) ? 19 : 20)],
(object) ['name' => 'summer', 'date' => $current_date->setDate($current_date->format('Y'),5,($current_date->format('Y') % 4 === 0) ? 20 : 21)],
(object) ['name' => 'autumn', 'date' => $current_date->setDate($current_date->format('Y'),8,($current_date->format('Y') % 4 === 0) ? 22 : 23)],
(object) ['name' => 'winter', 'date' => $current_date->setDate($current_date->format('Y'),11,($current_date->format('Y') % 4 === 0) ? 20 : 21)]
];
$season = array_slice(array_filter($seasons, fn($season) => $season->date <= $current_date),-1)[0]->name;
echo $season;
If your seasons are variable, and stored in the database, you can fix your problem by simply
Splitting the season that intersects newyear
Set all yearstamps to 2000
Do a a < b < c check
Splitting the season elïminates your problem straightaway
Here's a .NET implementation
Here's a JSfiddle
I am trying to calculate $work_in_daytime and $work_in_nighttime.
$nightStart = '22:00';
$nightEnd = '07:00';
$workers = array(
'0' => array(
'name' => 'Lyons',
'start' => '15:15',
'end' => '23:45'
),
'1' => array(
'name' => 'Santos',
'start' => '10:00',
'end' => '22:00'
),
'2' => array(
'name' => 'Montgomery',
'start' => '22:30',
'end' => '08:00'
)
);
I have tried following code.
foreach ($workers as $worker) {
$startTime = strtotime($em['start']);
$endTime = strtotime($em['end']);
$length = formattedTime($endTime - $startTime);
$nightTimeStart = strtotime($nightStart);
$nightTimeEnd = strtotime($nightEnd);
$dayTimeLength = 0;
$nightTimeLength = 0;
if ($startTime > $nightTimeStart) {
$nightTimeLength += $startTime - $nightTimeStart;
}
if ($startTime < $nightTimeStart) {
$dayTimeLength += $nightTimeStart - $startTime;
}
if ($endTime > $nightTimeStart) {
$nightTimeLength += $endTime - $nightTimeStart;
}
if ($endTime < $nightTimeStart) {
$dayTimeLength += $endTime - $nightTimeStart;
}
echo 'Day Time: '.$dayTimeLength.PHP_EOL;
echo 'Night Time: '.$nightTimeLength.PHP_EOL;
}
I am stuck with correct calculation.
Try This:
$nightStart = '22:00';
$nightEnd = '07:00';
$workers = array(
'0' => array(
'name' => 'Lyons',
'start' => '15:15',
'end' => '23:45'
),
'1' => array(
'name' => 'Santos',
'start' => '6:00',
'end' => '22:00'
),
'2' => array(
'name' => 'Montgomery',
'start' => '22:30',
'end' => '08:00'
)
);
function timetodate($time)
{
return date('H:i', $time);
}
foreach ($workers as $worker) {
$startTime = strtotime($worker['start']);
$endTime = strtotime($worker['end']);
$length = date('H:i',($endTime - $startTime));
$day = strtotime("24H");
$nightTimeStart = strtotime($nightStart);
$nightTimeEnd = strtotime($nightEnd);
$dayTimeLength = 0;
$nightTimeLength = 0;
/* Night Time Calculations */
if ($endTime <= $startTime) {
if ($startTime >= $nightTimeStart) {
$nightTimeLength += $day - $startTime;
if ($endTime <= $nightTimeEnd) {
$nightTimeLength += $nightTimeEnd - $endTime;
}
else
{
$nightTimeLength += $nightTimeEnd;
}
}
}
elseif ($endTime > $nightTimeStart) {
$nightTimeLength += $endTime - $nightTimeStart;
}
elseif ($startTime < $nightTimeEnd) {
$nightTimeLength += $nightTimeEnd - $startTime;
}
/* Day Time Calculations */
if ($startTime >= $nightTimeEnd) {
if ($endTime <= $nightTimeStart) {
if ($startTime < $endTime) {
$dayTimeLength += $endTime - $startTime;
}
else
{
$dayTimeLength += $endTime - $nightTimeEnd;
}
}
else
{
$dayTimeLength += $nightTimeStart - $startTime;
}
}
else
{
if ($endTime <= $nightTimeStart) {
$dayTimeLength += ($endTime - $nightTimeEnd);
}
else
{
$dayTimeLength += $nightTimeStart - $nightTimeEnd;
}
}
echo "Name:". $worker['name'].PHP_EOL;
echo 'Day Time: '.timetodate($dayTimeLength).PHP_EOL;
echo 'Night Time: '.timetodate($nightTimeLength).PHP_EOL.PHP_EOL;
}
https://www.tehplayground.com/CkZ53jjD1cyFEymB
earlier post:
Disregard ---- https://www.tehplayground.com/PohT0L7s35m9VKOe
Like this?
Although I haven't adjusted it, but i think i need to change it a bit more to get it correctly for the turn of the new day (it doesnt see it as a continous shift i dont think)
The variable $em is undefined.
Unsure of what your constants are for daytime and nighttime, but
assuming you calculate daytime from 6am to 6pm and night time from
6pm to 6am:
<?php
$start_nighttime = strtotime('18:00');
$end_nighttime = strtotime('05:59');
$start_daytime = strtotime('06:00');
$end_daytime = strtotime('17:59');
foreach($worker as $data){
$worker_start = strtotime($data['start']);
$worker_end = strtotime($data['end']);
if ($worker_start > $start_daytime && $worker_end < $start_nighttime) {
//Worked only during the day
$daytime = round(abs($worker_start - $worker_end) / 60, 2);
} elseif ($worker_start > $start_daytime && $worker_end > $end_nighttime) {
//Worked during the day and extended past defined night time
$daytime = round(abs($worker_start - $end_daytime) / 60, 2);
$nighttime = round(abs($start_nightime - $worker_end) / 60, 2);
} elseif ($worker_start > $start_nighttime && $worker_end < $end_nighttime){
//Worked only during the night
$nighttime = round(abs($worker_start - $worker_end));
} elseif ($worker_start > $start_nighttime && $worker_end > $end_nighttime){
//Worked only during the night up until the moring
$nighttime = round(abs($worker_start - $end_nighttime));
$daytime = round(abs($start_daytime - $worker_end));
}
}
?>
I have a two-dimensional array containing events and dates:
$events = array(
array('event' => 'event1', 'date' => '2016-05-05'),
array('event' => 'event2', 'date' => '2016-05-08'),
array('event' => 'event3', 'date' => '2016-05-08'),
array('event' => 'event4', 'date' => '2016-05-10'),
array('event' => 'event5', 'date' => '2016-05-10'),
array('event' => 'event6', 'date' => '2016-05-11'),
array('event' => 'event7', 'date' => '2016-05-11'),
array('event' => 'event8', 'date' => '2016-05-13')
};
Let's say today is 2016-05-10 and I want to create 3 new arrays:
$recent - all events happened on the previous available day
$today - all events today
$upcoming - all events happening on the next available day
$today is easy:
$today = array();
for($i = 0; $i < count($events); ++$i) {
if($events[$i]['date'] == date("Y-m-d") {
array_push($today, $events[$i]['event']);
}
}
So, I will need $recent to contain event2 and event3, and $upcoming to contain event6 and event7.
The question is how to find the recent and the upcoming ones.
*Clarification:
I don't want all the events in $recent happened before today, but the events happened on the previous available day. So in this case only events happened on 2016-05-08
// Take all dates from source array
$dates = array_unique(array_map(function ($i) { return strtotime($i); } , array_column($events, 'date')));
sort($dates);
$today = strtotime('midnight');
// find previouse date. It will be 1970-1-1 if not present in array
$prev = #max(array_filter($dates, function($i) use($today) { return $i < $today; }));
// find туче date. It will be 1970-1-1 if not present in array
$next = #min(array_filter($dates, function($i) use($today) { return $i > $today; }));
$prev = date('Y-m-d', $prev);
$next = date('Y-m-d', $next);
// fill arrays
$recent = array();
$upcoming = array();
$today = array();
for($i = 0; $i < count($events); ++$i) {
if($events[$i]['date'] == date('Y-m-d')) {
array_push($today, $events[$i]['event']);
}
if($events[$i]['date'] == $prev) {
array_push($recent, $events[$i]['event']);
}
if($events[$i]['date'] == $next) {
array_push($upcoming , $events[$i]['event']);
}
}
Try with creating three (3) blank array, check the date is greater or less than today or not and push into array according to conditions.
$today = array();
$upcoming = array();
$recent = array();
$thisDay = date("Y-m-d");
$count = count($events);
$max = max(array_column($events, 'date'));
$min = min(array_column($events, 'date'));
for($i = 0; $i < $count; $i++){
if($events[$i]['date'] > $thisDay){
$max = ($max > $events[$i]['date']) ? $events[$i]['date'] : $max;
array_push($upcoming, $events[$i]['event']);
array_push($upcoming_dates, $events[$i]['date']);
}
elseif($events[$i]['date'] < $thisDay){
$min = ($min < $events[$i]['date']) ? $events[$i]['date'] : $min;
array_push($recent, $events[$i]['event']);
array_push($recent_dates, $events[$i]['date']);
}
else
array_push($today, $events[$i]['event']);
}
foreach($recent_dates as $key => $value){
if($value != $min)
unset($recent[$key]);
}
foreach($upcoming_dates as $key => $value){
if($value != $max)
unset($upcoming[$key]);
}
echo '<pre>';
print_r($today);
print_r($upcoming);
print_r($recent);
Result
Today:
Array
(
[0] => event4
[1] => event5
)
Upcoming:
Array
(
[0] => event6
[1] => event7
)
Recent:
Array
(
[1] => event2
[2] => event3
)
Note: You use push_array which is not any library function in PHP. For Re-index of recent and upcoming you can use array_values.
Another solution should be
$recent = array();
$upcoming = array();
$today = array();
$all_dates = array();
foreach ($events as $event):
array_push($all_dates, $event['date']);
endforeach;
if ($key = array_search('2016-05-10', $all_dates)) {
$prev_date = $all_dates[$key - 1];
}
for ($i = 0; $i < count($all_dates); $i++) {
if ($all_dates[$i] > $all_dates[$key]) {
$next_date = $all_dates[$i + 1];
break;
}
}
for ($i = 0; $i < count($events); ++$i) {
if ($events[$i]['date'] == date('Y-m-d')) {
array_push($today, $events[$i]['event']);
}
if ($events[$i]['date'] == $prev_date) {
array_push($recent, $events[$i]['event']);
}
if ($events[$i]['date'] == $next_date) {
array_push($upcoming, $events[$i]['event']);
}
}
echo '<pre>';
print_r($upcoming);
print_r($today);
print_r($recent);
Output will be
Array
(
[0] => event6
[1] => event7
)
Array
(
[0] => event4
[1] => event5
)
Array
(
[0] => event2
[1] => event3
)