#!/usr/pd/tk/bin/tclsh 
# CHANGE: The row above must be set to find your tclsh!

#
# This script checks if the infile is a valid galaxy report.
# If it's a new report the data files are updated.
# The resource file is created by <install_mailrec> and should be in your root
#
# written by Tomas Aronsson, d0malaga@dtek.chalmers.se
# last rev 941120


# This variable will be solved in a better way in the future
# As is all forecasts are saved in the same game as ggrep works on

set forematchexpr ^Subject:.*:.preprocessor.results.* 


# If the script is running under maildaemon USER is undefined
# and the incoming mail is piped into the script.
# A user is supposed to give the name of a report

if [info exists env(USER)] {
    if [expr $argc == 0] {
	puts "Usage: mailreceiver <report>";
	exit 1;
    }
    set infile [lindex $argv 0]
    set maildata [split [exec cat $infile] \012]
    set resourcefile $env(HOME)/.galaxyrsc
} else {
    set infile .mailin
    exec cat >$infile;
    set maildata [split [exec cat $infile] \012]
    set resourcefile .galaxyrsc;
}

set galaxydata [split [exec cat $resourcefile] \012];

#
# Procedures to be used by main script
#

# Splitline: Splits a string into substrings, tabs & spaces are delimiters
#
# In:  String to be splitted into substrings
# Out: List of substrings
#

proc splitline instring {
	set inlist [split $instring];
	foreach s1 $inlist {
		if [string compare "$s1" ""] {
			lappend outlist $s1;
		}
	}
	return $outlist;
}


# Buildline: builds a string by inserting \tab as delimiter between substrings
#
# In:  List of substrings
# Out: New string with substrings separated with tabs
#

proc buildline inlist {
	set outstring "";
	foreach s1 $inlist {
		lappend outstring $s1;
#		lappend outstring "  \t";
		lappend outstring " ";
	}
	return [join $outstring];
}


# Update_visitors, adds visitors to a planets data
#
# In:  playername planetnum
# Out: new player is added to planetdata
#

proc update_visitors {name num} {
    upvar planetdata loc_planetdata;

    set num [expr $num+1];
    set t2 [splitline [lindex $loc_planetdata $num]];
    set prev [lindex $t2 6];
    if [expr [string first $name $prev] == -1] {
	if [expr [string length $prev] > 1] {
	    set prev "$prev,$name";
	} else {
	    set prev $name;
	}    
    }
    set t2 [lreplace $t2 6 6 $prev];
    set loc_planetdata [lreplace $loc_planetdata $num $num [buildline $t2]];
}



# Main script
#
# This script receives mail and checks wether its a turn report or not.
# If it's a new report it's stored and analyzed, status files are updated.
# It can also be used as a report analyzer.

set status noreport;

