#!/usr/bin/env python

# freeciv-score-log.py, a script to make some png:s out of civscore.log
# Copyright (C) 2003 Ragnar Ouchterlony
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

# Version 1.0

# Use -h to list options.
# Requires python and biggles (http://biggles.sourceforge.net/)


import getopt
import sys
import string
import time
import pprint
import biggles
import gzip

def stdout_write(text):
    global quiet
    if not quiet:
        sys.stdout.write(text)
        sys.stdout.flush()

def usage():
    print "Usage: %s [options] [FILE]"
    print
    print "  -h --help           Print this message."
    print "  -f --firstturn=NUM  The first turn to use."
    print "  -l --lastturn=NUM   The last turn."
    print "  -s --size=GEOMETRY  The size of the images [default=600x600]."
    print "  -t --tags=WORD      The tags to generate images for [default=all]."
    print "  -v --verbose        Print progress messages [default]."
    print "  -q --quiet          No messages."

try:
    opts, args = getopt.getopt(sys.argv[1:], "hf:l:s:t:q", \
                               ["help", "firstturn=", "lastturn=", "size=", "tags=", "quiet"])
except getopt.GetoptError:
    # print help information and exit:
    usage()
    sys.exit(2)

firstturn = None
lastturn  = None
size      = (600,600)
taglimit  = []
quiet     = False
for o, a in opts:
    if o in ["-h", "--help"]:
        usage()
        sys.exit()
    elif o in ["-f", "--firstturn"]:
        firstturn = int(a)
    elif o in ["-l", "--lastturn"]:
        lastturn = int(a)
    elif o in ["-s", "--size"]:
        size = [int(string.strip(x)) for x in string.split(a, "x", 1)]
    elif o in ["-t", "--tags"]:
        alist = string.split(a, ",")
        alist = [string.strip(al) for al in alist]
        taglimit += alist
    elif o in ["-v", "--verbose"]:
        quiet = False
    elif o in ["-q", "--quiet"]:
        quiet = True

if not len(args) > 0:
    args = ["civscore.log"]

try:
    f = gzip.open(args[0], 'rb')
except:
    print "Couldn't open %s." % args[0]

FCid = ""
FCtags = {}
FCturns = {}
FCplayers = {}
FCdata = {}

stdout_write("Reading data ...")
t = time.time()
lineno = 0
while 1:
    line = f.readline()
    if line == "":
        break

    lineno += 1
    if lineno % 5000 == 0:
        stdout_write(" %d" % lineno)

    if line[0] in ['\n', "#"]:
        continue

    line = line.strip()
    command, args = string.split(line, maxsplit = 1)

    if command == "id":
        FCid = args

    elif command == "tag":
        tid, descr = string.split(args, maxsplit = 1)
        tid = int(tid)
        FCtags[tid] = descr

    elif command == "turn":
        turn, num, descr = string.split(args, maxsplit = 2)
        turn = int(turn)
        num = int(num)
        FCturns[turn] = (num, descr)

    elif command == "addplayer":
        turn, pid, name = string.split(args, maxsplit = 2)
        turn = int(turn)
        pid = int(pid)
        if FCplayers.has_key(pid):
            FCplayers[pid][1].append((turn,None))
        else:
            FCplayers[pid] = (name, [(turn, None)])

    elif command == "delplayer":
        turn, pid = string.split(args, maxsplit = 1)
        turn = int(turn)
        pid = int(pid)
        if FCplayers.has_key(pid):
            begturn = FCplayers[pid][1][-1][0]
            FCplayers[pid][1][-1] = (begturn, turn)
        else:
            print "Can't delete nonexisting player."

    elif command == "data":
        turn, tid, pid, value = string.split(args, maxsplit = 3)
        turn = int(turn)
        tid = int(tid)
        pid = int(pid)
        value = float(value)

        if not FCdata.has_key(tid):
            FCdata[tid] = {}
        if not FCdata[tid].has_key(pid):
            FCdata[tid][pid] = []
        FCdata[tid][pid].append((turn,value))

stdout_write(" ... done\n")
stdout_write("Read a total of %d lines.\n" % lineno)
stdout_write("Reading data took %.2f seconds.\n" % (time.time() - t))

colorlist = {0: "red", 1: "green", 2: "blue", 3: "yellow", \
             4: "black", 5: "darkblue", 6: "brown", 7: "cyan", \
             8: "orange", 9: "gold", 10: "magenta", 11: "forest green", \
             12: "moccasin", 13: "lemon chiffon", 14: "lavender", 15: "gray"}

if firstturn != None and lastturn != None:
    filter_func = lambda d: firstturn <= d[0] <= lastturn
elif firstturn == None and lastturn != None:
    filter_func = lambda d: d[0] <= lastturn
elif firstturn != None and lastturn == None:
    filter_func = lambda d: firstturn <= d[0]
else:
    filter_func = None

t = time.time()
for tid in FCtags.keys():

    if not (len(taglimit) == 0 or FCtags[tid] in taglimit):
        continue

    filename = FCtags[tid] + ".png"
    stdout_write("Generating %s ..." % filename)

    p = biggles.FramedPlot()

    p.title = FCtags[tid]
    p.xlabel = "turn"
    p.ylabel = FCtags[tid]

    for pid in FCplayers.keys():
        stdout_write(" %d" % pid)
        if filter_func != None:
            data = filter(filter_func, FCdata[tid][pid])
        else:
            data = FCdata[tid][pid]
        if len(data) > 0:
            x, y = zip(*data)
            p.add(biggles.Curve(x, y, color=colorlist[pid]))

    stdout_write(" ... writing ...")
    p.write_img(size[0], size[1], filename)
    stdout_write(" done\n")

stdout_write("Graphic generation took %.2f seconds.\n" % (time.time() - t))
