merge with spawn branch
[brisk.git] / web / briskin5 / Obj / briskin5.phh
diff --git a/web/briskin5/Obj/briskin5.phh b/web/briskin5/Obj/briskin5.phh
new file mode 100644 (file)
index 0000000..c1c0f5b
--- /dev/null
@@ -0,0 +1,463 @@
+<?php
+define(BRISKIN5_PLAYERS_N, 3);
+define(BRISKIN5_MAX_PLAYERS, BRISKIN5_PLAYERS_N);
+// define(BRISKIN5_SHM_MIN, (50000 * BRISKIN5_MAX_PLAYERS));
+define(BRISKIN5_SHM_MIN, 32768);
+define(BRISKIN5_SHM_MAX, (BRISKIN5_SHM_MIN + 1048576));
+define(BRISKIN5_SHM_DLT, 32768);
+
+class Briskin5 {
+  var $user;
+  var $table;
+  var $table_idx;
+  var $table_token;
+
+  var $comm; // commands for many people
+  var $step; // current step of the comm array
+  var $garbage_timeout;
+
+  var $the_end;
+  
+  var $tok;
+  var $shm_sz;
+
+  function Briskin5 (&$room, $table_idx, $table_token) {
+    $this->user = array();
+    $this->table = array();
+
+    $this->the_end = FALSE;
+    $this->shm_sz = BRISKIN5_SHM_MIN;
+    if (($this->tok = @ftok(FTOK_PATH."/table".$table_idx, "B")) == -1) {
+      echo "FTOK FAILED";
+      exit;
+    }
+
+    $user  =& $room->user;
+    $table =& $room->table[$table_idx];
+
+    log_wr("Briskin5 constructor");
+
+    for ($i = 0 ; $i < $table->player_n ; $i++) {
+      $user[$table->player[$i]]->table_token = $table_token;
+      $this->user[$i] =& User::spawn(&$user[$table->player[$i]], 0, $i);
+    }
+    $this->table[0] =& Table::spawn(&$table);
+    $this->table_idx = $table_idx;
+    $this->table_token = $table_token;
+    $this->garbage_timeout = 0;
+    
+    log_wr("Briskin5 constructor end");
+  }
+
+
+  function &get_user($sess, &$idx)
+  {
+    GLOBAL $PHP_SELF, $G_false;
+
+    if (validate_sess($sess)) {
+      for ($i = 0 ; $i < BRISKIN5_MAX_PLAYERS ; $i++) {
+       if (strcmp($sess, $this->user[$i]->sess) == 0) {
+         // find it
+         $idx = $i;
+         $ret = &$this->user[$i];
+         return ($ret);
+       }
+      }
+      log_main(sprintf("get_user: Wrong sess from page [%s]",$PHP_SELF));
+      // for ($i = 0 ; $i < BRISKIN5_MAX_PLAYERS ; $i++) 
+      // log_main(sprintf("get_user: Wrong sess compared with [%s]",$this->user[$i]->sess));
+    }
+    else {
+      log_main(sprintf("get_user: Wrong strlen [%s]",$sess));
+    }
+
+    return ($G_false);
+  }
+
+
+  function garbage_manager($force)
+  {
+    
+    /* Garbage collector degli utenti in timeout */
+    $ismod = FALSE;
+    $curtime = time();
+    if ($force || $this->garbage_timeout < $curtime) {
+      
+      for ($i = 0 ; $i < BRISKIN5_MAX_PLAYERS ; $i++) {
+       $user_cur = &$this->user[$i];
+       if ($user_cur->sess == "" || 
+           ($user_cur->stat == 'table' && ($user_cur->subst == 'shutdowned' || $user_cur->subst == 'shutdowner')))
+         continue;
+       
+       if ($user_cur->lacc + EXPIRE_TIME_RD < $curtime) { // Auto logout dell'utente
+         log_rd2($user_cur->sess." bin5 AUTO LOGOUT.");
+
+         if ($user_cur->stat == 'table') {
+           log_auth($user_cur->sess," bin5 Autologout session.");
+
+           /* SI DELEGA AL garbage_manager principale LA RIMOZIONE DELL'UTENTE 
+
+           $tmp_sess = $user_cur->sess;
+           $user_cur->sess = "";
+           step_unproxy($tmp_sess);
+           $user_cur->name = "";
+           $user_cur->the_end = FALSE;
+           
+            */
+
+           $this->table_wakeup(&$user_cur);
+         }
+       }
+      }
+      log_rd2($user_cur->sess." GARBAGE UPDATED!");
+      
+      $this->garbage_timeout = $curtime + GARBAGE_TIMEOUT;
+      $ismod = TRUE;
+    }
+
+    return ($ismod);
+  }
+
+
+
+
+  //
+  //  static functions
+  //
+  function &load_data($table_idx, $table_token = "") 
+  {
+    GLOBAL $G_false, $sess;
+    $doexit = FALSE;
+    $shm = FALSE;
+
+    log_wr("TABLE_IDX ".FTOK_PATH."/table".$table_idx);
+    
+    do {
+      if (($tok = @ftok(FTOK_PATH."/table".$table_idx, "B")) == -1) {
+       log_main("ftok failed");
+       $doexit = TRUE;
+       break;
+      }
+
+      if (($shm_sz = sharedmem_sz($tok)) == -1) {
+       log_main("shmop_open failed");
+       break;
+      }
+       
+      if (($shm = shm_attach($tok, $shm_sz)) == FALSE)
+       break;
+
+      if (($bri = @shm_get_var($shm, $tok)) == FALSE) 
+       break;
+
+      if ($table_token != "" && $bri->table_token != $table_token) {
+       log_wr("bri->table_token: ".$bri->table_token."table_token: ".$table_token);
+       
+       break;
+      }
+      $bri->tok = $tok;
+
+      shm_detach($shm);
+       
+      $ret = &$bri;
+      return ($ret); 
+    } while (FALSE);
+
+    if ($shm != FALSE)
+      shm_detach($shm);
+
+    log_wr("briskin5 load_data failed");
+    if ($doexit)
+      exit();
+    
+    return ($G_false);
+  }
+  
+
+
+  function save_data(&$bri) 
+  {
+    GLOBAL $sess;
+    
+    $ret =   FALSE;
+    $shm =   FALSE;
+    
+    log_main("SAVE BRISKIN5 DATA");
+    
+    if (!isset($bri->tok))
+      return (FALSE);
+    
+    while ($bri->shm_sz < BRISKIN5_SHM_MAX) {
+      if (($shm = shm_attach($bri->tok, $bri->shm_sz)) == FALSE)
+       break;
+      
+      if (@shm_put_var($shm, $bri->tok, $bri) != FALSE) {
+       shm_detach($shm);
+       return (TRUE);
+      }
+      if (shm_remove($shm) === FALSE) {
+       log_only("REMOVE FALLITA");
+       break;
+      }
+      shm_detach($shm);
+      $bri->shm_sz += BRISKIN5_SHM_DLT;
+    } 
+
+    log_crit("save data failed!");
+
+    if ($shm)
+      shm_detach($shm);
+    
+    return ($ret);
+  }
+
+
+
+  function destroy_data($table_idx) 
+  {
+    GLOBAL $sess;
+
+    $ret =   FALSE;
+    $shm =   FALSE;
+    log_main("DESTROY BRISKIN5 DATA");
+    
+    do {
+      log_main("DESTROY2 BRISKIN5 DATA");
+
+      if (($tok = @ftok(FTOK_PATH."/table".$table_idx, "B")) == -1) 
+       break;
+
+      if (($shm = @shmop_open($tok, 'a', 0, 0)) == FALSE)
+       break;
+      
+      if (shmop_delete($shm) == 0) {
+       log_only("REMOVE FALLITA ");
+       break;
+      }
+   
+      $shm = FALSE;
+      log_main("DESTROY2 BRISKIN5 DATA SUCCESS");
+      
+      // log_main("QUI CI ARRIVA [".$bri->user[0]->name."]");
+      $ret = TRUE;
+    } while (0);
+    
+    if ($shm)
+      shm_detach($shm);
+    
+    return ($ret);
+  }
+
+  function lock_data($table_idx)
+  {
+    GLOBAL $sess; 
+    
+    log_wr("LOCK_DATA ".FTOK_PATH."/table".$table_idx);
+    //  echo "LOCK: ".FTOK_PATH."/main";
+    //  exit;
+    // WARNING monitor this step
+    if (($tok = @ftok(FTOK_PATH."/table".$table_idx, "B")) == -1) {
+      echo "FTOK FAILED";
+      exit;
+    }
+    // WARNING monitor this step
+    if (($res = @sem_get($tok)) == FALSE) {
+      echo "SEM_GET FAILED";
+      exit;
+    }
+    if (sem_acquire($res)) {   
+      log_lock("LOCK table ".$table_idx."[res: ".$res."]");
+      return ($res);
+    }
+    else {
+      log_lock("LOCK table ".$table_idx.":FAILED");
+      return (FALSE);
+    }
+  }
+  
+  function unlock_data($res)
+  {
+    GLOBAL $sess; 
+    
+    log_lock("UNLOCK table [res: ".$res."]");
+
+    return (sem_release($res));
+  }
+
+
+  function chatt_send(&$user, $mesg)
+  {
+    if ($user->stat == 'table') {
+      $table = &$this->table[$user->table];
+    }
+    
+    $user_mesg = substr($mesg,6);
+    
+    $curtime = time();
+    
+    $dt = date("H:i ", $curtime);
+    if (strncmp($user_mesg, "/nick ", 6) == 0) {
+      log_main($user->sess." chatt_send BEGIN");
+
+      if (($name_new = validate_name(substr($user_mesg, 6))) == FALSE) {
+         $user->comm[$user->step % COMM_N] = "gst.st = ".($user->step+1)."; ";
+         $user->comm[$user->step % COMM_N] .= sprintf('chatt_sub("%s","Il nickname deve contenere almeno una lettera dell\'alfabeto o una cifra.");', $dt.NICKSERV);
+         $user->step_inc();
+
+         return;
+      }
+      $user_mesg = "COMMAND ".$user_mesg;
+      // Search dup name
+      // change
+      // update local graph
+      // update remote graphs
+      for ($i = 0 ; $i < BRISKIN5_MAX_PLAYERS ; $i++) {
+       $user_cur = &$this->user[$i];
+       //      if ($user_cur->sess == '' || $user_cur->stat != 'room')
+       if ($user_cur->sess == '')
+         continue;
+       if ($user_cur->name == $name_new) {
+         $user->comm[$user->step % COMM_N] = "gst.st = ".($user->step+1)."; ";
+         $user->comm[$user->step % COMM_N] .= sprintf('chatt_sub("%s","Nickname <b>%s</b> gi&agrave; in uso.");', $dt.NICKSERV, xcape($name_new));
+         $user->step_inc();
+         break;
+       }
+      }
+      if ($i == BRISKIN5_MAX_PLAYERS) {
+       $user->name = $name_new;
+
+      log_main($user->sess." chatt_send start set");
+       
+
+       for ($i = 0 ; $i < BRISKIN5_MAX_PLAYERS ; $i++) {
+         log_main($user->sess." chatt_send set loop");
+         
+         $user_cur = &$this->user[$i];
+         if ($user_cur->sess == '')
+           continue;
+         if ($user_cur->stat == 'room') {
+           if ($user->stat == 'room' && $user->subst == 'standup') {
+             $this->standup_update(&$user);
+           }
+           else if ($user->stat == 'room' && $user->subst == 'sitdown' ||
+                    $user->stat == 'table') {
+             log_main($user->sess." chatt_send pre table update");
+
+             $this->table_update(&$user);
+
+             log_main($user->sess." chatt_send post table update");
+           }
+         }
+         else if ($user_cur->stat == 'table' && $user_cur->table == $user->table) {
+           $table = &$this->table[$user->table];
+           
+           $user_cur->comm[$user_cur->step % COMM_N] = "gst.st = ".($user_cur->step+1)."; ";
+           $user_cur->comm[$user_cur->step % COMM_N] .= sprintf('set_names(" %s", " %s", " %s", " %s", " %s"); ',
+               xcape($this->user[$table->player[($user_cur->table_pos) % BRISKIN5_PLAYERS_N]]->name),
+               xcape($this->user[$table->player[($user_cur->table_pos+1) % BRISKIN5_PLAYERS_N]]->name),
+               xcape($this->user[$table->player[($user_cur->table_pos+2) % BRISKIN5_PLAYERS_N]]->name),
+               (BRISKIN5_PLAYERS_N == 3 ? "" :  xcape($this->user[$table->player[($user_cur->table_pos+3) % BRISKIN5_PLAYERS_N]]->name)),
+               (BRISKIN5_PLAYERS_N == 3 ? "" :  xcape($this->user[$table->player[($user_cur->table_pos+4) % BRISKIN5_PLAYERS_N]]->name)));
+           if ($user_cur == $user)
+             $user_cur->comm[$user_cur->step % COMM_N] .= sprintf('$("myname").innerHTML = "<b>%s</b>";', 
+                                                                  xcape($user->name,ENT_COMPAT,"UTF-8"));
+           $user_cur->step_inc();
+         }
+       }
+      }
+    }
+    else {
+      for ($i = 0 ; $i < ($user->stat == 'room' ? BRISKIN5_MAX_PLAYERS : BRISKIN5_PLAYERS_N) ; $i++) {
+       if ($user->stat == 'room') {
+         $user_cur = &$this->user[$i];
+         if ($user_cur->sess == '' || $user_cur->stat != 'room')
+           continue;
+       }
+       else {
+         $user_cur = &$this->user[$table->player[$i]];
+       }
+       
+       $user_cur->comm[$user_cur->step % COMM_N] = "gst.st = ".($user_cur->step+1)."; ";
+       $user_cur->comm[$user_cur->step % COMM_N] .= sprintf('chatt_sub("%s","%s");',
+                                                            $dt.xcape($user->name), xcape($user_mesg));
+       $user_cur->step_inc();
+      }
+      log_legal($curtime, $user->sess, $user->name, 
+               ($user->stat == 'room' ? 'room' : 'table '.$user->table),$user_mesg);
+    }
+  }
+
+  function table_wakeup(&$user)
+  {
+    $table = &$this->table[0];
+
+    log_main("BRISKIN5_WAKEUP begin function table  stat: ".$user->stat."  subst: ".$user->subst);
+
+    $curtime = time();
+
+    log_main("BRISKIN5_WAKEUP from table [".$user->table."] nplayers_n: ".$this->table[$user->table]->player_n);
+    
+    for ($i = 0 ; $i < $table->player_n ; $i++) {
+      $user_cur = &$this->user[$i];
+      log_main("PREIMPOST INLOOP name: ".$user_cur->name);
+      
+      if ($user_cur == $user)
+       $user_cur->subst = "shutdowner";
+      else
+       $user_cur->subst = "shutdowned";
+      $user_cur->laccwr = $curtime;
+
+      $ret = "gst.st = ".($user_cur->step+1)."; ";
+      $ret .= 'gst.st_loc++; the_end=true; window.onunload = null; document.location.assign("../index.php");|';
+
+      log_wr($user_cur->sess." BRISKIN5_WAKEUP: ".$ret);
+      $user_cur->comm[$user_cur->step % COMM_N] = $ret;
+      $user_cur->step_inc();
+    }
+
+    $this->the_end = TRUE;
+  }
+  
+  /*
+   *  If all players are freezed the room garbage_manager clean up table and users.
+   */ 
+  function is_abandoned() 
+  {
+    $is_ab = TRUE;
+    $curtime = time();
+
+    $table = &$this->table[0];
+
+    for ($i = 0 ; $i < $table->player_n ; $i++) {
+      $user_cur = &$this->user[$i];
+
+      if ($user_cur->lacc + (EXPIRE_TIME_RD * 2) >= $curtime) { 
+       $is_ab = FALSE;
+       break;
+      }
+    }
+
+    return ($is_ab);
+  }
+} // end class Briskin5
+
+function locshm_exists($tok)
+{
+  // return (TRUE);
+
+  if (($id = @shmop_open($tok,"a", 0, 0)) == FALSE) {
+    log_main($tok." SHM NOT exists");
+
+    return (FALSE);
+  }
+  else {
+    shmop_close($id);
+    log_main($tok." SHM exists");
+
+    return (TRUE);
+  }
+    
+}
+
+
+?>