foreach row $maildata {
    switch $status {

    noreport { 	# Check if subject matches any headers in the rsc file

	foreach g $galaxydata {
	    set matchexpr [string range $g [string first "^Subj" $g] end];
	    if [regexp $matchexpr $row t1 t2] {
		set dir [string range $g 0 [expr [string first " " $g]-1]];
	        set status getturn;
		puts $row;
		puts $dir;
		break;
	    } elseif [regexp $forematchexpr $row] {
		puts $row;
		set dir [string range $g 0 [expr [string first " " $g]-1]];
 	        exec cp $infile $dir/reports/forecast;
	        exit 0;
	    }
	}
    }


    getturn {   # Find out which turn it is and read data files

	if [regexp {[^0-z]*([0-z]+).Report.for.Galaxy.Turn.(.*)} $row t1 player turn] {
	    if [file exists $dir/reports/$turn] {
		puts "\012Report $turn already exists no files will be written\012";
		set nowrite 1;
	    } else {	
		exec cp $infile $dir/reports/$turn;
		exec cp $infile $dir/reports/latest;
	    }
	    set playerdata [split [exec cat $dir/reports/players] \012];
	    set planetdata [split [exec cat $dir/reports/planets] \012];
	    set battledata [split [exec cat $dir/reports/battles] \012];
	    set shipdata [lreplace [split [exec cat $dir/reports/ships] \012] 0 0];
	    set status identify;
	    set skipinhab 0;
	}
    }

    identify {  # Identify interesting parts of the report

	if [regexp .*N.*D.*W.*S.*C.*M.*P.* $row] {
	    puts "Status for players";
	    set status playlist;
	} elseif [regexp .*N.*D.*W.*S.*C.*M.*S.* $row] {
	    puts "Ship types for $name";
	    set status shiplist;
	} elseif [regexp .*W.*O.*#.*N.*P $row] {
	    puts "Bombings";
	    set status bomblist;
	} elseif [regexp .*N\040+#\040+X\040+Y\040+S\040+R.* $row] {
	    puts "\012Uninhabited systems\012";
	    set status planetlist;
	} elseif [regexp .*N\040+#\040+X\040+Y\040+S\040+P.* $row] {
	    if $skipinhab {
		set skipinhab 0;
	    } else {
		puts "Inhabited systems ($name)";
		set status ownerlist;
	    }
	} elseif [regexp ^\040*#.*T.*D.*W.*S.*C.*T.*Q.*M.*S.*D.*.L $row] {
	    puts "$name groups";
	    set status grouplist;
	} elseif [regexp ^.*R.*#.*T.*D.* $row] {
	    set p_battle 0;
	    set a_battle 0;
	    set max_w 0;
	    set max_s 0;
	    set status battlelist;
	} elseif [regexp {^.*Battle.at.([0-9]+)[^0-9]*} $row t1 t2] {
	    set b_planet [string trim $t2];
	    puts "Battle at $b_planet";
	} elseif [regexp {[^!-z]*([!-z]+).Groups.*} $row t1 t2] {
	    if [string compare "Your" $t2] {
		set name $t2;
	    } else {
		set name $player;
	    }	
	} elseif [regexp {[^!-z]*([!-z]+).Ship.Types.*} $row t1 t2] {
	    if [string compare "Your" $t2] {
		set name $t2;
	    } else {
		set name $player;
	    }	
	} elseif [regexp {[^!-z]*([!-z]+).Systems.*} $row t1 t2] {
	    if [string compare "Your" $t2] {
		set name $t2;
	    } else {
		set name $player;
	    }	
	} elseif [regexp ^Full.Report.on.* $row] {
	    set skipinhab 1;
	}    
	if [regexp .*O.*N.*D.*N.*R.*S.*M.* $row] {
	    puts "\012** Incoming Groups **\012";
	    set status incomelist;
	}
    }

    playlist {  # Add new players, update higher techs

	if [string length $row] {
	    set t1 [lreplace [splitline $row] 5 end $turn];
	    set name [lindex $t1 0];
	    set num [lsearch -regexp $playerdata $name.*];
	    if [expr $num == -1] {
		lappend playerdata $t1;
	    } else {
		set t2 [splitline [lindex $playerdata $num]];
		for {set i 1} {$i<5} {set i [expr $i+1]} {
		    if [expr [lindex $t2 $i] < [lindex $t1 $i]] {
			set t2 [lreplace $t2 $i $i [lindex $t1 $i]];
		    }
		}
		set t2 [buildline $t2];
		set playerdata [lreplace $playerdata $num $num $t2];
	    }
	} else {
	    set status identify;
	}
    }

    planetlist {  # Unknown planets, store size and res, set owner to unknown

	if [string length $row] {
	    set t1 [splitline $row];
	    set num [expr [lindex $t1 1]+1];
	    set size [lindex $t1 4];
	    set res [lindex $t1 5];
	    set t2 [splitline [lindex $planetdata $num]];
	    set t2 [lreplace $t2 3 5 $size $res ?];
	    set planetdata [lreplace $planetdata $num $num [buildline $t2]];
	} else {
	    set status identify;
	}
    }

    ownerlist {  # Inhabited planets, set size, res and owner

	if [string length $row] {
	    set t1 [splitline $row];
	    set num [expr [lindex $t1 1]+1];
	    set size [lindex $t1 4];
	    set res [lindex $t1 7];
	    set t2 [splitline [lindex $planetdata $num]];
	    set t2 [lreplace $t2 3 5 $size $res $name];
	    set planetdata [lreplace $planetdata $num $num [buildline $t2]];
	} else {
	    set status identify;
	}
    }

    grouplist {  # Other players groups, update vistors on planet 

	if [string length $row] {
	    set t1 [splitline $row];
	    set num [lindex $t1 [expr [llength $t1]-1]];
	    update_visitors $name $num;
	} else {
	    set status identify;
	}
    }

    shiplist {  # New shiptypes are added, old are updated

	if [string length $row] {
	    set t1 [lreplace [splitline $row] 9 end $turn];
	    set ship [lindex $t1 0];
	    set t1 [linsert $t1 0 $name];
	    set t1 [buildline $t1];
	    set num [lsearch -regexp $shipdata .*$name.*$ship.*];
	    if [expr $num == -1] {
		lappend shipdata $t1;
	    } else {
		set shipdata [lreplace $shipdata $num $num $t1];
	    }
	} else {
	    set status identify;
	}
    }

    battlelist {  # Calculate total mass, max weapon and max shield for battles

	if [string length $row] {
	    set t1 [splitline $row];
	    set num [lindex $t1 [expr [llength $t1]-2]];
	    set a_battle [expr $a_battle + [expr $num * [lindex $t1 0]]];
	    set p_battle [expr $p_battle + [expr $num * [lindex $t1 1]]];
	    set ship [lindex $t1 2];
	    set num [lsearch -regexp $shipdata .*$name.*$ship.*];
	    if [expr $num != -1] {
		set ship [lindex $shipdata $num];
		set t2 [expr [lindex $t1 4] * [lindex $ship 4]];
		if [expr $t2>$max_w] {
		    set max_w $t2;
		}
		set t2 [expr [lindex $t1 5] * [lindex $ship 5] * pow(30,0.3333)/ pow([lindex $ship 7],0.3333)];
		if [expr $t2>$max_s] {
		    set max_s $t2;
		}
	    }
	} else {
	    if [string compare $name $player] {
		update_visitors $name $b_planet;
	    }
	    lappend battledata [buildline [splitline "$turn battle $b_planet $name $p_battle $a_battle $max_w $max_s"]];
	    set status identify;
	}
    }

    incomelist {  # Incomings are NOT stored, just some info written to stdout

	if [string length $row] {
	    puts $row;
	} else {
	    puts " ";
	    set status identify;
	}
    }

    bomblist {  # Bombings are stored in the same file as battles

	if [string length $row] {
	    set t1 [splitline $row];
	    set t1 "$turn [lindex $t1 0] bombing [lindex $t1 2] [lindex $t1 1] [lindex $t1 4] [lindex $t1 5]";
	    lappend battledata [buildline [splitline $t1]];
	} else {
	    set status identify;
	}
    }
    }
}
# end of report analyzer


