Jump to content

Recommended Posts

Every week we have a bid on scheduled shifts.  What I want to do is make this list of users rotate every week so the person who got first pick this week is now last on the list.

 

Example....

Week 1

User1

User2

User3

 

Week 2

User2

User3

User1

 

Week 3

User3

User1

User2

 

And so on with many other users.  I have no idea where to start on this.  All I could think was to assign each user a number then every week, add 10 to the first person in the list but I think this is not the way to do it.

 

My app is done in PHP/MySQL.

Link to comment
https://forums.phpfreaks.com/topic/203486-rotate-a-list-of-users/
Share on other sites

Put them into a multi array and array_shift and array-push each week.

 

Thanks for the quick response teamatomic.  I've been reading up on what you suggested and I just can't grasp it.  I'm by no means a good programmer so this basically went over my head.

 

Although i'm learning a lot from the reading, I'm just not at a point where I can build it from scratch.

array_shift

array_push


$userStack = array('User1', 'User2', 'User3');

function sortUserList(&$userStack)
{
   /* &$userStack is a reference to the array passed meaning that it will
       be modified outside the scope of the function. 
    */

   // Return user at the bottom of the stack (array element 0) and remove element
   $selectedUser = array_shift($userStack);
   // Push the user returned onto the top of the stack.
   $userStack    = array_push($selectedUser);
   //return the user selected to assign to the variable on the left of the function call.
   return $selectedUser;
}

$user = sortUserList($userStack);

array_shift

array_push


$userStack = array('User1', 'User2', 'User3');

function sortUserList(&$userStack)
{
   /* &$userStack is a reference to the array passed meaning that it will
       be modified outside the scope of the function. 
    */

   // Return user at the bottom of the stack (array element 0) and remove element
   $selectedUser = array_shift($userStack);
   // Push the user returned onto the top of the stack.
   $userStack    = array_push($selectedUser);
   //return the user selected to assign to the variable on the left of the function call.
   return $selectedUser;
}

$user = sortUserList($userStack);

 

Ok, starting to see how these are used.

 

Getting Warning: Wrong parameter count for array_push() though, looks right when I checking the php manual for array_push.

array_shift

array_push


$userStack = array('User1', 'User2', 'User3');

function sortUserList(&$userStack)
{
   /* &$userStack is a reference to the array passed meaning that it will
       be modified outside the scope of the function. 
    */

   // Return user at the bottom of the stack (array element 0) and remove element
   $selectedUser = array_shift($userStack);
   // Push the user returned onto the top of the stack.
   array_push($userStack, $selectedUser);
   //return the user selected to assign to the variable on the left of the function call.
   return $selectedUser;
}

$user = sortUserList($userStack);

Oops lol

Wicked stuff!

 

When I do

print_r($user);

I see

User1

 

Am i displaying this right?

 

Also, how is this script rotating the users and what time frame is it basing this rotation?  Like if I wanted the users to change say every sunday.

 

Pardon my lack of programming knowledge.  I'm just really digging this work and learning lots :)

It is not implementing the rotation on any tine scale, for that you need a way to store your list of users (a database) and pull them out once a week, using a cronjob or include file with a few datetime functions to check last execution. Then after the rotation you would need to use the returned data and store your new user stack in your database. To demonstrate how the stack currently works you can ammend the current script like so:

 


$userStack = array('User1', 'User2', 'User3');

function sortUserList(&$userStack)
{
   /* &$userStack is a reference to the array passed meaning that it will
       be modified outside the scope of the function. 
    */

   // Return user at the bottom of the stack (array element 0) and remove element
   $selectedUser = array_shift($userStack);
   // Push the user returned onto the top of the stack.
   array_push($userStack, $selectedUser);
   //return the user selected to assign to the variable on the left of the function call.
   return $selectedUser;
}
for ($i = 0; $i < count($userStack); $i++)
{
   echo '<pre>' . print_r($userStack, true) . '</pre><br >';
   echo 'Current user: ' . sortUserList($userStack);
   echo '<br ><br >';
}

 

//edit, tested it locally and returned

 

Array
(
    [0] => User1
    [1] => User2
    [2] => User3
)


Current user: User1

Array
(
    [0] => User2
    [1] => User3
    [2] => User1
)


Current user: User2

Array
(
    [0] => User3
    [1] => User1
    [2] => User2
)


Current user: User3

Something about your methods confuse me Andy-H...

 

To simplify his request he could simply do

 

$array = array('tacos','pacos','sockos');
shuffle($array);
echo $array[rand(0,count($array)-1)]; // for one value returned
foreach($array AS $name){ // for multiple values returned
     echo $name . "<br />\n";
}

Something about your methods confuse me Andy-H...

 

To simplify his request he could simply do

 

$array = array('tacos','pacos','sockos');
shuffle($array);
echo $array[rand(0,count($array)-1)]; // for one value returned
foreach($array AS $name){ // for multiple values returned
     echo $name . "<br />\n";
}

 

My method was what he asked for, a way to rotate a list of users in a FIFO stack, your method simply returns a random element of the array, also, you don't need to use shuffle and rand (to specify the numerical index). You could simply use shuffle() and return element 0. (If your method did what the OP asked for that is...)

I got a bit bored so I decided to build a class to encapsulate the behaviour, it's the first class I've built from scratch (which is why I did it, to get some experience with OOPHP :D ) anyway, it works fine from what I've tested.

 

Feel free to use it.

 

class userStack
{
   private $_userStack = array();
   private $_dateToRotate;
   
   const XML_PATH = 'userlist.xml';
   
   public function __construct()
   {
      if (!$data = simplexml_load_file(self::XML_PATH))
      {
         throw new Exception('Could not load XML from file: ' . self::XML_PATH);
      }
         
         foreach($data->user as $user)
         {
            $this->addUser($user->name);
         }
         
      $this->_dateToRotate = isset($data->dateToRotate) ? $data->dateToRotate : date("d-m-Y", strtotime("+1 week"));

      if (strtotime(date("d-m-Y")) >= strtotime($this->_dateToRotate))
      {
         $this->rotateStack();
         $this->_dateToRotate = date("d-m-Y", strtotime("+1 week"));
      }
   }
   
   public function addUser($user)
   {
      $this->_userStack[] = $user;
   }
   
   public function getCurrentUser()
   {
      return $this->_userStack[0];
   }

   private function rotateStack()
   {
      $user = array_shift($this->_userStack);
      array_push($this->_userStack, $user);
   }
   
   public function __destruct()
   {
      $doc   = new DomDocument('1.0');
      $root  = $doc->createElement('userList');
      $root  = $doc->appendChild($root);
      $date  = $doc->createElement('dateToRotate');
      $date  = $root->appendChild($date);
      $value = $doc->createTextNode($this->_dateToRotate);
      $date->appendChild($value);
      
      foreach($this->_userStack as $user)
      {
         $child = $doc->createElement('user');
         $child = $root->appendChild($child);
         $name  = $doc->createElement('name');
         $name  = $child->appendChild($name);
         $value = $doc->createTextNode($user);
         $value = $name->appendChild($value);
      }
      
      $xmlString = $doc->saveXML();
      
      if (!$fh = fopen(self::XML_PATH, 'w'))
      {
         throw new Exception('Error opening file: ' . self::XML_PATH);
      }
      else
      {
         if (!fwrite($fh, $xmlString, strlen($xmlString)))
         {
            throw new Exception('Error writing XML to file: ' . self::XML_PATH);
         }
         
         fclose($fh);
      }
   }
}

 

include "userStack.inc.php";

try
{
   $stack = new userStack;
   echo $stack->getCurrentUser();
}
catch(Exception $e)
{
   echo $e->getMessage();
}

 

And this is all stored in an XML file like so:

 

<?xml version="1.0"?>
<userList><dateToRotate>08-06-2010</dateToRotate>
<user>
   <name>Andy</name>
</user>
<user>
   <name>Joe</name>
</user>
<user>
   <name>Sue</name>
</user>
</userList>

 

To create the XML file in the first place, just comment out the constructor, and run addUser a few times, and let the class destruct.

Sorry, was late last night, I updated the code to make it work when creating the XML file, (i.e comment out the constructor and run addUser for whatever users you wish to add). Last time the list would be rotated once the constructor was uncommented and the date updated.

 

class userStack
{
   private $_userStack = array();
   private $_dateToRotate;
   
