Zergman Posted June 1, 2010 Share Posted June 1, 2010 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. Quote Link to comment https://forums.phpfreaks.com/topic/203486-rotate-a-list-of-users/ Share on other sites More sharing options...
teamatomic Posted June 1, 2010 Share Posted June 1, 2010 Put them into a multi array and array_shift and array-push each week. HTH Teamatomic Quote Link to comment https://forums.phpfreaks.com/topic/203486-rotate-a-list-of-users/#findComment-1066009 Share on other sites More sharing options...
Zergman Posted June 1, 2010 Author Share Posted June 1, 2010 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. Quote Link to comment https://forums.phpfreaks.com/topic/203486-rotate-a-list-of-users/#findComment-1066359 Share on other sites More sharing options...
Andy-H Posted June 1, 2010 Share Posted June 1, 2010 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); Quote Link to comment https://forums.phpfreaks.com/topic/203486-rotate-a-list-of-users/#findComment-1066362 Share on other sites More sharing options...
Zergman Posted June 1, 2010 Author Share Posted June 1, 2010 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. Quote Link to comment https://forums.phpfreaks.com/topic/203486-rotate-a-list-of-users/#findComment-1066373 Share on other sites More sharing options...
Andy-H Posted June 1, 2010 Share Posted June 1, 2010 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 Quote Link to comment https://forums.phpfreaks.com/topic/203486-rotate-a-list-of-users/#findComment-1066380 Share on other sites More sharing options...
Zergman Posted June 1, 2010 Author Share Posted June 1, 2010 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 Quote Link to comment https://forums.phpfreaks.com/topic/203486-rotate-a-list-of-users/#findComment-1066387 Share on other sites More sharing options...
Andy-H Posted June 1, 2010 Share Posted June 1, 2010 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 Quote Link to comment https://forums.phpfreaks.com/topic/203486-rotate-a-list-of-users/#findComment-1066398 Share on other sites More sharing options...
marcus Posted June 1, 2010 Share Posted June 1, 2010 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"; } Quote Link to comment https://forums.phpfreaks.com/topic/203486-rotate-a-list-of-users/#findComment-1066403 Share on other sites More sharing options...
Andy-H Posted June 2, 2010 Share Posted June 2, 2010 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...) Quote Link to comment https://forums.phpfreaks.com/topic/203486-rotate-a-list-of-users/#findComment-1066424 Share on other sites More sharing options...
Andy-H Posted June 2, 2010 Share Posted June 2, 2010 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 ) 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. Quote Link to comment https://forums.phpfreaks.com/topic/203486-rotate-a-list-of-users/#findComment-1066451 Share on other sites More sharing options...
Zergman Posted June 2, 2010 Author Share Posted June 2, 2010 Sweet Mary Jane, thats pretty epic Andy-H! Quote Link to comment https://forums.phpfreaks.com/topic/203486-rotate-a-list-of-users/#findComment-1066480 Share on other sites More sharing options...
Andy-H Posted June 2, 2010 Share Posted June 2, 2010 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(); } Quote Link to comment https://forums.phpfreaks.com/topic/203486-rotate-a-list-of-users/#findComment-1066765 Share on other sites More sharing options...
Andy-H Posted June 9, 2010 Share Posted June 9, 2010 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 Quote Link to comment https://forums.phpfreaks.com/topic/203486-rotate-a-list-of-users/#findComment-1069784 Share on other sites More sharing options...
Zergman Posted July 2, 2010 Author Share Posted July 2, 2010 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 Quote Link to comment https://forums.phpfreaks.com/topic/203486-rotate-a-list-of-users/#findComment-1080081 Share on other sites More sharing options...
Psycho Posted July 2, 2010 Share Posted July 2, 2010 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); Quote Link to comment https://forums.phpfreaks.com/topic/203486-rotate-a-list-of-users/#findComment-1080092 Share on other sites More sharing options...
Zergman Posted July 2, 2010 Author Share Posted July 2, 2010 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. Quote Link to comment https://forums.phpfreaks.com/topic/203486-rotate-a-list-of-users/#findComment-1080105 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.