#
# Delete mailfile if running from maildaemon
#

if [expr ![info exists env(USER)]] {
    exec rm $infile;
}

#
# Update data files if it was a new valid report 
#
if [string compare "$status" "noreport"] {

    if [info exists nowrite] {
	puts "\012Report $turn already exists no files was written";
	exit 0;
    }

    exec mv $dir/reports/players $dir/reports/bkp$turn-players
    puts "Writing players";
    set filep [open $dir/reports/players w];
    foreach s1 $playerdata {
	puts $filep $s1;
    }
    close $filep;

    exec mv $dir/reports/planets $dir/reports/bkp$turn-planets
    puts "Writing planets";
    set filep [open $dir/reports/planets w];
    foreach s1 $planetdata {
	puts $filep $s1;
    }
    close $filep;

    exec mv $dir/reports/ships $dir/reports/bkp$turn-ships
    puts "Writing ships";
    set shipdata [lsort $shipdata];
    set filep [open $dir/reports/ships w];
    puts $filep [buildline [splitline "Player_Name D A W S C M    Speed  sh  Turn"]];
    foreach s1 $shipdata {
	puts $filep $s1;
    }
    close $filep;

    exec mv $dir/reports/battles $dir/reports/bkp$turn-battles
    puts "Writing battles";
    set filep [open $dir/reports/battles w];
    foreach s1 $battledata {
	puts $filep $s1;
    }
    close $filep;

} else {
    puts "Not a valid report";
}
exit 0;