   const XML_PATH = 'userlist.xml';
   /*
    *Remove these comments after the script has run and created the XML file.
   public function __construct()
   {
      if (!$data = simplexml_load_file(self::XML_PATH))
      {
         throw new Exception('Could not load XML from file: ' . self::XML_PATH);
      }
         
         foreach($data->user as $user)
         {
            $this->addUser($user->name);
         }
         
      $this->_dateToRotate = $data->dateToRotate;

      if (strtotime(date("d-m-Y")) >= strtotime($this->_dateToRotate))
      {
         $this->rotateStack();
         $this->_dateToRotate = date("d-m-Y", strtotime("+1 week"));
      }
   }
   */

   public function __tostring()
   {
      return '<pre>Current user: ' . "\t\t" . $this->getCurrentUser() . "\r\n"
           . 'To be updated: '     . "\t\t" . $this->_dateToRotate    . '</pre>';
   }
   
   public function addUser($user)
   {
      $this->_userStack[] = $user;
   }
   
   public function getCurrentUser()
   {
      return $this->_userStack[0];
   }

   private function rotateStack()
   {
      $user = array_shift($this->_userStack);
      array_push($this->_userStack, $user);
   }
   
   public function __destruct()
   {
      $this->_dateToRotate = isset($this->_dateToRotate) 
                                 ? $this->_dateToRotate 
                                 : date("d-m-Y", strtotime("+1 week"));
                                 
      $doc   = new DomDocument('1.0');
      $root  = $doc->createElement('userList');
      $root  = $doc->appendChild($root);
      $date  = $doc->createElement('dateToRotate');
      $date  = $root->appendChild($date);
      $value = $doc->createTextNode($this->_dateToRotate);
      $date->appendChild($value);
      
      foreach($this->_userStack as $user)
      {
         $child = $doc->createElement('user');
         $child = $root->appendChild($child);
         $name  = $doc->createElement('name');
         $name  = $child->appendChild($name);
         $value = $doc->createTextNode($user);
         $value = $name->appendChild($value);
      }
      
      $xmlString = $doc->saveXML();
      
      if (!$fh = fopen(self::XML_PATH, 'w'))
      {
         throw new Exception('Error opening file: ' . self::XML_PATH);
      }
      else
      {
         if (!fwrite($fh, $xmlString))
         {
            throw new Exception('Error writing XML to file: ' . self::XML_PATH);
         }
         
         fclose($fh);
      }
   }
}

try
{
   $stack = new userStack;
   $stack->addUser('User 1');
   $stack->addUser('User 2');
   $stack->addUser('User 3');
   //etc...
}
catch(Exception $e)
{
   echo $e->getMessage();
}

Updated it again..

 

<?php

class userStack
{
   protected $_userStack = array();
   protected $_dateToRotate;
   
   const XML_PATH = 'D:\\wamp\\www\\userlist.xml';
   
   public function __construct()
   {
      if (!$data = simplexml_load_file(self::XML_PATH))
      {
         throw new Exception('Could not load XML from file: ' . self::XML_PATH);
      }
         
         foreach($data->user as $user)
         {
            $this->addUser($user->name);
         }
         
      $this->_dateToRotate = $data->dateToRotate;

      if (strtotime(date("d-m-Y")) >= strtotime($this->_dateToRotate))
      {
         $this->rotateStack();
         $this->_dateToRotate = date("d-m-Y", strtotime("+1 week", strtotime($this->_dateToRotate)));
      }
   }
   
   public function __tostring()
   {
      $i = 0;
      return '<pre>Current user:' . "\t\t"     . $this->getCurrentUser()                . "\r\n"
           . 'To be updated:'     . "\t\t"     . $this->_dateToRotate                   . "\r\n\r\n"
           . 'All users:'         . "\r\n\t\t" . implode("\r\n\t\t", $this->_userStack) . '</pre>';
   }
   
   public function addUser($user)
   {
      $this->_userStack[] = $user;
   }
   
   public function getCurrentUser()
   {
      return $this->_userStack[0];
   }

   private function rotateStack()
   {
      $user = array_shift($this->_userStack);
      array_push($this->_userStack, $user);
   }
   
   public function __destruct()
   {
      $this->_dateToRotate = isset($this->_dateToRotate) 
                                 ? $this->_dateToRotate 
                                 : date("d-m-Y", strtotime("+1 week"));
                                 
      $doc   = new DomDocument('1.0');
      $root  = $doc->createElement('userList');
      $root  = $doc->appendChild($root);
      $date  = $doc->createElement('dateToRotate');
      $date  = $root->appendChild($date);
      $value = $doc->createTextNode($this->_dateToRotate);
      $date->appendChild($value);
      
      foreach($this->_userStack as $user)
      {
         $child = $doc->createElement('user');
         $child = $root->appendChild($child);
         $name  = $doc->createElement('name');
         $name  = $child->appendChild($name);
         $value = $doc->createTextNode($user);
         $value = $name->appendChild($value);
      }
      
      $xmlString = $doc->saveXML();
      
      if (!$fh = fopen(self::XML_PATH, 'w'))
      {
         throw new Exception('Error opening file: ' . self::XML_PATH);
      }
      else
      {
         if (!fwrite($fh, $xmlString))
         {
            throw new Exception('Error writing XML to file: ' . self::XML_PATH);
         }
         
         fclose($fh);
      }
   }
}

/*
* #######################################
* # Remove this class after firts run. ##
* #######################################
*
* This extenstion of userStack creates the XML file in which the
* stack data is stored.
*
* It must be ran before instantiating userStack.
*
* #######################################
* # Example of use: #####################
* #######################################
*
* $file = new createStackFile;
* $file->addUser('User1');
* $file->addUser('User2');
* $file->addUser('User3');
* echo $file;
*
*/
class createStackFile Extends userStack
{
   public function __construct(){}
}
?>

 

Now updates to one week from the last stored date rather than one week from the current date, sorry, only just spotted the mistake. Been playing with it due to EXTREME boredom :P

  • 4 weeks later...

I really appreciate all the work and scripts you made Andy-H, really do but what you did was way over my head :)

 

Finally got it to do what I wanted.  Chaotic and amateur, but it works

<?php 
$query_rsCheckTotal = "
SELECT rotation_num
FROM tcAgent_list
WHERE active = '1' 
AND active_group = 'TC'
ORDER BY rotation_num DESC
";
$rsCheckTotal = mysql_query($query_rsCheckTotal, $cnepix) or die(mysql_error());
$row_rsCheckTotal = mysql_fetch_assoc($rsCheckTotal);
$totalRows_rsCheckTotal = mysql_num_rows($rsCheckTotal);

$swap = $totalRows_rsCheckTotal + 1;
$max_emp = $totalRows_rsCheckTotal;

mysql_query("UPDATE tcAgent_list SET rotation_num='$swap' WHERE active='1' AND active_group = 'TC' AND rotation_num='1'");

do {
mysql_query("UPDATE tcAgent_list SET `rotation_num` = `rotation_num` - 1 WHERE active='1' AND active_group = 'TC' AND rotation_num NOT LIKE '$swap'");
 }
while ($max_emp<=1); 

mysql_query("UPDATE tcAgent_list SET rotation_num='$max_emp' WHERE active='1' AND active_group = 'TC' AND rotation_num='$swap'");
}
?>

 

So basically it figures out how many there are, sets the current #1 person to one higher than the total, subtracts 1 from existing then changes the highest to 1 lower.

 

Complex and clumsy YEP, but it works :)

Hmm, this would seem to allow for the same functionality without all that code and doesn't even require a daatabase. Just pop all the users into an array and the array order is determine each week automatically using date('W'):

//Array of all users
$userStack = array('User1', 'User2', 'User3');

//Reorder array for current week
for($idx=0; $idx<(date('W')%count($userStack)); $idx++)
{
    array_push($userStack, array_shift($userStack));
}

print_r($userStack);

 

 

Hmm, this would seem to allow for the same functionality without all that code and doesn't even require a daatabase. Just pop all the users into an array and the array order is determine each week automatically using date('W'):

//Array of all users
$userStack = array('User1', 'User2', 'User3');

//Reorder array for current week
for($idx=0; $idx<(date('W')%count($userStack)); $idx++)
{
    array_push($userStack, array_shift($userStack));
}

print_r($userStack);

 

 

 

Problem I had with this approach is the user list is dynamic and changes all the time but is also stored in a database.

 

Boss also changed the demand and asked that the rotation be manually set by him depending on the schedule he sets.  So basically the way I do it is when he puts in a new schedule, it triggers the rotate script.

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.