Mercurial > libervia-web
changeset 36:1d406077b49b
Tarot Game: first draft
author | Goffi <goffi@goffi.org> |
---|---|
date | Tue, 17 May 2011 01:33:12 +0200 |
parents | d43d6e4b9dc8 |
children | b306aa090438 |
files | browser_side/card_game.py browser_side/games.py browser_side/panels.py libervia.py libervia.tac public/libervia.css |
diffstat | 6 files changed, 227 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/browser_side/card_game.py Tue May 17 01:33:12 2011 +0200 @@ -0,0 +1,110 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" +Libervia: a Salut à Toi frontend +Copyright (C) 2011 Jérôme Poisson (goffi@goffi.org) + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +""" + +import pyjd # this is dummy in pyjs +from pyjamas.ui.AbsolutePanel import AbsolutePanel +from pyjamas.ui.Image import Image + +from pyjamas.dnd import makeDraggable +from pyjamas.ui.DragWidget import DragWidget, DragContainer +from jid import JID +from tools import html_sanitize +from datetime import datetime +from time import time +from games import TarotCard + + + +CARD_WIDTH = 74 +CARD_HEIGHT = 136 +MIN_WIDTH = 950 #Minimum size of the panel +MIN_HEIGHT = 500 + + +class CardWidget(TarotCard, Image): + """This class is used to represent a card, graphically and logically""" + + def __init__(self, file): + """@param file: path of the PNG file""" + Image.__init__(self,file) + root_name = file[file.rfind("/")+1:-4] + suit,value = root_name.split('_') + TarotCard.__init__(self, (suit, value)) + print "Carte:",suit, value #, self.bout + + def draw(self, dc, x, y): + """Draw the card on the device context + @param dc: device context + @param x: abscissa + @param y: ordinate""" + pass + #dc.DrawBitmap(self.bitmap, x, y, True) + +class CardPanel(AbsolutePanel): + + def __init__(self, parent, referee, players, player_nick): + self._parent = parent + self._autoplay = None #XXX: use 0 to activate fake play, None else + self.referee = referee + self.players = players + self.played = {} + for player in players: + self.played[player] = None + self.player_nick = player_nick + self.bottom_nick = self.player_nick + idx = self.players.index(self.player_nick) + idx = (idx + 1) % len(self.players) + self.right_nick = self.players[idx] + idx = (idx + 1) % len(self.players) + self.top_nick = self.players[idx] + idx = (idx + 1) % len(self.players) + self.left_nick = self.players[idx] + self.bottom_nick = player_nick + self.selected = [] #Card choosed by the player (e.g. during ecart) + self.hand_size = 13 #number of cards in a hand + self.hand = [] + self.to_show = [] + self.state = None + AbsolutePanel.__init__(self) + self.setSize("%spx" % MIN_WIDTH, "%spx" % MIN_HEIGHT) + self.setStyleName("cardPanel") + self.loadCards() + self.mouse_over_card = None #contain the card to highlight + self.visible_size = CARD_WIDTH/2 #number of pixels visible for cards + + def _getTarotCardsPathsCb(self, paths): + for file in paths: + card = CardWidget(file) + self.cards[(card.suit, card.value)]=card + self.deck.append(card) + + def loadCards(self, dir): + """Load all the cards in memory + @param dir: directory where the PNG files are""" + self.cards={} + self.deck=[] + self.cards["atout"]={} #As Tarot is a french game, it's more handy & logical to keep french names + self.cards["pique"]={} #spade + self.cards["coeur"]={} #heart + self.cards["carreau"]={} #diamond + self.cards["trefle"]={} #club + self._parent.host.bridge.call('getTarotCardsPaths', self._getTarotCardsPathsCb) +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/browser_side/games.py Tue May 17 01:33:12 2011 +0200 @@ -0,0 +1,78 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" +Libervia: a Salut à Toi frontend +Copyright (C) 2011 Jérôme Poisson (goffi@goffi.org) + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +""" + +"""This library help manage general games (e.g. card games)""" + + +suits_order = ['pique', 'coeur', 'trefle', 'carreau', 'atout'] #I have switched the usual order 'trefle' and 'carreau' because card are more easy to see if suit colour change (black, red, black, red) +values_order = map(str,range(1,11))+["valet","cavalier","dame","roi"] + +class TarotCard(): + """This class is used to represent a car logically""" + #TODO: move this in a library in tools, and share this with frontends (e.g. card_game in wix use the same class) + + def __init__(self, tuple_card): + """@param tuple_card: tuple (suit, value)""" + self.suit, self.value = tuple_card + self.bout = True if self.suit=="atout" and self.value in ["1","21","excuse"] else False + if self.bout or self.value == "roi": + self.points = 4.5 + elif self.value == "dame": + self.points = 3.5 + elif self.value == "cavalier": + self.points = 2.5 + elif self.value == "valet": + self.points = 1.5 + else: + self.points = 0.5 + + def get_tuple(self): + return (self.suit,self.value) + + @staticmethod + def from_tuples(tuple_list): + result = [] + for card_tuple in tuple_list: + result.append(TarotCard(card_tuple)) + return result + + def __cmp__(self, other): + if other == None: + return 1 + if self.suit != other.suit: + idx1 = suits_order.index(self.suit) + idx2 = suits_order.index(other.suit) + return idx1.__cmp__(idx2) + if self.suit == 'atout': + if self.value == other.value == 'excuse': + return 0 + if self.value == 'excuse': + return -1 + if other.value == 'excuse': + return 1 + return int(self.value).__cmp__(int(other.value)) + #at this point we have the same suit which is not 'atout' + idx1 = values_order.index(self.value) + idx2 = values_order.index(other.value) + return idx1.__cmp__(idx2) + + def __str__(self): + return "[%s,%s]" % (self.suit, self.value)
--- a/browser_side/panels.py Mon May 16 18:19:35 2011 +0200 +++ b/browser_side/panels.py Tue May 17 01:33:12 2011 +0200 @@ -47,6 +47,7 @@ from pyjamas.dnd import makeDraggable from pyjamas.ui.DragWidget import DragWidget, DragContainer +from card_game import CardPanel from jid import JID from tools import html_sanitize from datetime import datetime @@ -555,6 +556,13 @@ return self.content.add(ChatText(timestamp, nick, mymess, msg)) self.content_scroll.scrollToBottom() + + def startGame(self, game_type, referee, players): + """Configure the chat window to start a game""" + if game_type=="Tarot": + self.tarot_panel = CardPanel(self, referee, players, self.nick) + self.vpanel.insert(self.tarot_panel, 1) + self.vpanel.setCellHeight(self.tarot_panel, self.tarot_panel.getHeight()) class MainDiscussionPanel(HorizontalPanel):
--- a/libervia.py Mon May 16 18:19:35 2011 +0200 +++ b/libervia.py Tue May 17 01:33:12 2011 +0200 @@ -66,7 +66,7 @@ def __init__(self): LiberviaJsonProxy.__init__(self, "/json_api", ["getContacts", "sendMessage", "sendMblog", "getMblogNodes", "getProfileJid", "getHistory", - "getPresenceStatus", "getRoomJoined", "launchTarotGame"]) + "getPresenceStatus", "getRoomJoined", "launchTarotGame", "getTarotCardsPaths"]) class BridgeSignals(LiberviaJsonProxy): def __init__(self): @@ -167,6 +167,8 @@ self._roomUserJoinedCb(*args) elif name == 'roomUserLeft': self._roomUserLeftCb(*args) + elif name == 'tarotGameStarted': + self._tarotGameStartedCb(*args) def _getProfileJidCB(self, jid): self.whoami = JID(jid) @@ -189,7 +191,7 @@ else: _groups=None for panel in self.mpanels: - if isinstance(panel,MicroblogPanel) and (panel.isJidAccepted(sender) or _groups == None or _groups.intersection(panel.accepted_groups)): + if isinstance(panel,MicroblogPanel) and (panel.isJidAccepted(sender) or _groups == None or _groups.intersection(panel.accepted_groups)): #TODO: check this content = data['content'] author = data.get('author') timestamp = float(data.get('timestamp',0)) #XXX: int doesn't work here @@ -231,7 +233,13 @@ for panel in self.mpanels + self.other_panels: if isinstance(panel,ChatPanel) and panel.type == 'group' and panel.target.bare == "%s@%s" % (room_id, room_service): panel.userLeft(user_nick, user_data) - + + def _tarotGameStartedCb(self, room_jid, referee, players): + print ("Tarot Game Started \o/") + for panel in self.mpanels + self.other_panels: + if isinstance(panel,ChatPanel) and panel.type == 'group' and panel.target.bare == room_jid: + panel.startGame("Tarot", referee, players) + def _getPresenceStatusCB(self, presence_data): for entity in presence_data: for resource in presence_data[entity]:
--- a/libervia.tac Mon May 16 18:19:35 2011 +0200 +++ b/libervia.tac Tue May 17 01:33:12 2011 +0200 @@ -33,10 +33,13 @@ from txjsonrpc import jsonrpclib from sat_frontends.bridge.DBus import DBusBridgeFrontend,BridgeExceptionNoService import re +import glob +import os.path from server_side.blog import MicroBlog TIMEOUT = 120 #Session's time out, after that the user will be disconnected - +LIBERVIA_DIR = "output/" +CARDS_DIR = "cards/" class MethodHandler(jsonrpc.JSONRPC): @@ -121,6 +124,12 @@ profile = self.session.sat_profile self.sat_host.bridge.tarotGameLaunch(other_players, profile) + def jsonrpc_getTarotCardsPaths(self): + """Give the path of all the tarot cards""" + return map(lambda x: x[len(LIBERVIA_DIR):],glob.glob(os.path.join(LIBERVIA_DIR,CARDS_DIR,'*_*.png'))); + + + class Register(jsonrpc.JSONRPC): """This class manage the registration procedure with SàT It provide an api for the browser, check password and setup the web server""" @@ -329,7 +338,7 @@ class Libervia(service.Service): def __init__(self): - root = File("output/") + root = File(LIBERVIA_DIR) self.signal_handler = SignalHandler(self) _register = Register(self) self.signal_handler.plugRegister(_register) @@ -344,7 +353,7 @@ sys.exit(1) self.bridge.register("connected", self.signal_handler.connected) self.bridge.register("connectionError", self.signal_handler.connectionError) - for signal_name in ['presenceUpdate', 'personalEvent', 'newMessage', 'roomJoined', 'roomUserJoined', 'roomUserLeft']: + for signal_name in ['presenceUpdate', 'personalEvent', 'newMessage', 'roomJoined', 'roomUserJoined', 'roomUserLeft', 'tarotGameStarted']: self.bridge.register(signal_name, self.signal_handler.getGenericCb(signal_name)) root.putChild('json_signal_api', self.signal_handler) root.putChild('json_api', MethodHandler(self))
--- a/public/libervia.css Mon May 16 18:19:35 2011 +0200 +++ b/public/libervia.css Tue May 17 01:33:12 2011 +0200 @@ -288,7 +288,14 @@ height: 100%; } -/* Test drag and drop */ +/* Games */ + +.cardPanel { + background: green; + margin: 0 auto; +} + +/* Drag and drop */ .dragover { background: #8f8;