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) {
...
@@ -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
(
"maxBets
Number"
,
"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
...
...
plugin/dapp/guess/executor/doc.go
View file @
af1ce4be
...
@@ -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(任何人)
说明:这里的管理员不是特殊地址,而是谁创建竞猜游戏,谁就是本局竞猜游戏的管理员。
*/
*/
plugin/dapp/guess/executor/guess.go
View file @
af1ce4be
...
@@ -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
calc
PB
GameAddrPrefix
(
addr
string
)
[]
byte
{
func
calc
Guess
GameAddrPrefix
(
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
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
)
key
:=
fmt
.
Sprintf
(
"LODB-guess-addr:%s:%018d"
,
addr
,
index
)
return
[]
byte
(
key
)
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
)
key
:=
fmt
.
Sprintf
(
"LODB-guess-status-index:%d:"
,
status
)
return
[]
byte
(
key
)
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
)
key
:=
fmt
.
Sprintf
(
"LODB-guess-status-index:%d:%018d"
,
status
,
index
)
return
[]
byte
(
key
)
return
[]
byte
(
key
)
}
}
...
...
plugin/dapp/guess/executor/guessdb.go
View file @
af1ce4be
...
@@ -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
(
calc
PB
GameAddrPrefix
(
addr
),
nil
,
DefaultCount
,
ListDESC
)
values
,
err
=
db
.
List
(
calc
Guess
GameAddrPrefix
(
addr
),
nil
,
DefaultCount
,
ListDESC
)
}
else
{
}
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
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
var
gameIds
[]
*
pkt
.
PB
GameRecord
var
gameIds
[]
*
pkt
.
Guess
GameRecord
for
_
,
value
:=
range
values
{
for
_
,
value
:=
range
values
{
var
record
pkt
.
PB
GameRecord
var
record
pkt
.
Guess
GameRecord
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
(
calc
PB
GameStatusPrefix
(
status
),
nil
,
DefaultCount
,
ListDESC
)
values
,
err
=
db
.
List
(
calc
Guess
GameStatusPrefix
(
status
),
nil
,
DefaultCount
,
ListDESC
)
}
else
{
}
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
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
var
gameIds
[]
*
pkt
.
PB
GameRecord
var
gameIds
[]
*
pkt
.
Guess
GameRecord
for
_
,
value
:=
range
values
{
for
_
,
value
:=
range
values
{
var
record
pkt
.
PB
GameRecord
var
record
pkt
.
Guess
GameRecord
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
.
Receipt
PB
Game
{}
r
:=
&
pkt
.
Receipt
Guess
Game
{}
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
.
PB
GameActionStart
,
Status
:
pkt
.
Guess
GameActionStart
,
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
.
PB
GameStart
)
(
*
types
.
Receipt
,
error
)
{
func
(
action
*
Action
)
GameStart
(
start
*
pkt
.
Guess
GameStart
)
(
*
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
{
...
...
plugin/dapp/guess/proto/guess.proto
View file @
af1ce4be
...
@@ -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
)
{}
...
...
plugin/dapp/guess/rpc/rpc.go
View file @
af1ce4be
...
@@ -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
{
...
...
plugin/dapp/guess/types/const.go
View file @
af1ce4be
...
@@ -31,8 +31,8 @@ const (
...
@@ -31,8 +31,8 @@ const (
TyLogGuessGameStart
=
901
TyLogGuessGameStart
=
901
TyLogGuessGameBet
=
902
TyLogGuessGameBet
=
902
TyLogGuessGame
Draw
=
903
TyLogGuessGame
Abort
=
903
TyLogGuessGame
Close
=
904
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