prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Change the way the UI receives game updates
  The UI currently polls the frontend server constantly for updates.
  
  Implement a solution where the _game simulation_ server pushes updates instead - e.g. using web sockets (or some other better solution that you can think of!)
  
  Possible server-side solutions:
  1. client ==> proxy (on Kubernetes) ==> game simulation (on Kubernetes)
  Here we only need one public IP address for the proxy, no matter how many game simulation servers we spawn.
  1. client ==> game simulation (on Kubernetes)
     We need a public IP address per game simulation. We need to investigate whether this would be a problem (e.g. can't be done dynamically, or is expensive).
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `aimmo-game/simulation/turn_manager.py`
  Content:
  ```
  1 import logging
  2 import requests
  3 import threading
  4 import time
  5 from threading import Lock
  6 from simulation import world_map
  7 from simulation.action import ACTIONS
  8 
  9 LOGGER = logging.getLogger(__name__)
  10 
  11 
  12 class WorldStateProvider:
  13     """
  14     Thread-safe container for the world state.
  15 
  16     TODO: think about changing to snapshot rather than lock?
  17     """
  18 
  19     def __init__(self):
  20         self._world_state = None
  21         self._lock = Lock()
  22 
  23     def lock_and_get_world(self):
  24         self._lock.acquire()
  25         return self._world_state
  26 
  27     def release_lock(self):
  28         self._lock.release()
  29 
  30     def set_world(self, new_world_state):
  31         self._lock.acquire()
  32         self._world_state = new_world_state
  33         self._lock.release()
  34 
  35 world_state_provider = WorldStateProvider()
  36 
  37 
  38 class TurnManager(threading.Thread):
  39     """
  40     Game loop
  41     """
  42     daemon = True
  43 
  44     def __init__(self, game_state):
  45         world_state_provider.set_world(game_state)
  46         super(TurnManager, self).__init__()
  47 
  48     def _update_environment(self, game_state):
  49         num_avatars = len(game_state.avatar_manager.active_avatars)
  50         game_state.world_map.reconstruct_interactive_state(num_avatars)
  51 
  52     def run_turn(self):
  53         try:
  54             game_state = world_state_provider.lock_and_get_world()
  55 
  56             for avatar in game_state.avatar_manager.active_avatars:
  57                 turn_state = game_state.get_state_for(avatar)
  58                 try:
  59                     data = requests.post(avatar.worker_url, json=turn_state).json()
  60                 except ValueError as err:
  61                     LOGGER.info("Failed to get turn result: %s", err)
  62                 else:
  63                     try:
  64                         action_data = data['action']
  65                         action = ACTIONS[action_data['action_type']](**action_data.get('options', {}))
  66                     except (KeyError, ValueError) as err:
  67                         LOGGER.info("Bad action data supplied: %s", err)
  68                     else:
  69                         action.apply(game_state, avatar)
  70 
  71             self._update_environment(game_state)
  72 
  73         finally:
  74             world_state_provider.release_lock()
  75 
  76     def run(self):
  77         while True:
  78             self.run_turn()
  79             time.sleep(0.5)
  80
  ```
  
  Path: `setup.py`
  Content:
  ```
  1 # -*- coding: utf-8 -*-
  2 from setuptools import find_packages, setup
  3 
  4 setup(name='aimmo',
  5     packages=find_packages(),
  6     include_package_data=True,
  7     install_requires = [
  8         'django >= 1.8.3, < 1.9.0',
  9         'django-autoconfig >= 0.3.6, < 1.0.0',
  10         'django-js-reverse',
  11         'flask',
  12         'flask-cors',
  13         'requests',
  14     ],
  15     tests_require=[
  16         'django-setuptest',
  17     ],
  18     test_suite='setuptest.setuptest.SetupTestSuite',
  19     version='0.0.0',
  20     zip_safe=False,
  21 )
  22
  ```
  
  Path: `aimmo-game/service.py`
  Content:
  ```
  1 #!/usr/bin/env python
  2 import logging
  3 
  4 import flask
  5 from flask.ext.cors import CORS
  6 
  7 from simulation.turn_manager import world_state_provider
  8 from simulation import map_generator
  9 from simulation.avatar.avatar_manager import AvatarManager
  10 from simulation.game_state import GameState
  11 from simulation.turn_manager import TurnManager
  12 from simulation.worker_manager import LocalWorkerManager
  13 
  14 app = flask.Flask(__name__)
  15 CORS(app)
  16 
  17 
  18 def to_cell_type(cell):
  19     if not cell.habitable:
  20         return 1
  21     if cell.generates_score:
  22         return 2
  23     return 0
  24 
  25 
  26 def player_dict(avatar):
  27     # TODO: implement better colour functionality: will eventually fall off end of numbers
  28     colour = "#%06x" % (avatar.player_id * 4999)
  29     return {
  30         'id': avatar.player_id,
  31         'x': avatar.location.x,
  32         'y': avatar.location.y,
  33         'health': avatar.health,
  34         'score': avatar.score,
  35         'rotation': 0,
  36         "colours": {
  37             "bodyStroke": "#0ff",
  38             "bodyFill": colour,
  39             "eyeStroke": "#aff",
  40             "eyeFill": "#eff",
  41         }
  42     }
  43 
  44 
  45 @app.route('/')
  46 def get_world_state():
  47     try:
  48         world = world_state_provider.lock_and_get_world()
  49         num_cols = len(world.world_map.grid)
  50         num_rows = len(world.world_map.grid[0])
  51         grid = [[None for x in xrange(num_cols)] for y in xrange(num_rows)]
  52         for cell in world.world_map.all_cells():
  53             grid[cell.location.x][cell.location.y] = to_cell_type(cell)
  54         player_data = {p.player_id: player_dict(p) for p in world.avatar_manager.avatars}
  55         return flask.jsonify(
  56             players=player_data,
  57             score_locations=[(cell.location.x, cell.location.y) for cell in world.world_map.score_cells()],
  58             pickup_locations=[(cell.location.x, cell.location.y) for cell in world.world_map.pickup_cells()],
  59             map_changed=True,  # TODO: experiment with only sending deltas (not if not required)
  60             width=num_cols,
  61             height=num_rows,
  62             layout=grid,
  63         )
  64     finally:
  65         world_state_provider.release_lock()
  66 
  67 
  68 def run_game():
  69     print("Running game...")
  70     my_map = map_generator.generate_map(15, 15, 0.1)
  71     player_manager = AvatarManager()
  72     game_state = GameState(my_map, player_manager)
  73     turn_manager = TurnManager(game_state=game_state)
  74     worker_manager = LocalWorkerManager(game_state=game_state, users_url='http://localhost:8000/players/api/games/')
  75     worker_manager.start()
  76     turn_manager.start()
  77 
  78 
  79 if __name__ == '__main__':
  80     logging.basicConfig(level=logging.DEBUG)
  81 
  82     run_game()
  83     app.run(debug=True, use_reloader=False)
  84
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/aimmo-game/service.py b/aimmo-game/service.py
  --- a/aimmo-game/service.py
  +++ b/aimmo-game/service.py
  @@ -1,8 +1,11 @@
   #!/usr/bin/env python
   import logging
   
  +import eventlet
  +eventlet.monkey_patch()
  +
   import flask
  -from flask.ext.cors import CORS
  +from flask.ext.socketio import SocketIO, emit
   
   from simulation.turn_manager import world_state_provider
   from simulation import map_generator
  @@ -12,7 +15,7 @@
   from simulation.worker_manager import LocalWorkerManager
   
   app = flask.Flask(__name__)
  -CORS(app)
  +socketio = SocketIO(app)
   
   
   def to_cell_type(cell):
  @@ -42,7 +45,6 @@
       }
   
   
  -@app.route('/')
   def get_world_state():
       try:
           world = world_state_provider.lock_and_get_world()
  @@ -52,25 +54,41 @@
           for cell in world.world_map.all_cells():
               grid[cell.location.x][cell.location.y] = to_cell_type(cell)
           player_data = {p.player_id: player_dict(p) for p in world.avatar_manager.avatars}
  -        return flask.jsonify(
  -            players=player_data,
  -            score_locations=[(cell.location.x, cell.location.y) for cell in world.world_map.score_cells()],
  -            pickup_locations=[(cell.location.x, cell.location.y) for cell in world.world_map.pickup_cells()],
  -            map_changed=True,  # TODO: experiment with only sending deltas (not if not required)
  -            width=num_cols,
  -            height=num_rows,
  -            layout=grid,
  -        )
  +        return {
  +                'players': player_data,
  +                'score_locations': [(cell.location.x, cell.location.y) for cell in world.world_map.score_cells()],
  +                'pickup_locations': [(cell.location.x, cell.location.y) for cell in world.world_map.pickup_cells()],
  +                'map_changed': True,  # TODO: experiment with only sending deltas (not if not required)
  +                'width': num_cols,
  +                'height': num_rows,
  +                'layout': grid,
  +            }
       finally:
           world_state_provider.release_lock()
   
   
  +@socketio.on('connect')
  +def world_update_on_connect():
  +    emit(
  +        'world-update',
  +        get_world_state(),
  +    )
  +
  +
  +def send_world_update():
  +    socketio.emit(
  +        'world-update',
  +        get_world_state(),
  +        broadcast=True,
  +    )
  +
  +
   def run_game():
       print("Running game...")
       my_map = map_generator.generate_map(15, 15, 0.1)
       player_manager = AvatarManager()
       game_state = GameState(my_map, player_manager)
  -    turn_manager = TurnManager(game_state=game_state)
  +    turn_manager = TurnManager(game_state=game_state, end_turn_callback=send_world_update)
       worker_manager = LocalWorkerManager(game_state=game_state, users_url='http://localhost:8000/players/api/games/')
       worker_manager.start()
       turn_manager.start()
  @@ -80,4 +98,4 @@
       logging.basicConfig(level=logging.DEBUG)
   
       run_game()
  -    app.run(debug=True, use_reloader=False)
  +    socketio.run(app, debug=True, use_reloader=False)
  diff --git a/aimmo-game/simulation/turn_manager.py b/aimmo-game/simulation/turn_manager.py
  --- a/aimmo-game/simulation/turn_manager.py
  +++ b/aimmo-game/simulation/turn_manager.py
  @@ -41,8 +41,9 @@
       """
       daemon = True
   
  -    def __init__(self, game_state):
  +    def __init__(self, game_state, end_turn_callback):
           world_state_provider.set_world(game_state)
  +        self.end_turn_callback = end_turn_callback
           super(TurnManager, self).__init__()
   
       def _update_environment(self, game_state):
  @@ -76,4 +77,5 @@
       def run(self):
           while True:
               self.run_turn()
  +            self.end_turn_callback()
               time.sleep(0.5)
  diff --git a/setup.py b/setup.py
  --- a/setup.py
  +++ b/setup.py
  @@ -8,8 +8,9 @@
           'django >= 1.8.3, < 1.9.0',
           'django-autoconfig >= 0.3.6, < 1.0.0',
           'django-js-reverse',
  +        'eventlet',
           'flask',
  -        'flask-cors',
  +        'flask-socketio',
           'requests',
       ],
       tests_require=[
  
verification_info: {"golden_diff": "diff --git a/aimmo-game/service.py b/aimmo-game/service.py\n--- a/aimmo-game/service.py\n+++ b/aimmo-game/service.py\n@@ -1,8 +1,11 @@\n #!/usr/bin/env python\n import logging\n \n+import eventlet\n+eventlet.monkey_patch()\n+\n import flask\n-from flask.ext.cors import CORS\n+from flask.ext.socketio import SocketIO, emit\n \n from simulation.turn_manager import world_state_provider\n from simulation import map_generator\n@@ -12,7 +15,7 @@\n from simulation.worker_manager import LocalWorkerManager\n \n app = flask.Flask(__name__)\n-CORS(app)\n+socketio = SocketIO(app)\n \n \n def to_cell_type(cell):\n@@ -42,7 +45,6 @@\n     }\n \n \n-@app.route('/')\n def get_world_state():\n     try:\n         world = world_state_provider.lock_and_get_world()\n@@ -52,25 +54,41 @@\n         for cell in world.world_map.all_cells():\n             grid[cell.location.x][cell.location.y] = to_cell_type(cell)\n         player_data = {p.player_id: player_dict(p) for p in world.avatar_manager.avatars}\n-        return flask.jsonify(\n-            players=player_data,\n-            score_locations=[(cell.location.x, cell.location.y) for cell in world.world_map.score_cells()],\n-            pickup_locations=[(cell.location.x, cell.location.y) for cell in world.world_map.pickup_cells()],\n-            map_changed=True,  # TODO: experiment with only sending deltas (not if not required)\n-            width=num_cols,\n-            height=num_rows,\n-            layout=grid,\n-        )\n+        return {\n+                'players': player_data,\n+                'score_locations': [(cell.location.x, cell.location.y) for cell in world.world_map.score_cells()],\n+                'pickup_locations': [(cell.location.x, cell.location.y) for cell in world.world_map.pickup_cells()],\n+                'map_changed': True,  # TODO: experiment with only sending deltas (not if not required)\n+                'width': num_cols,\n+                'height': num_rows,\n+                'layout': grid,\n+            }\n     finally:\n         world_state_provider.release_lock()\n \n \n+@socketio.on('connect')\n+def world_update_on_connect():\n+    emit(\n+        'world-update',\n+        get_world_state(),\n+    )\n+\n+\n+def send_world_update():\n+    socketio.emit(\n+        'world-update',\n+        get_world_state(),\n+        broadcast=True,\n+    )\n+\n+\n def run_game():\n     print(\"Running game...\")\n     my_map = map_generator.generate_map(15, 15, 0.1)\n     player_manager = AvatarManager()\n     game_state = GameState(my_map, player_manager)\n-    turn_manager = TurnManager(game_state=game_state)\n+    turn_manager = TurnManager(game_state=game_state, end_turn_callback=send_world_update)\n     worker_manager = LocalWorkerManager(game_state=game_state, users_url='http://localhost:8000/players/api/games/')\n     worker_manager.start()\n     turn_manager.start()\n@@ -80,4 +98,4 @@\n     logging.basicConfig(level=logging.DEBUG)\n \n     run_game()\n-    app.run(debug=True, use_reloader=False)\n+    socketio.run(app, debug=True, use_reloader=False)\ndiff --git a/aimmo-game/simulation/turn_manager.py b/aimmo-game/simulation/turn_manager.py\n--- a/aimmo-game/simulation/turn_manager.py\n+++ b/aimmo-game/simulation/turn_manager.py\n@@ -41,8 +41,9 @@\n     \"\"\"\n     daemon = True\n \n-    def __init__(self, game_state):\n+    def __init__(self, game_state, end_turn_callback):\n         world_state_provider.set_world(game_state)\n+        self.end_turn_callback = end_turn_callback\n         super(TurnManager, self).__init__()\n \n     def _update_environment(self, game_state):\n@@ -76,4 +77,5 @@\n     def run(self):\n         while True:\n             self.run_turn()\n+            self.end_turn_callback()\n             time.sleep(0.5)\ndiff --git a/setup.py b/setup.py\n--- a/setup.py\n+++ b/setup.py\n@@ -8,8 +8,9 @@\n         'django >= 1.8.3, < 1.9.0',\n         'django-autoconfig >= 0.3.6, < 1.0.0',\n         'django-js-reverse',\n+        'eventlet',\n         'flask',\n-        'flask-cors',\n+        'flask-socketio',\n         'requests',\n     ],\n     tests_require=[\n", "issue": "Change the way the UI receives game updates\nThe UI currently polls the frontend server constantly for updates.\n\nImplement a solution where the _game simulation_ server pushes updates instead - e.g. using web sockets (or some other better solution that you can think of!)\n\nPossible server-side solutions:\n1. client ==> proxy (on Kubernetes) ==> game simulation (on Kubernetes)\nHere we only need one public IP address for the proxy, no matter how many game simulation servers we spawn.\n1. client ==> game simulation (on Kubernetes)\n   We need a public IP address per game simulation. We need to investigate whether this would be a problem (e.g. can't be done dynamically, or is expensive).\n\n", "before_files": [{"content": "import logging\nimport requests\nimport threading\nimport time\nfrom threading import Lock\nfrom simulation import world_map\nfrom simulation.action import ACTIONS\n\nLOGGER = logging.getLogger(__name__)\n\n\nclass WorldStateProvider:\n    \"\"\"\n    Thread-safe container for the world state.\n\n    TODO: think about changing to snapshot rather than lock?\n    \"\"\"\n\n    def __init__(self):\n        self._world_state = None\n        self._lock = Lock()\n\n    def lock_and_get_world(self):\n        self._lock.acquire()\n        return self._world_state\n\n    def release_lock(self):\n        self._lock.release()\n\n    def set_world(self, new_world_state):\n        self._lock.acquire()\n        self._world_state = new_world_state\n        self._lock.release()\n\nworld_state_provider = WorldStateProvider()\n\n\nclass TurnManager(threading.Thread):\n    \"\"\"\n    Game loop\n    \"\"\"\n    daemon = True\n\n    def __init__(self, game_state):\n        world_state_provider.set_world(game_state)\n        super(TurnManager, self).__init__()\n\n    def _update_environment(self, game_state):\n        num_avatars = len(game_state.avatar_manager.active_avatars)\n        game_state.world_map.reconstruct_interactive_state(num_avatars)\n\n    def run_turn(self):\n        try:\n            game_state = world_state_provider.lock_and_get_world()\n\n            for avatar in game_state.avatar_manager.active_avatars:\n                turn_state = game_state.get_state_for(avatar)\n                try:\n                    data = requests.post(avatar.worker_url, json=turn_state).json()\n                except ValueError as err:\n                    LOGGER.info(\"Failed to get turn result: %s\", err)\n                else:\n                    try:\n                        action_data = data['action']\n                        action = ACTIONS[action_data['action_type']](**action_data.get('options', {}))\n                    except (KeyError, ValueError) as err:\n                        LOGGER.info(\"Bad action data supplied: %s\", err)\n                    else:\n                        action.apply(game_state, avatar)\n\n            self._update_environment(game_state)\n\n        finally:\n            world_state_provider.release_lock()\n\n    def run(self):\n        while True:\n            self.run_turn()\n            time.sleep(0.5)\n", "path": "aimmo-game/simulation/turn_manager.py"}, {"content": "# -*- coding: utf-8 -*-\nfrom setuptools import find_packages, setup\n\nsetup(name='aimmo',\n    packages=find_packages(),\n    include_package_data=True,\n    install_requires = [\n        'django >= 1.8.3, < 1.9.0',\n        'django-autoconfig >= 0.3.6, < 1.0.0',\n        'django-js-reverse',\n        'flask',\n        'flask-cors',\n        'requests',\n    ],\n    tests_require=[\n        'django-setuptest',\n    ],\n    test_suite='setuptest.setuptest.SetupTestSuite',\n    version='0.0.0',\n    zip_safe=False,\n)\n", "path": "setup.py"}, {"content": "#!/usr/bin/env python\nimport logging\n\nimport flask\nfrom flask.ext.cors import CORS\n\nfrom simulation.turn_manager import world_state_provider\nfrom simulation import map_generator\nfrom simulation.avatar.avatar_manager import AvatarManager\nfrom simulation.game_state import GameState\nfrom simulation.turn_manager import TurnManager\nfrom simulation.worker_manager import LocalWorkerManager\n\napp = flask.Flask(__name__)\nCORS(app)\n\n\ndef to_cell_type(cell):\n    if not cell.habitable:\n        return 1\n    if cell.generates_score:\n        return 2\n    return 0\n\n\ndef player_dict(avatar):\n    # TODO: implement better colour functionality: will eventually fall off end of numbers\n    colour = \"#%06x\" % (avatar.player_id * 4999)\n    return {\n        'id': avatar.player_id,\n        'x': avatar.location.x,\n        'y': avatar.location.y,\n        'health': avatar.health,\n        'score': avatar.score,\n        'rotation': 0,\n        \"colours\": {\n            \"bodyStroke\": \"#0ff\",\n            \"bodyFill\": colour,\n            \"eyeStroke\": \"#aff\",\n            \"eyeFill\": \"#eff\",\n        }\n    }\n\n\n@app.route('/')\ndef get_world_state():\n    try:\n        world = world_state_provider.lock_and_get_world()\n        num_cols = len(world.world_map.grid)\n        num_rows = len(world.world_map.grid[0])\n        grid = [[None for x in xrange(num_cols)] for y in xrange(num_rows)]\n        for cell in world.world_map.all_cells():\n            grid[cell.location.x][cell.location.y] = to_cell_type(cell)\n        player_data = {p.player_id: player_dict(p) for p in world.avatar_manager.avatars}\n        return flask.jsonify(\n            players=player_data,\n            score_locations=[(cell.location.x, cell.location.y) for cell in world.world_map.score_cells()],\n            pickup_locations=[(cell.location.x, cell.location.y) for cell in world.world_map.pickup_cells()],\n            map_changed=True,  # TODO: experiment with only sending deltas (not if not required)\n            width=num_cols,\n            height=num_rows,\n            layout=grid,\n        )\n    finally:\n        world_state_provider.release_lock()\n\n\ndef run_game():\n    print(\"Running game...\")\n    my_map = map_generator.generate_map(15, 15, 0.1)\n    player_manager = AvatarManager()\n    game_state = GameState(my_map, player_manager)\n    turn_manager = TurnManager(game_state=game_state)\n    worker_manager = LocalWorkerManager(game_state=game_state, users_url='http://localhost:8000/players/api/games/')\n    worker_manager.start()\n    turn_manager.start()\n\n\nif __name__ == '__main__':\n    logging.basicConfig(level=logging.DEBUG)\n\n    run_game()\n    app.run(debug=True, use_reloader=False)\n", "path": "aimmo-game/service.py"}], "after_files": [{"content": "import logging\nimport requests\nimport threading\nimport time\nfrom threading import Lock\nfrom simulation import world_map\nfrom simulation.action import ACTIONS\n\nLOGGER = logging.getLogger(__name__)\n\n\nclass WorldStateProvider:\n    \"\"\"\n    Thread-safe container for the world state.\n\n    TODO: think about changing to snapshot rather than lock?\n    \"\"\"\n\n    def __init__(self):\n        self._world_state = None\n        self._lock = Lock()\n\n    def lock_and_get_world(self):\n        self._lock.acquire()\n        return self._world_state\n\n    def release_lock(self):\n        self._lock.release()\n\n    def set_world(self, new_world_state):\n        self._lock.acquire()\n        self._world_state = new_world_state\n        self._lock.release()\n\nworld_state_provider = WorldStateProvider()\n\n\nclass TurnManager(threading.Thread):\n    \"\"\"\n    Game loop\n    \"\"\"\n    daemon = True\n\n    def __init__(self, game_state, end_turn_callback):\n        world_state_provider.set_world(game_state)\n        self.end_turn_callback = end_turn_callback\n        super(TurnManager, self).__init__()\n\n    def _update_environment(self, game_state):\n        num_avatars = len(game_state.avatar_manager.active_avatars)\n        game_state.world_map.reconstruct_interactive_state(num_avatars)\n\n    def run_turn(self):\n        try:\n            game_state = world_state_provider.lock_and_get_world()\n\n            for avatar in game_state.avatar_manager.active_avatars:\n                turn_state = game_state.get_state_for(avatar)\n                try:\n                    data = requests.post(avatar.worker_url, json=turn_state).json()\n                except ValueError as err:\n                    LOGGER.info(\"Failed to get turn result: %s\", err)\n                else:\n                    try:\n                        action_data = data['action']\n                        action = ACTIONS[action_data['action_type']](**action_data.get('options', {}))\n                    except (KeyError, ValueError) as err:\n                        LOGGER.info(\"Bad action data supplied: %s\", err)\n                    else:\n                        action.apply(game_state, avatar)\n\n            self._update_environment(game_state)\n\n        finally:\n            world_state_provider.release_lock()\n\n    def run(self):\n        while True:\n            self.run_turn()\n            self.end_turn_callback()\n            time.sleep(0.5)\n", "path": "aimmo-game/simulation/turn_manager.py"}, {"content": "# -*- coding: utf-8 -*-\nfrom setuptools import find_packages, setup\n\nsetup(name='aimmo',\n    packages=find_packages(),\n    include_package_data=True,\n    install_requires = [\n        'django >= 1.8.3, < 1.9.0',\n        'django-autoconfig >= 0.3.6, < 1.0.0',\n        'django-js-reverse',\n        'eventlet',\n        'flask',\n        'flask-socketio',\n        'requests',\n    ],\n    tests_require=[\n        'django-setuptest',\n    ],\n    test_suite='setuptest.setuptest.SetupTestSuite',\n    version='0.0.0',\n    zip_safe=False,\n)\n", "path": "setup.py"}, {"content": "#!/usr/bin/env python\nimport logging\n\nimport eventlet\neventlet.monkey_patch()\n\nimport flask\nfrom flask.ext.socketio import SocketIO, emit\n\nfrom simulation.turn_manager import world_state_provider\nfrom simulation import map_generator\nfrom simulation.avatar.avatar_manager import AvatarManager\nfrom simulation.game_state import GameState\nfrom simulation.turn_manager import TurnManager\nfrom simulation.worker_manager import LocalWorkerManager\n\napp = flask.Flask(__name__)\nsocketio = SocketIO(app)\n\n\ndef to_cell_type(cell):\n    if not cell.habitable:\n        return 1\n    if cell.generates_score:\n        return 2\n    return 0\n\n\ndef player_dict(avatar):\n    # TODO: implement better colour functionality: will eventually fall off end of numbers\n    colour = \"#%06x\" % (avatar.player_id * 4999)\n    return {\n        'id': avatar.player_id,\n        'x': avatar.location.x,\n        'y': avatar.location.y,\n        'health': avatar.health,\n        'score': avatar.score,\n        'rotation': 0,\n        \"colours\": {\n            \"bodyStroke\": \"#0ff\",\n            \"bodyFill\": colour,\n            \"eyeStroke\": \"#aff\",\n            \"eyeFill\": \"#eff\",\n        }\n    }\n\n\ndef get_world_state():\n    try:\n        world = world_state_provider.lock_and_get_world()\n        num_cols = len(world.world_map.grid)\n        num_rows = len(world.world_map.grid[0])\n        grid = [[None for x in xrange(num_cols)] for y in xrange(num_rows)]\n        for cell in world.world_map.all_cells():\n            grid[cell.location.x][cell.location.y] = to_cell_type(cell)\n        player_data = {p.player_id: player_dict(p) for p in world.avatar_manager.avatars}\n        return {\n                'players': player_data,\n                'score_locations': [(cell.location.x, cell.location.y) for cell in world.world_map.score_cells()],\n                'pickup_locations': [(cell.location.x, cell.location.y) for cell in world.world_map.pickup_cells()],\n                'map_changed': True,  # TODO: experiment with only sending deltas (not if not required)\n                'width': num_cols,\n                'height': num_rows,\n                'layout': grid,\n            }\n    finally:\n        world_state_provider.release_lock()\n\n\n@socketio.on('connect')\ndef world_update_on_connect():\n    emit(\n        'world-update',\n        get_world_state(),\n    )\n\n\ndef send_world_update():\n    socketio.emit(\n        'world-update',\n        get_world_state(),\n        broadcast=True,\n    )\n\n\ndef run_game():\n    print(\"Running game...\")\n    my_map = map_generator.generate_map(15, 15, 0.1)\n    player_manager = AvatarManager()\n    game_state = GameState(my_map, player_manager)\n    turn_manager = TurnManager(game_state=game_state, end_turn_callback=send_world_update)\n    worker_manager = LocalWorkerManager(game_state=game_state, users_url='http://localhost:8000/players/api/games/')\n    worker_manager.start()\n    turn_manager.start()\n\n\nif __name__ == '__main__':\n    logging.basicConfig(level=logging.DEBUG)\n\n    run_game()\n    socketio.run(app, debug=True, use_reloader=False)\n", "path": "aimmo-game/service.py"}]}