Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
plugin
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
JIRA
JIRA
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
link33
plugin
Commits
af1ce4be
Commit
af1ce4be
authored
Nov 26, 2018
by
张振华
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
guess
parent
6ed5261f
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
191 additions
and
156 deletions
+191
-156
game.go
plugin/dapp/guess/commands/game.go
+20
-8
doc.go
plugin/dapp/guess/executor/doc.go
+31
-33
guess.go
plugin/dapp/guess/executor/guess.go
+4
-4
guessdb.go
plugin/dapp/guess/executor/guessdb.go
+67
-77
guess.proto
plugin/dapp/guess/proto/guess.proto
+66
-31
rpc.go
plugin/dapp/guess/rpc/rpc.go
+1
-1
const.go
plugin/dapp/guess/types/const.go
+2
-2
guess.pb.go
plugin/dapp/guess/types/guess.pb.go
+0
-0
No files found.
plugin/dapp/guess/commands/game.go
View file @
af1ce4be
...
...
@@ -50,30 +50,37 @@ func addGuessStartFlags(cmd *cobra.Command) {
cmd
.
Flags
()
.
StringP
(
"options"
,
"o"
,
""
,
"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
.
Flags
()
.
StringP
(
"symbol"
,
"s"
,
"bty"
,
"token symbol"
)
cmd
.
Flags
()
.
StringP
(
"exec"
,
"e"
,
"coins"
,
"excutor name"
)
cmd
.
Flags
()
.
Uint32P
(
"oneBet"
,
"b"
,
0
,
"one bet number"
)
cmd
.
MarkFlagRequired
(
"oneBet"
)
cmd
.
Flags
()
.
Uint32P
(
"maxBets"
,
"m"
,
0
,
"max bets one time"
)
cmd
.
MarkFlagRequired
(
"maxBets"
)
cmd
.
Flags
()
.
Uint32P
(
"oneBet"
,
"b"
,
10
,
"one bet number, eg:10 bty / 10 token"
)
//cmd.MarkFlagRequired("oneBet")
cmd
.
Flags
()
.
Uint32P
(
"maxBets
Number"
,
"n"
,
100
,
"max bets number
"
)
cmd
.
MarkFlagRequired
(
"maxBetsNumber
"
)
cmd
.
Flags
()
.
Uint32P
(
"maxBets
"
,
"m"
,
10000
,
"max bets one time
"
)
//cmd.MarkFlagRequired("maxBets
")
cmd
.
Flags
()
.
Uint32P
(
"maxBetsNumber"
,
"n"
,
100000
,
"max bets number"
)
//cmd.MarkFlagRequired("maxBetsNumber")
cmd
.
Flags
()
.
Float64P
(
"fee"
,
"f"
,
0
,
"fee"
)
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
)
{
rpcLaddr
,
_
:=
cmd
.
Flags
()
.
GetString
(
"rpc_laddr"
)
topic
,
_
:=
cmd
.
Flags
()
.
GetString
(
"topic"
)
options
,
_
:=
cmd
.
Flags
()
.
GetString
(
"options"
)
maxTime
,
_
:=
cmd
.
Flags
()
.
GetString
(
"maxTime"
)
maxHeight
,
_
:=
cmd
.
Flags
()
.
GetUint32
(
"maxHeight"
)
symbol
,
_
:=
cmd
.
Flags
()
.
GetString
(
"symbol"
)
exec
,
_
:=
cmd
.
Flags
()
.
GetString
(
"exec"
)
...
...
@@ -82,12 +89,15 @@ func guessStart(cmd *cobra.Command, args []string) {
maxBetsNumber
,
_
:=
cmd
.
Flags
()
.
GetUint32
(
"maxBetsNumber"
)
fee
,
_
:=
cmd
.
Flags
()
.
GetFloat64
(
"fee"
)
feeAddr
,
_
:=
cmd
.
Flags
()
.
GetString
(
"feeAddr"
)
expire
,
_
:=
cmd
.
Flags
()
.
GetString
(
"expire"
)
expireHeight
,
_
:=
cmd
.
Flags
()
.
GetUint32
(
"expireHeight"
)
feeInt64
:=
uint64
(
fee
*
1e4
)
params
:=
&
pkt
.
GuessStartTxReq
{
Topic
:
topic
,
Options
:
options
,
MaxTime
:
maxTime
,
MaxHeight
:
maxHeight
,
Symbol
:
symbol
,
Exec
:
exec
,
...
...
@@ -96,6 +106,8 @@ func guessStart(cmd *cobra.Command, args []string) {
MaxBetsNumber
:
maxBetsNumber
,
Fee
:
feeInt64
,
FeeAddr
:
feeAddr
,
Expire
:
expire
,
ExpireHeight
:
expireHeight
,
}
var
res
string
...
...
plugin/dapp/guess/executor/doc.go
View file @
af1ce4be
...
...
@@ -5,44 +5,42 @@
package
executor
/*
区块链
卡牌游戏:斗牛
区块链
游戏:竞猜
一、玩法简介:
游戏可以由2-5人进行,总共52张牌(除大小王),系统将随机发给玩家每人5张牌,并根据5张牌进行排列组合,进行大小比较确定胜负。
支持两种游戏玩法,普通玩法和庄家玩法
普通玩法:没有庄家,所有玩家直接比大小,最大的玩家赢得所有筹码
庄家玩法:玩家只和庄家比大小,比庄家大则赢得庄家筹码,反之则输给庄家筹码,庄家有创建者开始按加入游戏的顺序轮换
菠菜平台的管理员可以发布竞猜游戏,玩家可以对竞猜游戏进行投注.
截止时间达到后,玩家不能再进行投注,等待管理员公布结果.
竞猜内容的结果出来以后,管理员根据竞猜内容的真实结果触发智能合约进行输赢判断及结算。
二、
发牌和洗牌
1、
洗牌由游戏创建者发起交易的区块时间blocktime作为随机数因子,所以排序链上可见
2、
发牌使用各玩家加入游戏所在交易的hash作为随机数因子,由于nonce的存在,txhash本身具有随机性,且每个玩家每一局的txhash都不一样,可以保证发牌具有随机性
二、
创建及参与游戏
1、
游戏管理员创建一局竞猜游戏时,可以设定竞猜内容,选项,赌注类型、大小及上限,截止时间等,比如竞猜一场足球比赛的结果,每注10BTY,单次最多可下100注,比赛开始前2小时截止投注。
2、
玩家按规则进行投注,如果已过截止时间,则不能继续投注。
三、制胜策略
将玩家a的5张牌分为两组(3+2)后,与玩家b进行大小比较。
1、第一组3张牌的比较规则:要求将5张牌中取出任意3张组成10、20、30的整数(加法运算)。数字A-10的扑克牌数字代表其大小,JQK统一以10计算。
若玩家a和b有那么三张牌能凑成10或20或30的整数,我们称之为有牛,那么则进行第2组两张牌的大小比较。若玩家a或b有某人无法使用3张牌凑成10或20
或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、竞猜游戏对应的现实世界的结果出来以后,游戏管理员向区块链合约公布胜出的竞猜选项。
2、合约将投注的所有赌注向压注正确选项的玩家进行分配,分配原则根据每个地址实际投注的数额占比进行分配,比如一个地址投注占了正确选项投注总额的1/2,则该地址将获得所有赌注总额的1/2。
3、如果因为现实世界的突发异常导致竞猜不能继续(比如某场足球比赛因为不可抗力取消了),则管理员可以终止竞猜,合约将把所有地址的投注返还。
四、游戏过程和状态
1、充值,往pokerbull合约对应的合约账户充值
2、玩家指定游戏人数和筹码加入游戏,如果有等待状态的游戏,直接加入,如果没有,创建新游戏
3、等待指定游戏人数的玩家加入,等待期间,可发送quit交易退出
4、最后一名玩家加入,游戏开始、发牌,计算结果
5、根据结果,划转筹码
6、合约账户提现到真实账户
7、状态:start->continue->quit
1、创建游戏,一个地址可以作为本局竞猜游戏的管理员发起竞猜游戏。
2、管理员创建游戏时指定
竞猜的内容(比如:未来的一场足球比赛)、
选项(比如:A队赢或者B队赢或者打平)、
赌注类型(比如BTY)、
单注大小(比如5BTY)、
单次最多可下注数量(比如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(任何人)
说明:这里的管理员不是特殊地址,而是谁创建竞猜游戏,谁就是本局竞猜游戏的管理员。
*/
plugin/dapp/guess/executor/guess.go
View file @
af1ce4be
...
...
@@ -45,22 +45,22 @@ func (g *Guess) GetDriverName() string {
return
pkt
.
GuessX
}
func
calc
PB
GameAddrPrefix
(
addr
string
)
[]
byte
{
func
calc
Guess
GameAddrPrefix
(
addr
string
)
[]
byte
{
key
:=
fmt
.
Sprintf
(
"LODB-guess-addr:%s:"
,
addr
)
return
[]
byte
(
key
)
}
func
calc
PB
GameAddrKey
(
addr
string
,
index
int64
)
[]
byte
{
func
calc
Guess
GameAddrKey
(
addr
string
,
index
int64
)
[]
byte
{
key
:=
fmt
.
Sprintf
(
"LODB-guess-addr:%s:%018d"
,
addr
,
index
)
return
[]
byte
(
key
)
}
func
calc
PB
GameStatusPrefix
(
status
int32
)
[]
byte
{
func
calc
Guess
GameStatusPrefix
(
status
int32
)
[]
byte
{
key
:=
fmt
.
Sprintf
(
"LODB-guess-status-index:%d:"
,
status
)
return
[]
byte
(
key
)
}
func
calc
PB
GameStatusKey
(
status
int32
,
index
int64
)
[]
byte
{
func
calc
Guess
GameStatusKey
(
status
int32
,
index
int64
)
[]
byte
{
key
:=
fmt
.
Sprintf
(
"LODB-guess-status-index:%d:%018d"
,
status
,
index
)
return
[]
byte
(
key
)
}
...
...
plugin/dapp/guess/executor/guessdb.go
View file @
af1ce4be
...
...
@@ -7,6 +7,7 @@ package executor
import
(
"errors"
"fmt"
"github.com/33cn/chain33/client"
"sort"
"strconv"
...
...
@@ -23,7 +24,8 @@ const (
ListASC
=
int32
(
1
)
DefaultCount
=
int32
(
20
)
//默认一次取多少条记录
MAX_PLAYER_NUM
=
5
MaxBetsNumber
=
100000
MaxHeight
=
1000000000
MIN_PLAY_VALUE
=
10
*
types
.
Coin
//DefaultStyle = pkt.PlayStyleDefault
)
...
...
@@ -38,6 +40,7 @@ type Action struct {
execaddr
string
localDB
dbm
.
Lister
index
int
api
client
.
QueueProtocolAPI
}
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
)),
localDB
:
guess
.
GetLocalDB
(),
index
:
index
,
api
:
guess
.
GetApi
(),
}
}
...
...
@@ -122,17 +126,17 @@ func getGameListByAddr(db dbm.Lister, addr string, index int64) (types.Message,
var
values
[][]
byte
var
err
error
if
index
==
0
{
values
,
err
=
db
.
List
(
calc
PB
GameAddrPrefix
(
addr
),
nil
,
DefaultCount
,
ListDESC
)
values
,
err
=
db
.
List
(
calc
Guess
GameAddrPrefix
(
addr
),
nil
,
DefaultCount
,
ListDESC
)
}
else
{
values
,
err
=
db
.
List
(
calc
PBGameAddrPrefix
(
addr
),
calcPB
GameAddrKey
(
addr
,
index
),
DefaultCount
,
ListDESC
)
values
,
err
=
db
.
List
(
calc
GuessGameAddrPrefix
(
addr
),
calcGuess
GameAddrKey
(
addr
,
index
),
DefaultCount
,
ListDESC
)
}
if
err
!=
nil
{
return
nil
,
err
}
var
gameIds
[]
*
pkt
.
PB
GameRecord
var
gameIds
[]
*
pkt
.
Guess
GameRecord
for
_
,
value
:=
range
values
{
var
record
pkt
.
PB
GameRecord
var
record
pkt
.
Guess
GameRecord
err
:=
types
.
Decode
(
value
,
&
record
)
if
err
!=
nil
{
continue
...
...
@@ -140,24 +144,24 @@ func getGameListByAddr(db dbm.Lister, addr string, index int64) (types.Message,
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
)
{
var
values
[][]
byte
var
err
error
if
index
==
0
{
values
,
err
=
db
.
List
(
calc
PB
GameStatusPrefix
(
status
),
nil
,
DefaultCount
,
ListDESC
)
values
,
err
=
db
.
List
(
calc
Guess
GameStatusPrefix
(
status
),
nil
,
DefaultCount
,
ListDESC
)
}
else
{
values
,
err
=
db
.
List
(
calc
PBGameStatusPrefix
(
status
),
calcPB
GameStatusKey
(
status
,
index
),
DefaultCount
,
ListDESC
)
values
,
err
=
db
.
List
(
calc
GuessGameStatusPrefix
(
status
),
calcGuess
GameStatusKey
(
status
,
index
),
DefaultCount
,
ListDESC
)
}
if
err
!=
nil
{
return
nil
,
err
}
var
gameIds
[]
*
pkt
.
PB
GameRecord
var
gameIds
[]
*
pkt
.
Guess
GameRecord
for
_
,
value
:=
range
values
{
var
record
pkt
.
PB
GameRecord
var
record
pkt
.
Guess
GameRecord
err
:=
types
.
Decode
(
value
,
&
record
)
if
err
!=
nil
{
continue
...
...
@@ -165,7 +169,7 @@ func getGameListByStatus(db dbm.Lister, status int32, index int64) (types.Messag
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
)
{
...
...
@@ -187,10 +191,10 @@ func queryGameListByStatusAndPlayer(db dbm.Lister, stat int32, player int32, val
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
)
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
}
...
...
@@ -198,31 +202,22 @@ func (action *Action) getIndex(game *pkt.PokerBull) int64 {
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
{}
r
:=
&
pkt
.
Receipt
PB
Game
{}
r
:=
&
pkt
.
Receipt
Guess
Game
{}
r
.
Addr
=
action
.
fromaddr
if
game
.
Status
==
pkt
.
PBGameActionStart
{
log
.
Ty
=
pkt
.
TyLogPBGameStart
}
else
if
game
.
Status
==
pkt
.
PBGameActionContinue
{
log
.
Ty
=
pkt
.
TyLogPBGameContinue
}
else
if
game
.
Status
==
pkt
.
PBGameActionQuit
{
log
.
Ty
=
pkt
.
TyLogPBGameQuit
if
game
.
Status
==
pkt
.
GuessGameActionStart
{
log
.
Ty
=
pkt
.
TyLogGuessGameStart
}
else
if
game
.
Status
==
pkt
.
GuessGameActionBet
{
log
.
Ty
=
pkt
.
TyLogGuessGameBet
}
else
if
game
.
Status
==
pkt
.
GuessGameActionAbort
{
log
.
Ty
=
pkt
.
TyLogGuessGameAbort
}
else
if
game
.
Status
==
pkt
.
GuessGameActionPublish
{
log
.
Ty
=
pkt
.
TyLogGuessGamePublish
}
r
.
GameId
=
game
.
GameId
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
)
return
log
}
...
...
@@ -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
)
{
var
game
*
pkt
.
PokerBull
// 不指定赌注,默认按照最低赌注
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
{
func
(
action
*
Action
)
newGame
(
gameId
string
,
start
*
pkt
.
GuessGameStart
)
(
*
pkt
.
GuessGame
,
error
)
{
var
game
*
pkt
.
GuessGame
game
=
&
pkt
.
GuessGame
{
GameId
:
gameId
,
Status
:
pkt
.
PB
GameActionStart
,
StartTime
:
action
.
blocktime
,
Status
:
pkt
.
Guess
GameActionStart
,
//
StartTime: action.blocktime,
StartTxHash
:
gameId
,
Value
:
start
.
GetValue
(),
Poker
:
NewPoker
(),
PlayerNum
:
start
.
PlayerNum
,
Index
:
action
.
getIndex
(
game
),
DealerAddr
:
action
.
fromaddr
,
IsWaiting
:
true
,
PreStatus
:
0
,
Topic
:
start
.
Topic
,
Category
:
start
.
Category
,
Options
:
start
.
Options
,
MaxTime
:
start
.
MaxTime
,
MaxHeight
:
start
.
MaxHeight
,
Symbol
:
start
.
Symbol
,
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
}
...
...
@@ -545,17 +533,24 @@ func (action *Action) checkPlayerExistInGame() bool {
return
true
}
func
(
action
*
Action
)
GameStart
(
start
*
pkt
.
PB
GameStart
)
(
*
types
.
Receipt
,
error
)
{
func
(
action
*
Action
)
GameStart
(
start
*
pkt
.
Guess
GameStart
)
(
*
types
.
Receipt
,
error
)
{
var
logs
[]
*
types
.
ReceiptLog
var
kv
[]
*
types
.
KeyValue
if
start
.
PlayerNum
>
MAX_PLAYER_NUM
{
if
start
.
MaxHeight
>=
MaxHeight
{
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
}
gameId
:=
common
.
ToHex
(
action
.
txhash
)
/*
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)
return nil, types.ErrNoBalance
...
...
@@ -564,9 +559,10 @@ func (action *Action) GameStart(start *pkt.PBGameStart) (*types.Receipt, error)
if action.checkPlayerExistInGame() {
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")
}
}
*/
var
game
*
pkt
.
PokerBull
=
nil
var
game
*
pkt
.
GuessGame
=
nil
/*
ids, err := queryGameListByStatusAndPlayer(action.localDB, pkt.PBGameActionStart, start.PlayerNum, start.Value)
if err != nil || len(ids) == 0 {
if err != types.ErrNotFound {
...
...
@@ -586,20 +582,14 @@ func (action *Action) GameStart(start *pkt.PBGameStart) (*types.Receipt, error)
return nil, err
}
}
}
//发牌随机数取txhash
txrng
,
err
:=
action
.
genTxRnd
(
action
.
txhash
)
}*/
game
,
err
:=
action
.
newGame
(
gameId
,
start
)
if
err
!=
nil
{
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
)
{
...
...
@@ -628,7 +618,7 @@ func (action *Action) GameStart(start *pkt.PBGameStart) (*types.Receipt, error)
logs
=
append
(
logs
,
receiptLog
)
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
{
...
...
plugin/dapp/guess/proto/guess.proto
View file @
af1ce4be
...
...
@@ -7,25 +7,28 @@ package types;
//竞猜游戏内容
message
GuessGame
{
string
gameId
=
1
;
//游戏ID
uint32
status
=
2
;
//游戏的状态:创建->投注->截止投注->开奖
uint32
status
=
2
;
//游戏的状态:创建->投注->截止投注->开奖
int64
startTime
=
3
;
//创建游戏的时间
string
startTxHash
=
4
;
//创建游戏的交易hash
string
topic
=
5
;
//主题
string
options
=
6
;
//选项
int64
stopTime
=
7
;
//截止下注时间
uint32
maxHeight
=
8
;
//截止下注的块高
string
symbol
=
9
;
//bty或者具体token
string
exec
=
10
;
//coins或者token
uint32
oneBet
=
11
;
//一注等于多少bty或者token
uint32
maxBets
=
12
;
//单次可以下多少注,默认100
uint32
maxBetsNumber
=
13
;
//最多可以下多少注
uint32
fee
=
14
;
//收取费用,不带则表示不收费
string
feeAddr
=
15
;
//收费地址
string
adminAddr
=
16
;
//游戏创建者地址,只有该地址可以开奖
uint32
betsNumber
=
17
;
//已下注数,如果数量达到maxBetsNumber,则不允许再下注
repeated
GuessPlayer
plays
=
18
;
//参与游戏下注的玩家投注信息
string
result
=
19
;
repeated
GuessBet
bets
=
20
;
string
category
=
6
;
//分类
string
options
=
7
;
//选项
string
maxTime
=
8
;
//截止下注时间
uint32
maxHeight
=
9
;
//截止下注的块高
string
symbol
=
10
;
//bty或者具体token
string
exec
=
11
;
//coins或者token
uint32
oneBet
=
12
;
//一注等于多少bty或者token
uint32
maxBets
=
13
;
//单次可以下多少注,默认100
uint32
maxBetsNumber
=
14
;
//最多可以下多少注
uint32
fee
=
15
;
//收取费用,不带则表示不收费
string
feeAddr
=
16
;
//收费地址
string
expire
=
17
;
//游戏过期时间
uint32
expireHeight
=
18
;
//游戏过期区块高度
string
adminAddr
=
19
;
//游戏创建者地址,只有该地址可以开奖
uint32
betsNumber
=
20
;
//已下注数,如果数量达到maxBetsNumber,则不允许再下注
repeated
GuessPlayer
plays
=
21
;
//参与游戏下注的玩家投注信息
string
result
=
22
;
repeated
GuessBet
bets
=
23
;
}
message
GuessPlayer
{
...
...
@@ -140,14 +143,18 @@ message GuessGameAction {
message
GuessGameStart
{
string
topic
=
1
;
string
options
=
2
;
uint32
maxHeight
=
3
;
string
symbol
=
4
;
string
exec
=
5
;
uint32
oneBet
=
6
;
uint32
maxBets
=
7
;
uint32
maxBetsNumber
=
8
;
uint64
fee
=
9
;
string
feeAddr
=
10
;
string
category
=
3
;
string
maxTime
=
4
;
uint32
maxHeight
=
5
;
string
symbol
=
6
;
string
exec
=
7
;
uint32
oneBet
=
8
;
uint32
maxBets
=
9
;
uint32
maxBetsNumber
=
10
;
uint64
fee
=
11
;
string
feeAddr
=
12
;
string
expire
=
13
;
uint32
expireHeight
=
14
;
}
//参与游戏下注
...
...
@@ -229,19 +236,29 @@ message ReceiptPBGame {
int32
preStatus
=
10
;
}
message
ReceiptGuessGame
{
string
gameId
=
1
;
uint32
status
=
2
;
string
addr
=
3
;
int64
index
=
4
;
}
message
GuessStartTxReq
{
string
topic
=
1
;
string
options
=
2
;
int64
startTime
=
3
;
int64
stopTime
=
4
;
uint32
maxHeight
=
5
;
string
maxTime
=
4
;
uint32
maxHeight
=
5
;
string
symbol
=
6
;
string
exec
=
7
;
uint32
oneBet
=
8
;
uint32
maxBets
=
9
;
uint32
maxBetsNumber
=
10
;
uint64
fee
=
11
;
uint32
oneBet
=
8
;
uint32
maxBets
=
9
;
uint32
maxBetsNumber
=
10
;
uint64
fee
=
11
;
string
feeAddr
=
12
;
string
expire
=
13
;
uint32
expireHeight
=
14
;
}
message
GuessBetTxReq
{
...
...
@@ -275,7 +292,25 @@ message PBQueryReq {
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
{
//游戏开始
rpc
GuessStart
(
GuessGameStart
)
returns
(
UnsignTx
)
{}
...
...
plugin/dapp/guess/rpc/rpc.go
View file @
af1ce4be
...
...
@@ -20,7 +20,7 @@ func (c *channelClient) GuessStart(ctx context.Context, head *pb.GuessGameStart)
val
:=
&
pb
.
GuessGameAction
{
Ty
:
pb
.
GuessGameActionStart
,
Value
:
&
pb
.
GuessGameAction_Start
{
head
},
Value
:
&
pb
.
GuessGameAction_Start
{
head
},
}
tx
,
err
:=
types
.
CreateFormatTx
(
pb
.
GuessX
,
types
.
Encode
(
val
))
if
err
!=
nil
{
...
...
plugin/dapp/guess/types/const.go
View file @
af1ce4be
...
...
@@ -31,8 +31,8 @@ const (
TyLogGuessGameStart
=
901
TyLogGuessGameBet
=
902
TyLogGuessGame
Draw
=
903
TyLogGuessGame
Close
=
904
TyLogGuessGame
Abort
=
903
TyLogGuessGame
Publish
=
904
)
//包的名字可以通过配置文件来配置
...
...
plugin/dapp/guess/types/guess.pb.go
View file @
af1ce4be
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment