ichirin2501's diary

いっちりーん。

まだ解いてないPKUの問題を列挙するクソコード

$perl pku_tool.pl username password case pagerange
のように引数を4つ取る。
caseは 1 or 2 の数字で入力
1のとき、ACの降順
2のとき、pageごとの問題の総AC/各問題のACの値で昇順
pagerangeは 1-10 のように入力
上記だと、1〜10ページまでを計算して出力
デフォルトで上位50位まで出力させています


example:
$perl pku_tool.pl hoge pass 1 1-10

#!/usr/local/bin/perl -w

use Socket;
use strict;

my $host = 'acm.pku.edu.cn';
my $port = getservbyname('http','tcp');
my $iaddr = inet_aton($host) or die "$host is none\n";
my $sock_addr = pack_sockaddr_in($port, $iaddr);
my $username;
my $password;
my $sock;
my $setcookie;
my $case;
my $pagerange;
my ($range1,$range2);

($#ARGV+1 == 4) or die "error:\$perl ~.pl username password (case:1 or case:2) pagerange(e.g.: 1-2)\n";
$username = $ARGV[0];
$password = $ARGV[1];
$case     = $ARGV[2]; ($case==1||$case==2) or die "error:case...\n";
$pagerange= $ARGV[3];
if($pagerange=~/(\d{1,2})-(\d{1,2})/){
  ($1<=$2 && 1<=$1 && $2<=28) or die "error:pagerange...\n";
  $range1 = $1;  $range2 = $2;
}else{
  die "error:pagerange...\n";
}



socket($sock, PF_INET, SOCK_STREAM, 0) or die "error:failed socket(head)\n";
connect($sock, $sock_addr) or die "error:failed connect(head)\n";
select($sock); $|=1; select(STDOUT);
print $sock "HEAD /JudgeOnline/login HTTP/1.1\r\n";
print $sock "Host: $host\r\n";
print $sock "\r\n";
while(<$sock>){
  if( /^Set-Cookie: ([^;]+).*$/ ){
    $setcookie = $1;
    last;
  }
}
socket($sock, PF_INET, SOCK_STREAM, 0) or die "error:failed socket(post)\n";
connect($sock, $sock_addr) or die "error:failed connect(post)\n";

# after get cashe
my $postdata ="user_id1=$username&password1=$password&B1=login&url=/JudgeOnline/";

my $size = length($postdata);
my $url = "http://acm.pku.edu.cn/JudgeOnline/";

print $sock "POST /JudgeOnline/login HTTP/1.1\r\n";
print $sock "Host: $host\r\n";
print $sock "Connection: close\r\n";
print $sock "Content-Length: $size\r\n";
print $sock "Content-Type: application/x-www-form-urlencoded\r\n";
print $sock "Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n";
print $sock "Cookie: $setcookie\r\n";
print $sock "\r\n";
print $sock "$postdata";
while(<$sock>){last;}

sub get_socket{
  my ($number,$sock,$host,$setcookie) = @_;
  my $url = "/JudgeOnline/problemlist?volume=$number";

  print $sock "GET $url HTTP/1.1\r\n";
  print $sock "Host: $host\r\n";
  print $sock "Connection: close\r\n";
  print $sock "Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n";
  print $sock "Cookie: $setcookie\r\n";
  print $sock "\r\n";
}

my @data = ();
for(my $i=$range1; $i<=$range2; $i++){
  my $sum = 0;
  my @t_data = ();
  
  socket($sock, PF_INET, SOCK_STREAM, 0) or die "error:failed socket(get)\n";
  connect($sock, $sock_addr) or die "error:failed connect(get)\n";
  &get_socket($i,$sock,$host,$setcookie);
  while(<$sock>){
    if( /^<tr align=center>(<td>(.*)<\/td>){0,1}<td>(\d{4})<\/td><td align=left><a lang="en-US" href=problem\?id=\d{4}>(.+)<\/a><\/td><td>(.{1,4})\(<a href=problemstatus\?problem_id=\d{4}>(\d+)<\/a>\/<a href=status\?problem_id=\d{4}>(\d+)<\/a>\)<\/td><td>\d{4}-\d{1,2}-\d{1,2}<\/td><\/tr>$/ ){

      defined($1) or die "error: login failed(may...)\n";
      if( $2 eq "" or $2 eq "<img src=images/wrong.gif>" ){
        #print "yes: _$1 _$2 _$3 $4 $5/$6 $7\n";
        push(@t_data,{'num'=>$3,'name'=>$4,'cent'=>$5,'b'=>$6,'a'=>$7,'cost'=>0})
      }
      $sum += $6;
    }
  }
  for my $i (0..$#t_data){
    if( $t_data[$i]{'b'} == 0 ){ $t_data[$i]{'b'} = 1; }
    
    if   ( $case==2 ){ $t_data[$i]{'cost'} = $sum/$t_data[$i]{'b'}; }
    elsif( $case==1 ){ $t_data[$i]{'cost'} = -$t_data[$i]{'b'}; }
  }
  push(@data,@t_data);
}

@data = sort{$a->{'cost'} <=> $b->{'cost'}} @data;
for my $i (0..49){
  printf("%3d: %4d, %4s, %d/%d, %s\n",$i+1,$data[$i]{'num'},
          $data[$i]{'cent'},$data[$i]{'b'},$data[$i]{'a'},$data[$i]{'name'});
}