I have a program which uses a deck of cards (not a standard deck of 52, more like the cards in a game like Dominion). Each card has a row in the DB, and a column for it's current deck_spot. When the card gets used, the deck_spot is set to 0. When the number of cards left in the deck (ie, have a spot > 0) is under a set point (4 for now), I need to shuffle the deck. I want to keep the remaining 3 cards in the "top" of the deck so they are used first, then the freshly shuffled deck is used, rather than the 3 being put in the shuffle. Here's what I have now.
function shuffleDeck(){
//Get the cards which are still in the deck
$sql = "SELECT user_sail_card_id FROM user_sail_cards WHERE deck_spot != 0 ORDER BY deck_spot ASC";
$rows = $this->getRows($sql); //This gets an array of all the rows
//Build an update statement to put the remaining cards in order.
$update = "UPDATE user_sail_cards SET deck_spot = ( CASE ";
foreach($rows AS $k=>$row){
$update .= " WHEN user_sail_card_id = {$row['user_sail_card_id']} THEN ".($k+1);
}
$update .= " ELSE 0 END) WHERE deck_spot != 0";
$total_cards = $k+1;
/*At this point update statement looks like:
UPDATE user_sail_cards SET deck_spot = ( CASE WHEN user_sail_card = 3 THEN 1 WHEN user_sail_card = 2 THEN 2 ELSE 0)
*/
//Update those cards, then select the cards which will be shuffled.
if(dbUp($update)){
$sql = "SELECT user_sail_card_id FROM user_sail_cards WHERE deck_spot = 0 ORDER BY deck_spot ASC";
$rows = $this->getRows($sql);
//Shuffle the deck
shuffle($rows);
$update = "UPDATE user_sail_cards SET deck_spot = ( CASE ";
foreach($rows AS $row){
//Put these cards AFTER the other cards
$update .= " WHEN user_sail_card_id = {$row['user_sail_card_id']} THEN ".($total_cards++);
}
$update .= " ELSE 0 END) WHERE deck_spot = 0";
return dbUp($update);
}
}
I'm using the ADODB library with a few custom wrapper functions.
Is there a more efficient way to do this? Right now I'm making 4 queries to do it. I was hoping to do it in 1 or 2 if possible.
Edit: fixed typos.