Commit af1ce4be authored by 张振华's avatar 张振华

guess

parent 6ed5261f
...@@ -50,30 +50,37 @@ func addGuessStartFlags(cmd *cobra.Command) { ...@@ -50,30 +50,37 @@ func addGuessStartFlags(cmd *cobra.Command) {
cmd.Flags().StringP("options", "o", "", "options") cmd.Flags().StringP("options", "o", "", "options")
cmd.MarkFlagRequired("options") cmd.MarkFlagRequired("options")
cmd.Flags().Uint32P("maxHeight", "h", 0, "max height to bet") cmd.Flags().StringP("maxTime", "mt", "", "max time to bet, after this bet is forbidden")
cmd.Flags().Uint32P("maxHeight", "h", 0, "max height to bet, after this bet is forbidden")
cmd.MarkFlagRequired("maxHeight") cmd.MarkFlagRequired("maxHeight")
cmd.Flags().StringP("symbol", "s", "bty", "token symbol") cmd.Flags().StringP("symbol", "s", "bty", "token symbol")
cmd.Flags().StringP("exec", "e", "coins", "excutor name") cmd.Flags().StringP("exec", "e", "coins", "excutor name")
cmd.Flags().Uint32P("oneBet", "b", 0, "one bet number") cmd.Flags().Uint32P("oneBet", "b", 10, "one bet number, eg:10 bty / 10 token")
cmd.MarkFlagRequired("oneBet") //cmd.MarkFlagRequired("oneBet")
cmd.Flags().Uint32P("maxBets", "m", 0, "max bets one time")
cmd.MarkFlagRequired("maxBets")
cmd.Flags().Uint32P("maxBetsNumber", "n", 100, "max bets number") cmd.Flags().Uint32P("maxBets", "m", 10000, "max bets one time")
cmd.MarkFlagRequired("maxBetsNumber") //cmd.MarkFlagRequired("maxBets")
cmd.Flags().Uint32P("maxBetsNumber", "n", 100000, "max bets number")
//cmd.MarkFlagRequired("maxBetsNumber")
cmd.Flags().Float64P("fee", "f", 0, "fee") cmd.Flags().Float64P("fee", "f", 0, "fee")
cmd.Flags().StringP("feeAddr", "a", "", "fee address") cmd.Flags().StringP("feeAddr", "a", "", "fee address")
cmd.Flags().StringP("expire", "ex", "", "expire time of the game, after this any addr can abort it")
cmd.Flags().Uint32P("expireHeight", "eh", 0, "expire height of the game, after this any addr can abort it")
} }
func guessStart(cmd *cobra.Command, args []string) { func guessStart(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr") rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
topic, _ := cmd.Flags().GetString("topic") topic, _ := cmd.Flags().GetString("topic")
options, _ := cmd.Flags().GetString("options") options, _ := cmd.Flags().GetString("options")
maxTime, _ := cmd.Flags().GetString("maxTime")
maxHeight, _ := cmd.Flags().GetUint32("maxHeight") maxHeight, _ := cmd.Flags().GetUint32("maxHeight")
symbol, _ := cmd.Flags().GetString("symbol") symbol, _ := cmd.Flags().GetString("symbol")
exec, _ := cmd.Flags().GetString("exec") exec, _ := cmd.Flags().GetString("exec")
...@@ -82,12 +89,15 @@ func guessStart(cmd *cobra.Command, args []string) { ...@@ -82,12 +89,15 @@ func guessStart(cmd *cobra.Command, args []string) {
maxBetsNumber, _ := cmd.Flags().GetUint32("maxBetsNumber") maxBetsNumber, _ := cmd.Flags().GetUint32("maxBetsNumber")
fee, _ := cmd.Flags().GetFloat64("fee") fee, _ := cmd.Flags().GetFloat64("fee")
feeAddr, _ := cmd.Flags().GetString("feeAddr") feeAddr, _ := cmd.Flags().GetString("feeAddr")
expire, _ := cmd.Flags().GetString("expire")
expireHeight, _ := cmd.Flags().GetUint32("expireHeight")
feeInt64 := uint64(fee * 1e4) feeInt64 := uint64(fee * 1e4)
params := &pkt.GuessStartTxReq{ params := &pkt.GuessStartTxReq{
Topic: topic, Topic: topic,
Options: options, Options: options,
MaxTime: maxTime,
MaxHeight: maxHeight, MaxHeight: maxHeight,
Symbol: symbol, Symbol: symbol,
Exec: exec, Exec: exec,
...@@ -96,6 +106,8 @@ func guessStart(cmd *cobra.Command, args []string) { ...@@ -96,6 +106,8 @@ func guessStart(cmd *cobra.Command, args []string) {
MaxBetsNumber: maxBetsNumber, MaxBetsNumber: maxBetsNumber,
Fee: feeInt64, Fee: feeInt64,
FeeAddr: feeAddr, FeeAddr: feeAddr,
Expire: expire,
ExpireHeight: expireHeight,
} }
var res string var res string
......
...@@ -5,44 +5,42 @@ ...@@ -5,44 +5,42 @@
package executor package executor
/* /*
区块链卡牌游戏:斗牛 区块链游戏:竞猜
一、玩法简介: 一、玩法简介:
游戏可以由2-5人进行,总共52张牌(除大小王),系统将随机发给玩家每人5张牌,并根据5张牌进行排列组合,进行大小比较确定胜负。 菠菜平台的管理员可以发布竞猜游戏,玩家可以对竞猜游戏进行投注.
支持两种游戏玩法,普通玩法和庄家玩法 截止时间达到后,玩家不能再进行投注,等待管理员公布结果.
普通玩法:没有庄家,所有玩家直接比大小,最大的玩家赢得所有筹码 竞猜内容的结果出来以后,管理员根据竞猜内容的真实结果触发智能合约进行输赢判断及结算。
庄家玩法:玩家只和庄家比大小,比庄家大则赢得庄家筹码,反之则输给庄家筹码,庄家有创建者开始按加入游戏的顺序轮换
二、发牌和洗牌 二、创建及参与游戏
1、洗牌由游戏创建者发起交易的区块时间blocktime作为随机数因子,所以排序链上可见 1、游戏管理员创建一局竞猜游戏时,可以设定竞猜内容,选项,赌注类型、大小及上限,截止时间等,比如竞猜一场足球比赛的结果,每注10BTY,单次最多可下100注,比赛开始前2小时截止投注。
2、发牌使用各玩家加入游戏所在交易的hash作为随机数因子,由于nonce的存在,txhash本身具有随机性,且每个玩家每一局的txhash都不一样,可以保证发牌具有随机性 2、玩家按规则进行投注,如果已过截止时间,则不能继续投注。
三、制胜策略 三、制胜策略
将玩家a的5张牌分为两组(3+2)后,与玩家b进行大小比较。 1、竞猜游戏对应的现实世界的结果出来以后,游戏管理员向区块链合约公布胜出的竞猜选项。
1、第一组3张牌的比较规则:要求将5张牌中取出任意3张组成10、20、30的整数(加法运算)。数字A-10的扑克牌数字代表其大小,JQK统一以10计算。 2、合约将投注的所有赌注向压注正确选项的玩家进行分配,分配原则根据每个地址实际投注的数额占比进行分配,比如一个地址投注占了正确选项投注总额的1/2,则该地址将获得所有赌注总额的1/2。
若玩家a和b有那么三张牌能凑成10或20或30的整数,我们称之为有牛,那么则进行第2组两张牌的大小比较。若玩家a或b有某人无法使用3张牌凑成10或20 3、如果因为现实世界的突发异常导致竞猜不能继续(比如某场足球比赛因为不可抗力取消了),则管理员可以终止竞猜,合约将把所有地址的投注返还。
或30的整数,我们称之为没牛,同时该玩家判定为输。
2、第二组牌的比较则把剩下的两张牌按照加法计算,10的整数倍数最大,1最小,若大于10小于20则取个位数计算。数字越大则牌型越大,数字越小则牌型
越小。若第2组牌数字为1我们称之为牛一,若第2组数字为10或20我们称之为牛牛,其他以牛二、牛三等名称称呼。牌型从小到大排序为:没牛-牛一-牛二……牛八-牛九-牛牛。
3、若玩家a和b都无法使用3张牌凑成10或20或30的整数,即两家均无牛,则此时进行5张牌中最大一张牌的比较,大小次序为K-Q-J-10-9……A,若最大一
张牌也相同则根据花色进行比较,大小次序为黑桃、红桃、梅花、方片。
4、牌型翻倍
没牛、牛1-6: 1倍
牛7-9: 2倍
牛牛: 3倍
四花: 4倍
五花: 5倍
四、游戏过程和状态 四、游戏过程和状态
1、充值,往pokerbull合约对应的合约账户充值 1、创建游戏,一个地址可以作为本局竞猜游戏的管理员发起竞猜游戏。
2、玩家指定游戏人数和筹码加入游戏,如果有等待状态的游戏,直接加入,如果没有,创建新游戏 2、管理员创建游戏时指定
3、等待指定游戏人数的玩家加入,等待期间,可发送quit交易退出 竞猜的内容(比如:未来的一场足球比赛)、
4、最后一名玩家加入,游戏开始、发牌,计算结果 选项(比如:A队赢或者B队赢或者打平)、
5、根据结果,划转筹码 赌注类型(比如BTY)、
6、合约账户提现到真实账户 单注大小(比如5BTY)、
7、状态:start->continue->quit 单次最多可下注数量(比如100注)、
截止下注时间(比如UTC时间2018-12-12 10:00:00或者区块高度1000000)
游戏超时时间(比如UTC时间2018-12-20 10:00:00或者区块高度1080000)
可下注的最大地址数量(比如20000个)
3、截止下注时间之前,玩家可根据游戏要求进行下注,下注金额注入合约地址。如果投注地址数量已经超过上限,则不允许新的地址投注。
4、截止下注时间达到后,玩家不可再下注。
5、现实世界的竞猜结果出现后,管理员在游戏超时时间之前公布游戏结果。
6、合约根据管理员输入的正确结果,对每个地址的投注进行输赢判断,并将所有赌注对所有竞猜正确的地址按各自的投注额占比进行比例分配。
7、如果因为现实世界的突发异常导致竞猜不能继续(比如某场足球比赛因为不可抗力取消了),则管理员可以终止竞猜,合约将把所有地址的投注返还。
8、如果游戏超时,管理员仍未公布结果,则任何地址都可以触发合约异常终止竞猜,合约中的投注返还给投注地址。
8、游戏状态:
start(管理员)->bet(玩家)->publish(管理员)
start(管理员)->bet(玩家)->abort(管理员)
start(管理员)->bet(玩家)->timeout->abort(任何人)
说明:这里的管理员不是特殊地址,而是谁创建竞猜游戏,谁就是本局竞猜游戏的管理员。
*/ */
...@@ -45,22 +45,22 @@ func (g *Guess) GetDriverName() string { ...@@ -45,22 +45,22 @@ func (g *Guess) GetDriverName() string {
return pkt.GuessX return pkt.GuessX
} }
func calcPBGameAddrPrefix(addr string) []byte { func calcGuessGameAddrPrefix(addr string) []byte {
key := fmt.Sprintf("LODB-guess-addr:%s:", addr) key := fmt.Sprintf("LODB-guess-addr:%s:", addr)
return []byte(key) return []byte(key)
} }
func calcPBGameAddrKey(addr string, index int64) []byte { func calcGuessGameAddrKey(addr string, index int64) []byte {
key := fmt.Sprintf("LODB-guess-addr:%s:%018d", addr, index) key := fmt.Sprintf("LODB-guess-addr:%s:%018d", addr, index)
return []byte(key) return []byte(key)
} }
func calcPBGameStatusPrefix(status int32) []byte { func calcGuessGameStatusPrefix(status int32) []byte {
key := fmt.Sprintf("LODB-guess-status-index:%d:", status) key := fmt.Sprintf("LODB-guess-status-index:%d:", status)
return []byte(key) return []byte(key)
} }
func calcPBGameStatusKey(status int32, index int64) []byte { func calcGuessGameStatusKey(status int32, index int64) []byte {
key := fmt.Sprintf("LODB-guess-status-index:%d:%018d", status, index) key := fmt.Sprintf("LODB-guess-status-index:%d:%018d", status, index)
return []byte(key) return []byte(key)
} }
......
...@@ -7,6 +7,7 @@ package executor ...@@ -7,6 +7,7 @@ package executor
import ( import (
"errors" "errors"
"fmt" "fmt"
"github.com/33cn/chain33/client"
"sort" "sort"
"strconv" "strconv"
...@@ -23,7 +24,8 @@ const ( ...@@ -23,7 +24,8 @@ const (
ListASC = int32(1) ListASC = int32(1)
DefaultCount = int32(20) //默认一次取多少条记录 DefaultCount = int32(20) //默认一次取多少条记录
MAX_PLAYER_NUM = 5 MaxBetsNumber = 100000
MaxHeight = 1000000000
MIN_PLAY_VALUE = 10 * types.Coin MIN_PLAY_VALUE = 10 * types.Coin
//DefaultStyle = pkt.PlayStyleDefault //DefaultStyle = pkt.PlayStyleDefault
) )
...@@ -38,6 +40,7 @@ type Action struct { ...@@ -38,6 +40,7 @@ type Action struct {
execaddr string execaddr string
localDB dbm.Lister localDB dbm.Lister
index int index int
api client.QueueProtocolAPI
} }
func NewAction(guess *Guess, tx *types.Transaction, index int) *Action { func NewAction(guess *Guess, tx *types.Transaction, index int) *Action {
...@@ -54,6 +57,7 @@ func NewAction(guess *Guess, tx *types.Transaction, index int) *Action { ...@@ -54,6 +57,7 @@ func NewAction(guess *Guess, tx *types.Transaction, index int) *Action {
execaddr: dapp.ExecAddress(string(tx.Execer)), execaddr: dapp.ExecAddress(string(tx.Execer)),
localDB: guess.GetLocalDB(), localDB: guess.GetLocalDB(),
index: index, index: index,
api: guess.GetApi(),
} }
} }
...@@ -122,17 +126,17 @@ func getGameListByAddr(db dbm.Lister, addr string, index int64) (types.Message, ...@@ -122,17 +126,17 @@ func getGameListByAddr(db dbm.Lister, addr string, index int64) (types.Message,
var values [][]byte var values [][]byte
var err error var err error
if index == 0 { if index == 0 {
values, err = db.List(calcPBGameAddrPrefix(addr), nil, DefaultCount, ListDESC) values, err = db.List(calcGuessGameAddrPrefix(addr), nil, DefaultCount, ListDESC)
} else { } else {
values, err = db.List(calcPBGameAddrPrefix(addr), calcPBGameAddrKey(addr, index), DefaultCount, ListDESC) values, err = db.List(calcGuessGameAddrPrefix(addr), calcGuessGameAddrKey(addr, index), DefaultCount, ListDESC)
} }
if err != nil { if err != nil {
return nil, err return nil, err
} }
var gameIds []*pkt.PBGameRecord var gameIds []*pkt.GuessGameRecord
for _, value := range values { for _, value := range values {
var record pkt.PBGameRecord var record pkt.GuessGameRecord
err := types.Decode(value, &record) err := types.Decode(value, &record)
if err != nil { if err != nil {
continue continue
...@@ -140,24 +144,24 @@ func getGameListByAddr(db dbm.Lister, addr string, index int64) (types.Message, ...@@ -140,24 +144,24 @@ func getGameListByAddr(db dbm.Lister, addr string, index int64) (types.Message,
gameIds = append(gameIds, &record) gameIds = append(gameIds, &record)
} }
return &pkt.PBGameRecords{gameIds}, nil return &pkt.GuessGameRecords{Records: gameIds}, nil
} }
func getGameListByStatus(db dbm.Lister, status int32, index int64) (types.Message, error) { func getGameListByStatus(db dbm.Lister, status int32, index int64) (types.Message, error) {
var values [][]byte var values [][]byte
var err error var err error
if index == 0 { if index == 0 {
values, err = db.List(calcPBGameStatusPrefix(status), nil, DefaultCount, ListDESC) values, err = db.List(calcGuessGameStatusPrefix(status), nil, DefaultCount, ListDESC)
} else { } else {
values, err = db.List(calcPBGameStatusPrefix(status), calcPBGameStatusKey(status, index), DefaultCount, ListDESC) values, err = db.List(calcGuessGameStatusPrefix(status), calcGuessGameStatusKey(status, index), DefaultCount, ListDESC)
} }
if err != nil { if err != nil {
return nil, err return nil, err
} }
var gameIds []*pkt.PBGameRecord var gameIds []*pkt.GuessGameRecord
for _, value := range values { for _, value := range values {
var record pkt.PBGameRecord var record pkt.GuessGameRecord
err := types.Decode(value, &record) err := types.Decode(value, &record)
if err != nil { if err != nil {
continue continue
...@@ -165,7 +169,7 @@ func getGameListByStatus(db dbm.Lister, status int32, index int64) (types.Messag ...@@ -165,7 +169,7 @@ func getGameListByStatus(db dbm.Lister, status int32, index int64) (types.Messag
gameIds = append(gameIds, &record) gameIds = append(gameIds, &record)
} }
return &pkt.PBGameRecords{gameIds}, nil return &pkt.GuessGameRecords{Records: gameIds}, nil
} }
func queryGameListByStatusAndPlayer(db dbm.Lister, stat int32, player int32, value int64) ([]string, error) { func queryGameListByStatusAndPlayer(db dbm.Lister, stat int32, player int32, value int64) ([]string, error) {
...@@ -187,10 +191,10 @@ func queryGameListByStatusAndPlayer(db dbm.Lister, stat int32, player int32, val ...@@ -187,10 +191,10 @@ func queryGameListByStatusAndPlayer(db dbm.Lister, stat int32, player int32, val
return gameIds, nil return gameIds, nil
} }
func (action *Action) saveGame(game *pkt.PokerBull) (kvset []*types.KeyValue) { func (action *Action) saveGame(game *pkt.GuessGame) (kvset []*types.KeyValue) {
value := types.Encode(game) value := types.Encode(game)
action.db.Set(Key(game.GetGameId()), value) action.db.Set(Key(game.GetGameId()), value)
kvset = append(kvset, &types.KeyValue{Key(game.GameId), value}) kvset = append(kvset, &types.KeyValue{Key: Key(game.GameId), value})
return kvset return kvset
} }
...@@ -198,31 +202,22 @@ func (action *Action) getIndex(game *pkt.PokerBull) int64 { ...@@ -198,31 +202,22 @@ func (action *Action) getIndex(game *pkt.PokerBull) int64 {
return action.height*types.MaxTxsPerBlock + int64(action.index) return action.height*types.MaxTxsPerBlock + int64(action.index)
} }
func (action *Action) GetReceiptLog(game *pkt.PokerBull) *types.ReceiptLog { func (action *Action) GetReceiptLog(game *pkt.GuessGame) *types.ReceiptLog {
log := &types.ReceiptLog{} log := &types.ReceiptLog{}
r := &pkt.ReceiptPBGame{} r := &pkt.ReceiptGuessGame{}
r.Addr = action.fromaddr r.Addr = action.fromaddr
if game.Status == pkt.PBGameActionStart { if game.Status == pkt.GuessGameActionStart {
log.Ty = pkt.TyLogPBGameStart log.Ty = pkt.TyLogGuessGameStart
} else if game.Status == pkt.PBGameActionContinue { } else if game.Status == pkt.GuessGameActionBet {
log.Ty = pkt.TyLogPBGameContinue log.Ty = pkt.TyLogGuessGameBet
} else if game.Status == pkt.PBGameActionQuit { } else if game.Status == pkt.GuessGameActionAbort {
log.Ty = pkt.TyLogPBGameQuit log.Ty = pkt.TyLogGuessGameAbort
} else if game.Status == pkt.GuessGameActionPublish {
log.Ty = pkt.TyLogGuessGamePublish
} }
r.GameId = game.GameId r.GameId = game.GameId
r.Status = game.Status r.Status = game.Status
r.Index = game.GetIndex()
r.PrevIndex = game.GetPrevIndex()
r.PlayerNum = game.PlayerNum
r.Value = game.Value
r.IsWaiting = game.IsWaiting
if !r.IsWaiting {
for _, v := range game.Players {
r.Players = append(r.Players, v.Address)
}
}
r.PreStatus = game.PreStatus
log.Log = types.Encode(r) log.Log = types.Encode(r)
return log return log
} }
...@@ -462,39 +457,32 @@ func (action *Action) checkDupPlayerAddress(id string, pbPlayers []*pkt.PBPlayer ...@@ -462,39 +457,32 @@ func (action *Action) checkDupPlayerAddress(id string, pbPlayers []*pkt.PBPlayer
} }
// 新建一局游戏 // 新建一局游戏
func (action *Action) newGame(gameId string, start *pkt.PBGameStart) (*pkt.PokerBull, error) { func (action *Action) newGame(gameId string, start *pkt.GuessGameStart) (*pkt.GuessGame, error) {
var game *pkt.PokerBull var game *pkt.GuessGame
game = &pkt.GuessGame{
// 不指定赌注,默认按照最低赌注
if start.GetValue() == 0 {
start.Value = MIN_PLAY_VALUE
}
//TODO 庄家检查闲家数量倍数的资金
if DefaultStyle == pkt.PlayStyleDealer {
if !action.CheckExecAccountBalance(action.fromaddr, start.GetValue()*POKERBULL_LEVERAGE_MAX*int64(start.PlayerNum-1), 0) {
logger.Error("GameStart", "addr", action.fromaddr, "execaddr", action.execaddr, "id",
gameId, "err", types.ErrNoBalance)
return nil, types.ErrNoBalance
}
}
game = &pkt.PokerBull{
GameId: gameId, GameId: gameId,
Status: pkt.PBGameActionStart, Status: pkt.GuessGameActionStart,
StartTime: action.blocktime, //StartTime: action.blocktime,
StartTxHash: gameId, StartTxHash: gameId,
Value: start.GetValue(), Topic: start.Topic,
Poker: NewPoker(), Category: start.Category,
PlayerNum: start.PlayerNum, Options: start.Options,
Index: action.getIndex(game), MaxTime: start.MaxTime,
DealerAddr: action.fromaddr, MaxHeight: start.MaxHeight,
IsWaiting: true, Symbol: start.Symbol,
PreStatus: 0, Exec: start.Exec,
OneBet: start.OneBet,
MaxBets: start.MaxBets,
MaxBetsNumber: start.MaxBetsNumber,
Fee: start.Fee,
FeeAddr: start.FeeAddr,
Expire: start.Expire,
ExpireHeight: start.ExpireHeight,
//AdminAddr: action.fromaddr,
//Index: action.getIndex(game),
} }
Shuffle(game.Poker, action.blocktime) //洗牌
return game, nil return game, nil
} }
...@@ -545,17 +533,24 @@ func (action *Action) checkPlayerExistInGame() bool { ...@@ -545,17 +533,24 @@ func (action *Action) checkPlayerExistInGame() bool {
return true return true
} }
func (action *Action) GameStart(start *pkt.PBGameStart) (*types.Receipt, error) { func (action *Action) GameStart(start *pkt.GuessGameStart) (*types.Receipt, error) {
var logs []*types.ReceiptLog var logs []*types.ReceiptLog
var kv []*types.KeyValue var kv []*types.KeyValue
if start.PlayerNum > MAX_PLAYER_NUM { if start.MaxHeight >= MaxHeight {
logger.Error("GameStart", "addr", action.fromaddr, "execaddr", action.execaddr, logger.Error("GameStart", "addr", action.fromaddr, "execaddr", action.execaddr,
"err", fmt.Sprintf("The maximum player number is %d", MAX_PLAYER_NUM)) "err", fmt.Sprintf("The maximum height number is %d", MaxHeight))
return nil, types.ErrInvalidParam
}
if start.MaxBetsNumber >= MaxBetsNumber {
logger.Error("GameStart", "addr", action.fromaddr, "execaddr", action.execaddr,
"err", fmt.Sprintf("The maximum bets number is %d", MaxBetsNumber))
return nil, types.ErrInvalidParam return nil, types.ErrInvalidParam
} }
gameId := common.ToHex(action.txhash) gameId := common.ToHex(action.txhash)
/*
if !action.CheckExecAccountBalance(action.fromaddr, start.GetValue()*POKERBULL_LEVERAGE_MAX, 0) { if !action.CheckExecAccountBalance(action.fromaddr, start.GetValue()*POKERBULL_LEVERAGE_MAX, 0) {
logger.Error("GameStart", "addr", action.fromaddr, "execaddr", action.execaddr, "id", gameId, "err", types.ErrNoBalance) logger.Error("GameStart", "addr", action.fromaddr, "execaddr", action.execaddr, "id", gameId, "err", types.ErrNoBalance)
return nil, types.ErrNoBalance return nil, types.ErrNoBalance
...@@ -564,9 +559,10 @@ func (action *Action) GameStart(start *pkt.PBGameStart) (*types.Receipt, error) ...@@ -564,9 +559,10 @@ func (action *Action) GameStart(start *pkt.PBGameStart) (*types.Receipt, error)
if action.checkPlayerExistInGame() { if action.checkPlayerExistInGame() {
logger.Error("GameStart", "addr", action.fromaddr, "execaddr", action.execaddr, "err", "Address is already in a game") logger.Error("GameStart", "addr", action.fromaddr, "execaddr", action.execaddr, "err", "Address is already in a game")
return nil, fmt.Errorf("Address is already in a game") return nil, fmt.Errorf("Address is already in a game")
} }*/
var game *pkt.PokerBull = nil var game *pkt.GuessGame = nil
/*
ids, err := queryGameListByStatusAndPlayer(action.localDB, pkt.PBGameActionStart, start.PlayerNum, start.Value) ids, err := queryGameListByStatusAndPlayer(action.localDB, pkt.PBGameActionStart, start.PlayerNum, start.Value)
if err != nil || len(ids) == 0 { if err != nil || len(ids) == 0 {
if err != types.ErrNotFound { if err != types.ErrNotFound {
...@@ -586,20 +582,14 @@ func (action *Action) GameStart(start *pkt.PBGameStart) (*types.Receipt, error) ...@@ -586,20 +582,14 @@ func (action *Action) GameStart(start *pkt.PBGameStart) (*types.Receipt, error)
return nil, err return nil, err
} }
} }
} }*/
game, err := action.newGame(gameId, start)
//发牌随机数取txhash
txrng, err := action.genTxRnd(action.txhash)
if err != nil { if err != nil {
return nil, err return nil, err
} }
game.StartTime = action.blocktime
game.AdminAddr = action.fromaddr
//加入当前玩家信息
game.Players = append(game.Players, &pkt.PBPlayer{
Address: action.fromaddr,
TxHash: txrng,
Ready: false,
})
// 如果人数达标,则发牌计算斗牛结果 // 如果人数达标,则发牌计算斗牛结果
if len(game.Players) == int(game.PlayerNum) { if len(game.Players) == int(game.PlayerNum) {
...@@ -628,7 +618,7 @@ func (action *Action) GameStart(start *pkt.PBGameStart) (*types.Receipt, error) ...@@ -628,7 +618,7 @@ func (action *Action) GameStart(start *pkt.PBGameStart) (*types.Receipt, error)
logs = append(logs, receiptLog) logs = append(logs, receiptLog)
kv = append(kv, action.saveGame(game)...) kv = append(kv, action.saveGame(game)...)
return &types.Receipt{types.ExecOk, kv, logs}, nil return &types.Receipt{Ty: types.ExecOk, KV: kv, Logs: logs}, nil
} }
func getReadyPlayerNum(players []*pkt.PBPlayer) int { func getReadyPlayerNum(players []*pkt.PBPlayer) int {
......
...@@ -7,25 +7,28 @@ package types; ...@@ -7,25 +7,28 @@ package types;
//竞猜游戏内容 //竞猜游戏内容
message GuessGame { message GuessGame {
string gameId = 1; //游戏ID string gameId = 1; //游戏ID
uint32 status = 2; //游戏的状态:创建->投注->截止投注->开奖 uint32 status = 2; //游戏的状态:创建->投注->截止投注->开奖
int64 startTime = 3; //创建游戏的时间 int64 startTime = 3; //创建游戏的时间
string startTxHash = 4; //创建游戏的交易hash string startTxHash = 4; //创建游戏的交易hash
string topic = 5; //主题 string topic = 5; //主题
string options = 6; //选项 string category = 6; //分类
int64 stopTime = 7; //截止下注时间 string options = 7; //选项
uint32 maxHeight = 8; //截止下注的块高 string maxTime = 8; //截止下注时间
string symbol = 9; //bty或者具体token uint32 maxHeight = 9; //截止下注的块高
string exec = 10; //coins或者token string symbol = 10; //bty或者具体token
uint32 oneBet = 11; //一注等于多少bty或者token string exec = 11; //coins或者token
uint32 maxBets = 12; //单次可以下多少注,默认100 uint32 oneBet = 12; //一注等于多少bty或者token
uint32 maxBetsNumber = 13; //最多可以下多少注 uint32 maxBets = 13; //单次可以下多少注,默认100
uint32 fee = 14; //收取费用,不带则表示不收费 uint32 maxBetsNumber = 14; //最多可以下多少注
string feeAddr = 15; //收费地址 uint32 fee = 15; //收取费用,不带则表示不收费
string adminAddr = 16; //游戏创建者地址,只有该地址可以开奖 string feeAddr = 16; //收费地址
uint32 betsNumber = 17; //已下注数,如果数量达到maxBetsNumber,则不允许再下注 string expire = 17; //游戏过期时间
repeated GuessPlayer plays = 18; //参与游戏下注的玩家投注信息 uint32 expireHeight = 18; //游戏过期区块高度
string result = 19; string adminAddr = 19; //游戏创建者地址,只有该地址可以开奖
repeated GuessBet bets = 20; uint32 betsNumber = 20; //已下注数,如果数量达到maxBetsNumber,则不允许再下注
repeated GuessPlayer plays = 21; //参与游戏下注的玩家投注信息
string result = 22;
repeated GuessBet bets = 23;
} }
message GuessPlayer { message GuessPlayer {
...@@ -140,14 +143,18 @@ message GuessGameAction { ...@@ -140,14 +143,18 @@ message GuessGameAction {
message GuessGameStart{ message GuessGameStart{
string topic = 1; string topic = 1;
string options = 2; string options = 2;
uint32 maxHeight = 3; string category = 3;
string symbol = 4; string maxTime = 4;
string exec = 5; uint32 maxHeight = 5;
uint32 oneBet = 6; string symbol = 6;
uint32 maxBets = 7; string exec = 7;
uint32 maxBetsNumber = 8; uint32 oneBet = 8;
uint64 fee = 9; uint32 maxBets = 9;
string feeAddr = 10; uint32 maxBetsNumber = 10;
uint64 fee = 11;
string feeAddr = 12;
string expire = 13;
uint32 expireHeight = 14;
} }
//参与游戏下注 //参与游戏下注
...@@ -229,19 +236,29 @@ message ReceiptPBGame { ...@@ -229,19 +236,29 @@ message ReceiptPBGame {
int32 preStatus = 10; int32 preStatus = 10;
} }
message ReceiptGuessGame {
string gameId = 1;
uint32 status = 2;
string addr = 3;
int64 index = 4;
}
message GuessStartTxReq { message GuessStartTxReq {
string topic = 1; string topic = 1;
string options = 2; string options = 2;
int64 startTime = 3; int64 startTime = 3;
int64 stopTime = 4; string maxTime = 4;
uint32 maxHeight = 5; uint32 maxHeight = 5;
string symbol = 6; string symbol = 6;
string exec = 7; string exec = 7;
uint32 oneBet = 8; uint32 oneBet = 8;
uint32 maxBets = 9; uint32 maxBets = 9;
uint32 maxBetsNumber = 10; uint32 maxBetsNumber = 10;
uint64 fee = 11; uint64 fee = 11;
string feeAddr = 12; string feeAddr = 12;
string expire = 13;
uint32 expireHeight = 14;
} }
message GuessBetTxReq { message GuessBetTxReq {
...@@ -275,7 +292,25 @@ message PBQueryReq { ...@@ -275,7 +292,25 @@ message PBQueryReq {
int64 fee = 2; int64 fee = 2;
} }
// pokerbull 对外提供服务的接口
// 索引value值
message GuessGameRecord {
string gameId = 1;
int32 status = 2;
int64 index = 3;
}
message GuessGameIndexRecord {
string gameId = 1;
int64 index = 2;
}
message GuessGameRecords {
repeated GuessGameRecord records = 1;
}
// guess 对外提供服务的接口
service guess { service guess {
//游戏开始 //游戏开始
rpc GuessStart(GuessGameStart) returns (UnsignTx) {} rpc GuessStart(GuessGameStart) returns (UnsignTx) {}
......
...@@ -20,7 +20,7 @@ func (c *channelClient) GuessStart(ctx context.Context, head *pb.GuessGameStart) ...@@ -20,7 +20,7 @@ func (c *channelClient) GuessStart(ctx context.Context, head *pb.GuessGameStart)
val := &pb.GuessGameAction{ val := &pb.GuessGameAction{
Ty: pb.GuessGameActionStart, Ty: pb.GuessGameActionStart,
Value: &pb.GuessGameAction_Start{head}, Value: &pb.GuessGameAction_Start{head},
} }
tx, err := types.CreateFormatTx(pb.GuessX, types.Encode(val)) tx, err := types.CreateFormatTx(pb.GuessX, types.Encode(val))
if err != nil { if err != nil {
......
...@@ -31,8 +31,8 @@ const ( ...@@ -31,8 +31,8 @@ const (
TyLogGuessGameStart = 901 TyLogGuessGameStart = 901
TyLogGuessGameBet = 902 TyLogGuessGameBet = 902
TyLogGuessGameDraw = 903 TyLogGuessGameAbort = 903
TyLogGuessGameClose = 904 TyLogGuessGamePublish = 904
) )
//包的名字可以通过配置文件来配置 //包的名字可以通过配置文件来配置
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment