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()

```

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=[

{"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"}]}