tracer.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. from pypdevs.tracers.tracerBase import BaseTracer
  2. from pypdevs.util import runTraceAtController
  3. import sys
  4. from dataclasses import dataclass
  5. from de2.elements import Pool, Sailer
  6. # TODO: Update always!
  7. class TracerPort(BaseTracer):
  8. """
  9. A tracer for port simulation output
  10. """
  11. def __init__(self, uid, server, filename):
  12. """
  13. Constructor
  14. :param uid: the UID of this tracer
  15. :param server: the server to make remote calls on
  16. :param filename: file to save the trace to, can be None for output to stdout
  17. """
  18. super(TracerPort, self).__init__(uid, server)
  19. if server.getName() == 0:
  20. self.filename = filename
  21. else:
  22. self.filename = None
  23. self.prevtime = (-1, -1)
  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, Pool):
  64. for vessel in aDEVS.state["waiting"].values():
  65. runTraceAtController(self.server, self.uid, aDEVS,
  66. [aDEVS.time_last, '"' + self._vesselStr(vessel) + '"'])
  67. elif isinstance(aDEVS, Sailer):
  68. for vessel in aDEVS.state["vessels"]:
  69. runTraceAtController(self.server, self.uid, aDEVS,
  70. [aDEVS.time_last, '"' + self._vesselStr(vessel) + '"'])
  71. def traceExternal(self, aDEVS):
  72. """
  73. Tracing done for the external transition function
  74. :param aDEVS: the model that transitioned
  75. """
  76. if isinstance(aDEVS, Pool):
  77. for vessel in aDEVS.state["waiting"].values():
  78. runTraceAtController(self.server, self.uid, aDEVS,
  79. [aDEVS.time_last, '"' + self._vesselStr(vessel) + '"'])
  80. elif isinstance(aDEVS, Sailer):
  81. for vessel in aDEVS.state["vessels"]:
  82. runTraceAtController(self.server, self.uid, aDEVS,
  83. [aDEVS.time_last, '"' + self._vesselStr(vessel) + '"'])
  84. @dataclass
  85. class StreamedVessel:
  86. mmsi: str
  87. name: str
  88. source: tuple
  89. target: tuple
  90. task: str
  91. total_distance: float
  92. distance_left: float
  93. velocity: float
  94. class Streamer:
  95. def __init__(self):
  96. self.time = 0
  97. self.starting_time = None
  98. self.vessels = []
  99. def write(self, text: str):
  100. texts = text.split("\n")
  101. for t in texts:
  102. if t.startswith("TIME: "):
  103. self.time = float(t[6:])
  104. if self.starting_time is None:
  105. self.starting_time = self.time
  106. self.vessels.clear()
  107. elif len(t) > 0:
  108. self.vessels.append(StreamedVessel(*eval(t)))
  109. def flush(self): pass