#!/usr/bin/env python
# -*- coding: Latin-1 -*-
"""
@file    TraveltimeMulti.py
@author  Sascha Krieg
@author  Daniel Krajzewicz
@author  Michael Behrisch
@date    2008-04-21
@version $Id: TraveltimeMulti.py 20433 2016-04-13 08:00:14Z behrisch $

Compares the travel time of vtypeprobe and FCD. (avg=False)

Secondly the average travel time will be calculate (avg=True). 

SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
Copyright (C) 2008-2016 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.
"""
from __future__ import absolute_import
from __future__ import print_function

from pylab import *
from analysis.Taxi import *
import util.Reader as reader
import util.Path as path
from util import CalcTime
from math import sqrt
from glob import iglob

PERC = True  # sets the view (absolute or relative)
colorTupel = ('#ff4500', '#7fff00', '#dc143c', '#ffd700', '#1e90ff', '#9932cc')
traveltimeList = []
avg = False
WEE = True


def main():
    print("start program")

    if avg:
        clacAvg()
    else:
        if PERC:
            # drawPieChart()
            drawBarChart()
        else:
            drawBarChart()
        show()

    # getBarsMulti()
    print("end")


def getPiePieces():
    """Classifies the relative time difference into pieces (intervals) used for drawing the pie chart."""
    taxis = reader.readAnalysisInfo()
    pieces = [0, 0, 0, 0, 0, 0]
    for taxi in taxis:
        try:
            diff = getTimeDiff(taxi.getSteps())
        except TypeError as e:
            print("Error by taxi %s : %s" % (taxi.id, e.message))

        # classify the relative time difference
        #<10%', '10%-30%', '30%-50%', '50%-70%', '70%-90%', '>90%
        if diff < 10:
            pieces[0] += 1
        elif diff < 30:
            pieces[1] += 1
        elif diff < 50:
            pieces[2] += 1
        elif diff < 70:
            pieces[3] += 1
        elif diff < 90:
            pieces[4] += 1
        else:
            pieces[5] += 1
    print(pieces)
    print(sum(pieces))
    return pieces


def median(vList):
    """Calculates the median value of a list."""
    try:
        if len(vList) % 2:  # unequal
            return vList[((len(vList) + 1) / 2) - 1]
        else:
            return vList[((len(vList) / 2) + 1) - 1]

    except IndexError:
        print("IndexError in 'median'")


def getBarsMulti():
    """Classifies the time difference in single bars.
     But uses insted of getBars() several analysis-File and calculates a mean value"""

    fileIter = iglob(path.newPath(
        path.main, "auswertung/reisezeit/analysisFiles/taxiAnalysisInformation*.xml"))
    fcdDiffDict = {}
    simDiffDict = {}
    barsDict = {}
    barsDictSim = {}
    stdDev = []
    mw = []
    # calc diffs
    for file in fileIter:  # for each
        path.analysisWEE = path.newPath(file)
        print(path.analysisWEE)
        taxis = reader.readAnalysisInfo(WEE)

        for taxi in taxis:
            if len(taxi.getSteps()) < 1:
                continue
            try:
                # diff=getTimeDiff(taxi.getSteps(),False)
                diffSim, fcd, sim, no = getTimeDiff(taxi.getSteps())
                simDiffDict.setdefault(taxi.id, []).append(sim)
                fcdDiffDict.setdefault(taxi.id, fcd)

            except TypeError as e:
                tueNichts = True
                # print "Error by taxi %s : %s"  %(taxi.id,e.message)

    for taxi, simList in simDiffDict.iteritems():
        simDiffDict[taxi] = sum(simList) / (len(simList) + 0.0)
    # create barsDict
    for taxi in fcdDiffDict:
        fcd = fcdDiffDict[taxi]
        sim = simDiffDict[taxi]
        diff = sim - fcd
        relDiff = int(round(((100.0 * diff) / fcd)))
        barsDictSim[
            (relDiff / 10) * 10] = barsDictSim.setdefault((relDiff / 10) * 10, 0) + 1
        # standard deviation
        stdDev.append((relDiff - 9.53) * (relDiff - 9.53))
        mw.append(relDiff)
    print("mw", sum(mw) / (len(mw) + 0.0))  # 9.91 #kor 0.48
    print("standard deviation ", sqrt(sum(stdDev) / (len(stdDev) + 0.0)))
    return (barsDictSim, barsDict)


def getBars():
    """Classifies the time difference in single bars."""
    taxis = reader.readAnalysisInfo(WEE)
    barsDict = {}
    barsDictSim = {}
    stdDev = []
    mw = []
    for taxi in taxis:
        if len(taxi.getSteps()) < 1:
            continue
        try:
            # diff=getTimeDiff(taxi.getSteps(),False)
            diffSim, fcd, sim, no = getTimeDiff(taxi.getSteps())

            # anna
            if diffSim > 150:
                print(diffSim, " ", taxi.id, " ", no, " ", fcd, " ", sim)

            # standard deviation
            stdDev.append((diffSim - 9.46) * (diffSim - 9.46))
            mw.append(diffSim)
            # classify the absolute time difference
            # barsDict[(diff/10)*10]=barsDict.setdefault((diff/10)*10,0)+1
            barsDictSim[
                (diffSim / 10) * 10] = barsDictSim.setdefault((diffSim / 10) * 10, 0) + 1
        except TypeError as e:
            tueNichts = True
            # print "Error by taxi %s : %s"  %(taxi.id,e.message)
    print("mw", sum(mw) / (len(mw) + 0.0))  # 9.46
    print("standard deviation ", sqrt(sum(stdDev) / (len(stdDev) + 0.0)))
    return (barsDictSim, barsDict)


