Reverse long PHP if function for number calculation - php

I'm making application for recording and processing company leave records using PHP and mysql. In my application I have to process three main leave type as below with their respective counts.
causal - 7
annual - 14
medical - 7
In my database I have table called leaves and it contian those three columns and their values respectively as follows
---name----casual----annual----medical
---jhon------7---------14--------7---
---mary------7---------14--------7---
---bill------5----------3--------0---
when employee applying a leave PHP function check available leave counts and subtract applied leave number from those three values like this
if leave type is casual and leave count is 15 it should be subtract both casual, medical and annual leaves to fulfill the employees leave requirement.I managed to implement up to this part. below is my code
if ($ltype == "medical")
{
if ($medical >= $hmd)
{
$medical-= $hmd;
}
else
{
$tval = $hmd - $medical;
$tval2 = $hmd - $tval;
$medical-= $tval2;
if ($casual >= $tval && $tval > 0)
{
$casual-= $tval;
}
else
{
$tval3 = $tval - $casual;
$tval4 = $tval - $tval3;
$casual-= $tval4;
if ($annual >= $tval3 && $tval3 > 0)
{
$annual-= $tval3;
}
else
{
$tval5 = $tval3 - $annual;
$tval6 = $tval3 - $tval5;
$annual-= $tval6;
$nopay += $tval5;
}
}
}
}
I have three code sets for three leave types and above code do the math as what I want. But my problem is when sometime users want to re-add those subtracted leave to the leave table. when comes to this I have to calculate this function reverse for get the exact numbers subtracted by each column form the first function. then I planned to calculate add how many leaves subtracted by each columns to the end of the leave record. but when reversing this also not working since those records not process as any order.
I want to implement way to re-add those leaves to the leaves table without any error.
I know my method may not suitable for this type of problem and this is extremely basic programming question. could someone please explain me how do I revers my first function exactly as the same or is there any other programming concepts that should I follow for solve these type of problems.

Okay, well assuming $hmd is number of days...this should get you very close:
http://sandbox.onlinephpfunctions.com/code/f16d899de4318a89e1d80e8737c49b079a5ee179
<?php
$ltype = 'medical';
$casual = 7;
$annual = 15;
$medical = 7;
$nopay = 0;
$hmd = 9;
echo "medical $medical, casual $casual, annual $annual, nopay $nopay\n";
if ($ltype == "medical") {
if ($medical >= $hmd) {
$medical -= $hmd;
} else {
// sorry no more med leave
$rem = $hmd - $medical;
$medical = 0;
if ($casual >= $rem && $rem > 0) {
$casual -= $rem;
} else {
// sorry no more cas leave
$rem2 = $rem - $casual;
$casual = 0;
if ($annual >= $rem2 && $rem2 > 0) {
$annual -= $rem2;
} else {
// sorry now you owe us money
$nopay += ($rem2 - $annual);
$annual = 0;
}
}
}
}
echo "medical $medical, casual $casual, annual $annual, nopay $nopay\n";
// need to set these to know when to "roll" to the next leave type...
$max_casual = 7;
$max_annual = 15;
$max_medical = 7;
if ($ltype == "medical") {
$rem = 0; // remainder after paying back nopay
if ($nopay >= $hmd) {
$nopay -= $hmd;
// well, we put some back but you still owe us!
} else {
// alright you paid it back!
$rem = $hmd - $nopay;
$nopay = 0;
}
if ($rem > 0) {
// let's restore some annual
$annual += $rem;
if ($annual > $max_annual) {
$rem = $annual - $max_annual;
$annual = $max_annual;
} else {
$rem = 0;
}
}
if ($rem > 0) {
// let's restore some casual
$casual += $rem;
if ($casual > $max_casual) {
$rem = $casual - $max_casual;
$casual = $max_casual;
} else {
$rem = 0;
}
}
if ($rem > 0) {
// whoa you're rolling in days off
$medical += $rem;
if ($medical > $max_medical) {
$rem_not_possible = $medical - $max_medical;
$medical = $max_medical;
} else {
$rem = 0;
}
}
}
echo "medical $medical, casual $casual, annual $annual, nopay $nopay\n";

Related

Comparing results in Gravity Forms

