Dynamické povolování registrací

Z ZděchovNET
Verze z 5. 2. 2011, 09:29, kterou vytvořil Chronos (diskuse | příspěvky) (Založena nová stránka: =Úvod= Existují servery malé, střední a velké. Co server, to různá koncepce jak jej co nejlevněji financovat. Zatímco v případě velkých serverů majitelé v…)
(rozdíl) ← Starší verze | zobrazit aktuální verzi (rozdíl) | Novější verze → (rozdíl)
Skočit na navigaci Skočit na vyhledávání

Úvod

Existují servery malé, střední a velké. Co server, to různá koncepce jak jej co nejlevněji financovat. Zatímco v případě velkých serverů majitelé většinou investují do drahého hardware a rychlého internetového připojení, které je nutno odpovídajícím způsobem měsíčně platit, tak některé menší servery jdou spíše cestou minimálních nákladů a majitelé je provozují např. doma, kde však nemusí mít dostatečnou kapacitu internetové linky v odchozím směru. Tak či tak, každý server může narazit pod náporem hráčů na své limity a musí pak přistoupit k omezení množství hráčů.

Existují dvě místa, kde lze tento počet omezit:

  • Omezit max. počet hráčů online
  • Omezit počet nových registrací

V prvním případě jsou však hráči při dosažení kapacity zařazovány do fronty a musí čekat, až se na ně dostane řada. To je nevýhodné z toho pohledu, že starší hráči musí čekat na úkor nově příchozích a v konečném důsledku mohou být nespokojeni všichni.


Naproti tomu pokud se zabrání příchodu nových hráčů, tak staří se mohou kdykoliv připojit a noví se na server ani nedostanou a tak nemají pocit, že o něco přicházejí.

Omezit registrace lze různým způsobem:

  • Ručně je podle uvážení zablokovat
  • Ručně zpracovávat všechny registrace přes email
  • Pouze stávající hráči mohou rozdávat pozvánky novým hráčům
  • Konstantně omezit denní počet registrací
  • Dynamicky povolovat registrace k dosažen požadovaného množství hráčů

Každý ze způsobů má své výhody a nevýhody a jejich realizace je různě složitá. Každopádně pokud server má omezenu kapacitu a majitel chce udržovat počet online hráčů na určité úrovni, tak může s výhodou použít poslední uvedenou variantu a tedy automatický systém regulace. Pak počty připojených hráčů budou se budou přibližovat k žádané hodnotě a budou kolem ní v obou směrech oscilovat. Samotný online limit lze nastavit např. na 1,5 násobek předpokládané hodnoty, aby se všichni hráči vždy mohly připojit.

Realizace

Aby mohlo automatické omezování správně fungovat, potřebuje mít k výpočtu informaci o:

  • Počtu účtů na konci předchozího dne
  • Aktuální počet účtů
  • Nejvyšší počet hráčů online během předchozího dne
  • Požadovaný počet online hráčů

Inicializace databáze

Aby bylo možné tyto údaje získat a někde uchovat, je potřeba si vytvořit v databázi pomocnou tabulku:

