Dynamické povolování registrací
Obsah
Ú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 } ?>