I've created a questionnaire with three categories. Each possible answer in the questionnaire corresponds with one of the categories. I have three admin numeric fields where I add the number of answers selected from each category (fields 121, 122, 123). This part of the form is working. I'd like to compare the totals from these fields to see which is greatest and then return that result to a hidden field (field 126). So far my code is triggering a critical error when I submit the form.
add_filter("gform_pre_submission_9", "find_highest_percent");
function find_highest_percent ($vata, $pitta, $kapha, $form) {
$total = 0;
$vata = $_POST["input_121"] ;
$pitta = $_POST["input_122"] ;
$kapha = $_POST["input_123"] ;
$total = $vata + $pitta + $kapha;
$vata_percent = ($vata / $total) * 100;
$pitta_percent = ($pitta / $total) * 100;
$kapha_percent = ($kapha / $total) * 100;
if (abs($vata - $kapha) <= 10) {
$result = "Vata-Kapha";
} elseif (abs($vata - $pitta) <= 10) {
$result = "Vata-Pitta";
} elseif (abs($pitta - $kapha) <= 10) {
$result = "Pitta-Kapha";
} elseif (abs($vata - $pitta) <= 10 && abs($vata - $kapha) <= 10 && abs($pitta - $kapha) <= 10) {
$result = "Tri-Doshic";
} else {
if ($vata > $pitta && $vata > $kapha) {
$result = "Vata";
} elseif ($pitta > $vata && $pitta > $kapha) {
$result = "Pitta";
} else {
$result = "Kapha";
}
}
$_POST["input_126"] = $result;
}
I've tested by removing all calculations and simply returning the number 100 but this also triggers the error. Grateful for any suggestions.
Does it help to set the variables to integers?
$vata = (int)$_POST["input_121"] ;
$pitta = (int)$_POST["input_122"] ;
$kapha = (int)$_POST["input_123"] ;

Get lowest price on sum of combinations in given array