CREATE TABLE IF NOT EXISTS `CharacterOnlineHistory` (
  `Date` date NOT NULL,
  `Min` int(11) NOT NULL,
  `Max` int(11) NOT NULL,
  `AccountCount` int(11) NOT NULL,
  PRIMARY KEY  (`Date`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;

Zde je uveden datum Date jakožto primární klíč a pak maximální počet online hráčů a počet účtů ke konci daného dne AccountCount. Hodnota Min je zde spíše pro zajímavost.


Základní třída RegistrationLimit

Zde je PHP třída uložená v souboru registration_limit.php:

<?php

class RegistrationLimit
{
  var $db;
  var $Server;
  var $Config;
  
  function __construct($db, $Server, $Config)
  {
    $this->db = $db;
    $this->Server = $Server;
    $this->Config = $Config;
  }
  
  function Update()
  {
    $AccountOnlineCount = $this->Server->RealmOnline();
    $AccountCount = $this->Server->AccountCount();

    $this->db->select_db($this->Config['Database']['Database']);
    $DbResult = $this->db->query('SELECT * FROM `CharacterOnlineHistory` WHERE `Date` = CURDATE()');
    if($DbResult->num_rows > 0)
    {
      // Update max, min
      $this->db->query('UPDATE `CharacterOnlineHistory` SET `Max` = GREATEST(`Max`, '.$AccountOnlineCount.'), `Min` = LEAST(`Min`, '.$AccountOnlineCount.'), `AccountCount` = '.$AccountCount.' WHERE `Date` = CURDATE()');
    } else 
      $this->db->query('INSERT INTO `CharacterOnlineHistory` (`Max`, `Min`, `Date`, `AccountCount`) VALUES ('.$AccountOnlineCount.', '.$AccountOnlineCount.', CURDATE(), '.$AccountCount.')');
  }
  
  function GetFreeRegistrationCount()
  {
    $AccountCount = $this->Server->AccountCount();

    $this->db->select_db($this->Config['Database']['Database']);
    $DbResult = $this->db->query('SELECT * FROM `CharacterOnlineHistory` WHERE `Date` = DATE_SUB(CURDATE(), INTERVAL 1 DAY)');
    if($DbResult->num_rows > 0)
    {
      $Yesterday = $DbResult->fetch_assoc();
    } else 
      $Yesterday = array('Max' => 0, 'AccountCount' => 0);
 
    $NextDayFreeRegistration = $this->Config['Mangos']['RequiredOnlinePlayers'] - $Yesterday['Max'];
    if($NextDayFreeRegistration < 0) $NextDayFreeRegistration = 0;
    $NextDayUsedRegistration = $AccountCount - $Yesterday['AccountCount'];
    $FreeRegistration = $NextDayFreeRegistration - $NextDayUsedRegistration;
    if($FreeRegistration < 0) $FreeRegistration = 0;
    return($FreeRegistration);
  }

  function GetPerDeyRegistrationCount()
  {
    $AccountCount = $this->Server->AccountCount();

    $this->db->select_db($this->Config['Database']['Database']);
    $DbResult = $this->db->query('SELECT * FROM `CharacterOnlineHistory` WHERE `Date` = DATE_SUB(CURDATE(), INTERVAL 1 DAY)');
    if($DbResult->num_rows > 0)
    {
      $Yesterday = $DbResult->fetch_assoc();
    } else 
      $Yesterday = array('Max' => 0, 'AccountCount' => 0);
  
    $NextDayFreeRegistration = $this->Config['Mangos']['RequiredOnlinePlayers'] - $Yesterday['Max'];
    if($NextDayFreeRegistration < 0) $NextDayFreeRegistration = 0;
    return($NextDayFreeRegistration);
  }
}

?>

Třída poskytuje tři funkce:

  • Update() - tuto funkci je potřeba během dne periodicky volat, aby bylo možné zjistit maximum hráčů online. Také ukládá počet účtů na konci dne.
  • GetFreeRegistrationCount() - Vrací zbývající počet povolených registrací pro aktuální den.
  • GetPerDeyRegistrationCount() - Vrací celkový počet povolených registrací pro aktuální den.


Konfigurační soubor

Nastavení lze provést přes parametr $Config. Ten lze inicializovat pomocí souboru config.php např. takto:

<?php

$Config = array(
  'Database' => array
  (
    'Host' => 'localhost',
    'User' => 'root',
    'Password' => '',
    'Database' => 'wow',
    'Prefix' => '',
    'Charset' => 'utf8',
  ),
  'Mangos' => array(
    'DatabaseRealmd' => 'realmd',
    'RequiredOnlinePlayers' => 200,
  ),
);

?>

Samozřejmě je potřeba doplnit patřičné přihlašovací údaje k databázi s umístěním pomocné tabulky.


Aktualizace dat

Pro zjištění počtu hráčů online je nutno pravidelně během dnes např. každých 5 minut kontrolovat jejich stav. To zajistí jednoduchý skript registration_update.php:

<?php

include('server.php');
include('registration_limit.php');
include('config.php');

$db = new mysqli($Config['Database']['Host'], $Config['Database']['User'], $Config['Database']['Password'], $Config['Database']['Database']);
$Server = new Server($db, $Config);
$RegistrationLimit = new RegistrationLimit($db, $Server, $Config);

$RegistrationLimit->Update();

?>

Volání lze realizovat pomocí systémového plánovače ve Windows nebo v Linuxu pomocí plánovače cron:

Soubor registration_update.sh:

#!/bin/sh
cd /var/www/html
php registration_update.php

Provádění každou minutu přes cron:

* * * * * registration_update.sh

Třída Server

Ke správnému spuštění je pak ještě nutné doplnit třídu obstarávající užitečné funkce k serveru server.php. Zde jsou alespoň nejnutnější funkce:

class Server
{
  private $db;
  private $Config;

  public function __construct($db, $Config)
  {
    $this->db = $db;
    $this->Config = $Config;
  }

  public function RealmOnline()
  {
    $this->db->select_db($this->Config['Mangos']['DatabaseRealmd']);
    $DbResult = $this->db->query('SELECT COUNT(*) FROM `account` WHERE `online` = 1');
    $DbRow = $DbResult->fetch_row();
    return($DbRow[0]);
  }

  public function AccountCount()
  {
    $this->db->select_db($this->Config['Mangos']['DatabaseRealmd']);
    $row = $this->db->query('SELECT COUNT(*) FROM account')->fetch_row();
    return($row[0]);
  }
}


Zobrazení a kontrola stavu

Nakonec na stránce Registrace lze pak už jednoduše povolovat registrace a zobrazit jejich stav.

<?php

include('server.php');
include('registration_limit.php');
include('config.php');

$db = new mysqli($Config['Database']['Host'], $Config['Database']['User'], $Config['Database']['Password'], $Config['Database']['Database']);
$Server = new Server($db, $Config);
$RegistrationLimit = new RegistrationLimit($db, $Server, $Config);

echo('Dnes celkem povolených registrací: '.$RegistrationLimit->GetPerDeyRegistrationCount().'<br/>');
echo('Dnes zbývajících registrací: '.$RegistrationLimit->GetFreeRegistrationCount().'<br/>');
echo('<br/>');
if($RegistrationLimit->GetFreeRegistrationCount() > 0)
{
  // Zobrazení registračního formuláře
} else
{
  // Registrace nejsou povoleny
}

?>