def getTimeDiff(steps, sim=True):
    """Calculates the travel time for each source found in the steps."""
    global traveltimeList
    fcdDataNo = 0
    times = [None, None, None, None]
    getSecondEdgeSim = True
    getSecondEdgeFcd = True
    for step in steps:
        # add first and last times of fcd and vtypeprobe to the timesList
        if sim:
            source = SOURCE_SIMFCD
        else:
            source = SOURCE_VTYPE
        if step.source == source:
            if times[0] != None:
                times[1] = step.time
            else:
                if getSecondEdgeSim:
                    times[0] = step.time
                getSecondEdgeSim = True
        elif step.source == SOURCE_FCD:
            fcdDataNo += 1
            if times[2] != None:
                times[3] = step.time
            else:
                if getSecondEdgeFcd:
                    times[2] = step.time
                getSecondEdgeFcd = True
    if fcdDataNo <= 6:
        raise TypeError("not enough values")

    if (None in times and not avg) or (avg and times[2] == None or times[3] == None):
        raise TypeError("Can't calculate time difference because not all needed values are available. %s Source:%s" % (
            times, source))

    if not avg:
        # clac travel time diff
        traveltimeList.append(times[3] - times[2])
        # traveltimeList.append(times[1]-times[0])
        fcd = times[3] - times[2]
        sim = (times[1] - times[0])
        diff = sim - fcd
        if PERC:
            """
            if (times[3]-times[2])>0 and (100*diff)/(times[3]-times[2])<-1000:     
                print  "%%",(100*diff)/(times[3]-times[2])         
                print "Diff",diff
                print "fcd",(times[3]-times[2])  
                print "vtype",times[1]-times[0]
            """
            if fcd == 0:
                return 0
            else:
                return (int(round((100.0 * diff) / fcd)), fcd, sim, fcdDataNo)
        else:
            return diff
    else:  # for calc of avg
        return fcd  # FCD duration


def clacAvg():
    durationList = []
    taxis = reader.readAnalysisInfo()
    for taxi in taxis:
        try:
            dur = getTimeDiff(taxi.getSteps())
            durationList.append(dur)
            if dur >= 1479:
                print("maxtaxi", taxi)
        except TypeError as e:
            print("Error by taxi %s : %s" % (taxi.id, e.message))
    print("no", len(durationList))
    print("avg", sum(durationList) / (len(durationList) + 0.0), "s =", end=' ')
    CalcTime.getSecsInTime(
        int(round(sum(durationList) / (len(durationList) + 0.0))))
    print("min", min(durationList), "s =", end=' ')
    CalcTime.getSecsInTime(min(durationList))
    print("max", max(durationList), "s =", end=' ')
    CalcTime.getSecsInTime(max(durationList))


def drawPieChart():
    """Draws a pie chart with the relative travel time aberrance."""
    # sets the window size
    figure(1, figsize=(10, 10))

    labels = 'Diff <10%', 'Diff 10%-30%', 'Diff 30%-50%', 'Diff 50%-70%', 'Diff 70%-90%', 'Diff >90%'
    #fracs = [15,30,45, 10,66,7]

    pie(getPiePieces(), labels=labels, autopct='%1.1f%%',
        shadow=True, colors=colorTupel, labeldistance=1.2)
    title(
        "Relative Differenz der Reisezeit zwischen simulierten Taxis und Taxi-FCD\n(nicht simulierten Taxi-FCD!)\n")


def drawBarChart():
    """Draws a bar chart with the relative travel time aberrance."""
    barsDictSim, barsDict = getBarsMulti()
    xList = []
    yList = []
    xListSim = []
    yListSim = []
    under100 = 0
    over100 = 0
    simFaster = 0
    simSlower = 0
    """
    for k in sorted(barsDict.keys()):
       
       if k >100:
          over100+=0    
       elif k<-100:
           under100+=0
       else:
           xList.append(k)
           yList.append(barsDict[k])
    """
    for k in sorted(barsDictSim.keys()):
        if k >= 100:
            over100 += barsDictSim[k]
        elif k < -100:
            under100 += barsDictSim[k]
        else:
            xListSim.append(k)
            yListSim.append(barsDictSim[k])
            if k < 0:
                simSlower += barsDictSim[k]
            else:
                simFaster += barsDictSim[k]

    textsize = 18
    subplots_adjust(left=0.10, right=0.60, bottom=0.10, top=0.90)
    xticks(range(-110, 130, 20), size=textsize)
    yticks(size=textsize)
    #b=bar(xList,yList, width=10, alpha=0.5)
    bSim = bar(xListSim, yListSim, width=10, color="red", alpha=0.5)
    legend((None,), ('Taxis gesamt: ' + str(sum(barsDictSim.values())),
                     '> 0 Sim. langsammer', '< 0 Sim. schneller'), shadow=True)
    #u'\u00f8'+' Reisezeit: '+str(sum(traveltimeList)/len(traveltimeList))+'s'
    title(
        "Abweichung der Reisezeit zwischen realen und simulierten FCD", size=textsize)
    xlabel(
        '\nrelative Abweichung der Reisezeiten [%] (bei ' + str(over100) + ' Taxis > 100%)', size=textsize)
    ylabel('Anzahl der Taxis', size=textsize)


# start the program
# profile.run('main()')
main()
