root/dev/common/kill_related.php @ 197

Revision 197, 13.6 KB (checked in by exi, 14 years ago)

Some improvements for the battle summary, it went down from over 1500 db queries to 270 for a battle of ~55 kills.
I also improved handling of pods when people made it on a killmail with them.
The config class now writes directly into its cache during initialization, this should bring a few milliseconds.

Line 
1<?php
2require_once('common/includes/class.page.php');
3require_once('common/includes/class.corp.php');
4require_once('common/includes/class.alliance.php');
5require_once('common/includes/class.killlist.php');
6require_once('common/includes/class.killlisttable.php');
7require_once('common/includes/class.killsummarytable.php');
8
9if (!$kll_id = intval($_GET['kll_id']))
10{
11    echo 'No valid kill id specified';
12    exit;
13}
14
15$page = new Page('Related kills & losses');
16
17// this is a fast query to get the system and timestamp
18$rqry = new DBQuery();
19$rsql = 'SELECT kll_timestamp, kll_system_id from kb3_kills where kll_id = '.$kll_id;
20$rqry->execute($rsql);
21$rrow = $rqry->getRow();
22$system = new SolarSystem($rrow['kll_system_id']);
23
24// now we get all kills in that system for +-12 hours
25$query = 'SELECT kll.kll_timestamp AS ts FROM kb3_kills kll WHERE kll.kll_system_id='.$rrow['kll_system_id'].'
26            AND kll.kll_timestamp <= date_add( \''.$rrow['kll_timestamp'].'\', INTERVAL \'12\' HOUR )
27            AND kll.kll_timestamp >= date_sub( \''.$rrow['kll_timestamp'].'\', INTERVAL \'12\' HOUR )
28            ORDER BY kll.kll_timestamp ASC';
29$qry = new DBQuery();
30$qry->execute($query);
31$ts = array();
32while ($row = $qry->getRow())
33{
34    $time = strtotime($row['ts']);
35    $ts[intval(date('H', $time))][] = $row['ts'];
36}
37
38// this tricky thing looks for gaps of more than 1 hour and creates an intersection
39$baseh = date('H', strtotime($rrow['kll_timestamp']));
40$maxc = count($ts);
41$times = array();
42for ($i = 0; $i < $maxc; $i++)
43{
44    $h = ($baseh+$i) % 24;
45    if (!isset($ts[$h]))
46    {
47        break;
48    }
49    foreach ($ts[$h] as $timestamp)
50    {
51        $times[] = $timestamp;
52    }
53}
54for ($i = 0; $i < $maxc; $i++)
55{
56    $h = ($baseh-$i) % 24;
57    if ($h < 0)
58    {
59        $h += 24;
60    }
61    if (!isset($ts[$h]))
62    {
63        break;
64    }
65    foreach ($ts[$h] as $timestamp)
66    {
67        $times[] = $timestamp;
68    }
69}
70unset($ts);
71asort($times);
72
73// we got 2 resulting timestamps
74$firstts = array_shift($times);
75$lastts = array_pop($times);
76
77$kslist = new KillList();
78$kslist->setOrdered(true);
79$kslist->addSystem($system);
80$kslist->setStartDate($firstts);
81$kslist->setEndDate($lastts);
82if (CORP_ID)
83    $kslist->addInvolvedCorp(new Corporation(CORP_ID));
84if (ALLIANCE_ID)
85    $kslist->addInvolvedAlliance(new Alliance(ALLIANCE_ID));
86
87$lslist = new KillList();
88$lslist->setOrdered(true);
89$lslist->addSystem($system);
90$lslist->setStartDate($firstts);
91$lslist->setEndDate($lastts);
92if (CORP_ID)
93    $lslist->addVictimCorp(new Corporation(CORP_ID));
94if (ALLIANCE_ID)
95    $lslist->addVictimAlliance(new Alliance(ALLIANCE_ID));
96
97$summarytable = new KillSummaryTable($kslist, $lslist);
98$summarytable->setBreak(6);
99$html .= $summarytable->generate();
100
101$klist = new KillList();
102$klist->setOrdered(true);
103$klist->addSystem($system);
104$klist->setStartDate($firstts);
105$klist->setEndDate($lastts);
106if (CORP_ID)
107    $klist->addInvolvedCorp(new Corporation(CORP_ID));
108if (ALLIANCE_ID)
109    $klist->addInvolvedAlliance(new Alliance(ALLIANCE_ID));
110
111$llist = new KillList();
112$llist->setOrdered(true);
113$llist->addSystem($system);
114$llist->setStartDate($firstts);
115$llist->setEndDate($lastts);
116if (CORP_ID)
117    $llist->addVictimCorp(new Corporation(CORP_ID));
118if (ALLIANCE_ID)
119    $llist->addVictimAlliance(new Alliance(ALLIANCE_ID));
120
121if ($_GET['scl_id'])
122{
123    $klist->addVictimShipClass(new ShipClass($_GET['scl_id']));
124    $llist->addVictimShipClass(new ShipClass($_GET['scl_id']));
125}
126
127function handle_involved($kill, $side)
128{
129    global $pilots;
130
131    // we need to get all involved pilots, killlists dont supply them
132    $qry = new DBQuery();
133    $sql = "select ind_plt_id, ind_crp_id, ind_all_id, ind_sec_status, ind_shp_id, ind_wep_id,
134            itm_name, plt_name, crp_name, all_name, shp_name, scl_points, scl_id, shp_externalid
135            from kb3_inv_detail
136            left join kb3_items on ind_wep_id=itm_id
137            left join kb3_pilots on ind_plt_id=plt_id
138            left join kb3_corps on ind_crp_id=crp_id
139            left join kb3_alliances on ind_all_id=all_id
140            left join kb3_ships on ind_shp_id=shp_id
141            left join kb3_ship_classes on shp_class=scl_id
142            where ind_kll_id = ".$kill->getID()."
143            order by ind_order";
144
145    $qry->execute($sql);
146    while ($row = $qry->getRow())
147    {
148        //$ship = new Ship($row['ind_shp_id']);
149        //$shipc = $ship->getClass();
150
151        // check for npc names (copied from pilot class)
152        $pos = strpos($row['plt_name'], "#");
153        if ($pos !== false)
154        {
155            $name = explode("#", $row['plt_name']);
156            $item = new Item($name[2]);
157            $row['plt_name'] = $item->getName();
158        }
159
160        // dont set pods as ships for pilots we already have
161        if (isset($pilots[$side][$row['ind_plt_id']]))
162        {
163            if ($row['scl_id'] == 18 || $row['scl_id'] == 2)
164            {
165                continue;
166            }
167        }
168
169        // search for ships with the same id
170        if (isset($pilots[$side][$row['ind_plt_id']]))
171        {
172            foreach ($pilots[$side][$row['ind_plt_id']] as $id => $_ship)
173            {
174                if ($row['ind_shp_id'] == $_ship['sid'])
175                {
176                    // we already got that pilot in this ship, continue
177                    continue 2;
178                }
179            }
180        }
181
182        $shipimage = IMG_URL.'/ships/32_32/'.$row['shp_externalid'].'.png';
183        $pilots[$side][$row['ind_plt_id']][] = array('name' => $row['plt_name'], 'sid' => $row['ind_shp_id'],
184               'spic' => $shipimage, 'aid' => $row['ind_all_id'], 'ts' => strtotime($kill->getTimeStamp()),
185               'corp' =>$row['crp_name'], 'alliance' => $row['all_name'], 'scl' => $row['scl_points'],
186               'ship' => $row['shp_name'], 'weapon' => $row['itm_name'], 'cid' => $row['ind_crp_id']);
187    }
188}
189
190function handle_destroyed($kill, $side)
191{
192    global $destroyed, $pilots;
193
194    $destroyed[$kill->getID()] = $kill->getVictimID();
195
196    $ship = new Ship();
197    $ship->lookup($kill->getVictimShipName());
198    $shipc = $ship->getClass();
199
200    $ts = strtotime($kill->getTimeStamp());
201
202    // mark the pilot as podded
203    if ($shipc->getID() == 18 || $shipc->getID() == 2)
204    {
205        // increase the timestamp of a podkill by 1 so its after the shipkill
206        $ts++;
207        global $pods;
208        $pods[$kill->getID()] = $kill->getVictimID();
209
210        // return when we've added him already
211        if (isset($pilots[$side][$kill->getVictimId()]))
212        {
213            #return;
214        }
215    }
216
217    // search for ships with the same id
218    if (isset($pilots[$side][$kill->getVictimId()]))
219    {
220        foreach ($pilots[$side][$kill->getVictimId()] as $id => $_ship)
221        {
222            if ($ship->getID() == $_ship['sid'])
223            {
224                $pilots[$side][$kill->getVictimId()][$id]['destroyed'] = true;
225                return;
226            }
227        }
228    }
229
230    $pilots[$side][$kill->getVictimId()][] = array('name' => $kill->getVictimName(), 'kll_id' => $kill->getID(),
231           'spic' => $ship->getImage(32), 'scl' => $shipc->getPoints(), 'destroyed' => true,
232           'corp' => $kill->getVictimCorpName(), 'alliance' => $kill->getVictimAllianceName(), 'aid' => $kill->getVictimAllianceID(),
233           'ship' => $kill->getVictimShipname(), 'sid' => $ship->getID(), 'cid' => $kill->getVictimCorpID(), 'ts' => $ts);
234}
235
236$destroyed = $pods = array();
237$pilots = array('a' => array(), 'e' => array());
238$kslist->rewind();
239$classified = false;
240while ($kill = $kslist->getKill())
241{
242    handle_involved($kill, 'a');
243    handle_destroyed($kill, 'e');
244    if ($kill->isClassified())
245    {
246        $classified = true;
247    }
248}
249$lslist->rewind();
250while ($kill = $lslist->getKill())
251{
252    handle_involved($kill, 'e');
253    handle_destroyed($kill, 'a');
254    if ($kill->isClassified())
255    {
256        $classified = true;
257    }
258}
259function cmp_func($a, $b)
260{
261    // select the biggest fish of that pilot
262    $t_scl = 0;
263    foreach ($a as $i => $ai)
264    {
265        if ($ai['scl'] > $t_scl)
266        {
267            $t_scl = $ai['scl'];
268            $cur_i = $i;
269        }
270    }
271    $a = $a[$cur_i];
272
273    $t_scl = 0;
274    foreach ($b as $i => $bi)
275    {
276        if ($bi['scl'] > $t_scl)
277        {
278            $t_scl = $bi['scl'];
279            $cur_i = $i;
280        }
281    }
282    $b = $b[$cur_i];
283
284    if ($a['scl'] > $b['scl'])
285    {
286        return -1;
287    }
288    // sort after points, shipname, pilotname
289    elseif ($a['scl'] == $b['scl'])
290    {
291        if ($a['ship'] == $b['ship'])
292        {
293            if ($a['name'] > $b['name'])
294            {
295                return 1;
296            }
297            return -1;
298        }
299        elseif ($a['ship'] > $b['ship'])
300        {
301            return 1;
302        }
303        return -1;
304    }
305    return 1;
306}
307
308function is_destroyed($pilot)
309{
310    global $destroyed;
311
312    if ($result = array_search((string)$pilot, $destroyed))
313    {
314        global $smarty;
315
316        $smarty->assign('kll_id', $result);
317        return true;
318    }
319    return false;
320}
321
322function podded($pilot)
323{
324    global $pods;
325
326    if ($result = array_search((string)$pilot, $pods))
327    {
328        global $smarty;
329
330        $smarty->assign('pod_kll_id', $result);
331        return true;
332    }
333    return false;
334}
335
336function cmp_ts_func($a, $b)
337{
338    if ($a['ts'] < $b['ts'])
339    {
340        return -1;
341    }
342    return 1;
343}
344
345// sort pilot ships, order pods after ships
346foreach ($pilots as $side => $pilot)
347{
348    foreach ($pilot as $id => $kll)
349    {
350        usort($pilots[$side][$id], 'cmp_ts_func');
351    }
352}
353
354// sort arrays, ships with high points first
355uasort($pilots['a'], 'cmp_func');
356uasort($pilots['e'], 'cmp_func');
357
358// now get the pods out and mark the ships the've flown as podded
359foreach ($pilots as $side => $pilot)
360{
361    foreach ($pilot as $id => $kll)
362    {
363        $max = count($kll);
364        for ($i = 0; $i < $max; $i++)
365        {
366            if ($kll[$i]['ship'] == 'Capsule')
367            {
368                if (isset($kll[$i-1]['sid']) && isset($kll[$i]['destroyed']))
369                {
370                    $pilots[$side][$id][$i-1]['podded'] = true;
371                    $pilots[$side][$id][$i-1]['podid'] = $kll[$i]['kll_id'];
372                    unset($pilots[$side][$id][$i]);
373                }
374                else
375                {
376                    // now sort out all pods from pilots who previously flown a real ship
377                    $valid_ship = false;
378                    foreach ($kll as $ship)
379                    {
380                        if ($ship['ship'] != 'Capsule')
381                        {
382                            $valid_ship = true;
383                            break;
384                        }
385                    }
386                    if ($valid_ship)
387                    {
388                        unset($pilots[$side][$id][$i]);
389                    }
390                }
391            }
392        }
393    }
394}
395
396$smarty->assign_by_ref('pilots_a', $pilots['a']);
397$smarty->assign_by_ref('pilots_e', $pilots['e']);
398
399$pod = new Ship(6);
400$smarty->assign('podpic', $pod->getImage(32));
401$smarty->assign('friendlycnt', count($pilots['a']));
402$smarty->assign('hostilecnt', count($pilots['e']));
403if ($classified)
404{
405    $smarty->assign('system', 'Classified System');
406}
407else
408{
409    $smarty->assign('system', $system->getName());
410}
411$smarty->assign('firstts', $firstts);
412$smarty->assign('lastts', $lastts);
413
414$html .= $smarty->fetch(get_tpl('battle_overview'));
415
416$html .= '<div class="kb-kills-header">Battle Statistics</div>';
417$html .= "<table class=kb-table width=\"100%\" border=\"0\" cellspacing=1><tr class=kb-table-row-even>";
418
419$kill_summary = new KillSummaryTable($klist, $llist);
420$summary_html = $kill_summary->generate();
421
422$html .= "<td class=kb-table-cell width=180><b>Kills:</b></td><td class=kl-kill>".$kill_summary->getTotalKills()."</td></tr>";
423$html .= "<tr class=kb-table-row-even><td class=kb-table-cell><b>Losses:</b></td><td class=kl-loss>".$kill_summary->getTotalLosses()."</td></tr>";
424$html .= "<tr class=kb-table-row-even><td class=kb-table-cell><b>Damage done (ISK):</b></td><td class=kl-kill>".round($kill_summary->getTotalKillISK()/1000000, 2)."M</td></tr>";
425$html .= "<tr class=kb-table-row-even><td class=kb-table-cell><b>Damage received (ISK):</b></td><td class=kl-loss>".round($kill_summary->getTotalLossISK()/1000000, 2)."M</td></tr>";
426if ($kill_summary->getTotalKillISK())
427{
428    $efficiency = round($kill_summary->getTotalKillISK() / ($kill_summary->getTotalKillISK() + $kill_summary->getTotalLossISK()) * 100, 2);
429}
430else
431{
432    $efficiency = 0;
433}
434
435$html .= "<tr class=kb-table-row-even><td class=kb-table-cell><b>Efficiency:</b></td><td class=kb-table-cell><b>" . $efficiency . "%</b></td></tr>";
436
437$html .= "</table>";
438$html .= "<br/>";
439
440
441$html .= "<div class=\"kb-kills-header\">Related kills</div>";
442
443$ktable = new KillListTable($klist);
444$html .= $ktable->generate();
445
446$html .= "<div class=\"kb-losses-header\">Related losses</div>";
447
448$ltable = new KillListTable($llist);
449$html .= $ltable->generate();
450
451$menubox = new Box("Menu");
452$menubox->setIcon("menu-item.gif");
453$menubox->addOption("caption", "View");
454$menubox->addOption("link", "Back to Killmail", "?a=kill_detail&kll_id=".$_GET['kll_id']);
455$menubox->addOption("link", "Kills & losses", "?a=kill_related&kll_id=".$_GET['kll_id']);
456$page->addContext($menubox->generate());
457
458$page->setContent($html);
459$page->generate();
460?>
Note: See TracBrowser for help on using the browser.