vendredi 15 décembre 2017

Distribute lottery tickets randomly from pre-gerenated set in PHP

I'm looking for an atomic way to pick one ticket from a poll of tickets and give it to someone in PHP. So far I have thought of a few different solutions but I'm not sure how atomic they are (two people must NEVER have the same ticket).

All tickets are pre-generated in the range of 1-N (random numbers as tickets can't be used). The methods I think are viable are:

1) Use a file to store the tickets shuffled and pick the first one and rewrite the file (or pick the last one and only truncate without rewrite). Simplest example:

function NextTicket()
{
  $fh = fopen('tickets.txt', 'rw+');
  flock($fh, LOCK_EX)) //hopefully this should prevent parallel access

  $all = explode("\n", stream_get_contents($arq));
  $return = $all[0]; //ticket to be returned

  unset($all[0]);
  rewind($fh);
  ftruncate($fh,0);
  fwrite($fh, implode("\n", $all);
  fclose($fh);

  return $ticket;
}

2) Use a sqlite file to hold all tickets and extract a row at a time (supposes shuffled rows inserted).

function NextTicket()
{
  $db = new SQLite3('tickets.sqlite');
  $db->exec('BEGIN');
    $res = $db->query('SELECT rowid,TI_NUMBER FROM tickets LIMIT 1');
    $ticket = $res->fetchArray(SQLITE3_ASSOC);
    $db->exec('DELETE FROM tickets WHERE rowid='.$ticket['rowid']);
  $db->exec('COMMIT');

  return $ticket['TI_NUMBER'];
}

3) Use sqlite as a counter with a single row instead of holding each ticket number in a row (I cannot use this method because the delivery should be random).

function NextTicket()
{
  $db = new SQLite3('/tmp/tickets.sqlite');
  $db->exec('BEGIN');
    $res = $db->query('SELECT rowid,TI_NUMBER FROM tickets LIMIT 1');
    $ticket = $res->fetchArray(SQLITE3_ASSOC);
    $res = $db->query('UPDATE tickets SET TI_NUMBER=TI_NUMBER+1 WHERE rowid='.$ticket['rowid']);
  $db->exec('COMMIT');

  return $ticket['TI_NUMBER'];
}

4) Other approaches? Mysql 5.6 database is also available. Auto increment cannot be used as it's sequential and I need random row from the set. Maybe combining 1 and 3 to get a specific position from inside the shuffled file based in the auto increment.

Has anyone faced a similar issue? How was it solved?

Thanks in advance.




Aucun commentaire:

Enregistrer un commentaire