tracer.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. from pypdevs.tracers.tracerBase import BaseTracer
  2. from pypdevs.util import runTraceAtController
  3. from dataclasses import dataclass
  4. import sys
  5. from de2.elements import Pool, Sailer, Clock, Scheduler
  6. class TracerPort(BaseTracer):
  7. """
  8. A tracer for port simulation output
  9. """
  10. def __init__(self, uid, server, filename):
  11. """
  12. Constructor
  13. :param uid: the UID of this tracer
  14. :param server: the server to make remote calls on
  15. :param filename: file to save the trace to, can be None for output to stdout
  16. """
  17. super(TracerPort, self).__init__(uid, server)
  18. if server.getName() == 0:
  19. self.filename = filename
  20. else:
  21. self.filename = None
  22. self.prevtime = (-1, -1)
  23. self.starting_time = 0
  24. def startTracer(self, recover):
  25. """
  26. Starts up the tracer
  27. :param recover: whether or not this is a recovery call (so whether or not the file should be appended to)
  28. """
  29. if self.filename is None:
  30. self.verb_file = sys.stdout
  31. elif isinstance(self.filename, str):
  32. if recover:
  33. self.verb_file = open(self.filename, 'a+')
  34. else:
  35. self.verb_file = open(self.filename, 'w')
  36. else:
  37. self.verb_file = self.filename
  38. def stopTracer(self):
  39. """
  40. Stop the tracer
  41. """
  42. self.verb_file.flush()
  43. def trace(self, time, text):
  44. """
  45. Actual tracing function
  46. :param time: time at which this trace happened
  47. :param text: the text that was traced
  48. """
  49. string = ""
  50. if time > self.prevtime:
  51. string = "TIME: %10.6f\n" % time[0]
  52. self.prevtime = time
  53. string += text + "\n"
  54. self.verb_file.write(string)
  55. def _vesselStr(self, vessel):
  56. # VESSEL: mmsi, name, source, target, task, total distance, distance left, velocity
  57. return "%s, %s, %s, %s, %s, %.6f, %.6f, %.6f" % vessel.tuple()
  58. def traceInternal(self, aDEVS):
  59. """
  60. Tracing done for the internal transition function
  61. :param aDEVS: the model that transitioned
  62. """
  63. if isinstance(aDEVS, Clock):
  64. par = aDEVS.parent
  65. for model in par.component_set:
  66. if isinstance(model, Pool):
  67. for vessel in model.state["waiting"].values():
  68. runTraceAtController(self.server, self.uid, aDEVS,
  69. [aDEVS.time_last, '"' + self._vesselStr(vessel) + '"'])
  70. elif isinstance(model, Sailer):
  71. for vessel in model.state["vessels"]:
  72. runTraceAtController(self.server, self.uid, aDEVS,
  73. [aDEVS.time_last, '"' + self._vesselStr(vessel) + '"'])
  74. def traceInit(self, aDEVS, t):
  75. if isinstance(aDEVS, Scheduler):
  76. self.starting_time = aDEVS.starting_time / 1000
  77. runTraceAtController(self.server, self.uid, aDEVS,
  78. [aDEVS.time_last, '"START: %10.6f"' % self.starting_time])
  79. @dataclass
  80. class StreamedVessel:
  81. mmsi: str
  82. name: str
  83. source: tuple
  84. target: tuple
  85. task: str
  86. total_distance: float
  87. distance_left: float
  88. velocity: float
  89. @staticmethod
  90. def from_str(args):
  91. vec = args.split(", ")
  92. if vec[2] == "None":
  93. st = None
  94. if vec[3] == "None":
  95. tt = None
  96. else:
  97. tt = float(vec[3][1:]), float(vec[4][:-1])
  98. else:
  99. st = float(vec[2][1:]), float(vec[3][:-1])
  100. if vec[4] == "None":
  101. tt = None
  102. else:
  103. tt = float(vec[4][1:]), float(vec[5][:-1])
  104. alist = vec[:2] + [st, tt, vec[-4]] + [float(x) for x in vec[-3:]]
  105. return StreamedVessel(*alist)
  106. class Streamer:
  107. def __init__(self):
  108. self.time = 0
  109. self.starting_time = 0
  110. self.vessels = []
  111. def write(self, text: str):
  112. # print(text, end='')
  113. texts = text.split("\n")
  114. for t in texts:
  115. if t.startswith("TIME: "):
  116. self.time = float(t[6:])
  117. self.vessels.clear()
  118. elif t.startswith("START: "):
  119. self.starting_time = float(t[7:])
  120. elif len(t) > 0:
  121. sv = StreamedVessel.from_str(t)
  122. if not any([v.mmsi == sv.mmsi for v in self.vessels]):
  123. self.vessels.append(sv)
  124. def flush(self): pass