+ my $grouped = 1; # race headers
+ if (exists $get{order}) {
+ $grouped = 0;
+ $get{order} ||= '';
+ if ($get{order} eq 'size') {
+ $_->{order} = (
+ $_->{unit}*16 + ($_->{size} // $_->{suit}) + $_->{cargo}/8
+ + $_->{hp}/512 + $_->{min}/8192
+ ) for @$units;
+ }
+ elsif ($get{order} eq 'cost') {
+ $_->{order} = (
+ $_->{gas}*1.5 + $_->{min} + $_->{unit}/8 + $_->{build}/256/8
+ ) for @$units;
+ }
+ elsif ($get{order} eq 'attack') {
+ $_->{order} = $_->{hp} / 1024 + $_->{shield} / 1008 + max(
+ map {
+ ((map { ref $_ ? $_->[-1] : $_ } $_->{damage})[0])
+ * ($_->{count} // 1) / ($_->{cooldown} // 1)
+ * ($_->{splash} ? 1.01 : 1)
+ * ($_->{type} eq 'implosive' ? .96 : 1)
+ * ($_->{type} eq 'explosive' ? .98 : 1)
+ } @{ $_->{attack} }
+ ) for @$units;
+ }
+ else {
+ $units->[$_]->{order} = $_ for 0 .. $#$units;
+ }
+ }
+ my @rows = @{$units};
+ @rows = sort {$a->{order} <=> $b->{order}} @rows unless $grouped;
+
+ my ($race, $cat) = ('', '');
+ for (@rows) {
+ if ($grouped) {
+ printf '<tbody id="%s"><tr class="race"><th colspan="20"><h2>%s</h2>'."\n",
+ $race = $_->{race}, ucfirst $race
+ unless $race eq $_->{race};
+ }
+ else {
+ $_->{cat} = $_->{race};
+ }
+
+ print(
+ '<tr>',
+ '<th class="cat">', $cat ne $_->{cat} && ($cat = $_->{cat}),
+ '<td>', $_->{name},
+ showunitcols($_),
+ );
+
+ for my $subrow (@{ $_->{special} }) {
+ $subrow->{alt} or next;