#!/usr/local/bin/perl
# eval "exec /usr/local/bin/perl -S $0 $*"
#    if $running_under_some_shell;
			# this emulates #! processing on NIH machines.
			# (remove #! line above if indigestible)

# eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_]+=)(.*)/ && shift;
			# process any FOO=bar switches

#
#                               Edata
#
#                written by Ken Stevens for chainsaw 3.0
#
# DESCRIPTION:
# This script does two things.  First, it reads the output of your spy
# satellites and stores all of the information in an internal database.
# You can query the information in this database by sending commands to Edata.
#
# The other thing that this script does is it generates "bdes" commands based
# on a list you give it of one letter of the alphabet for each country.
# The "bdes" script it then writes (which you can run using "exec" in eif)
# will bdes enemy sectors to letters according to their owner.  If
# there are any land units in the sector, then it will use a capital letter.
#
# INSTALLATION:
# Before you run this script, make sure that you have typed:
# chmod +x Edata
# chmod +x dat
# chmod +x startEdata
# chmod +x endEdata
#
# HOW TO RUN IT:
# If you are going to use the "bdes" feature of Edata, then you should copy
# the "bdesinfo" file and change it to suit your needs.  For example, you
# may wish to change it so that "m" is for "Mirkwood" and "w" is for "Waffen".
#
# The next thing you will need to do is get the satellite info into a file.
# In eif you should do this by typing "sat * >! .sat".  You should
# also get the list of coutries by typing "relat >! .rel". Once you have done
# this, you are ready to try running this script.  Type:
# Edata
# Then it will say:
# <+ Edata started +>
# Now you can type "help" to get a list of commands.  The first command you
# should do is this:
# <+ Edata started +> load .sat
# where .sat contains the output of a "sat" command from empire.
# This will load the satellite data into the database.  Now you can start
# Querying the database.  Try typing "la" at the prompt.  It should list
# all the land units that your radars saw.  If you just type the co-ordinates
# for s sector, then it will tell you about that sector and list any units
# or ships in it.  You can also query sectors by owner or type or both, 
# and you can query ships and units by owner.
# 
# To create a power report, you should first load the country names into
# the database by typing:
# Edata +> rload .rel
# Where .rel contains the ouput of a "relat" command from empire.
# Now that Edata knows the country names, you can ask for a power report
# by typing "power" at the prompt.
#
# If you want to have a look at the world "coloured in" by country, then you
# will use the "bdes" feature.  Once the satellite data is loaded in, then
# load your personal bdesinfo file by typing something like this:
# Edata +> bload bdesinfo
# And then once it has read the file in, you can type "bdes" to create a 
# script for colouring your map.  The file it creates is called "bdes" and
# you can run it in eif by typing "exec bdes".
#
# Now if you have windows, you can just run Edata in one window and eif in
# the other, and you will not need to use the files "dat", "startEdata" and 
# "endEdata".  These are for people like me who play over a modem on a
# dumb terminal.  They allow you to run Edata and eif at the same time
# (through the use of a named pipe), and to access the Edata database from
# within eif.  If you want to try this, this is what you have to do:
# In your .eifrc file, put the lines:
# alias Edata "@startEdata ; @dat noprompt ; @dat load .sat ; @dat rload .rel"
# alias dat "@dat"
# Now in eif, just type "Edata", and the Edata programme will be started up 
# in the background, and if you want to send anything to it, just type
# "dat" in front of it in eif, and eif will send the command to Edata.
# For example, in eif I could type "dat la 7" to get a list of country #7's
# land units, or I could type "dat 15,3" to get the rundown on that sector.
# When you quit eif, make sure to run endEdata so that your Edata
# process shuts down.  You can do that by putting these lines in your
# .eifrc file:
# alias x "@endEdata; exit"
# alias q "@endEdata; quit"
# and then just typing "x" or "q" to exit or quit eif.
#
# BUG REPORTS:
# mail your bug-reports and comments to:
# stevens@math.utoronto.ca

