"""
@file    statisticsElements.py
@author  Yun-Pang Wang
@author  Daniel Krajzewicz
@author  Michael Behrisch
@date    2008-07-10
@version $Id: statisticsElements.py 14677 2013-09-11 08:30:08Z behrisch $

This script is to define classes, functions, parse-reader and output files/format for
- calculating network performances
- conducting significance tests (either t-Test or Kruskal-Wallis-Test) and
- writing results into files.

SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
Copyright (C) 2008-2013 DLR (http://www.dlr.de/) and contributors

This file is part of SUMO.
SUMO 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 3 of the License, or
(at your option) any later version.
"""

import string
from xml.sax import saxutils, make_parser, handler


# This class is for storing vehicle information, such as departure time, route and travel time.
class Vehicle:
    def __init__(self, label):
        self.label = label
        self.method = None
        self.depart = 0.
        self.arrival = 0.       
        self.speed = 0.
        self.route = []
        self.traveltime = 0.
        self.travellength = 0.
        self.departdelay = 0.
        self.waittime = 0.
        self.rank = 0.

    def __repr__(self):
        return "%s_%s_%s_%s_%s_%s<%s>" % (self.label, self.depart, self.arrival, self.speed, self.traveltime, self.travellength, self.route)

# This class is used in the significance test.
class Assign:
    def __init__(self, method, totalVeh, totalTravelTime, totalTravelLength, totalDepartDelay, totalWaitTime, avgTravelTime, avgTravelLength, avgTravelSpeed, avgDepartDelay, avgWaitTime, SDTravelTime, SDLength, SDSpeed, SDWaitTime):
        self.label = method
        self.totalVeh = totalVeh
        self.totalTravelTime = totalTravelTime
        self.totalTravelLength = totalTravelLength
        self.totalDepartDelay = totalDepartDelay
        self.totalWaitTime = totalWaitTime
        self.avgTravelTime = avgTravelTime
        self.avgTravelLength = avgTravelLength
        self.avgTravelSpeed = avgTravelSpeed
        self.avgDepartDelay = avgDepartDelay
        self.avgWaitTime = avgWaitTime
        self.SDTravelTime = SDTravelTime
        self.SDLength = SDLength      
        self.SDSpeed = SDSpeed
        self.SDWaitTime = SDWaitTime
        self.sumrank = 0.
        
    def __repr__(self):
        return "%s_<%s|%s|%s|%s|%s|%s|%s|%s|%s>" % (self.label, self.totalVeh, self.avgTravelTime, self.avgTravelLength, self.avgTravelSpeed,
                                                     self.avgWaitTime, self.SDTravelTime, self.SDLength, self.SDSpeed, self.SDWaitTime)

# This cloass is used for the t test in the significance test.
class T_Value:
    def __init__(self, avgtraveltime, avgtravelspeed, avgtravellength, avgwaittime, lowvalue, highvalue):
        self.avgtraveltime = avgtraveltime
        self.avgtravelspeed = avgtravelspeed
        self.avgtravellength = avgtravellength
        self.avgwaittime = avgwaittime
        self.lowtvalue = lowvalue
        self.hightvalue = highvalue
        
    def __repr__(self):
        return "%<%s|%s|%s|%s>" % (self.avgtraveltime, self.avgtravelspeed, self.avgtravellength, self.avgwaittime)

# This class is used for the Kruskal-Wallis test in the significance test.
class H_Value:
    def __init__(self, label, lowvalue, highvalue):
        self.label = label
        self.traveltime = 0.
        self.travelspeed = 0.
        self.travellength = 0.
        self.waittime = 0.
        # 95% confidence interval
        self.lowchivalue = lowvalue 
        # 99% confidence interval
        self.highchivalue = highvalue
        
    def __repr__(self):
        return "%<%s|%s|%s|%s|%s|%s>" % (self.traveltime, self.travelspeed, self.travellength, self.waittime, self.lowchivalue, self.highchivalue)
        