This code is working fine when the array length is 8 or 10 only. When we are checking this same code for more than 10 array length.it get loading not showing the results.
How do reduce my code. If you have algorithm please share. Please help me.
This program working flow:
$allowed_per_room_accommodation =[2,3,6,5,3,5,2,5,4];
$allowed_per_room_price =[10,30,60,40,30,50,20,60,80];
$search_accommodation = 10;
i am get subsets = [5,5],[5,3,2],[6,4],[6,2,2],[5,2,3],[3,2,5]
Show lowest price room and then equal of 10 accommodation; output like as [5,3,2];
<?php
$dp=array(array());
$GLOBALS['final']=[];
$GLOBALS['room_key']=[];
function display($v,$room_key)
{
$GLOBALS['final'][] = $v;
$GLOBALS['room_key'][] = $room_key;
}
function printSubsetsRec($arr, $i, $sum, $p,$dp,$room_key='')
{
// If we reached end and sum is non-zero. We print
// p[] only if arr[0] is equal to sun OR dp[0][sum]
// is true.
if ($i == 0 && $sum != 0 && $dp[0][$sum]) {
array_push($p,$arr[$i]);
array_push($room_key,$i);
display($p,$room_key);
return $p;
}
// If $sum becomes 0
if ($i == 0 && $sum == 0) {
display($p,$room_key);
return $p;
}
// If given sum can be achieved after ignoring
// current element.
if (isset($dp[$i-1][$sum])) {
// Create a new vector to store path
// if(!is_array(#$b))
// $b = array();
$b = $p;
printSubsetsRec($arr, $i-1, $sum, $b,$dp,$room_key);
}
// If given $sum can be achieved after considering
// current element.
if ($sum >= $arr[$i] && isset($dp[$i-1][$sum-$arr[$i]]))
{
if(!is_array($p))
$p = array();
if(!is_array($room_key))
$room_key = array();
array_push($p,$arr[$i]);
array_push($room_key,$i);
printSubsetsRec($arr, $i-1, $sum-$arr[$i], $p,$dp,$room_key);
}
}
// Prints all subsets of arr[0..n-1] with sum 0.
function printAllSubsets($arr, $n, $sum,$get=[])
{
if ($n == 0 || $sum < 0)
return;
// Sum 0 can always be achieved with 0 elements
// $dp = new bool*[$n];
$dp = array();
for ($i=0; $i<$n; ++$i)
{
// $dp[$i][$sum + 1]=true;
$dp[$i][0] = true;
}
// Sum arr[0] can be achieved with single element
if ($arr[0] <= $sum)
$dp[0][$arr[0]] = true;
// Fill rest of the entries in dp[][]
for ($i = 1; $i < $n; ++$i) {
for ($j = 0; $j < $sum + 1; ++$j) {
// echo $i.'d'.$j.'.ds';
$dp[$i][$j] = ($arr[$i] <= $j) ? (isset($dp[$i-1][$j])?$dp[$i-1][$j]:false) | (isset($dp[$i-1][$j-$arr[$i]])?($dp[$i-1][$j-$arr[$i]]):false) : (isset($dp[$i - 1][$j])?($dp[$i - 1][$j]):false);
}
}
if (isset($dp[$n-1][$sum]) == false) {
return "There are no subsets with";
}
$p;
printSubsetsRec($arr, $n-1, $sum, $p='',$dp);
}
$blockSize = array('2','3','6','5','3','5','2','5','4');
$blockvalue = array('10','30','60','40','30','50','20','60','80');
$blockname = array("map","compass","water","sandwich","glucose","tin","banana","apple","cheese");
$processSize = 10;
$m = count($blockSize);
$n = count($processSize);
// sum of sets in array
printAllSubsets($blockSize, $m, $processSize);
$final_subset_room = '';
$final_set_room_keys = '';
$final_set_room =[];
if($GLOBALS['room_key']){
foreach ($GLOBALS['room_key'] as $set_rooms_key => $set_rooms) {
$tot = 0;
foreach ($set_rooms as $set_rooms) {
$tot += $blockvalue[$set_rooms];
}
$final_set_room[$set_rooms_key] = $tot;
}
asort($final_set_room);
$final_set_room_first_key = key($final_set_room);
$final_all_room['set_room_keys'] = $GLOBALS['room_key'][$final_set_room_first_key];
$final_all_room_price['set_room_price'] = $final_set_room[$final_set_room_first_key];
}
if(isset($final_all_room_price)){
asort($final_all_room_price);
$final_all_room_first_key = key($final_all_room_price);
foreach ($final_all_room['set_room_keys'] as $key_room) {
echo $blockname[$key_room].'---'. $blockvalue[$key_room];
echo '<br>';
}
}
else
echo 'No Results';
?>
I'm assuming your task is, given a list rooms, each with the amount of people it can accommodate and the price, to accommodate 10 people (or any other quantity).
This problem is similar to 0-1 knapsack problem which is solvable in polynomial time. In knapsack problem one aims to maximize the price, here we aim to minimize it. Another thing that is different from classic knapsack problem is that full room cost is charged even if the room is not completely occupied. It may reduce the effectiveness of the algorithm proposed at Wikipedia. Anyway, the implementation isn't going to be straightforward if you have never worked with dynamic programming before.
If you want to know more, CLRS book on algorithms discusses dynamic programming in Chapter 15, and knapsack problem in Chapter 16. In the latter chapter they also prove that 0-1 knapsack problem doesn't have trivial greedy solution.

Php level and exp system

How can i make a level system where i have 2 table, one for the level and another for amount of exp earned?
I want to be able to manage the different exp requierments myself, like level 2 will need 340exp and level 3 need 450exp. I dont want to set one exp amount and then multiply it. I want to manage the whole system.
I also want to set default level and max level, and give exp directly to the database column without too much problem (for forum posts etc).
I have seen a few questions here but i find them outdated or just not what im looking for.
PS: sorry for bad english and bad explenation.
I found a realy good solution and was able to rewrite it to work with my setup. if anyone is interested i will leave the original link and my edit of it bellow.
my edit:
<?php
// Connect to your database like you normally do, then get any value into the $count variable
$count = $exp;
if($level == 0){
$lvl = 1;
}else{
$lvl = $level;
}
if ($count >= 12800) { $lvl = 10; }
else if ($count >= 6400) { $lvl = 9; }
else if ($count >= 3200) { $lvl = 8; }
else if ($count >= 1600) { $lvl = 7; }
else if ($count >= 800) { $lvl = 6; }
else if ($count >= 400) { $lvl = 5; }
else if ($count >= 200) { $lvl = 4; }
else if ($count >= 100) { $lvl = 3; }
else if ($count >= 50) { $lvl = 2; }
// Render stars or any graphics/images according to dynamic $lvl number
$stars = "";
$i = 1;
while ($i <= $lvl) {
$stars .= "★";
$i++;
}
echo "level $lvl";
?>
Original link:
https://www.developphp.com/video/PHP/Experience-Level-Evaluation-Programming-Tutorial