$[ = 1;			# set array base to 1
$, = ' ';		# set output field separator
$\ = "\n";		# set output record separator

print $QWE;
$prompt = 'Edata +> ';
printf "\n<+ Edata started +> ";

{
  while (<>) {
    chop;
    @Cmd = split(' ', $_);
    if ($Cmd[1] eq 'noprompt') {
      $prompt = '';
    }
    elsif ($Cmd[1] eq 'help' || $Cmd[1] eq 'h' || $Cmd[1] eq '?') {
      print 'List of commands for the Edata program:';
      print 'load <filename>   Load satellite information from the file <filename>.';
      print '                  This file should contain the output of a "sat" command';

      print 'se                List all the sectors in the database.';
      print 'se <n>            List the sectors owned by country number <n>.';
      print 'sd <des>          List sectors designated as <des>.';
      print 'sd <des> <n>      List sectors designated <des> owned by <n>.';
      print 'sh                List all the ships in the database.';
      print 'sh <n>            List the ships owned by country <n>.';
      print 'la                List all the land units in the database.';
      print 'la <n>            List the land units owned by country <n>.';
      print 'power             Print a power report.';
      print '<x>,<y>           Print the info on sector <x>,<y>.';
      print 'quit              Quit this program';
      print 'bload <filename>  Load bdes info from <filename>.  This file should';
      print '                  have on each line a country number, followed by a';
      print '                  space, followed by a letter of the alphabet.';
      print 'bdes              Using the information from the bload command,';
      print '                  write a list of bdes commands to a file called "bdes".';
      print '                  These will make your bmap show who owns what sectors.';
      print 'rload <filename>  Load a file containing the output of the "relat" command';
      print '                  (This is used by the "power" command)';
      print 'noprompt          Turn off the prompt.';
    }
    elsif ($Cmd[1] eq 'quit' || $Cmd[1] eq 'q' || $Cmd[1] eq 'x') {
      exit;
    }
    elsif ($Cmd[1] eq 'load') {
      &load_data($Cmd[2]);
    }
    elsif ($Cmd[1] eq 'rload') {
      &rload_data($Cmd[2]);
    }
    elsif ($Cmd[1] eq 'bload') {
      &bload_data($Cmd[2]);
    }    
    elsif (!%st) {
      print "You must first use the \"load\" command to load data into the database.";
      printf "\n%s", $prompt;
      next;
    }
    elsif ($Cmd[1] eq 'bdes') {
      if (!%bdata) {
	print "You must first use the \"bload\" command to load the bdes data into the database.";
	printf "\n%s", $prompt;
	next;
      }
      &create_bdes();
    }
    elsif ($Cmd[1] eq 'power') {
      &print_power();
    }
    elsif ($Cmd[1] eq 'se') {
      if ($Cmd[2]) {
	@sects = sort sectsort grep($so{$_} == $Cmd[2], keys %so);
      }
      else {
	@sects = sort sectsort (keys %st);
      }
      &print_sectors();
    }
    elsif ($Cmd[1] eq 'sd') {
      if (!$Cmd[2]) {
	print "Syntax: sd <des> <n>";
      }
      elsif ($Cmd[3]) {
	@sects = sort sectsort 
	  grep($st{$_} eq $Cmd[2] && $so{$_} == $Cmd[3], keys %so);
      }
      else {
	@sects = sort sectsort grep($st{$_} eq $Cmd[2], keys %so);
      }
      &print_sectors();
    }
    elsif ($Cmd[1] eq 'sh') {
      if ($Cmd[2]) {
	@n = sort shipsort grep($ho{$_} eq $Cmd[2], keys %ho);
      }
      else {
	@n = sort shipsort (keys %ho);
      }
      &print_ships();
    }
    elsif ($Cmd[1] eq 'la') {
      if ($Cmd[2]) {
	@n = sort landsort grep($lo{$_} == $Cmd[2], keys %lo);
      }
      else {
	@n = sort landsort (keys %lo);
      }
      &print_units();
    }
    else {
      &print_sector('h');
      &print_sector($Cmd[1]);
      @n = sort shipsort grep($hs{$_} eq $Cmd[1], keys %hs);
      if ($#n) {
	&print_ships();
      }
      @n = sort landsort grep($ls{$_} eq $Cmd[1], keys %ls);
      if ($#n) {
	&print_units();
      }
    }
    if ($prompt) {
      printf "\n%s", $prompt;
    }
  }

  sub load_data {
    if (!open(_DATA, "<@_")) {
      print "Cannot open file @_.";
      return 0;
    }
    while (<_DATA>) {
      chop;
      @F = split(' ', $_);
      if (/Satellite sector report/) {
	$mode = 'sec';
      }
      if (/Satellite ship report/) {
	$mode = 'shi';
      }
      if (/Satellite unit report/) {
	$mode = 'uni';
      }
      if (/Satellite radar report/) {
	$mode = 'none';
      }

      if ($F[5] == 1994 || $F[1] eq 'sect' || $F[2] eq 'sectors' ||
	  $F[1] eq 'own' || $F[2] eq 'ships' || $F[2] eq 'units' ||
	  $F[1] eq 'Satellite' || $F[2] eq 'spysat') {
	next;
      }
      if ($mode eq 'sec' && $F[1]) {
	$st{$F[1]} = $F[2];
	$so{$F[1]} = $F[3];
	$se{$F[1]} = $F[4];
	$sc{$F[1]} = $F[5];
	$sm{$F[1]} = $F[6];
	$ss{$F[1]} = $F[7];
	$sg{$F[1]} = $F[8];
	$si{$F[1]} = $F[9];
	$sp{$F[1]} = $F[10];
	$sf{$F[1]} = $F[11];
      }
      elsif ($mode eq 'shi' && $F[1]) {
	$ho{$F[2]} = $F[1];
	$ht{$F[2]} = substr($_, 11, 38);
	@a = split(' ', substr($_, 55, 7));
	$hs{$F[2]} = $a[1];
	$he{$F[2]} = substr($_, 64, 3);
      }
      elsif ($mode eq 'uni' && $F[1]) {
	$lo{$F[2]} = $F[1];
	$Lt{$F[2]} = substr($_, 11, 18);
	@a = split(' ', substr($_, 30, 7));
	$ls{$F[2]} = $a[1];
	$Le{$F[2]} = substr($_, 38, 3);
      }
    }
    print "loaded $. lines from @_.";
    close(_DATA);
  }

  sub rload_data {
    if (!open(_RDATA, "<@_")) {
      print "Cannot open file \"@_\".";
      return 0;
    }
    while (<_RDATA>) {
      chop;
      @F = split(' ', $_);
      if (!$F[4] || $F[1] eq 'Formal' || $F[2] eq 'Diplomatic') {
	next;
      }
      chop($F[1]);
      $name{$F[1]} = substr($F[2], 1, 9);
    }
    print "loaded $. lines from \"@_\".";
    close(_RDATA);
  }

  sub bload_data {
    if (!open(_BDATA, "<@_")) {
      print "Cannot open file \"@_\".";
      return 0;
    }
    while (<_BDATA>) {
      chop;
      @F = split(' ', $_);
      foreach $b (values %bdata) {
	if ($b eq $F[2]) {
	  print "Warning:  The symbol \"$F[2]\" is multiply defined in the file \"@_\".";
	}
      }
      $bdata{$F[1]} = $F[2];
    }
    print "loaded $. lines from \"@_\".";
    close(_BDATA);
  }

  sub print_sector {
    local($S) = @_;
    if ($S eq 'h') {
      printf "%7s %4s %4s %3s %4s %4s %4s %4s %4s %4s %4s\n", 'sect',

      'type', 'own', 'eff', 'civ', 'mil', 'shl', 'gun', 'iron', 'pet',

      'food';
    }
    elsif ($st{$S}) {
      printf "%7s %4s %4d %3d %4d %4d %4d %4d %4d %4d %4d\n", $S, $st{$S},

      $so{$S}, $se{$S}, $sc{$S}, $sm{$S}, $ss{$S}, $sg{$S}, $si{$S},

      $sp{$S}, $sf{$S};
    }
    else {
      printf "sector %s not in database\n";
    }
  }

  sub print_ship {
    local($n) = @_;
    if ($n eq 'h') {
      printf "%4s %4s %-40s %7s %3s\n", 'own', 'shp#', 'ship type',

      'sector', 'eff';
    }
    elsif ($ho{$n}) {
      printf "%4s %4d %40s %7s %3d%%\n", $ho{$n}, $n, $ht{$n}, $hs{$n},

      $he{$n};
    }
    else {
      printf "ship %s not in database\n", $n;
    }
  }

  sub print_land {
    local($n) = @_;
    if ($n eq 'h') {
      printf " %4s %4s %-20s %-7s %3s\n", 'own', 'lnd#', 'unit type',

      'sector', 'eff';
    }
    elsif ($lo{$n}) {
      printf "%4d %4d %20s %7s %3d%%\n", $lo{$n}, $n, $Lt{$n}, $ls{$n},

      $Le{$n};
    }
    else {
      printf "land unit %s not in database\n", $n;
    }
  }

  sub create_bdes {
    if (!open(_BDES, ">bdes")) {
      print "Cannot create file \"bdes\".";
      return 0;
    }
    local($i) = 0;

    print "Creating file \"bdes\".";
    foreach $S (keys %so) {
      if ($bdata{$so{$S}}) {
	$bdes = $bdata{$so{$S}};
	foreach $n (keys %ls) {
	  if ($ls{$n} eq $S) {
	    $bdes = "\u$bdata{$so{$S}}";
	    last;
	  }
	}
	++$i;
	printf _BDES "bdes %s %s\n", $S, $bdes;
      }
    }
    print "$i lines written to the file \"bdes\".";
    close(_BDES);
  }

  sub print_power {
    print '         - = [   Edata Power Report   ] = -';
    print '';
    printf "%9s %4s %3s %4s %4s %5s %4s %4s %4s %4s %4s %4s %4s\n", '',
    'sects', 'eff', 'civ', 'mil', 'shell', 'gun', 'pet', 'iron', 'food',
    'oil', 'ship', 'unit';

    foreach $n (values %so) {
      $Ps{$n} = 0;
      $Pe{$n} = 0;
      $Pc{$n} = 0;
      $Pm{$n} = 0;
      $Pb{$n} = 0;
      $Pg{$n} = 0;
      $Pp{$n} = 0;
      $Pi{$n} = 0;
      $Pf{$n} = 0;
      $Po{$n} = 0;
      $Ph{$n} = 0;
      $Pl{$n} = 0;
    }
    foreach $S (keys %so) {
      $n = $so{$S};
      ++$Ps{$n};
      $Pe{$n} += $se{$S};
      $Pc{$n} += $sc{$S};
      $Pm{$n} += $sm{$S};
      $Pb{$n} += $ss{$S};
      $Pg{$n} += $sg{$S};
      $Pp{$n} += $sp{$S};
      $Pi{$n} += $si{$S};
      $Pf{$n} += $sf{$S};
      $Po{$n} += $so{$S};
    }
    foreach $x (keys %ho) {
      ++$Ph{$ho{$x}};
    }
    foreach $x (keys %lo) {
      ++$Pl{$lo{$x}};
    }
    for $n (sort {$Ps{$b} <=> $Ps{$a}} (keys %Ps)) {
      printf "%9s %4s %3s%% %4s %4s %5s %4s %4s %4s %4s %4s %4s %4s\n",
      $name{$n}?$name{$n}:$n,
      $Ps{$n}, int($Pe{$n}/$Ps{$n}), &con($Pc{$n}), &con($Pm{$n}),
      &con($Pb{$n}), &con($Pg{$n}), &con($Pp{$n}), &con($Pi{$n}),
      &con($Pf{$n}), &con($Po{$n}), &con($Ph{$n}), &con($Pl{$n});
    }
  }

  sub con {
    local($n) = @_;
    if ($n <= 999) {
      return $n;
    }
    if ($n <= 9999) {
      return sprintf("%d.%dK", int($n/1000), int($n%1000/100));
    } 
    if ($n <= 999999) {
      return sprintf("%dK", int($n/1000));
    }
    if ($n <= 9999999) {
      return sprintf("%d.%dM", int($n/1000000), int($n%1000000/100000));
    }
    if ($n <= 999999999) {
      return sprintf("%dM", int($n/1000000));
    }
    return 'huge';
  } 

  sub sectsort {
    if (@_) {
      @aa = split(',',@_[1]);
      @bb = split(',',@_[2]);
    }
    else {
      @aa = split(',',$a);
      @bb = split(',',$b);
    }
    if ($aa[2] == $bb[2]) {
      return $aa[1] <=> $bb[1];
    }
    return $aa[2] <=> $bb[2];
  }

  sub shipsort {
    if ($ho{$a} == $ho{$b}) {
      if ($hs{$a} eq $hs{$b}) {
	if ($ht{$a} eq $ht{b}) {
	  return $he{$a} <=> $he{$b};
	}
	return $ht{$a} cmp $ht{b};
      }
      return &sectsort($hs{$a},$hs{b});
    }
    return $ho{$a} <=> $ho{$b};
  }
  sub landsort {
    if ($lo{$a} == $lo{$b}) {
      if ($ls{$a} eq $ls{$b}) {
	if ($Lt{$a} eq $Lt{b}) {
	  return $Le{$a} <=> $Le{$b};
	}
	return $Lt{$a} cmp $Lt{b};
      }
      return &sectsort($ls{$a},$ls{$b});
    }
    return $lo{$a} <=> $lo{$b};
  }

  sub print_sectors {
    &print_sector('h');
    for (@sects) {
      &print_sector($_);
    }
    printf "%d sectors\n", $#sects;
  }

  sub print_units {
    &print_land('h');
    for (@n) {
      &print_land($_);
    }
    printf "%d units\n", $#n;
  }

  sub print_ships {
    &print_ship('h');
    for (@n) {
      &print_ship($_);
    }
    printf "%d ships\n", $#n;
  }
}
