PageRenderTime 65ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 1ms

/dkp_wizard/rosterdkp_logparse.php

http://wowroster-addons.googlecode.com/
PHP | 600 lines | 488 code | 72 blank | 40 comment | 54 complexity | 1d85d0acb0946798731f3fed772f0c55 MD5 | raw file
Possible License(s): GPL-3.0
  1. <?php
  2. /******************************
  3. * WoWRoster.net Roster
  4. * Copyright 2002-2006
  5. * Licensed under the Creative Commons
  6. * "Attribution-NonCommercial-ShareAlike 2.5" license
  7. *
  8. * Short summary
  9. * http://creativecommons.org/licenses/by-nc-sa/2.5/
  10. *
  11. * Full license information
  12. * http://creativecommons.org/licenses/by-nc-sa/2.5/legalcode
  13. * -----------------------------
  14. *
  15. * $Id: rosterdkp_logparse.php 64 2007-02-11 23:36:30Z mathos $
  16. *
  17. ******************************/
  18. require_once('xml_helper.php');
  19. class ct_raidtracker
  20. {
  21. var $raid_start = '21:00'; // Either H:i or Y-m-d H:i:s
  22. var $raid_end = '00:00'; // Either H:i or Y-m-d H:i:s
  23. var $quality_threshold = 2;
  24. var $items_forced = array();
  25. var $items_ignored = array();
  26. var $looters_ignored = array();
  27. var $zone_name = ''; // Name of the zone.
  28. var $raid_note = ''; // Raid note.
  29. var $players = array(); // List of players and their attendance duration
  30. var $players_ontime = array(); // Players who where on time
  31. var $players_tillend = array(); // Players who where present end of raid
  32. var $players_ontimethreshold = null; // Date / Time of the ontime mark.
  33. var $raid_endthreshold = null; // Date / Time of the end of raid mark.
  34. var $items = array(); // Loot array
  35. var $bosses = array(); // Bosses array
  36. var $zones = array(); // Bosses array
  37. var $log = ''; // Holds the log string.
  38. var $error = ''; // Error
  39. /**
  40. * Internal data holders.
  41. */
  42. var $start = null;
  43. var $end = null;
  44. var $boss_kills = null;
  45. var $zone = null;
  46. var $raidnote = null;
  47. var $player_info = null;
  48. var $loot = null;
  49. var $joins = null;
  50. var $leaves = null;
  51. function convert_date($string)
  52. {
  53. return preg_replace('|(\d+)/(\d+)/(\d+) (\d+):(\d+):(\d+)|', '20\3-\1-\2 \4:\5:\6', $string);
  54. }
  55. function ct_raidtracker($options = array() )
  56. {
  57. $this->xml = new xml_string();
  58. if(isset($options['raid_start']))
  59. {
  60. $this->raid_start = $options['raid_start'];
  61. }
  62. if(isset($options['raid_end']))
  63. {
  64. $this->raid_end = $options['raid_end'];
  65. }
  66. if(isset($options['gap_threshold']))
  67. {
  68. $this->gap_threshold = $options['gap_threshold'];
  69. }
  70. if(isset($options['quality_threshold']))
  71. {
  72. $this->quality_threshold = $options['quality_threshold'];
  73. }
  74. if(isset($options['items_forced']))
  75. {
  76. foreach($options['items_forced'] as $v)
  77. {
  78. $this->items_forced[]=strtolower($v);
  79. }
  80. }
  81. if(isset($options['items_ignored']))
  82. {
  83. foreach($options['items_ignored'] as $v)
  84. {
  85. $this->items_ignored[]=strtolower($v);
  86. }
  87. }
  88. if(isset($options['looters_ignored'])) {
  89. foreach($options['looters_ignored'] as $v) {
  90. $this->looters_ignored[]=strtolower($v);
  91. }
  92. }
  93. }
  94. function get_zone()
  95. {
  96. $zone = $this->xml->get('zone', $this->log);
  97. if(is_object($zone))
  98. {
  99. $this->zone = $zone->get_content();
  100. }
  101. }
  102. function get_start()
  103. {
  104. $start = $this->xml->get('start', $this->log);
  105. if(is_object($start))
  106. {
  107. $this->start = $this->convert_date($start->get_content());
  108. }
  109. }
  110. function get_end()
  111. {
  112. $end = $this->xml->get('end', $this->log);
  113. if(is_object($end))
  114. {
  115. $this->end = $this->convert_date($end->get_content());
  116. }
  117. }
  118. function get_raidnote()
  119. {
  120. $raid_note = $this->xml->get('note', $this->log);
  121. if(is_object($raid_note))
  122. {
  123. $this->note = $raid_note->get_content();
  124. }
  125. }
  126. function get_bosskills()
  127. {
  128. $this->boss_kills = $this->xml->get('BossKills', $this->log);
  129. }
  130. function get_loot()
  131. {
  132. $this->loot = $this->xml->get('Loot', $this->log);
  133. }
  134. function get_joins()
  135. {
  136. $this->joins = $this->xml->get('Join', $this->log);
  137. }
  138. function get_leaves()
  139. {
  140. $this->leaves = $this->xml->get('Leave', $this->log);
  141. }
  142. function get_playerinfo()
  143. {
  144. $this->player_info = $this->xml->get('PlayerInfos', $this->log);
  145. }
  146. function parse_bosses()
  147. {
  148. $tmpbosses = array();
  149. if(is_array($this->boss_kills->children))
  150. {
  151. foreach($this->boss_kills->children as $child)
  152. {
  153. $boss = array();
  154. foreach($child->children as $i)
  155. {
  156. switch($i->tagname)
  157. {
  158. case 'name':
  159. $boss['name']=$i->get_content();
  160. break;
  161. case 'time':
  162. $boss['time']=$this->convert_date($i->get_content());
  163. break;
  164. }
  165. }
  166. $tmpbosses[$boss['time']]=$boss;
  167. }
  168. }
  169. ksort($tmpbosses);
  170. foreach($tmpbosses as $boss)
  171. {
  172. $this->bosses[$boss['name']]=$boss;
  173. }
  174. }
  175. function parse_loot()
  176. {
  177. $tmpitems = array();
  178. if(is_array($this->loot->children))
  179. {
  180. foreach($this->loot->children as $child)
  181. {
  182. $item = array();
  183. foreach($child->children as $i)
  184. {
  185. switch($i->tagname)
  186. {
  187. case 'ItemName':
  188. $item['name']=utf8_decode($i->get_content());
  189. break;
  190. case 'Color':
  191. $item['quality']=$this->get_qualitybycolor($i->get_content());
  192. break;
  193. case 'Player':
  194. $item['player']=ucfirst(strtolower(utf8_decode($i->get_content())));
  195. break;
  196. case 'Time':
  197. $item['time']=$this->convert_date($i->get_content());
  198. break;
  199. case 'Zone':
  200. $item['zone']=$i->get_content();
  201. break;
  202. case 'Boss':
  203. $item['boss']=$i->get_content();
  204. break;
  205. case 'Note':
  206. $item['note']=$i->get_content();
  207. break;
  208. }
  209. }
  210. if( ($item['quality'] >= $this->quality_threshold || in_array(strtolower($item['name']), $this->items_forced)) && !in_array(strtolower($item['name']), $this->items_ignored) && !in_array(strtolower($item['player']), $this->looters_ignored))
  211. {
  212. // Save zone if it's not known yet
  213. if(strlen($item['zone']))
  214. {
  215. if(!isset($this->zones[$item['zone']])) $this->zones[$item['zone']]=array('name' => $item['zone']);
  216. }
  217. // Save boss zone if it's not known yet
  218. if(strlen($item['boss']))
  219. {
  220. if(isset($this->bosses[$item['boss']])) $this->bosses[$item['boss']]['zone']=$item['zone'];
  221. }
  222. // Get item value if it's supplied.
  223. if(preg_match('|[-] ([0-9.]+) DKP|i', $item['note'], $match))
  224. {
  225. $item['value'] = sprintf('%0.2f', $match[1]);
  226. }
  227. else
  228. {
  229. $item['value'] = null;
  230. }
  231. $tmpitems[$item['time']]=$item;
  232. }
  233. }
  234. }
  235. ksort($tmpitems);
  236. $this->items=$tmpitems;
  237. }
  238. function parse_players()
  239. {
  240. // Get player data
  241. if(is_array($this->player_info->children))
  242. {
  243. foreach($this->player_info->children as $child)
  244. {
  245. $currentplayer = array();
  246. foreach($child->children as $element)
  247. {
  248. switch(strtolower($element->tagname))
  249. {
  250. case 'name':
  251. $currentplayer['name'] = ucfirst(strtolower(utf8_decode($element->get_content())));
  252. break;
  253. case 'class':
  254. $currentplayer['class'] = $element->get_content();
  255. break;
  256. case 'race':
  257. $currentplayer['race'] = $element->get_content();
  258. break;
  259. case 'level':
  260. $currentplayer['level'] = $element->get_content();
  261. break;
  262. }
  263. }
  264. $this->players[$currentplayer['name']] = $currentplayer;
  265. }
  266. }
  267. $joins = array();
  268. $leaves = array();
  269. // Get join data
  270. if(is_array($this->joins->children))
  271. {
  272. foreach($this->joins->children as $child)
  273. {
  274. $currentplayer = array();
  275. foreach($child->children as $element)
  276. {
  277. switch($element->tagname)
  278. {
  279. case 'player':
  280. $currentplayer['name'] = ucfirst(strtolower(utf8_decode($element->get_content())));
  281. break;
  282. case 'time':
  283. $currentplayer['time'] = $this->convert_date($element->get_content());
  284. break;
  285. }
  286. }
  287. $this->players[$currentplayer['name']]['joins'][]=$currentplayer['time'];
  288. }
  289. }
  290. // Get leave data and find latest leave time
  291. $last_leave = 0;
  292. if(is_array($this->leaves->children))
  293. {
  294. foreach($this->leaves->children as $child)
  295. {
  296. $currentplayer = array();
  297. foreach($child->children as $element)
  298. {
  299. switch($element->tagname)
  300. {
  301. case 'player':
  302. $currentplayer['name'] = ucfirst(strtolower(utf8_decode($element->get_content())));
  303. break;
  304. case 'time':
  305. $currentplayer['time'] = $this->convert_date($element->get_content());
  306. break;
  307. }
  308. }
  309. $this->players[$currentplayer['name']]['leaves'][]=$currentplayer['time'];
  310. if(strtotime($currentplayer['time']) > $last_leave) $last_leave = $currentplayer['time'];
  311. }
  312. }
  313. // Set raid end time to latest leave time if none has been recorded.
  314. if(is_null($this->end))
  315. {
  316. $this->end = date('Y-m-d H:i:s', $last_leave);
  317. }
  318. // Clean up joins and leaves.
  319. $playerNames = array_keys($this->players);
  320. foreach($playerNames as $player)
  321. {
  322. if(!is_array( $this->players[$player]['joins']))
  323. {
  324. $this->players[$player]['joins']=array();
  325. }
  326. if(!is_array( $this->players[$player]['leaves']))
  327. {
  328. $this->players[$player]['leaves']=array();
  329. }
  330. }
  331. // Calculate on time threshold value
  332. $players_ontimethreshold = strtotime(substr($this->start, 0, 10).' '.$this->raid_start);
  333. // Calculate end of raid threshold value
  334. $raid_endthreshold = strtotime(substr($this->start, 0, 10).' '.$this->raid_end);
  335. if($raid_endthreshold < $players_ontimethreshold)
  336. {
  337. $raid_endthreshold = mktime(date('H', $raid_endthreshold), date('i', $raid_endthreshold), date('s', $raid_endthreshold), date('m', $raid_endthreshold), (date('d', $raid_endthreshold) +1), date('Y', $raid_endthreshold));
  338. }
  339. $this->was_ontimeThreshold = date('Y-m-d H:i:s', $players_ontimethreshold);
  340. $this->stay_tillendThreshold = date('Y-m-d H:i:s', $raid_endthreshold);
  341. foreach($playerNames as $player)
  342. {
  343. // Get a reference to the data array.
  344. $playerdata = &$this->players[$player];
  345. $jp = array();
  346. // Sort joins and parts and remove inconsistencies.
  347. foreach($playerdata['joins'] as $j)
  348. {
  349. $time = strtotime($j);
  350. $jp[$time]='join';
  351. }
  352. foreach($playerdata['leaves'] as $j)
  353. {
  354. $time = strtotime($j);
  355. //if(isset($jp[$time]) && $jp[$time] != 'leave') $doubles[$time]='leave';
  356. if(isset($jp[$time]))
  357. {
  358. $jp[$time+1]='leave';
  359. }
  360. else
  361. {
  362. $jp[$time]='leave';
  363. }
  364. }
  365. // Remove multiples.
  366. ksort($jp);
  367. $count = 0;
  368. $keys = array_keys($jp);
  369. $joins = array();
  370. $leaves = array();
  371. $last = '';
  372. foreach($keys as $k)
  373. {
  374. if($jp[$k] == $last)
  375. {
  376. unset($jp[$k]);
  377. }
  378. else
  379. {
  380. $last=$jp[$k];
  381. }
  382. }
  383. ksort($jp);
  384. // Last one should be a leave event.
  385. if(end($jp) != 'leave')
  386. {
  387. $jp[strtotime($this->end)]='leave';
  388. }
  389. if(reset($jp) != 'join')
  390. {
  391. $jp[strtotime($this->start)]='join';
  392. }
  393. ksort($jp);
  394. foreach($jp as $k=>$v)
  395. {
  396. if($v=='join')
  397. {
  398. $joins[]=date('Y-m-d H:i:s', $k);
  399. }
  400. if($v=='leave')
  401. {
  402. $leaves[]=date('Y-m-d H:i:s', $k);
  403. }
  404. }
  405. $playerdata['oldjoins']=$playerdata['joins'];
  406. $playerdata['oldleaves']=$playerdata['leaves'];
  407. $playerdata['joins']=$joins;
  408. $playerdata['leaves']=$leaves;
  409. // Get first join and last leave timestamps
  410. $first_join = strtotime(reset($playerdata['joins']));
  411. $last_leave = strtotime(end($playerdata['leaves']));
  412. $playerdata['first_join'] = date('Y-m-d H:i:s', $first_join);
  413. $playerdata['last_leave'] = date('Y-m-d H:i:s', $last_leave);
  414. // Was the player on time?
  415. if($first_join < $players_ontimethreshold && $last_leave > $players_ontimethreshold)
  416. {
  417. $playerdata['was_ontime'] = true;
  418. }
  419. else
  420. {
  421. $playerdata['was_ontime'] = false;
  422. }
  423. // Check whether player was there at the end of the raid.
  424. if($last_leave > $raid_endthreshold && $first_join < $raid_endthreshold)
  425. {
  426. $playerdata['stay_tillend'] = true;
  427. }
  428. else
  429. {
  430. $playerdata['stay_tillend'] = false;
  431. }
  432. $totaltime = $this->get_attendancetime($playerdata, $players_ontimethreshold, $raid_endthreshold);
  433. $time = $players_ontimethreshold;
  434. while($time < $last_leave)
  435. {
  436. $hourtime = $this->get_attendancetime($playerdata, $time, ($time+3600 > $last_leave ? $last_leave : $time+3600) );
  437. $playerdata['time_perhour'][]=$hourtime;
  438. $time += 3600;
  439. }
  440. $stringtime = $this->get_time($totaltime);
  441. $playerdata['totaltime'] = $totaltime;
  442. $playerdata['stringtime'] = $stringtime;
  443. $playerdata['percentage']= round($totaltime / ($raid_endthreshold-$players_ontimethreshold) * 100);
  444. }
  445. ksort($this->players);
  446. }
  447. function get_attendancetime(&$playerdata, $start, $end)
  448. {
  449. // Cap time at thresholds.
  450. $totaltime = 0;
  451. for($i=0; $i<count($playerdata['joins']); $i++)
  452. {
  453. $j = strtotime($playerdata['joins'][$i]);
  454. $l = strtotime($playerdata['leaves'][$i]);
  455. if($l >= $start && $j <= $end)
  456. {
  457. $totaltime += ($l > $end ? $end : $l) - ($j < $start ? $start : $j);
  458. }
  459. }
  460. return $totaltime;
  461. }
  462. function get_qualitybycolor($color)
  463. {
  464. $color = strtolower($color);
  465. if($color == "ffff8000")
  466. {
  467. return 5;
  468. }
  469. elseif($color == "ffa335ee")
  470. {
  471. return 4;
  472. }
  473. elseif($color == "ff0070dd")
  474. {
  475. return 3;
  476. }
  477. elseif($color == "ff1eff00")
  478. {
  479. return 2;
  480. }
  481. elseif($color == "ffffffff")
  482. {
  483. return 1;
  484. }
  485. elseif($color == "ff9d9d9d")
  486. {
  487. return 0;
  488. }
  489. else
  490. {
  491. return false;
  492. }
  493. }
  494. function get_time($seconds)
  495. {
  496. $minutes = floor($seconds / 60);
  497. $seconds = $seconds - $minutes * 60;
  498. $hours = floor($minutes / 60);
  499. $minutes = $minutes - $hours * 60;
  500. return sprintf("%01d:%02d:%02d", $hours, $minutes, $seconds);
  501. }
  502. function process($log)
  503. {
  504. $this->log = trim(str_replace(array("\r", "\n"), '', $log));
  505. if(!preg_match('|<raidinfo>.*</raidinfo>|i', $this->log))
  506. {
  507. $this->error = 'Invalid logdata';
  508. return false;
  509. }
  510. // Convert to DOM tree
  511. $this->log = $this->xml->getRootNode($this->log);
  512. // Retrieve subtrees
  513. $this->get_start();
  514. $this->get_end();
  515. $this->get_zone();
  516. $this->get_raidnote();
  517. $this->get_bosskills();
  518. $this->get_loot();
  519. $this->get_playerinfo();
  520. $this->get_joins();
  521. $this->get_leaves();
  522. $this->parse_players();
  523. $this->parse_bosses();
  524. $this->parse_loot();
  525. return true;
  526. }
  527. }
  528. ?>