Skip to content

Commit

Permalink
存储出牌信息
Browse files Browse the repository at this point in the history
  • Loading branch information
mailgyc committed Mar 19, 2020
1 parent b8ac73f commit 5dff943
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 35 deletions.
30 changes: 21 additions & 9 deletions doudizhu/apps/game/player.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import functools
import json
import logging
from enum import IntEnum
from typing import TYPE_CHECKING, List, Optional, Dict, Any
Expand All @@ -15,11 +16,11 @@
logger = logging.getLogger(__file__)


def shot_turn(method):
@functools.wraps(method)
def wrapper(player, *args, **kwargs):
def shot_turn(func):
@functools.wraps(func)
async def wrapper(player, *args, **kwargs):
if player.room and player.room.whose_turn == player.seat:
method(player, *args, **kwargs)
return await func(player, *args, **kwargs)
else:
player.write_error('TURN ERROR')

Expand Down Expand Up @@ -94,7 +95,7 @@ def compare_single_poker(poker: int):
def hand_pokers(self) -> List[int]:
return self._hand_pokers

def on_message(self, code: int, packet: Dict[str, Any]):
async def on_message(self, code: int, packet: Dict[str, Any]):
if self.is_left():
if self.handle_leave(code, packet):
return
Expand All @@ -108,9 +109,9 @@ def on_message(self, code: int, packet: Dict[str, Any]):
elif self.state == State.WAITING:
self.handle_waiting(code, packet)
elif self.state == State.CALL_SCORE:
self.handle_call_score(code, packet)
await self.handle_call_score(code, packet)
elif self.state == State.PLAYING:
self.handle_playing(code, packet)
await self.handle_playing(code, packet)
elif self.state == State.GAME_OVER:
self.handle_game_over(code, packet)

Expand Down Expand Up @@ -176,7 +177,7 @@ def handle_waiting(self, code: int, packet: Dict[str, Any]):
self.write_error('STATE[%s]' % self.state)

@shot_turn
def handle_call_score(self, code: int, packet: Dict[str, Any]):
async def handle_call_score(self, code: int, packet: Dict[str, Any]):
if code == Pt.REQ_CALL_SCORE:
self.rob = packet.get('rob')

Expand All @@ -197,7 +198,7 @@ def handle_call_score(self, code: int, packet: Dict[str, Any]):
self.write_error('STATE[%s]' % self.state)

@shot_turn
def handle_playing(self, code, packet):
async def handle_playing(self, code, packet):
if code == Pt.REQ_SHOT_POKER:
pokers = packet.get('pokers')

Expand All @@ -221,6 +222,7 @@ def handle_playing(self, code, packet):
else:
self.change_state(State.GAME_OVER)
self.room.on_game_over(self)
await self.save_shot_round()
else:
self.write_error('STATE[%s]' % self.state)

Expand All @@ -239,6 +241,16 @@ def write_error(self, reason: str):
self.socket.write_message([Pt.ERROR, {'reason': reason}])
logger.error('USER[%d][%s] %s', self.uid, self.state, reason)

async def save_shot_round(self):
robot = self.room.has_robot()
record = {
'left': {player.seat: player.hand_pokers for player in self.room.players},
'round': self.room.shot_round,
'lord': self.room.landlord.seat,
}
db = self.socket.db
await db.insert('INSERT INTO record(round, robot) VALUES(%s, %s)', json.dumps(record), robot)

@property
def ready(self) -> int:
return self._ready
Expand Down
4 changes: 2 additions & 2 deletions doudizhu/apps/game/timer.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class Timer(object):

def __init__(self, callback: Callable, timeout: int = 20):
self._callback = callback
self._timeout = timeout
self._timeout = timeout * 2
self._is_running = False
self._last_time = time.time()

Expand All @@ -18,7 +18,7 @@ def timeout(self) -> int:

def start_timing(self, timeout: int = 20):
if timeout:
self._timeout = timeout
self._timeout = timeout * 2

self._last_time = time.time()
if not self._is_running:
Expand Down
26 changes: 13 additions & 13 deletions doudizhu/apps/game/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ async def open(self):
self.player.socket = self
logging.info('SOCKET[%s] OPEN', self.player.uid)

def on_message(self, message):
async def on_message(self, message):
if message == 'ping':
self._write_message('pong')
return
Expand All @@ -67,17 +67,7 @@ def on_message(self, message):
self.write_message([Protocol.RSP_ROOM_LIST, {'rooms': Storage.room_list()}])
return

self.player.on_message(code, packet)

@staticmethod
def decode_message(message):
try:
code, packet = json.loads(message)
if isinstance(code, int) and isinstance(packet, dict):
return code, packet
except (json.decoder.JSONDecodeError, ValueError):
logging.error('ERROR MESSAGE: %s', message)
return None, None
await self.player.on_message(code, packet)

def on_close(self):
self.player.on_disconnect()
Expand All @@ -89,7 +79,7 @@ def check_origin(self, origin: str) -> bool:
def get_compression_options(self) -> Optional[Dict[str, Any]]:
return {'compression_level': 6, 'mem_level': 9}

def write_message(self, message: List[Union[Protocol, Dict[str, Any]]], binary=False):
def write_message(self, message: List[Union[Protocol, Dict[str, Any]]], binary=False) -> Optional[None]:
packet = json.dumps(message)
self._write_message(packet, binary)

Expand All @@ -102,6 +92,16 @@ def _write_message(self, message, binary=False):
except WebSocketClosedError:
logging.error('WebSockedClosed[%s][%s]', self.uid, message)

@staticmethod
def decode_message(message):
try:
code, packet = json.loads(message)
if isinstance(code, int) and isinstance(packet, dict):
return code, packet
except (json.decoder.JSONDecodeError, ValueError):
logging.error('ERROR MESSAGE: %s', message)
return None, None


class AdminHandler(RestfulHandler):
required_fields = ('allow_robot',)
Expand Down
48 changes: 37 additions & 11 deletions doudizhu/static/js/game.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,46 +76,69 @@ PG.Game.prototype = {
this.players[0].updateInfo(PG.playerInfo.uid, PG.playerInfo.username);
PG.Socket.connect(this.onopen.bind(this), this.onmessage.bind(this), this.onerror.bind(this));

let style = {font: "22px Arial", fill: "#fff", align: "center"};
let titleBar = this.game.add.text(this.game.world.centerX, 0, `房间号:${0} 底分: 0 倍数: 0`, style);
const width = this.game.world.width;
const height = this.game.world.height;

const titleBar = this.game.add.text(width / 2, 0, `房间号:${0} 底分: 0 倍数: 0`, {
font: "22px",
fill: "#fff",
align: "center"
});
titleBar.anchor.set(0.5, 0);
observer.subscribe('room', function (room) {
titleBar.text = `房间号:${room.id} 底分: ${room.origin} 倍数: ${room.multiple}`;
});

// 创建准备按钮
const sx = this.game.world.width / 2;
const sy = this.game.world.height * 0.6;
const that = this;
const countdown = this.game.add.text(width / 2, height / 2, '10', {
font: "80px",
fill: "#fff",
align: "center"
});
countdown.anchor.set(0.5);
countdown.visible = false;
observer.subscribe('countdown', function (timer) {
countdown.visible = timer >= 0;
if (timer >= 0) {
countdown.text = timer;
that.game.time.events.add(1000, function () {
observer.set('countdown', observer.get('countdown') - 1);
}, that);
}
});

let ready = this.game.make.button(sx, sy, "btn", function() {
const ready = this.game.make.button(width / 2, height * 0.6, "btn", function () {
this.send_message([PG.Protocol.REQ_READY, {"ready": 1}]);
observer.set('countdown', 10);
}, this, 'ready.png', 'ready.png', 'ready.png');
ready.anchor.set(0.5, 0);
this.game.world.add(ready);

observer.subscribe('ready', function(is_ready) {
observer.subscribe('ready', function (is_ready) {
ready.visible = !is_ready;
});

// 创建抢地主按钮
const group = this.game.add.group();
let pass = this.game.make.button(this.game.world.width * 0.4, sy, "btn", function () {
let pass = this.game.make.button(width * 0.4, height * 0.6, "btn", function () {
this.game.add.audio('f_score_0').play();
this.send_message([PG.Protocol.REQ_CALL_SCORE, {"rob": 0}]);
}, this, 'score_0.png', 'score_0.png', 'score_0.png');
pass.anchor.set(0.5, 0);
group.add(pass);

const rob = this.game.make.button(this.game.world.width * 0.6, sy, "btn", function() {
const rob = this.game.make.button(width * 0.6, height * 0.6, "btn", function () {
this.game.add.audio('f_score_1').play();
this.send_message([PG.Protocol.REQ_CALL_SCORE, {"rob": 1}]);
}, this, 'score_1.png', 'score_1.png', 'score_1.png');
rob.anchor.set(0.5, 0);
group.add(rob);
group.visible = false;

observer.subscribe('rob', function(is_rob) {
observer.subscribe('rob', function (is_rob) {
group.visible = is_rob;
observer.set('countdown', -1);
});
},

Expand Down Expand Up @@ -198,7 +221,7 @@ PG.Game.prototype = {
case PG.Protocol.RSP_GAME_OVER: {
const winner = packet['winner'];
const that = this;
packet['players'].forEach(function(player){
packet['players'].forEach(function (player) {
const seat = that.uidToSeat(player['uid']);
if (seat > 0) {
that.players[seat].replacePoker(player['pokers'], 0);
Expand All @@ -207,11 +230,13 @@ PG.Game.prototype = {
});

this.whoseTurn = this.uidToSeat(winner);

function gameOver() {
alert(that.players[that.whoseTurn].isLandlord ? "地主赢" : "农民赢");
observer.set('ready', false);
this.cleanWorld();
}

this.game.time.events.add(2000, gameOver, this);
break;
}
Expand All @@ -226,7 +251,7 @@ PG.Game.prototype = {
},

cleanWorld: function () {
this.players.forEach(function(player) {
this.players.forEach(function (player) {
player.cleanPokers();
// player.uiLeftPoker.kill();
player.uiHead.frameName = 'icon_farmer.png';
Expand Down Expand Up @@ -319,6 +344,7 @@ PG.Game.prototype = {
function adjust(p) {
that.game.add.tween(p).to({y: that.game.world.height - PG.PH / 2}, 400, Phaser.Easing.Default, true, 400);
}

tween.onComplete.add(adjust, this, p);
}
} else {
Expand Down
1 change: 1 addition & 0 deletions schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ CREATE TABLE IF NOT EXISTS ddz.account (
CREATE TABLE IF NOT EXISTS ddz.record (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
round TEXT NOT NULL,
robot TINYINT(1) NOT NULL,
last_modified DATETIME ON UPDATE CURRENT_TIMESTAMP
);

0 comments on commit 5dff943

Please sign in to comment.