comparison Ikariam.pm @ 101:592d3b3b7898

implemented the WAR robot
author "Rex Tsai <chihchun@kalug.linux.org.tw>"
date Wed, 29 Oct 2008 12:05:36 +0800
parents ed6160630329
children b369fe3c1992
comparison
equal deleted inserted replaced
100:ed6160630329 101:592d3b3b7898
6 } 6 }
7 7
8 use Class::DBI::AutoLoader ( 8 use Class::DBI::AutoLoader (
9 dsn => 'dbi:SQLite:dbname=ikariam.sqlite', 9 dsn => 'dbi:SQLite:dbname=ikariam.sqlite',
10 options => { RaiseError => 1 }, 10 options => { RaiseError => 1 },
11 tables => ['cities', 'island', 'user', 'ally'], 11 tables => ['cities', 'island', 'user', 'ally', 'report'],
12 use_base => 'Class::DBI::SQLite', 12 use_base => 'Class::DBI::SQLite',
13 namespace => 'Ikariam', 13 namespace => 'Ikariam',
14 ); 14 );
15 15
16 package Ikariam::Extractor; 16 package Ikariam::Extractor;
95 use HTTP::Cookies; 95 use HTTP::Cookies;
96 use WWW::Mechanize; 96 use WWW::Mechanize;
97 use HTML::TagParser; 97 use HTML::TagParser;
98 use XML::LibXML qw(:encoding); 98 use XML::LibXML qw(:encoding);
99 use IO::Uncompress::Gunzip qw(gunzip $GunzipError) ; 99 use IO::Uncompress::Gunzip qw(gunzip $GunzipError) ;
100 # use Time::ParseDate;
101 use POSIX;
100 use utf8; 102 use utf8;
101 103
102 sub new 104 sub new
103 { 105 {
104 my ($class, $server, $user, $pass) = @_; 106 my ($class, $server, $user, $pass) = @_;
175 searchUser => $user, 177 searchUser => $user,
176 view => 'highscore' 178 view => 'highscore'
177 ]); 179 ]);
178 my $extractor = new Ikariam::Extractor(content => $res->content); 180 my $extractor = new Ikariam::Extractor(content => $res->content);
179 my $result = $extractor->{doc}->find('//table[@class="table01"][2]//tr'); 181 my $result = $extractor->{doc}->find('//table[@class="table01"][2]//tr');
182
180 foreach my $tr ( @$result ) { 183 foreach my $tr ( @$result ) {
181 my %user; 184 my %user;
182 185 my $extractor = new Ikariam::Extractor(content => $tr->toString(1));
183 $extractor->{doc} = $tr; 186
184 my $href = $extractor->find('//td[@class="action"]/a/@href'); 187 my $href = $extractor->find('//td[@class="action"]/a/@href');
185 if($href =~ /index\.php\?view=sendMessage&with=(\d+)&oldView=highscore/) { 188 if($href =~ /index\.php\?view=sendMessage&with=(\d+)&oldView=highscore/) {
186 $user{'id'} = $1; 189 $user{'id'} = $1;
187 # $user{'name'} = $extractor->find('//td[@class="name"]');
188 $user{'name'} = $user; 190 $user{'name'} = $user;
191 $user{'name'} = $extractor->find('//td[@class="name"]');
189 192
190 $user{'ally'} = $extractor->find('//td[@class="allytag"]/a/text()'); 193 $user{'ally'} = $extractor->find('//td[@class="allytag"]/a/text()');
191 my $allyHref = $extractor->find('//td[@class="allytag"]/a/@href'); 194 my $allyHref = $extractor->find('//td[@class="allytag"]/a/@href');
192 if($allyHref =~ /\?view=allyPage&oldView=highscore&allyId=(\d+)/) { 195 if($allyHref =~ /\?view=allyPage&oldView=highscore&allyId=(\d+)/) {
193 $user{'allyId'} = $1; 196 $user{'allyId'} = $1;
195 $user{$type} = $extractor->find('//td[@class="score"]/text()'); 198 $user{$type} = $extractor->find('//td[@class="score"]/text()');
196 $user{$type} =~ s/,//g; 199 $user{$type} =~ s/,//g;
197 $users{$user{'id'}} = \%user; 200 $users{$user{'id'}} = \%user;
198 } 201 }
199 } 202 }
203 # print(Dumper(\%users));
200 return \%users; 204 return \%users;
201 } 205 }
202 206
203 sub viewWorldMap 207 sub viewWorldMap
204 { 208 {
410 } 414 }
411 } 415 }
412 return $out; 416 return $out;
413 } 417 }
414 418
415 sub checkCity { 419 sub plunderCity {
416 my $self = shift; 420 my $self = shift;
417 my $cityId = shift; 421 my $cityId = shift;
418 422 $self->{mech}->get(sprintf("http://%s/index.php?view=plunder&destinationCityId=%d", $self->{server}, $cityId));
419 # search for goods 423 $self->{mech}->submit_form(
424 form_number => 1,
425 fields => {
426 cargo_army_302 => '2',
427 }
428 );
429 }
430
431 sub changeCity {
432 my $self = shift;
433 my $cityId = shift;
434
420 $self->{mech}->get(sprintf("http://%s/index.php", $self->{server})); 435 $self->{mech}->get(sprintf("http://%s/index.php", $self->{server}));
421 $self->{mech}->submit_form( 436 $self->{mech}->submit_form(
422 form_number => 2, 437 form_number => 2,
423 fields => { 438 fields => {
424 cityId => $cityId, 439 cityId => $cityId,
425 } 440 }
426 ); 441 );
442 }
443
444 sub checkCity {
445 my $self = shift;
446 my $cityId = shift;
447
448 $self->changeCity($cityId);
449
427 my $res = $self->{mech}->get(sprintf("http://%s/index.php?view=city&id=%d", $self->{server}, $cityId)); 450 my $res = $self->{mech}->get(sprintf("http://%s/index.php?view=city&id=%d", $self->{server}, $cityId));
428 my $extractor = new Ikariam::Extractor(content => $res->content); 451 my $extractor = new Ikariam::Extractor(content => $res->content);
429 452
430 $self->{'cities'}->{$cityId}->{resources}->{gold} = $extractor->find('//span[@id="value_gold"]/text()'); 453 $self->{'cities'}->{$cityId}->{resources}->{gold} = $extractor->find('//span[@id="value_gold"]/text()');
431 $self->{'cities'}->{$cityId}->{resources}->{gold} =~ s/,//g; 454 $self->{'cities'}->{$cityId}->{resources}->{gold} =~ s/,//g;
476 499
477 500
478 sub checkMilitaryAdvisorMilitaryMovements { 501 sub checkMilitaryAdvisorMilitaryMovements {
479 my $self = shift; 502 my $self = shift;
480 # TODO 503 # TODO
481 # http://%s/index.php?view=militaryAdvisorMilitaryMovements
482 my $res = $self->{mech}->get(sprintf('http://%s/index.php?view=militaryAdvisorMilitaryMovements', $self->{server})); 504 my $res = $self->{mech}->get(sprintf('http://%s/index.php?view=militaryAdvisorMilitaryMovements', $self->{server}));
483 my $extractor = new Ikariam::Extractor(content => $res->content); 505 my $extractor = new Ikariam::Extractor(content => $res->content);
484 506
485 my @homeland = $extractor->find('//div[@id="homeland"]'); 507 $self->{'military'}->{wars} = 0;
486 my @elsewhere = $extractor->find('//div[@id="elsewhere"]'); 508 $self->{'military'}->{attack} = 0;
487 $self->{'military'}->{attacks} = $#elsewhere+1; 509
488 $self->{'military'}->{wars} = $#homeland+1; 510 foreach (qw/homeland elsewhere/) {
489 511 $self->{'military'}->{$_} = ();
490 # there are some details. 512 my $result = $extractor->{doc}->find(sprintf('//div[@id="%s"]//ul[@id="battleReports"]/li[@class="enroute"]', $_));
491 #<div id="homeland" class="content"> 513 foreach my $div ( @$result ) {
492 # <ul id="battleReports"> 514 my $extractor = new Ikariam::Extractor(content => $div->toString(1));
493 # <li class="groundfight"> 515 my $f = $extractor->find('//div[@class="report"]/a[1]/@href');
494 # <div class="type"/> 516 my $t = $extractor->find('//div[@class="report"]/a[2]/@href'),
495 # <div class="report"> 517 $f = $1 if($f =~ /\?view=island&cityId=(\d+)/);
496 # <table cellspacing="0" cellpadding="0" class="repTable"> 518 $t = $1 if($t =~ /\?view=island&cityId=(\d+)/);
497 # <tbody><tr> 519
498 # <th colspan="2"> 520 push @{$self->{'military'}->{$_}}, { from => $f, to => $t};
499 # 攻擊 卍严破碎虛空焱卐 </th> 521 if($_ eq 'homeland') {
500 # </tr> 522 $self->{'military'}->{wars}++;
501 # </tbody></table> 523 } else {
502 # </div> 524 $self->{'military'}->{attack}++;
503 # <br class="clearfloat"/> 525 }
504 # </li> 526 }
505 # <li class="enroute" style="height: 52px;"> 527 }
506 # <script type="text/javascript"> 528 # print(Dumper($self->{'military'}));
507 # Event.onDOMReady(function() { 529 }
508 # getCountdown({ 530
509 # enddate: 1224863393, 531 sub checkMilitaryAdvisorReportView {
510 # currentdate: 1224862910, 532 my $self = shift;
511 # el: "researchCountDown11396440" 533 my $combatId = shift;
512 # }, 3, " ", "", true, true); 534 my $res = $self->{mech}->get(sprintf('http://%s/index.php?view=militaryAdvisorReportView&detailedCombatId=%s', $self->{server}, $combatId));
513 # }); 535 my $extractor = new Ikariam::Extractor(content => $res->content);
514 # </script> 536
515 # <div class="type"> 537 my %report;
516 # <div id="researchCountDown11396440" class="time">5分 46秒</div><div class="undefined"> Finished 23:49:23</div> 538
517 # </div> 539 $report{id} = $combatId;
518 # <div class="report"> 540 my $c = $extractor->{doc}->toString(1);
519 #來自 <a href="?view=island&amp;cityId=98496">松鼠城</a> 的 3 兵力正在前往 <a href="?view=island&amp;cityId=82959">卍严破碎虛空焱卐</a> 的途中。 </div> 541
520 # <div class="action"> 542 # FIXME 城鎮 6 級)的城牆( 2 級)為防禦部隊增加了 7% 的防禦力。
521 # <div class="return"> 543 while($c =~ /城鎮\s+(\d+)/gs) {
522 # <a href="?action=transportOperations&amp;function=forceReturn&amp;actionRequest=46cc5fdb56b8cb0e65e2116ff9f61512&amp;eventId=11396440&amp;oldView=militaryAdvisorMilitaryMovements" title="返回">返回</a> 544 $report{cityLevel} = $1;
523 # </div> 545 $report{wallLevel} = $2;
524 # </div> 546 }
525 # <br class="clearfloat"/> 547
526 # </li> 548 $report{attacker} = $extractor->find('//div[@id="troopsReport"]//table[@id="result"]//th[@class="attackers"]');
527 # </ul> 549 $report{defender} = $extractor->find('//div[@id="troopsReport"]//table[@id="result"]//th[@class="defenders"]');
528 #</div> 550 $report{winner} = $extractor->find('//div[@id="troopsReport"]//table[@id="result"]//td[@class="winner"]');
529 551
530 552 $report{targetCity} = $extractor->find('//div[@id="troopsReport"]/div/h3/a/text()');
531 # <div id="elsewhere" class="content"> 553 my $href = $extractor->find('//div[@id="troopsReport"]/div/h3/a/@href');
532 # <ul id="battleReports"> 554 if($href =~ /index\.php\?view=island&id=(\d+)&selectCity=(\d+)/) {
533 # <li class="groundfight"> 555 $report{island} = $1;
534 # <div class="type"/> 556 $report{city} = $2;
535 # <div class="report"> 557 }
536 # <table cellspacing="0" cellpadding="0" class="repTable"> 558 $report{gold} = $extractor->find('//div[@id="troopsReport"]//ul[@class="resources"]/li[@class="gold"]');
537 # <tbody><tr> 559 $report{wood} = $extractor->find('//div[@id="troopsReport"]//ul[@class="resources"]/li[@class="wood"]');
538 # <th colspan="2"> 560 $report{crystal} = $extractor->find('//div[@id="troopsReport"]//ul[@class="resources"]/li[@class="glass"]');
539 # 攻擊 Rex </th> 561 $report{wine} = $extractor->find('//div[@id="troopsReport"]//ul[@class="resources"]/li[@class="wine"]');
540 # </tr> 562 $report{sulfur} = $extractor->find('//div[@id="troopsReport"]//ul[@class="resources"]/li[@class="sulfur"]');
541 # </tbody></table> 563
542 # </div> 564 foreach(qw/gold wood crystal wine sulfur attacker defender winner/) {
543 # <br class="clearfloat"/> 565 $report{$_} =~ s/^.*?:\s+//;
544 # </li> 566 $report{$_} =~ s/\s+$//;
545 # <li class="enroute"> 567 $report{$_} =~ s/,//g;
546 # <script type="text/javascript"> 568 }
547 # Event.onDOMReady(function() { 569 return \%report;
548 # getCountdown({
549 # enddate: 1224877160,
550 # currentdate: 1224861666,
551 # el: "researchCountDown159638"
552 # }, 3, " ", "", true, true);
553 # });
554 # </script>
555 # <div class="type">
556 # <div id="researchCountDown159638" class="time">4時 17分 35秒</div>
557 # </div>
558 # <div class="report">
559 #來自 <a href="?view=island&amp;cityId=6078">水晶交換各種資源</a> 的 3 兵力正在前往 <a href="?view=island&amp;cityId=6077">Rex</a> 的途中。 </div>
560 # </li>
561 # </ul>
562 # </div>
563 } 570 }
564 571
565 sub checkMilitaryAdvisorCombatReports { 572 sub checkMilitaryAdvisorCombatReports {
566 my $self = shift; 573 my $self = shift;
567 my $content; 574 my $page = shift || 0;
568 my $res = $self->{mech}->get(sprintf('http://%s/index.php?view=militaryAdvisorCombatReports', $self->{server})); 575
569 gunzip \$res->content => \$content 576 my $res = $self->{mech}->get(sprintf('http://%s/index.php?view=militaryAdvisorCombatReports&start=%s', $self->{server}, $page));
570 or die "gunzip failed: $GunzipError\n"; 577 my $extractor = new Ikariam::Extractor(content => $res->content);
571 578
572 # TODO 579 my $result = $extractor->{doc}->find('//div[@id="troopsOverview"]//table/tr[position()<=10]');
573 580 foreach my $tr ( @$result ) {
574 # list down reports. 581 my $trExtractor = new Ikariam::Extractor(content => $tr->toString(1));
575 # /index.php?view=militaryAdvisorReportView&amp;combatId=1887662 582 my $date = $trExtractor->find('//td[@class="date"]');
576 # //form[@id='finishedReports']//a 583 $date =~ s/^\s+//g; $date =~ s/\s+$//g;
584
585
586 my $href = $trExtractor->find('//td/a/@href');
587 if($href =~ /index.php\?view=militaryAdvisorReportView&combatId=(\d+)/) {
588 my $report = Ikariam::Report->retrieve($1);
589 if(!$report) {
590 my $report_hash = $self->checkMilitaryAdvisorReportView($1);
591 $report = Ikariam::Report->insert($report_hash);
592
593 if($date =~ /(\d+)\.(\d+)\. (\d+):(\d+)/) {
594 my $unixtime = mktime (0, $4, $3, $1, ($2-1), '108');
595 $report->set('date', $unixtime);
596 }
597 $report->set('time', time);
598
599 $report->update();
600 } else {
601 return;
602 }
603 } else {
604 return;
605 }
606 }
607
608 my @moreCombats = $extractor->find('//div[@id="troopsOverview"]//table/tr[position()>10]//a/@href');
609 foreach (@moreCombats){
610 last if(/^javascript/);
611 if(/\?view=militaryAdvisorCombatReports&start=(\d+)/) {
612 next if($1 le $page);
613 $self->checkMilitaryAdvisorCombatReports($1);
614 last;
615 }
616 }
577 } 617 }
578 618
579 sub checkTownHall { 619 sub checkTownHall {
580 my $self = shift; 620 my $self = shift;
581 my $cityId = shift; 621 my $cityId = shift;