1#!/usr/local/bin/python3.8
2# -*- coding: utf-8 -*-
3# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
4# Copyright (C) 2012-2019 German Aerospace Center (DLR) and others.
5# This program and the accompanying materials
6# are made available under the terms of the Eclipse Public License v2.0
7# which accompanies this distribution, and is available at
8# http://www.eclipse.org/legal/epl-v20.html
9# SPDX-License-Identifier: EPL-2.0
10
11# @file    analyze_teleports.py
12# @author  Jakob Erdmann
13# @author  Michael Behrisch
14# @date    2012-11-20
15# @version $Id$
16
17from __future__ import absolute_import
18from __future__ import print_function
19import sys
20import re
21from collections import defaultdict
22
23
24def parse_log(logfile, edges=True, aggregate=3600):
25    print("Parsing %s" % logfile)
26    reFrom = re.compile("lane='([^']*)'")
27    reFromMeso = re.compile("edge '([^']*)'")
28    reTime = re.compile("time.(\d*)\.")
29    reHRTime = re.compile("time.(\d):(\d\d):(\d\d):(\d*).")
30    # counts per lane
31    waitingCounts = defaultdict(lambda: 0)
32    collisionCounts = defaultdict(lambda: 0)
33    # counts per step
34    waitingStepCounts = defaultdict(lambda: 0)
35    collisionStepCounts = defaultdict(lambda: 0)
36    for index, line in enumerate(open(logfile)):
37        try:
38            if "Warning: Teleporting vehicle" in line:
39                # figure out whether its micro or meso
40                match = reFrom.search(line)
41                if match is None:
42                    edge = reFromMeso.search(line).group(1)
43                else:
44                    edge = match.group(1)
45                    if edges:
46                        edge = edge[:-2]
47                timeMatch = reTime.search(line)
48                if timeMatch:
49                    time = int(timeMatch.group(1))
50                else:
51                    timeMatch = reHRTime.search(line)
52                    time = (24 * 3600 * int(timeMatch.group(1))
53                            + 3600 * int(timeMatch.group(2))
54                            + 60 * int(timeMatch.group(3))
55                            + int(timeMatch.group(4)))
56                if "collision" in line:
57                    collisionCounts[edge] += 1
58                    collisionStepCounts[time / aggregate] += 1
59                else:
60                    waitingCounts[edge] += 1
61                    waitingStepCounts[time / aggregate] += 1
62        except Exception:
63            print(sys.exc_info())
64            sys.exit("error when parsing line '%s'" % line)
65        if index % 1000 == 0:
66            sys.stdout.write(".")
67            sys.stdout.flush()
68    print()
69    print("read %s lines" % index)
70
71    return (waitingCounts, collisionCounts,
72            waitingStepCounts, collisionStepCounts)
73
74
75def print_counts(countDict, label, num=10):
76    counts = sorted(countDict.items(), key=lambda k: -k[1])
77    print(label, "worst %s edges: " % num, counts[:num])
78    print(label, 'total:', sum(countDict.values()))
79
80
81def main(logfile):
82    waitingCounts, collisionCounts, waitingStepCounts, collisionStepCounts = parse_log(logfile)
83    print_counts(waitingCounts, 'waiting')
84    print_counts(collisionCounts, 'collisions')
85    # generate plot
86    if len(waitingStepCounts) + len(collisionStepCounts) > 0:
87        min_step = min(waitingStepCounts.keys() + collisionStepCounts.keys())
88        max_step = max(waitingStepCounts.keys() + collisionStepCounts.keys())
89        plotfile = logfile + '.plot'
90        with open(plotfile, 'w') as f:
91            f.write(("# plot '%s' using 1:2 with lines title 'waiting', '%s' using 1:3 with lines title " +
92                     "'collisions'\n") % (plotfile, plotfile))
93            for step in range(min_step, max_step + 1):
94                print(' '.join(
95                    map(str, [step, waitingStepCounts[step], collisionStepCounts[step]])), file=f)
96    with open(logfile + "data.xml", 'w') as f:
97        print('<meandata>\n    <interval begin="0" end="100:00:00:00">', file=f)
98        for item in waitingCounts.items():
99            print('        <edge id="%s" waiting_teleport="%s"/>' % item, file=f)
100        print("    </interval>\n</meandata>", file=f)
101
102
103if __name__ == "__main__":
104    main(*sys.argv[1:])
105