Skip to content

Instantly share code, notes, and snippets.

@janvarev
Last active Aug 19, 2017
Embed
What would you like to do?
Vindinium stat collector
<?php
class Service_SubVinidiumLeader extends XcBase {
/*
Sorry, but this class will work in my own environment.
So you need to adapt it to your framework.
I leave all needed comment - for $_kernel, $advOnto and $srvParser objects.
You just have to rewrite their functions.
*/
/**
* Wacko object
* @var Wacko
*/
var $_kernel;
/**
* AdvOntology object - think of this an DB access layer
* @var Service_AdvOntology
*/
var $advOnto;
/**
* UtilParser object - think of this as an Text parser utility
* @var Service_UtilParser
*/
var $srvParser;
function Service_SubVinidiumLeader($kernelLink) {
$this->_localname = 'SubVinidiumLeader';
$this->XcBase($kernelLink);
$this->_kernel = $this->srvMainKernel();
$this->advOnto = $this->_kernel->srvFactory("AdvOntology");
$this->srvParser = $this->_kernel->srvFactory("UtilParser");
}
// when we want to make a stat, we need to make a DB table to keep data
function onInstall($params) {
$advOnto = $this->advOnto;
// adding a table - think like this
$this->advOnto->addType("VinLeader", "varchar(250)"); // botId == userId
$this->advOnto->addTypeField("VinLeader", "vname", "varchar(255)", ""); // bot name
$this->advOnto->addTypeField("VinLeader", "elo", "int(11)", "0"); // bot elo
$this->advOnto->addTypeField("VinLeader", "gameid", "varchar(255)", ""); // last bot game id
$this->advOnto->addIndex("VinLeader", "elo");
$this->advOnto->addIndex("VinLeader", "gameid");
$this->advOnto->addIndex("VinLeader", "vname");
// VinLeader table also has
// id - autogenerated int
// _updateTime - automatically changed when changed data. It used to check when last game was played
return true;
}
function onUninstall($params) {
$this->advOnto->delType("VinLeader");
return true;
}
function getBotElo($botid) {
if($this->_kernel->symAlnum($botid)) { // just check that string is A-Za-z0-9
$txt = file_get_contents("http://vindinium.org/ai/".$botid);
$elo = $this->srvParser->tparseSingle($txt, '(_ "user-elo\\">(" #main ")</span>" _)');
return (int)$elo;
}
return -1;
}
function getRecentGames() {
$txt = file_get_contents("http://vindinium.org/");
$mainSection = $this->srvParser->tparseSingle($txt, '(_ "<h2>Recent games</h2>" #main "</section>" _)');
// in mainSection text between "<h2>Recent games</h2>" and "</section>"
$ahrefs = $this->srvParser->tparseSingleRest($mainSection, '(_ "<a href=\\"/" #main "\\">" #rest)');
// ahrefs is GameId array - like ["abcd", "efgh"]
return $ahrefs;
}
function getRecentGamesNum($max) {
$rec = $this->getRecentGames();
$r2 = array();
$shift = 0;
if(substr_count($rec[0], "?") > 0) { // skip unfinished game - it has ? in gameId
$shift = 1;
}
for($i = $shift; $i < $max+$shift; $i++) {
$r2[] = $rec[$i];
}
return $r2;
}
function getGameHeroes($gameid) {
if($this->_kernel->symAlnum($gameid)) { // just check that string is A-Za-z0-9
$txt = file_get_contents("http://vindinium.org/events/".$gameid);
$a1 = explode("\n\n", $txt, 2);
$start = $a1[0]; // wanna have just first move
//return $start;
$obj = json_decode(substr($start, 6), true);
$heroes = array();
for($i = 0; $i < 4; $i++) {
$hero = array();
$hero["vname"] = $obj["heroes"][$i]["name"];
$hero["elo"] = $obj["heroes"][$i]["elo"]; // this is elo at game start!!
$hero["data"] = $obj["heroes"][$i]["userId"];
$hero["gameid"] = $gameid;
$heroes[] = $hero;
}
return $heroes;
}
return array();
}
function updateLeaderboard() {
set_time_limit(0);
//print_r($this->getGameHeroes("9vb19035"));
$games = $this->getRecentGamesNum(4);
// check for cache
$ishero = $this->advOnto->getConceptsByFieldIds("VinLeader", array("gameid" => $games[0]));
//echo $games[0];
//print_r($ishero);
if(count($ishero) > 0) {
echo "updated! (no update required)";
return;
}
$games = array_reverse($games);
//print_r($games);
$herMain = array();
foreach ($games as $gameid) {
$heroes = $this->getGameHeroes($gameid);
for($i = 0; $i < count($heroes); $i++) {
$herMain[$heroes[$i]["data"]] = $heroes[$i];
}
}
//print_r($herMain);
foreach($herMain as $botid => $val) {
$newelo = $this->getBotElo($botid);
$herMain[$botid]["elo"] = $newelo;
}
//print_r($herMain);
foreach($herMain as $botid => $botinfo) {
// finding bot data in DB by botid
$bot = $this->advOnto->getConceptByData("VinLeader", $botid);
if($bot) {
// if we find bot - UPDATE it
$this->advOnto->setConcept2("VinLeader", $bot["id"], $botinfo);
} else {
// if we not find bot - ADD it
$this->advOnto->addConcept2("VinLeader", $botinfo);
}
}
echo "updated!";
}
// you must call this every 10 minutes - this collect stat and update DB
function cron_updVinLeaderboard() {
$this->updateLeaderboard();
}
// if you want receive stat to show it - call this
function getLeaderboard($maxdays, $maxbots) {
$maxdays = (int)$maxdays;
$maxbots = (int)$maxbots;
$d = strtotime("-".$maxdays." day");
$df = date("Y-m-d H:i:s",$d);
//echo $df;
// receive all records from table - with LIMIT maxbots, ORDER elo DESC, and where _updateTime > $df,
$bots = $this->advOnto->getConceptsByFieldIdsExt("VinLeader", array(), 0, $maxbots, "elo", "DESC", array("_updateTime" => $df));
return $bots;
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment