3 # no warranty for this script
9 use FindBin; use lib $FindBin::Bin;
10 use WeaponEncounterProfile;
12 my ($statsfile) = @ARGV;
17 $stats = WeaponEncounterProfile->new($statsfile);
27 my @bigmatrix = map { [ @{$m->[$_]}, $v->[$_] ] } 0..$n-1;
32 # first: bring the highest value to the top
37 my $v = $bigmatrix[$j]->[$i];
38 if($v*$v > $bestval*$bestval)
44 die "lindep" if $best == -1;
47 ($bigmatrix[$i], $bigmatrix[$best]) = ($bigmatrix[$best], $bigmatrix[$i]);
52 my $r = $bigmatrix[$j]->[$i];
55 $bigmatrix[$j]->[$k] -= $bigmatrix[$i]->[$k] * $r / $bestval;
61 for my $i(reverse 0..$n-1)
63 my $bestval = $bigmatrix[$i]->[$i];
66 my $r = $bigmatrix[$j]->[$i];
69 $bigmatrix[$j]->[$k] -= $bigmatrix[$i]->[$k] * $r / $bestval;
74 # 3. Read off solutions
75 return map { $bigmatrix[$_]->[$n] / $bigmatrix[$_]->[$_] } 0..($n-1);
78 sub SolveBestSquares($$)
93 my $weight = $w->[$i]->[$j];
94 $num += $weight * $d->[$i]->[$j];
97 push @result, $num / $denom;
102 # build linear equation system
104 my @matrix = map { [ map { 0 } 1..$n ] } 1..$n;
105 my @vector = map { 0 } 1..$n;
116 $matrix[$z][$i] += $w->[$i]->[$z];
117 $matrix[$z][$z] -= $w->[$i]->[$z];
118 $vector[$z] += $w->[$i]->[$z] * $d->[$i]->[$z];
122 return LinSolve(\@matrix, \@vector);
129 while(my ($k, $v) = each %$matrix)
131 for(my ($k2, $v2) = each %$v)
139 delete $allweps{"@!#%'n Tuba"};
140 #delete $allweps{"Port-O-Launch"};
141 my @allweps = keys %allweps;
144 my @dmatrix = map { [ map { 0 } @allweps ] } @allweps;
145 my @wmatrix = map { [ map { 0 } @allweps ] } @allweps;
147 for my $i(0..@allweps - 1)
149 my $attackweapon = $allweps[$i];
152 for my $j(0..@allweps - 1)
154 my $defendweapon = $allweps[$j];
155 next if $attackweapon eq $defendweapon;
156 my $win = ($matrix->{$attackweapon}{$defendweapon} || 0);
157 my $lose = ($matrix->{$defendweapon}{$attackweapon} || 0);
158 my $c = ($win + $lose);
161 my $w = 1 - 1/($c * 0.1 + 1);
163 $dmatrix[$i][$j] = $p - (1 - $p); # antisymmetric
164 $wmatrix[$i][$j] = $w; # symmetric
171 @val = SolveBestSquares(\@dmatrix, \@wmatrix);
176 @val = map { undef } @allweps;
179 for my $i(0..@allweps - 1)
181 my $attackweapon = $allweps[$i];
182 $values{$attackweapon} = $val[$i];
189 my ($event, @data) = @_;
190 if($event eq 'start')
193 elsif($event eq 'startmatrix')
195 my ($addr, $map, @columns) = @data;
198 print "For server @{[$addr || 'any']} map @{[$map || 'any']}:\n";
200 elsif($event eq 'startrow')
202 my ($row, $val) = @data;
203 printf " %-30s %8s |", $row, defined $val ? sprintf("%8.5f", $val) : "N/A";
205 elsif($event eq 'cell')
207 my ($win, $lose, $p) = @data;
218 printf " %+6.3f", $p;
221 elsif($event eq 'endrow')
225 elsif($event eq 'endmatrix')
229 print " Relevance: $min\n";
232 elsif($event eq 'end')
236 print " Relevance: $min\n";
241 my $out = \&out_text;
247 my ($addr, $map, $data) = @_;
248 my $values = Evaluate $data;
249 my $valid = defined [values %$values]->[0];
250 my @weapons_sorted = sort { $valid ? $values->{$b} <=> $values->{$a} : $a cmp $b } keys %$values;
252 $out->(startmatrix => ($addr, $map, @weapons_sorted));
253 for my $row(@weapons_sorted)
255 $out->(startrow => $row, ($valid ? $values->{$row} : undef));
256 for my $col(@weapons_sorted)
258 my $win = ($data->{$row}{$col} || 0);
259 my $lose = ($data->{$col}{$row} || 0);
261 if $row ne $col and (not defined $min or $min > $win + $lose);
262 $out->(cell => ($win, $lose, (($row ne $col) && ($win + $lose)) ? (2 * $win / ($win + $lose) - 1) : undef));
264 $out->(endrow => ());
266 $out->(endmatrix => ($addr, $min));