Newbie Spellweaver
- Joined
- Mar 22, 2012
- Messages
- 31
- Reaction score
- 14
Video Guide:
I know there are a few others out there, but this is a bit different.
Features:
- Reads evaLogs / FatalLogs
- Can be ran more than once a day for frequent updating, without adding duplicates of the unique kills. Personally I'm running it every 5 minutes.
- Proceeded evaLogs / FatalLogs (of previous days) are moved to a folder of your choice (default "finished\")
- More flexible. The other ones I tried missed a few unique kills here and there. Hence I made this one :
- Each unique kill is added to the database with the info of the killer, unique and the time.
Setting it up:
You will need the Microsoft SQL Driver for PHP (sqlsrv), it can be downloaded here:
Reason I use this is because it's maintained by Microsoft and works with SQL Server 2005 / 2008 and 2012
Creating the table:
Creating the connection file:
Now we'll need to establish a connection to the SQL server.
I've created a PHP class specifically for the sqlsrv php extension to make basic queries and connections easier... It contains a few functions that isn't being used for the unique reader, but it might be useful for your other applications / web interface.
Put this in a separate file (config.php) and edit the username/password/database names (inside the __construct function) to match your sql server info
Setting up the parser:
And for the parser itself, put this code in a separate file (unique_reader.php) and move it anywhere outside your web root to prevent web access.
At the very top of this file, you can edit:
- Timezone (get yours here
- The path to your config.php file above (DBCONN)
- The table name where kills are being inserted (TABLE)
- Which log types you want to scan (LOGTYPE). Can be either 'EVALOGS' or 'FATALLOGS'
- Path to the directory of your log files (LOGPATH)
- Path to where proceeded log files are moved (DONEDIR). This folder will be created automatically in your log directory.
Do not forget the backslashes after a directory path.
Running the program on a scheduled task:
- Start -> Search for "taskschd.msc"
- Click Create Task at the right hand side
General Tab:
- Name it whatever you want
- Under security options, check "Run whether user is logged on or not"
Triggers Tab:
- Begin the task: On a schedule
- Settings: Daily
- Recur every: 1 days
- Repeat task every: 5 minutes (or how often you want the rankings to be updated)
Actions Tab:
- Action: Start a program
- Program/Script (Modify this to your php path): "C\PHP\v5.3\php.exe"
- Arguments (Modify this to your unique_reader.php path: C:\cronjobs\unique_reader.php
Basic output page: (somefile.php)
- Just edit the config.php location at the top, and add which uniques you want to allow to the array. You can also edit their display names here.
You should be all set.
If you need any help with setting it up / using the functions of the mssql class / other stuff.. Let me know,
Cheers
You must be registered to see links
I know there are a few others out there, but this is a bit different.
Features:
- Reads evaLogs / FatalLogs
- Can be ran more than once a day for frequent updating, without adding duplicates of the unique kills. Personally I'm running it every 5 minutes.
- Proceeded evaLogs / FatalLogs (of previous days) are moved to a folder of your choice (default "finished\")
- More flexible. The other ones I tried missed a few unique kills here and there. Hence I made this one :
- Each unique kill is added to the database with the info of the killer, unique and the time.
Setting it up:
You will need the Microsoft SQL Driver for PHP (sqlsrv), it can be downloaded here:
You must be registered to see links
Reason I use this is because it's maintained by Microsoft and works with SQL Server 2005 / 2008 and 2012
Creating the table:
PHP:
USE [SRO_VT_SHARD_INIT]
GO
/****** Object: Table [dbo].[UniqueKills] Script Date: 04/11/2012 23:06:39 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[UniqueKills](
[CharName16] [varchar](20) NOT NULL,
[Monster] [varchar](50) NOT NULL,
[Timestamp] [varchar](12) NOT NULL
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
Creating the connection file:
Now we'll need to establish a connection to the SQL server.
I've created a PHP class specifically for the sqlsrv php extension to make basic queries and connections easier... It contains a few functions that isn't being used for the unique reader, but it might be useful for your other applications / web interface.
Put this in a separate file (config.php) and edit the username/password/database names (inside the __construct function) to match your sql server info
PHP:
<?php
// By Flowlance (danny@leetcake.net)
class mssql {
var $shard;
var $account;
var $params;
function __construct() {
// Database username
$id = "username";
// Database password
$pw = "password";
// Shard and Account database names
$con_shard = array("UID"=>$id, "PWD"=>$pw, "Database"=>"SRO_VT_SHARD_INIT");
$con_account = array("UID"=>$id, "PWD"=>$pw, "Database"=>"SRO_VT_ACCOUNT");
// Shard And Account hostname / Connection
$this->shard = sqlsrv_connect("localhost", $con_shard) or die( print_r( sqlsrv_errors(), true));
$this->account = sqlsrv_connect("localhost", $con_account) or die( print_r( sqlsrv_errors(), true));
$this->params = array("Scrollable" => SQLSRV_CURSOR_KEYSET);
}
function __destruct() {
sqlsrv_close($this->shard);
sqlsrv_close($this->account);
}
public function db($db) {
switch($db) {
case 'SHARD':
return $this->shard;
break;
case 'ACCOUNT':
return $this->account;
break;
}
}
public function query($db, $query, $values=array()) {
$db = $this->db($db);
$sql = sqlsrv_query($db, $query, $values, $this->params);
if($query === false )
return "Query error";
else
return $sql;
}
public function fetch($query) {
return sqlsrv_fetch_array($query);
}
public function get_num($db, $query) {
$db = $this->db($db);
$sql = sqlsrv_query($db, $query, array(), $this->params);
if($query === false )
return var_dump(sqlsrv_errors());
else
return sqlsrv_num_rows($sql);
}
public function num($query) {
return sqlsrv_num_rows($query);
}
public function last($query) {
sqlsrv_next_result($query);
sqlsrv_fetch($query);
return sqlsrv_get_field($query, 0);
}
public function safe($data) {
if ( !isset($data) or empty($data) ) return '';
if ( is_numeric($data) ) return $data;
$non_displayables = array(
'/%0[0-8bcef]/',
'/%1[0-9a-f]/',
'/[\x00-\x08]/',
'/\x0b/',
'/\x0c/',
'/[\x0e-\x1f]/'
);
foreach ( $non_displayables as $regex )
$data = preg_replace( $regex, '', $data );
$data = str_replace("'", "''", $data );
return $data;
}
}
$mssql = new mssql();
?>
Setting up the parser:
And for the parser itself, put this code in a separate file (unique_reader.php) and move it anywhere outside your web root to prevent web access.
At the very top of this file, you can edit:
- Timezone (get yours here
You must be registered to see links
)- The path to your config.php file above (DBCONN)
- The table name where kills are being inserted (TABLE)
- Which log types you want to scan (LOGTYPE). Can be either 'EVALOGS' or 'FATALLOGS'
- Path to the directory of your log files (LOGPATH)
- Path to where proceeded log files are moved (DONEDIR). This folder will be created automatically in your log directory.
Do not forget the backslashes after a directory path.
PHP:
<?php
// By Flowlance (danny@leetcake.net)
date_default_timezone_set("Europe/Amsterdam"); // Your server's timezone
$settings = array(
'DBCONN' => 'C:\\inetpub\\xomnhala\\config.php', // Path to db connection file
'TABLE' => 'UniqueKills', // Unique Ranking table name
'LOGTYPE' => 'EVALOGS', // "EVALOGS" or "FATALLOGS"
'LOGPATH' => 'C:\\Server\\evaLog\\', // Path to log files
'DONEDIR' => 'finished\\' // Proceeded/Scanned logs will be moved here
);
include($settings['DBCONN']);
class UniqueReader extends mssql {
var $table;
var $logptrn;
var $fileptrn;
var $path;
var $finished;
var $logfiles;
public function setVar($settings) {
$this->table = $settings['TABLE'];
$this->logfiles = $settings['LOGTYPE'];
$this->path = $settings['LOGPATH'];
$this->finished = $settings['DONEDIR'];
if($this->logfiles == "EVALOGS") {
$this->logptrn = "/\[([0-9_\-]{1,})\].*\[([a-zA-Z0-9_]{1,})\].*\[([a-zA-Z0-9_]{1,})\]/siU";
$this->fileptrn = "/^[0-9\-]{1,}\_uniquekills.txt$/";
} else {
$this->logptrn = "/([0-9_\-]{1,}\t[0-9_:]{1,})\t.*Unique\sMonster\sKilled!\sUNIQUE\[([a-zA-Z0-9_]{1,})\].*\sby\s\[([a-zA-Z0-9_]{1,})\]/siU";
$this->fileptrn = "/^[0-9\-]{1,}\_FatalLog.txt$/";
}
}
public function ts($datestr) {
if($this->logfiles == "EVALOGS") {
$split = split("_", $datestr);
$date = $split[0] . " " . str_replace("-", ":", $split[1]);
} else {
$date = str_replace("\t", " ", $datestr);
}
return strtotime($date);
}
public function match($search) {
if(preg_match_all($this->logptrn, $search, $m)) {
return $m;
} else {
return false;
}
}
public function isToday($filename) {
$split = split("_", $filename);
$date = $this->logfiles == "EVALOGS" ? date("j-n-Y") : date("Y-m-d");
if($date==$split[0]) {
return true;
}
}
public function move($v) {
if(!$this->isToday($v)) {
if(copy($this->path . $v,$this->path . $this->finished . $v)) {
unlink($this->path . $v);
}
}
}
public function folder_check() {
if(!file_exists($this->path . $this->finished)) {
mkdir($this->path . $this->finished);
}
}
public function scan() {
$this->folder_check();
$files = scandir($this->path);
foreach($files as $v) {
if(preg_match($this->fileptrn, $v)) {
$file = fopen($this->path . $v, "r");
while($line = fgets($file)) {
$cont = $this->match($line);
if($cont!=false) {
$exists = $this->get_num("SHARD", "SELECT * FROM ".$this->table." WHERE CharName16='".$this->safe($cont[3][0])."' AND Monster='".$this->safe($cont[2][0])."' AND Timestamp='".$this->ts($cont[1][0])."'");
if($exists==0) {
$params = array($this->safe($cont[3][0]), $this->safe($cont[2][0]), $this->ts($cont[1][0]));
$this->query("SHARD", "INSERT INTO ".$this->table." (CharName16, Monster, Timestamp) VALUES (?, ?, ?)", $params);
}
}
}
fclose($file);
$this->move($v);
}
}
}
}
$reader = new UniqueReader();
$reader->setVar($settings);
$reader->scan();
?>
Running the program on a scheduled task:
- Start -> Search for "taskschd.msc"
- Click Create Task at the right hand side
General Tab:
- Name it whatever you want
- Under security options, check "Run whether user is logged on or not"
Triggers Tab:
- Begin the task: On a schedule
- Settings: Daily
- Recur every: 1 days
- Repeat task every: 5 minutes (or how often you want the rankings to be updated)
Actions Tab:
- Action: Start a program
- Program/Script (Modify this to your php path): "C\PHP\v5.3\php.exe"
- Arguments (Modify this to your unique_reader.php path: C:\cronjobs\unique_reader.php
Basic output page: (somefile.php)
- Just edit the config.php location at the top, and add which uniques you want to allow to the array. You can also edit their display names here.
PHP:
<?php
include("config.php");
// Add uniques you want to allow / display in the following array:
$allowed = array(
'MOB_CH_TIGERWOMAN' => 'Tiger Girl',
'MOB_OA_URUCHI' => 'Uruchi',
'MOB_KK_ISYUTARU' => 'Isyutaru',
'MOB_TK_BONELORD' => 'Lord Yarkan',
'MOB_EU_KERBEROS' => 'Cerberus',
'MOB_AM_IVY' => 'Captain Ivy',
'MOB_RM_TAHOMET' => 'Demon Shaitan'
);
foreach($allowed as $k => $v) {
$uniques = empty($uniques) ? "" : $uniques . ",";
$uniques .= "'" . $k . "'";
}
echo "Top 15 Unique Killers:<br />\n";
$query = $mssql->query("SHARD", "SELECT TOP 15 CharName16, COUNT(*) AS Kills FROM UniqueKills WHERE Monster IN(".$uniques.") GROUP BY CharName16 ORDER BY Kills DESC");
while($row=$mssql->fetch($query)) {
echo $row['CharName16'] . " - " . $row['Kills'] . " kills<br />\n";
}
echo "Last 15 Unique Kills:<br />\n";
$query = $mssql->query("SHARD", "SELECT TOP 15 * FROM UniqueKills WHERE Monster IN(".$uniques.") ORDER BY Timestamp DESC");
while($row=$mssql->fetch($query)) {
echo $row['CharName16'] . " killed " . $allowed[$row['Monster']] . " at " . date("d-m-Y H:i", $row['Timestamp']) . "<br />\n";
}
?>
You should be all set.
If you need any help with setting it up / using the functions of the mssql class / other stuff.. Let me know,
Cheers
Last edited: