Permalink
Browse files

Chat: Implement game-by-game realtime chat.

  • Loading branch information...
1 parent 1840b47 commit feb164de93f78c793e14102a918d14a9684ddd2d @chellmuth committed Oct 16, 2008
Showing with 118 additions and 34 deletions.
  1. +6 −0 game/models.py
  2. +62 −10 templates/board_test.html
  3. +8 −9 tigris_stomper.py
  4. +3 −1 urls.py
  5. +39 −14 views.py
View
@@ -166,3 +166,9 @@ def get_piece(self):
return TempleCiv(self.temple_start - self.temple_remaining - 1)
assert(0)
+
+class Chat(models.Model):
+ message = models.CharField(maxlength=100)
+ game = models.ForeignKey(Game)
+ player = models.ForeignKey(Player)
+ time = models.DateTimeField(auto_now_add=True)
View
@@ -52,6 +52,16 @@
background-color: yellow;
}
+#chat-window {
+ position: absolute;
+ top: -71px;
+ left: 810px;
+ width: 275px;
+ height: 619px;
+ border: 3px solid #3C3251;
+ background: #FFED90;
+}
+
#board {
position: absolute;
top: {{ board_start_y }}px;
@@ -558,7 +568,11 @@
};
stomp.onclose = function(code) {
-
+ alert("trying to reconnect...");
+ stomp.subscribe(
+ '/home/cjh/{{ game_id }}',
+ {exchange:''}
+ );
};
stomp.onerror = function(error) {
alert("onerror: " + error);
@@ -567,20 +581,25 @@
alert("onerrorframe: " + frame.body);
};
stomp.onconnectedframe = function() {
- stomp.subscribe('/home/cjh',
- {exchange:''}
- );
-
+ stomp.subscribe(
+ '/home/cjh/{{ game_id }}',
+ {exchange:''}
+ );
};
stomp.onmessageframe = function(frame) {
call_json();
+ $.getJSON(
+ '/get_chat/{{ game_id }}/' + cur_chat_id + '/',
+ parse_chat
+ );
};
- stomp.connect('localhost',
- 61613,
- '{{ game_id }}-{{ player_no }}',
- 'testpw'
- );
+ stomp.connect(
+ 'localhost',
+ 61613,
+ '{{ game_id }}-{{ player_no }}',
+ 'testpw'
+ );
}
function call_json() {
@@ -591,6 +610,11 @@
setup_stomp();
call_json();
+ $.getJSON(
+ '/get_chat/{{ game_id }}/0/',
+ parse_chat
+ );
+
for(var i={{ num_players }} + 1; i<= 4; i++) {
$("#status_player_" + i).hide();
}
@@ -932,6 +956,34 @@
<div id="commit_choices" title="Choose Number of Tiles!">How many tiles to contribute?</div>
<div id="confirm_treasure">Would you like to choose these treasures?</div>
+<div id="chat-window">
+ <form action="javascript: chat_submit();">
+ <input id="chat-text" type="text" name="chat" />
+ <input id="chat-submit" value="Chat" type="submit" name="Submit" />
+ </form>
+ <script>
+ var cur_chat_id = 0;
+ function chat_submit() {
+ $.getJSON(
+ '/chat/{{ game_id }}/{{ player_no }}/' + cur_chat_id + '/',
+ { 'chat': $("#chat-text").val() },
+ parse_chat
+ );
+ }
+
+ function parse_chat(data) {
+ if (data['old_chat_id'] != cur_chat_id) {
+ // XXX should iterate over the diff too lazy to implement though.
+ return;
+ }
+ $.each(data['chats'], function(i, chat) { $("#chat-window").append(chat + "<br />"); });
+ cur_chat_id = data['new_chat_id'];
+ }
+
+ </script>
+ </form>
+</div>
+
</div>
<div id="ruler-bin">
View
@@ -10,12 +10,11 @@
stomper.utils.log_init(logging.DEBUG)
-DESTINATION="/home/cjh"
-
class StompProtocol(Protocol, stomper.Engine):
- def __init__(self, message='', username='', password=''):
+ def __init__(self, channel='', message='', username='', password=''):
stomper.Engine.__init__(self)
+ self.channel = channel
self.message = message
self.username = username
self.password = password
@@ -35,7 +34,7 @@ def connected(self, msg):
self.send("WHY HELLO!")
f = stomper.Frame()
- f.unpack(stomper.subscribe(DESTINATION))
+ f.unpack(stomper.subscribe(self.channel))
# ActiveMQ specific headers:
#
@@ -60,7 +59,7 @@ def send(self, msg):
self.log.info("Saying hello (%d)." % self.counter)
f = stomper.Frame()
- f.unpack(stomper.send(DESTINATION, self.message))
+ f.unpack(stomper.send(self.channel, self.message))
self.counter += 1
@@ -94,8 +93,7 @@ class StompClientFactory(ReconnectingClientFactory):
username, password, message = '', '', ''
def buildProtocol(self, addr):
- return StompProtocol(self.message, self.username, self.password)
-
+ return StompProtocol(self.channel, self.message, self.username, self.password)
def clientConnectionLost(self, connector, reason):
"""Lost connection
@@ -110,12 +108,13 @@ def clientConnectionFailed(self, connector, reason):
ReconnectingClientFactory.clientConnectionFailed(self, connector, reason)
reactor.stop()
-def start(message, host='localhost', port=61613, username='', password=''):
+def start(game_id, host='localhost', port=61613, username='', password=''):
"""Start twisted event loop and the fun should begin...
"""
StompClientFactory.username = username
StompClientFactory.password = password
- StompClientFactory.message = message
+ StompClientFactory.message = 'message'
+ StompClientFactory.channel = '/home/cjh/' + game_id
reactor.connectTCP(host, port, StompClientFactory())
reactor.run()
View
@@ -1,7 +1,9 @@
from django.conf.urls.defaults import *
-from tigris.views import print_custom_css_board, game_state_json, drop_civ, create_game, drop_ruler, external_war, choose_color, attack_commit, defend_commit, internal_attack, internal_defend, choose_treasure, splash, show_games, reposition_ruler, reposition_ruler_war, remove_ruler, drop_tiles
+from tigris.views import print_custom_css_board, game_state_json, drop_civ, create_game, drop_ruler, external_war, choose_color, attack_commit, defend_commit, internal_attack, internal_defend, choose_treasure, splash, show_games, reposition_ruler, reposition_ruler_war, remove_ruler, drop_tiles, chat, get_chat
urlpatterns = patterns('',
+ (r'^chat/(\d+)/(\d+)/(\d+)/$', chat),
+ (r'^get_chat/(\d+)/(\d+)/$', get_chat),
(r'^game/(\d+)/(\d+)/$', print_custom_css_board, { 'rows': 11, 'cols': 16, 'size': 50 }),
(r'^game_state_json/(\d+)/(\d+)/$', game_state_json),
(r'^drop_civ/(\d+)/(\d+)/[^\d]+(\d+)/(\d+)/$', drop_civ),
View
@@ -2,16 +2,41 @@
from django.http import HttpResponse, HttpResponseRedirect
from django.utils import simplejson
-from game.models import Game, CivBag, Hand, Player
+from game.models import Game, CivBag, Hand, Player, Chat
from game.board import StandardBoard, build_board_data
from game.board import split_legal_moves_by_type, safe_tile, safe_ruler, external_war_tile, internal_war_ruler
from game.board.piece import SettlementCiv, FarmCiv, TempleCiv, MerchantCiv, SettlementRuler, FarmRuler, TempleRuler, MerchantRuler
from game.board.cell import Ground
from tigris.forms import GameCreateForm
-def update_browsers():
+def chat(request, game_id, player_no, chat_id):
+ g = Game.objects.get(id=int(game_id))
+ p = g.__getattribute__('player_' + player_no)
+
+ chat = Chat.objects.create(game=g, player=p)
+ body = 'nothing to see here'
+ if request.has_key('chat'):
+ body = request['chat']
+
+ chat.message=p.user_name + ': ' + body
+ chat.save()
+
+ update_browsers(game_id)
+
+ return get_chat(request, game_id, chat_id)
+
+def get_chat(request, game_id, chat_id):
+ chats = Chat.objects.filter(id__gt=chat_id).order_by('id')
+ json_obj = { "chats": [ c.message for c in chats if c.game.id == int(game_id) ], "old_chat_id": int(chat_id), "new_chat_id": int(chats[len(chats)-1].id) }
+
+ resp = HttpResponse(simplejson.dumps(json_obj, indent=2))
+ resp.headers['Content-Type'] = 'text/javascript'
+
+ return resp
+
+def update_browsers(game_id):
from tigris_stomper import start
- start('update from view')
+ start(game_id)
def _convert(str):
if str[0] == 's':
@@ -52,7 +77,7 @@ def drop_tiles(request, game_id, player_no, tile0, tile1, tile2, tile3, tile4, t
g.increment_action()
g.save()
- update_browsers()
+ update_browsers(game_id)
return game_state_json(request, game_id, player_no)
@@ -74,7 +99,7 @@ def choose_treasure(request, game_id, player_no, cell_nos):
board.save()
- update_browsers()
+ update_browsers(game_id)
return game_state_json(request, game_id, player_no)
@@ -112,7 +137,7 @@ def internal_defend(request, game_id, player_no, num_committed):
g.save()
board.save()
- update_browsers()
+ update_browsers(game_id)
return game_state_json(request, game_id, player_no)
@@ -144,7 +169,7 @@ def internal_attack(request, game_id, player_no, cell_no, civ, num_committed):
g.save()
board.save()
- update_browsers()
+ update_browsers(game_id)
return game_state_json(request, game_id, player_no)
@@ -200,7 +225,7 @@ def defend_commit(request, game_id, player_no, tile_count):
g.save()
board.save()
- update_browsers()
+ update_browsers(game_id)
return game_state_json(request, game_id, player_no)
@@ -224,7 +249,7 @@ def attack_commit(request, game_id, player_no, tile_count):
g.waiting_for = _get_defender(g, board)
g.save()
- update_browsers()
+ update_browsers(game_id)
return game_state_json(request, game_id, player_no)
@@ -241,7 +266,7 @@ def choose_color(request, game_id, player_no, civ):
g.save()
- update_browsers()
+ update_browsers(game_id)
return game_state_json(request, game_id, player_no)
@@ -276,7 +301,7 @@ def external_war(request, game_id, player_no, civ, cell):
board.save()
hand.save()
- update_browsers()
+ update_browsers(game_id)
return game_state_json(request, game_id,player_no)
@@ -332,7 +357,7 @@ def remove_ruler(request, game_id, player_no, ruler):
g.save()
board.save()
- update_browsers()
+ update_browsers(game_id)
return game_state_json(request, game_id, player_no)
@@ -389,7 +414,7 @@ def drop_ruler(request, game_id, player_no, ruler, cell):
g.save()
board.save()
- update_browsers()
+ update_browsers(game_id)
return game_state_json(request, game_id, player_no)
@@ -437,7 +462,7 @@ def drop_civ(request, game_id, player_no, civ, cell):
g.save()
board.save()
- update_browsers()
+ update_browsers(game_id)
return game_state_json(request, game_id,player_no)

0 comments on commit feb164d

Please sign in to comment.