PageRenderTime 55ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/tools/game/runner.py

https://github.com/honr/sumo
Python | 183 lines | 166 code | 2 blank | 15 comment | 3 complexity | f37d80b9d36000b638ced9f2b9a84946 MD5 | raw file
Possible License(s): AGPL-1.0, GPL-2.0
  1. #!/usr/bin/env python
  2. """
  3. @file runner.py
  4. @author Michael.Behrisch@dlr.de
  5. @date 2010-01-30
  6. @version $Id$
  7. This script runs the gaming GUI for the LNdW traffic light game.
  8. It checks for possible scenarios in the current working directory
  9. and lets the user start them as a game. Furthermore it
  10. saves highscores to local disc and to the central highscore server.
  11. Copyright (C) 2010 DLR/TS, Germany
  12. All rights reserved
  13. """
  14. import os, subprocess, sys, re, pickle, httplib, glob, Tkinter
  15. _SCOREFILE = "scores.pkl"
  16. _SCORESERVER = "sumo.sourceforge.net"
  17. _SCORESCRIPT = "/scores.php?game=TLS&"
  18. _DEBUG = False
  19. def loadHighscore():
  20. try:
  21. conn = httplib.HTTPConnection(_SCORESERVER)
  22. conn.request("GET", _SCORESCRIPT + "top=10")
  23. response = conn.getresponse()
  24. if response.status == httplib.OK:
  25. scores = {}
  26. for line in response.read().splitlines():
  27. category, values = line.split()
  28. scores[category] = 10*[("", "", -1.)]
  29. for idx, item in enumerate(values.split(':')):
  30. name, game, points = item.split(',')
  31. scores[category][idx] = (name, game, float(points))
  32. return scores
  33. except:
  34. pass
  35. try:
  36. return pickle.load(open(_SCOREFILE))
  37. except:
  38. pass
  39. return {}
  40. def save(idx, category, name, game, points):
  41. high[category].insert(idx, (name, game, points))
  42. high[category].pop()
  43. try:
  44. f = open(_SCOREFILE, 'w')
  45. pickle.dump(high, f)
  46. f.close()
  47. except:
  48. pass
  49. try:
  50. conn = httplib.HTTPConnection(_SCORESERVER)
  51. conn.request("GET", _SCORESCRIPT + "category=%s&name=%s&instance=%s&points=%s" % (category, name, "_".join(game), points))
  52. if _DEBUG:
  53. r1 = conn.getresponse()
  54. print r1.status, r1.reason, r1.read()
  55. except:
  56. pass
  57. class StartDialog:
  58. def __init__(self):
  59. self.root = Tkinter.Tk()
  60. self.root.title("Traffic Light Game")
  61. for cfg in glob.glob(os.path.join(base, "*.sumo.cfg")):
  62. text = category = os.path.basename(cfg)[:-9]
  63. if text == "cross":
  64. text = "Einfache Kreuzung"
  65. elif text == "square":
  66. text = "Vier Kreuzungen"
  67. Tkinter.Button(self.root, text=text, command=lambda cfg=cfg:self.ok(cfg)).pack()
  68. Tkinter.Button(self.root, text="Bestenliste loeschen", command=high.clear).pack()
  69. Tkinter.Button(self.root, text="Ende", command=sys.exit).pack()
  70. # The following three commands are needed so the window pops
  71. # up on top on Windows...
  72. self.root.iconify()
  73. self.root.update()
  74. self.root.deiconify()
  75. self.root.mainloop()
  76. def ok(self, cfg):
  77. self.root.destroy()
  78. print "starting", cfg
  79. self.ret = subprocess.call([guisimPath, "-G", "-Q", "-c", cfg])
  80. self.category = os.path.basename(cfg)[:-9]
  81. class ScoreDialog:
  82. def __init__(self, game, points, category):
  83. self.root = Tkinter.Tk()
  84. self.name = None
  85. self.game = game
  86. self.points = points
  87. self.category = category
  88. haveHigh = False
  89. self.root.title("Bestenliste")
  90. if not category in high:
  91. high[category] = 10*[("", "", -1.)]
  92. idx = 0
  93. for n, g, p in high[category]:
  94. if not haveHigh and p < points:
  95. self.name = Tkinter.Entry(self.root)
  96. self.name.grid(row=idx, sticky=Tkinter.W)
  97. self.idx = idx
  98. p = points
  99. haveHigh = True
  100. self.root.title("Glueckwunsch")
  101. else:
  102. if p == -1:
  103. break
  104. Tkinter.Label(self.root, text=n).grid(row=idx, sticky=Tkinter.W)
  105. Tkinter.Label(self.root, text=str(p)).grid(row=idx, column=1)
  106. idx += 1
  107. Tkinter.Button(self.root, text="OK", command=self.ok).grid(row=idx)
  108. self.root.grid()
  109. self.root.bind("<Return>", self.ok)
  110. self.root.grab_set()
  111. if self.name:
  112. self.name.focus_set()
  113. # The following three commands are needed so the window pops
  114. # up on top on Windows...
  115. self.root.iconify()
  116. self.root.update()
  117. self.root.deiconify()
  118. self.root.mainloop()
  119. def ok(self, event=None):
  120. if self.name:
  121. save(self.idx, self.category, self.name.get(), self.game, self.points)
  122. self.root.destroy()
  123. base = os.path.dirname(sys.argv[0])
  124. high = loadHighscore()
  125. guisimBinary = "sumo-gui"
  126. if os.name != "posix":
  127. guisimBinary += ".exe"
  128. if os.path.exists(os.path.join(base, guisimBinary)):
  129. guisimPath = os.path.join(base, guisimBinary)
  130. else:
  131. guisimPath = os.environ.get("GUISIM_BINARY", os.path.join(base, '..', '..', 'bin', guisimBinary))
  132. if not os.path.exists(guisimPath):
  133. guisimPath = guisimBinary
  134. while True:
  135. start = StartDialog()
  136. totalDistance = 0
  137. totalFuel = 0
  138. totalArrived = 0
  139. complete = True
  140. for line in open(os.path.join(base, "netstate.xml")):
  141. m = re.search('<interval begin="0(.00)?" end="([^"]*)"', line)
  142. if m and float(m.group(2)) != 180:
  143. complete = False
  144. m = re.search('sampledSeconds="([^"]*)".*speed="([^"]*)"', line)
  145. if m:
  146. totalDistance += float(m.group(1)) * float(m.group(2))
  147. m = re.search('fuel_abs="([^"]*)"', line)
  148. if m:
  149. totalFuel += float(m.group(1))
  150. m = re.search('arrived="([^"]*)"', line)
  151. if m:
  152. totalArrived += float(m.group(1))
  153. switch = []
  154. lastProg = {}
  155. for line in open(os.path.join(base, "tlsstate.xml")):
  156. m = re.search('tlsstate time="(\d+(.\d+)?)" id="([^"]*)" programID="([^"]*)"', line)
  157. if m:
  158. tls = m.group(3)
  159. program = m.group(4)
  160. if tls not in lastProg or lastProg[tls] != program:
  161. lastProg[tls] = program
  162. switch += [m.group(3), m.group(1)]
  163. score = 25000 - 100000 * totalFuel / totalDistance
  164. if _DEBUG:
  165. print switch, score, totalArrived
  166. if complete:
  167. ScoreDialog(switch, score, start.category)
  168. if start.ret != 0:
  169. sys.exit(start.ret)