For part of a project i am working on in school i am building a room booking system. As part of this system, i have a page where users can enter criteria for a room and the page will return available rooms that fit that criteria and are free for booking. If a users search does not return any results i intend to lower the criteria entered, display a room that fits the altered criteria and display a message to the user informing them of the altered criteria. The call to function suggestroom() is shown here.
} else {
$reducecapacity = 1;
do {
$booking = new Booking();
$suggestedrooms = $booking->suggestroom(($capacity - $reducecapacity), $appletv, $printer);
$reducecapacity = $reducecapacity + 1;
} while($suggestedrooms === null);
echo 'This room has a cacpacity of: ' . ($capacity-($reducecapacity-1));
for($x=0; $x<count($suggestedrooms); $x++) {
echo $suggestedrooms[$x];
}
}
Public function SuggestRoom($capacity, $appletv, $printer) {
if($appletv == 1 and $printer ==0) {
$roomname = DB::GetInstance()->query("SELECT roomname FROM room WHERE capacity >= '$capacity' AND appletv ='$appletv'");
} elseif($appletv == 0 and $printer == 1) {
$roomname = DB::GetInstance()->query("SELECT roomname FROM room WHERE capacity >= '$capacity' AND printer = '$printer'");
} elseif($appletv == 1 and $printer == 1) {
$roomname = DB::GetInstance()->query("SELECT roomname FROM room WHERE capacity >= '$capacity' AND appletv ='$appletv' AND printer = '$printer'");
} else {
$roomname = DB::GetInstance()->query("SELECT roomname FROM room WHERE capacity >= '$capacity'");
}
$roomcount = $roomname->count();
if($roomcount == 0) {
echo 'No classes match your criteria';
} else {
for($x=0; $x<$roomcount; $x++) {
$RoomArray[$x] = $roomname->results()[$x]->roomname;
}
}
$LoopCount = 0;
$EndLoop = false;
$RNDnum = 0;
$availableroomcount = 0;
do {
$suggestedRoom = $RoomArray[$RNDnum];
$getRoomID = DB::GetInstance()->query("SELECT roomid FROM room WHERE roomname = '$suggestedRoom'");
$roomid = $getRoomID->results()[0]->roomid;
$bookingid = Input::get('bookingdate') . Input::get('period') . $roomid;
$CheckIfBooked = DB::GetInstance()->query("SELECT bookingid FROM booking WHERE bookingid = '$bookingid'");
if($CheckIfBooked->count() ==0) {
$availablerooms[$availableroomcount] = $suggestedRoom;
$availableroomcount = $availableroomcount+1;
}
if($LoopCount===$roomcount-1) {
$NoRoomMessage = true;
$EndLoop = true;
$suggestedRoom = null;
}
$LoopCount = $LoopCount+1;
$RNDnum = $RNDnum +1;
} while ($EndLoop <> 1);
return $availablerooms;
}
Thus, when there are no bookings, a null array will be returned to suggested rooms and this will continue until a room is found (if not, i will make it so other criteria is changed, not that far ahead yet).
A room can be found, and the code works however for x amount of times that the code is ran before a room is found i.e an empty array is returned, i get an undefined variable message. How can i get around this?
Switching off notices, warnings, errors is not the best way to code.
And unlike the above answers I prefer to always initialize a variable rather then using isset().
Use isset/empty
if(isset($var1) || !empty($var1)){
//do something
} else {
//do another
}
Let me change my question completely to explain myself better;
I have an order;
An order have multiple order rows. Each order row has two fields; Quantity ordered, and quantity delivered.
If all order rows' quantities delivered are the same as the quantity ordered, the entire order should get a status of '100% delivered'.
If multiple or even one order row's quantities delivered does not match the quantities ordered the entire order should get a status of 'partly delivered'.
If no order row have any deliveries (if all deliveries stands on 0) the status should be '0% delivered'.
What I have so far looks only at the last order row of the entire order because all the previous rows gets overridden by the latest check. This is my code;
public function deliveryAction(Request $request, $id) {
$em = $this->getDoctrine()->getManager();
$order = $em->getRepository('QiBssBaseBundle:PmodOrder')->find($id);
$orderRowsDelivered = $request->request->all();
$delivered = "0%";
foreach ($orderRowsDelivered['order_row_id'] as $orderRowId => $quantityDelivered) {
if($quantityDelivered != '' || $quantityDelivered != null) {
$orderRow = $em->getRepository("QiBssBaseBundle:PmodOrderRow")->find($orderRowId);
$orderDelivered = new PmodDelivery();
$orderDelivered->setOrderRow($orderRow);
$orderDelivered->setQuantity($quantityDelivered);
$orderDelivered->setTimeArrived(new \DateTime());
$em->persist($orderDelivered);
$em->flush();
if($orderRow->getQuantityDelivered() > 0 && $orderRow->getQuantityDelivered() < $orderRow->getQuantity()) {
$delivered = "partly";
} elseif ($orderRow->getQuantityDelivered() == $orderRow->getQuantity()) {
$delivered = "100%";
}
}
}
var_dump($delivered);exit;
return new RedirectResponse ... ;
}
Because as of this moment he looks at the last one with 10 and 8 in the example image, and give a status of 'partly', as soon as the 'quantity delivered' amounts is entered. But he should take all rows together.
I hope this makes more sense.
Based on what Cerad in the comments of his own answer said, this is my answer; (I'll make use of OP's scenario where he uses order rows per order.)
I've added an extra property to my OrderRow entity called $rowStatus.
After that I created a getter function for the $rowStatus called getRowStatus() that gives each row a status individually;
public function getRowStatus()
{
if ($this->getQuantityDelivered() == $this->getQuantity()) {
return $this->rowStatus = 100;
} elseif ($this->getQuantityDelivered() == 0) {
return $this->rowStatus = 0;
} else {
return $this->rowStatus = 50;
}
}
After that in my Order entity I've added a $deliveryStatus property, with a corresponding getter function called getDeliveryStatus() that looks like this;
public function getDeliveryStatus()
{
if (count($this->getOrderRows()) > 0) { //this check is to make sure there are orderRows, because you can't devide by zero if it might happen that there are no order rows. If not the delivery status will just be set on 0.
$sum = 0;
foreach ($this->getOrderRows() as $row) {
$sum += $row->getRowStatus();
}
$average = $sum / count($this->getOrderRows());
if ($average == 100) {
return $this->deliveryStatus = 100;
} elseif ($average == 0) {
return $this->deliveryStatus = 0;
} else {
return $this->deliveryStatus = 50;
}
} else {
return $this->deliveryStatus = 0;
}
}
That's it! After this I just use an enum function to display the 100 as "100% delivered", the 50 as "partly delivered", and the 0 as "0% delivered". I know this isn't really necessary, and you can instead change the status number directly to a string or whatever you want to display.
Just off the top of my head I might do:
$deliveredNone = true;
$deliveredAll = true;
$deliveredSome = false;
foreach ($orderRowsDelivered['order_row_id'] as $orderRowId => $quantityDelivered) {
if ($quantityDelivered) {
$deliveredNone = false; // Know that something has been delivered
}
...
if ($orderRow->getQuantityDelivered() != $orderRow->getQuantity()) {
$deliveredSome = true;
$deliveredAll = false;
}
}
$delivered = null;
if ($deliveredNone) $delivered = '0%';
if ($deliveredAll) $delivered = '100%';
if ($deliveredSome) $delivered = 'partly';
Though I would probably just update the order with the quantities delivered then use a different function to calculate the percentage delivered. As you can see, mixing the two processes can result in confusion.
Suppose I have an array with ie. $user_all_activity in code, i must check 5 activity in 10 minute(which is done by getDifference(),which return true is condition matches).If condition matched the condition,now i must check 5 activity in 10 minute after the condition matched.And this will be repeated several times.I put some late night programming here.
//$$user_all_activity take all activity of user A
if(!$user_all_activity == NULL)
{
$size = sizeof($user_all_activity);
//$prev_array = array();
for( $i=0; $i<$size-1;$i++)
{
if($i>3)
{
$prev_array = $user_all_activity[$i-4];
$current_array = $user_all_activity[$i];
//get difference check for difference 10
if($this->getDifference($current_array,$prev_array))
{
echo "Table update at id ".$current_array['id']." </br>";
}
}
}
}
The problem for me when condition matched.I must check again the same thing.May be good to use recursive.Sorry for not explaining the problem before.Hope you get the question.Thanks
Set a variable, and then check it later.
if($user_all_activity != NULL)
{
$size = sizeof($user_all_activity);
$difference_found = false;
for( $i=0; $i<$size-1;$i++)
{
if($i>3)
{
$prev_array = $user_all_activity[$i-4];
$current_array = $user_all_activity[$i];
//get difference check for difference 10
if($this->getDifference($current_array,$prev_array))
{
echo "Table update at id ".$current_array['id']." </br>";
$difference_found = true;
}
if ($difference_found) {
// do something
}
}
}
}
I have a simple function that do this:
1) User view some image and image_id is stored in session array
2) Then user can see the last 10 viewed images
Currently my function is this:
function lastSeen($image_id){
if(!isset($_SESSION['lastSeen'])){
$_SESSION['lastSeen'] = array($image_id);
}else{
$tmpSession = array_unique($_SESSION['lastSeen']);
if(count($tmpSession) > 9){
$tmpSession = array_slice($tmpSession,1);
}
$tmpSession[] = $image_id;
$_SESSION['lastSeen'] = array_unique($tmpSession);
}
return true;
}
This function works but the problem is that, if a user view one image more than one time, then in session are saved only 9 items.
Can anybody help me solve this problem? Maybe the whole function needs to be rewrite it...
You probably want to remove extraneous entries as the very last thing, and also only if it's more than 10 entries:
else {
$tmpSession = $_SESSION['lastSeen'];
$tmpSession[] = $image_id;
$tmpSession = array_unique($tmpSession);
if(count($tmpSession) > 10){
$tmpSession = array_slice($tmpSession,1);
}
$_SESSION['lastSeen'] = $tmpSession;
}
If you wouldn't mind that the order of images doesn't change, when the user views one image twice, then I would go with this simple solution. Just add line like this:
if (in_array($image_id, $tmpSession)) return true;
So your function would look like this:
function lastSeen($image_id){
if(!isset($_SESSION['lastSeen'])){
$_SESSION['lastSeen'] = array($image_id);
} elseif (in_array($image_id, $_SESSION['lastSeen'])) {
return true;
} else {
$tmpSession = array_unique($_SESSION['lastSeen']);
if(count($tmpSession) > 9){
$tmpSession = array_slice($tmpSession,1);
}
$tmpSession[] = $image_id;
$_SESSION['lastSeen'] = array_unique($tmpSession);
}
return true;
}
Another implementation of your function could be:
function lastSeen($image_id){
if(!isset($_SESSION['lastSeen']) || !is_array($_SESSION['lastSeen'])){
$_SESSION['lastSeen'] = array();
}
if(!in_array($image_id, $_SESSION['lastSeen']){
array_push($_SESSION['lastSeen'], $image_id);
}
if(sizeof($_SESSION['lastSeen']) > 10){
array_shift($_SESSION['lastSeen']);
}
}
If you want a function that stores the last visited image as the last item in the array, then just replace:
$tmpSession = array_slice($tmpSession,1);
with the following line:
if (in_array($image_id,$tmpSession))
array_splice($tmpSession, array_search($image_id, $tmpSession), 1);
else
$tmpSession = array_slice($tmpSession, 1);
The result function would look like:
function lastSeen($image_id) {
if (!isset($_SESSION['lastSeen'])) {
$_SESSION['lastSeen'] = array($image_id);
} else {
$tmpSession = array_unique($_SESSION['lastSeen']);
if (count($tmpSession) > 9){
if (in_array($image_id,$tmpSession))
array_splice($tmpSession, array_search($image_id, $tmpSession), 1);
else
$tmpSession = array_slice($tmpSession, 1);
}
$tmpSession[] = $image_id;
$_SESSION['lastSeen'] = array_unique($tmpSession);
}
return true;
}
I'm trying to loop through a set of records, all of which have a "number" property. I am trying to check if there are 3 consecutive records, e.g 6, 7 and 8.
I think i'm almost there with the code below, have hit the wall though at the last stage - any help would be great!
$nums = array();
while (count($nums <= 3))
{
//run through entries (already in descending order by 'number'
foreach ($entries as $e)
{
//ignore if the number is already in the array, as duplicate numbers may exist
if (in_array($e->number, $num))
continue;
else
{
//store this number in the array
$num[] = $e->number;
}
//here i need to somehow check that the numbers stored are consecutive
}
}
function isConsecutive($array) {
return ((int)max($array)-(int)min($array) == (count($array)-1));
}
You can achieve the same result without looping, too.
If they just have to be consecutive, store a $last, and check to make sure $current == $last + 1.
If you're looking for n numbers that are consecutive, use the same, except also keep a counter of how many ones fulfilled that requirement.
$arr = Array(1,2,3,4,5,6,7,343,6543,234,23432,100,101,102,103,200,201,202,203,204);
for($i=0;$i<sizeof($arr);$i++)
{
if(isset($arr[$i+1]))
if($arr[$i]+1==$arr[$i+1])
{
if(isset($arr[$i+2]))
if($arr[$i]+2==$arr[$i+2])
{
if(isset($arr[$i+3]))
if($arr[$i]+3==$arr[$i+3])
{
echo 'I found it:',$arr[$i],'|',$arr[$i+1],'|',$arr[$i+2],'|',$arr[$i+3],'<br>';
}//if3
}//if 2
}//if 1
}
I haven't investigated it thoroughly, maybe can be improved to work faster!
This will confirm if all items of an array are consecutive either up or down.
You could update to return an array of [$up, $down] or another value instead if you need direction.
function areAllConsecutive($sequence)
{
$up = true;
$down = true;
foreach($sequence as $key => $item)
{
if($key > 0){
if(($item-1) != $prev) $up = false;
if(($item+1) != $prev) $down = false;
}
$prev = $item;
}
return $up || $down;
}
// areAllConsecutive([3,4,5,6]); // true
// areAllConsecutive([3,5,6,7]); // false
// areAllConsecutive([12,11,10,9]); // true
Here's an example that can check this requirement for a list of any size:
class MockNumber
{
public $number;
public function __construct($number)
{
$this->number = $number;
}
static public function IsListConsecutive(array $list)
{
$result = true;
foreach($list as $n)
{
if (isset($n_minus_one) && $n->number !== $n_minus_one->number + 1)
{
$result = false;
break;
}
$n_minus_one = $n;
}
return $result;
}
}
$list_consecutive = array(
new MockNumber(0)
,new MockNumber(1)
,new MockNumber(2)
,new MockNumber(3)
);
$list_not_consecutive = array(
new MockNumber(5)
,new MockNumber(1)
,new MockNumber(3)
,new MockNumber(2)
);
printf("list_consecutive %s consecutive\n", MockNumber::IsListConsecutive($list_consecutive) ? 'is' : 'is not');
// output: list_consecutive is consecutive
printf("list_not_consecutive %s consecutive\n", MockNumber::IsListConsecutive($list_not_consecutive) ? 'is' : 'is not');
// output: list_not_consecutive is not consecutive
If u don't wanna mess with any sorting, picking any of three numbers that are consecutive should give you:
- it either is adjacent to both the other numbers (diff1 = 1, diff2 = -1)
- the only number that is adjacent (diff = +-1) should comply the previous statement.
Test for the first condition. If it fails, test for the second one and under success, you've got your secuence; else the set doesn't comply.
Seems right to me. Hope it helps.
I think you need something like the following function (no need of arrays to store data)
<?php
function seqOfthree($entries) {
// entries has to be sorted descending on $e->number
$sequence = 0;
$lastNumber = 0;
foreach($entries as $e) {
if ($sequence==0 or ($e->number==$lastNumber-1)) {
$sequence--;
} else {
$sequence=1;
}
$lastNumber = $e->number;
if ($sequence ==3) {
// if you need the array of sequence you can obtain it easy
// return $records = range($lastNumber,$lastNumber+2);
return true;
}
}
// there isn't a sequence
return false;
}
function isConsecutive($array, $total_consecutive = 3, $consecutive_count = 1, $offset = 0) {
// if you run out of space, e.g. not enough array values left to full fill the required # of consecutive count
if ( $offset + ($total_consecutive - $consecutive_count ) > count($array) ) {
return false;
}
if ( $array[$offset] + 1 == $array[$offset + 1]) {
$consecutive_count+=1;
if ( $consecutive_count == $total_consecutive ) {
return true;
}
return isConsecutive($array, $total_consecutive, $consecutive_count, $offset+=1 );
} else {
return isConsecutive($array, $total_consecutive, 1, $offset+=1 );
}
}
The following function will return the index of the first of the consecutive elements, and false if none exist:
function findConsecutive(array $numbers)
{
for ($i = 0, $max = count($numbers) - 2; $i < $max; ++$i)
if ($numbers[$i] == $numbers[$i + 1] - 1 && $numbers[$i] == $numbers[$i + 2] - 2)
return $i;
return false;
}
Edit: This seemed to cause some confusion. Like strpos(), this function returns the position of the elements if any such exists. The position may be 0, which can evaluate to false. If you just need to see if they exist, then you can replace return $i; with return true;. You can also easily make it return the actual elements if you need to.
Edit 2: Fixed to actually find consecutive numbers.