Sorting arrays with uncertain data

I am crafting a script for a browser game that will generate a random animal for the player to battle with anywhere from 0-5 markings. The markings on that animal are randomly generated and are fed into a custom imagick function, which will add them in order as they appear in the array.
While the markings are randomly decided, there are a lot of rules to how they are supposed to appear on an animal, for instance markings in the "full body" region show above markings in the "belly" region. To better explain, I'll attach an image of the tester so far:
So to break down the 5 markings on this randomly generated animal, the eyeshadow marking belongs to eye region, undertail belongs to tail, streaks belongs to fullbody, appaloosa belongs to back, and okapi belongs to legs. The order right now is just added as the script looped through the database and randomly selected markings, so okapi (the stripes on the legs) is on top since it was the last on in the array, and the last one added. But following the order rules, the last one in the array should have been streaks (the horizontal streaks across the body), since fullbody markings go on top.
Here is the code the selects markings, this is done using the Laravel engine:
// Determine number of markings
$num = mt_rand(1,10);
if ($num == 1) {
$markingNum = 0;
} elseif ($num > 1 && $num < 4) {
$markingNum = 1;
} elseif ($num > 4 && $num < 6) {
$markingNum = 2;
} elseif ($num > 6 && $num < 8) {
$markingNum = 3;
} elseif ($num > 8 && $num < 10) {
$markingNum = 4;
} else {
$markingNum = 5;
}
// Calculate Marking type and color
$markings = array();
if ($markingNum > 0) {
for ($m = 0 ; $m < $markingNum; $m++) {
// Set color values (pulls from the "pallet" selected earlier in the code, which will determine the range of color that marking can be)
if ($m == 1) {
$pal = $pallet->marking1;
} elseif ($m == 2) {
$pal = $pallet->marking2;
} elseif ($m == 3) {
$pal = $pallet->marking3;
} elseif ($m == 4) {
$pal = $pallet->marking4;
} else {
$pal = $pallet->marking5;
}
// Pull previous marking info
if (count($markings) != 0) {
$previous = DataMarking::whereIn('name', array_keys($markings))->get();
// This pulls the regions of the current markings in the array so it won't select a region that already has a marking.
foreach ($previous as $p) {
$regions[$p->region] = $p->name;
}
// Uncommon marking (10% chance)
$r = mt_rand(1, 10);
if ($r == 10) {
$marking = DataMarking::where('rarity', 1)
->where('public', 1)
->whereNotIn('name', array_keys($markings))
->whereNotIn('region', array_keys($regions))
->orderByRaw("RAND()")
->first();
// Common markings
} else {
$marking = DataMarking::where('rarity', 0)
->where('public', 1)
->whereNotIn('name', array_keys($markings))
->whereNotIn('region', array_keys($regions))
->orderByRaw("RAND()")
->first();
}
// Colors marking
if ($pal == 0) {
$markingColor = rand_color();
} else {
$range = ColorRange::where('id', $pal)->firstOrFail();
$markingColor = "#" . mixRange(substr($range->start_hex, 1), substr($range->end_hex, 1));
}
$markings[$marking->name] = $markingColor;
} else {
// Uncommon marking (10% chance)
$r = mt_rand(1, 10);
if ($r == 10) {
$marking = DataMarking::where('rarity', 1)
->where('public', 1)
->orderByRaw("RAND()")->first();
// Common marking
} else {
$marking = DataMarking::where('rarity', 0)
->where('public', 1)
->orderByRaw("RAND()")->first();
}
// Colors marking
if ($pal == 0) {
$markingColor = rand_color();
} else {
$range = ColorRange::where('id', $pal)->firstOrFail();
$markingColor = "#" . mixRange(substr($range->start_hex, 1), substr($range->end_hex, 1));
}
$markings[$marking->name] = $markingColor;
}
}
}
I figure I can accomplish this with a lot of complex if statements but it just doesn't seem like an elegant solution to me. In addition, there is an exception: 'Gradient', a fullbody marking, goes underneath everything even though it is a full body marking. So far it is the only marking with this sort of exception to it, though.
I have tried using various sort functions offered by PHP but I am not having much luck. uksort seems the most promising, but since the value we are sorting by exists in the database and not in the array we are sorting (the imagick function has to be fed a marking => color array format), it's proving difficult to work with.
Tl;dr: I need to reorder an array that an uncertain amount of data based off of values that exist in the DB for the keys (the region for the markings). What's the most elegant way to accomplish this?
Here are some optimizations to your code, there are comments inline to describe what was done. This is obviously not finished as there are some things Marcin pointed out in his answer that would be better.
// Determine number of markings
$num = mt_rand(1,10);
// Removed redundent $num > X as the conditions were already meet that it was > X by the previous if statement
if ($num == 1) {
$markingNum = 0;
} else if ($num < 4) {
$markingNum = 1;
} else if ($num < 6) {
$markingNum = 2;
} else if ($num < 8) {
$markingNum = 3;
} else if ($num < 10) {
$markingNum = 4;
} else {
$markingNum = 5;
}
// Calculate Marking type and color
$markings = array();
if ($markingNum > 0) {
for ($m = 1 ; $m <= $markingNum; $m++) { // incrimented to 1 and <= so we can dynamically select elements
// Set color values (pulls from the "pallet" selected earlier in the code, which will determine the range of color that marking can be)
$pal = $pallet->{'marking' . $m}; // Removed if/else and replaced with a dynamic variable
// Uncommon marking (10% chance)
$r = mt_rand(1, 10);
// removed duplicate database selections for a simple $rarity variable that accomplishes the same task
if ($r == 10) {
$rarity = 1;
} else {
$rarity = 0;
}
$marking = DataMarking::where('rarity', $rarity)
->where('public', 1)
->whereNotIn('name', array_keys($markings))
->whereNotIn('region', $regions)
->orderByRaw("RAND()")
->first();
// Colors marking
if ($pal == 0) {
$markingColor = rand_color();
} else {
$range = ColorRange::where('id', $pal)->firstOrFail();
$markingColor = "#" . mixRange(substr($range->start_hex, 1), substr($range->end_hex, 1));
}
$markings[$marking->name] = $marking; // adds all of the marking data, this is where you could have a z-index in the database
$markings[$marking->name] = $markingColor; // add your color to your marking data
$regions[] = $marking->region;
}
}
I won't answer your question, but looking at your code there are a lot of space for improvements.
Consider this:
if ($m == 1) {
$pal = $pallet->marking1;
} elseif ($m == 2) {
$pal = $pallet->marking2;
} elseif ($m == 3) {
$pal = $pallet->marking3;
} elseif ($m == 4) {
$pal = $pallet->marking4;
} else {
$pal = $pallet->marking5;
}
It could be changed for something much simpler:
$pa1 = (in_array($m,range(1,4))) ? $pallet->marking{$m} : $pallet->marking5;
Same for:
if ($r == 10) {
$marking = DataMarking::where('rarity', 1)
->where('public', 1)
->whereNotIn('name', array_keys($markings))
->whereNotIn('region', array_keys($regions))
->orderByRaw("RAND()")
->first();
// Common markings
} else {
$marking = DataMarking::where('rarity', 0)
->where('public', 1)
->whereNotIn('name', array_keys($markings))
->whereNotIn('region', array_keys($regions))
->orderByRaw("RAND()")
->first();
}
if could be rewritten to:
$marking = DataMarking::where('rarity', ($r == 10) ? 1 : 0)
->where('public', 1)
->whereNotIn('name', array_keys($markings))
->whereNotIn('region', array_keys($regions))
->orderByRaw("RAND()")
->first();
Of course in above ORDER BY RAND() might be not the best solution because of performance reasons.
You should really care about amount of your code and duplication or you'll soon be lost in what you are doing

Separating an array effectively

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.

Categories