# The class is for parsing the XML input file (vehicle information). This class is used in the networkStatistics.py for
# calculating the gloabal network performances, e.g. avg. travel time and avg. travel speed.
class VehInformationReader(handler.ContentHandler):
    def __init__(self, vehList):
        self._vehList = vehList
        self._Vehicle = None
        self._routeString = ''
            
    def startElement(self, name, attrs):
        if name == 'tripinfo':
            self._Vehicle = Vehicle(attrs['id'])
            self._Vehicle.traveltime = float(attrs['duration'])
            self._Vehicle.travellength = float(attrs['routeLength'])
            self._Vehicle.departdelay = float(attrs['departDelay'])
            self._Vehicle.waittime = float(attrs['departDelay']) + float(attrs['waitSteps']) 
            self._vehList.append(self._Vehicle)
           
# output the network statistics based on the sumo-simulation results
def getStatisticsOutput(assignments, outputfile):
    foutveh = file(outputfile, 'w')
    foutveh.write('average vehicular travel time(s) = the sum of all vehicular travel times / the number of vehicles\n')
    foutveh.write('average vehicular travel length(m) = the sum of all vehicular travel lengths / the number of vehicles\n')
    foutveh.write('average vehicular travel speed(m/s) = the sum of all vehicular travel speeds / the number of vehicles\n')
    for method in assignments.itervalues():
        foutveh.write('\nAssignment Method:%s\n' %method.label)
        foutveh.write('- total number of vehicles:%s\n' %method.totalVeh)
        foutveh.write('- total departure delay(s):%s, ' %method.totalDepartDelay)    
        foutveh.write('- average departure delay(s):%s\n' %method.avgDepartDelay)
        foutveh.write('- total waiting time(s):%s, ' %method.totalWaitTime)    
        foutveh.write('- average vehicular waiting time(s):%s\n' %method.avgWaitTime)
        foutveh.write('- total travel time(s):%s, ' % method.totalTravelTime)    
        foutveh.write('- average vehicular travel time(s):%s\n' %method.avgTravelTime)
        foutveh.write('- total travel length(m):%s, ' %method.totalTravelLength)
        foutveh.write('- average vehicular travel length(m):%s\n' %method.avgTravelLength)
        foutveh.write('- average vehicular travel speed(m/s):%s\n' %method.avgTravelSpeed)
    foutveh.close()
       
# output the results of the significance tests according to the sumo-simulation results
def getSignificanceTestOutput(assignments, tTest, tValueAvg, hValues, outputfile):
    foutSGtest = file(outputfile, 'w')
    if tTest:
        foutSGtest.write('The significances of the performance averages among the used assignment models are examined with the t test.\n')
        assignlist = list(assignments.itervalues())
        for num, A in enumerate(assignlist):
            for B in assignlist[num+1: ]:
                foutSGtest.write('\nmethod:%s' %A.label)
                foutSGtest.write('\nmethod:%s' %B.label)
                foutSGtest.write('\n   t-value for the avg. travel time:%s' %tValueAvg[A][B].avgtraveltime)
                foutSGtest.write('\n   t-value for the avg. travel length:%s'%tValueAvg[A][B].avgtravellength)
                foutSGtest.write('\n   t-value for the avg.travel speed:%s' %tValueAvg[A][B].avgtravelspeed)
                foutSGtest.write('\n   t-value for the avg. wait time:%s\n' %tValueAvg[A][B].avgwaittime)
                foutSGtest.write('\n95 t-value:%s' %tValueAvg[A][B].lowtvalue)
                foutSGtest.write('\n99 t-value:%s\n' %tValueAvg[A][B].hightvalue)
                
    foutSGtest.write('The significance test among the different assignment methods is also done with the Kruskal-Wallis test.\n')
    for h in hValues:
        foutSGtest.write('\n\nmethods:%s' %h.label)
        foutSGtest.write('\nH_traveltime:%s' %h.traveltime)
        foutSGtest.write('\nH_travelspeed:%s' %h.travelspeed)
        foutSGtest.write('\nH_travellength:%s' %h.travellength)
        foutSGtest.write('\nH_waittime:%s\n' %h.waittime)
        foutSGtest.write('\n95 chi-square value:%s' %h.lowchivalue)
        foutSGtest.write('\n99 chi-square value:%s\n' %h.highchivalue)
    foutSGtest.close()
