Commit 878799ee authored by vipwzw's avatar vipwzw Committed by 33cn

fix game bug

parent 150cc47b
......@@ -32,11 +32,14 @@ Table.prototype.joinkey = function(left, right) {
}
Table.prototype.get = function(key, row) {
if (!isstring(row)) {
row = tojson(row)
}
return table_get(this.id, key, row)
}
Table.prototype.query = function(indexName, prefix, primaryKey, count, direction) {
if (!count) {
function query_list(indexName, prefix, primaryKey, count, direction) {
if (count !== 0 && !count) {
count = 20
}
if (!direction) {
......@@ -52,7 +55,14 @@ Table.prototype.query = function(indexName, prefix, primaryKey, count, direction
indexName = ""
}
var q = table_query(this.id, indexName, prefix, primaryKey, count, direction)
return tojson(q)
if (q.err) {
return null
}
return q
}
Table.prototype.query = function(indexName, prefix, primaryKey, count, direction) {
return query_list.call(this, indexName, prefix, primaryKey, count, direction)
}
Table.prototype.replace = function(obj) {
......@@ -109,12 +119,31 @@ function print(obj) {
JoinTable.prototype.save = function() {
var ret = table_save(this.id)
print(ret)
if (this.kvc) {
this.kvc.save(ret)
}
return ret
}
JoinTable.prototype.get = function(key, row) {
if (!isstring(row)) {
row = tojson(row)
}
return table_get(this.id, key, row)
}
JoinTable.prototype.query = function(indexName, prefix, primaryKey, count, direction) {
return query_list.call(this, indexName, prefix, primaryKey, count, direction)
}
function querytojson(data) {
if (!data) {
return "[]"
}
return tojson(data)
}
JoinTable.prototype.close = function() {
table_close(this.lefttable.id)
table_close(this.righttable.id)
......@@ -424,6 +453,10 @@ function Query(context) {
}
}
Query.prototype.JoinKey = function(args) {
return table_joinkey(args.left, args.right).value
}
function throwerr(err) {
if (err) {
throw new Error(err)
......@@ -550,17 +583,22 @@ Exec.prototype.Guess = function(args) {
match.id = this.txID()
match.addr = this.context.from
match.hash = this.context.txhash
match.num = args.num
var game = this.kvc.get(match.gameid)
if (!game) {
throwerr("game id not found")
throwerr("guess: game id not found")
}
if (game.status != 1) {
throwerr("game status not open")
throwerr("guess: game status not open")
}
if (this.context.from == game.addr) {
throwerr("guess: game addr and match addr is same")
}
if (match.bet < 1 * COINS || match.bet > game.bet / RAND_MAX) {
throwerr("match bet litte than 1 or big than game.bet/10")
}
var err = this.acc.execFrozen(this.name, this.context.from, game.bet)
var err = this.acc.execFrozen(this.name, this.context.from, match.bet)
console.log(this.name, this.context.from, err)
throwerr(err)
this.kvc.add(match.id, match)
this.kvc.addlog(match)
......@@ -568,18 +606,21 @@ Exec.prototype.Guess = function(args) {
}
Exec.prototype.CloseGame = function(args) {
var local = new MatchLocalTable(this.kvc)
var game = this.kvc.get(args.id)
var local = MatchLocalTable(this.kvc)
var game = this.kvc.get(args.gameid)
if (!game) {
throwerr("game id not found")
}
var matches = local.getmath(args.id)
var querykey = local.get("gameid", args)
print("---------")
print(querykey)
var matches = local.query("gameid", querykey, "", 0, 1)
if (!matches) {
matches = []
}
var n = -1
for (var i = 0; i < RAND_MAX; i ++) {
if (sha256(args.randstr + i) == game.randhash) {
for (var i = 0; i < RAND_MAX; i++) {
if (Sha256(args.randstr + i) == game.randhash) {
n = i
}
}
......@@ -588,7 +629,7 @@ Exec.prototype.CloseGame = function(args) {
}
//必须可以让用户可以有一个区块的竞猜时间
if (this.context.height - game.height < MIN_WAIT_BLOCK) {
throwerr("close game must wait 2 block")
throwerr("close game must wait "+MIN_WAIT_BLOCK+" block")
}
for (var i = 0; i < matches.length; i++) {
var match = matches[i]
......@@ -661,27 +702,22 @@ Exec.prototype.ForceCloseGame = function(args) {
}
ExecLocal.prototype.NewGame = function(args) {
var local = MatchGameTable(this.kvc)
local.addlogs(this.logs)
local.save()
return this.kvc.receipt()
return localprocess.call(this, args)
}
ExecLocal.prototype.Guess = function(args) {
var local = MatchGameTable(this.kvc)
local.addlogs(this.logs)
local.save()
return this.kvc.receipt()
return localprocess.call(this, args)
}
ExecLocal.prototype.CloseGame = function(args) {
var local = MatchGameTable(this.kvc)
local.addlogs(this.logs)
local.save()
return this.kvc.receipt()
return localprocess.call(this, args)
}
ExecLocal.prototype.ForceCloseGame = function(args) {
return localprocess.call(this, args)
}
function localprocess(args) {
var local = MatchGameTable(this.kvc)
local.addlogs(this.logs)
local.save()
......@@ -690,16 +726,16 @@ ExecLocal.prototype.ForceCloseGame = function(args) {
Query.prototype.ListGameByAddr = function(args) {
var local = GameLocalTable(this.kvc)
return local.query("addr", args.addr, args.primaryKey, args.count, args.direction)
var q = local.query("addr", args.addr, args.primaryKey, args.count, args.direction)
return querytojson(q)
}
/*
game ->(1 : n) match
game.gameid -> primary
Query.prototype.ListMatchByAddr = function(args) {
var local = MatchGameTable(this.kvc)
var q= local.query("addr#status", args["addr#status"], args.primaryKey, args.count, args.direction)
return querytojson(q)
}
match.gameid -> fk
match.id -> primary
*/
function GameLocalTable(kvc) {
this.config = {
"#tablename" : "game",
......
......@@ -84,17 +84,22 @@ Exec.prototype.Guess = function(args) {
match.id = this.txID()
match.addr = this.context.from
match.hash = this.context.txhash
match.num = args.num
var game = this.kvc.get(match.gameid)
if (!game) {
throwerr("game id not found")
throwerr("guess: game id not found")
}
if (game.status != 1) {
throwerr("game status not open")
throwerr("guess: game status not open")
}
if (this.context.from == game.addr) {
throwerr("guess: game addr and match addr is same")
}
if (match.bet < 1 * COINS || match.bet > game.bet / RAND_MAX) {
throwerr("match bet litte than 1 or big than game.bet/10")
}
var err = this.acc.execFrozen(this.name, this.context.from, game.bet)
var err = this.acc.execFrozen(this.name, this.context.from, match.bet)
console.log(this.name, this.context.from, err)
throwerr(err)
this.kvc.add(match.id, match)
this.kvc.addlog(match)
......@@ -102,18 +107,21 @@ Exec.prototype.Guess = function(args) {
}
Exec.prototype.CloseGame = function(args) {
var local = new MatchLocalTable(this.kvc)
var game = this.kvc.get(args.id)
var local = MatchLocalTable(this.kvc)
var game = this.kvc.get(args.gameid)
if (!game) {
throwerr("game id not found")
}
var matches = local.getmath(args.id)
var querykey = local.get("gameid", args)
print("---------")
print(querykey)
var matches = local.query("gameid", querykey, "", 0, 1)
if (!matches) {
matches = []
}
var n = -1
for (var i = 0; i < RAND_MAX; i ++) {
if (sha256(args.randstr + i) == game.randhash) {
for (var i = 0; i < RAND_MAX; i++) {
if (Sha256(args.randstr + i) == game.randhash) {
n = i
}
}
......@@ -122,7 +130,7 @@ Exec.prototype.CloseGame = function(args) {
}
//必须可以让用户可以有一个区块的竞猜时间
if (this.context.height - game.height < MIN_WAIT_BLOCK) {
throwerr("close game must wait 2 block")
throwerr("close game must wait "+MIN_WAIT_BLOCK+" block")
}
for (var i = 0; i < matches.length; i++) {
var match = matches[i]
......@@ -195,27 +203,22 @@ Exec.prototype.ForceCloseGame = function(args) {
}
ExecLocal.prototype.NewGame = function(args) {
var local = MatchGameTable(this.kvc)
local.addlogs(this.logs)
local.save()
return this.kvc.receipt()
return localprocess.call(this, args)
}
ExecLocal.prototype.Guess = function(args) {
var local = MatchGameTable(this.kvc)
local.addlogs(this.logs)
local.save()
return this.kvc.receipt()
return localprocess.call(this, args)
}
ExecLocal.prototype.CloseGame = function(args) {
var local = MatchGameTable(this.kvc)
local.addlogs(this.logs)
local.save()
return this.kvc.receipt()
return localprocess.call(this, args)
}
ExecLocal.prototype.ForceCloseGame = function(args) {
return localprocess.call(this, args)
}
function localprocess(args) {
var local = MatchGameTable(this.kvc)
local.addlogs(this.logs)
local.save()
......@@ -224,16 +227,16 @@ ExecLocal.prototype.ForceCloseGame = function(args) {
Query.prototype.ListGameByAddr = function(args) {
var local = GameLocalTable(this.kvc)
return local.query("addr", args.addr, args.primaryKey, args.count, args.direction)
var q = local.query("addr", args.addr, args.primaryKey, args.count, args.direction)
return querytojson(q)
}
/*
game ->(1 : n) match
game.gameid -> primary
Query.prototype.ListMatchByAddr = function(args) {
var local = MatchGameTable(this.kvc)
var q= local.query("addr#status", args["addr#status"], args.primaryKey, args.count, args.direction)
return querytojson(q)
}
match.gameid -> fk
match.id -> primary
*/
function GameLocalTable(kvc) {
this.config = {
"#tablename" : "game",
......
......@@ -47,17 +47,22 @@ Exec.prototype.Guess = function(args) {
match.id = this.txID()
match.addr = this.context.from
match.hash = this.context.txhash
match.num = args.num
var game = this.kvc.get(match.gameid)
if (!game) {
throwerr("game id not found")
throwerr("guess: game id not found")
}
if (game.status != 1) {
throwerr("game status not open")
throwerr("guess: game status not open")
}
if (this.context.from == game.addr) {
throwerr("guess: game addr and match addr is same")
}
if (match.bet < 1 * COINS || match.bet > game.bet / RAND_MAX) {
throwerr("match bet litte than 1 or big than game.bet/10")
}
var err = this.acc.execFrozen(this.name, this.context.from, game.bet)
var err = this.acc.execFrozen(this.name, this.context.from, match.bet)
console.log(this.name, this.context.from, err)
throwerr(err)
this.kvc.add(match.id, match)
this.kvc.addlog(match)
......@@ -65,18 +70,19 @@ Exec.prototype.Guess = function(args) {
}
Exec.prototype.CloseGame = function(args) {
var local = new MatchLocalTable(this.kvc)
var game = this.kvc.get(args.id)
var local = MatchLocalTable(this.kvc)
var game = this.kvc.get(args.gameid)
if (!game) {
throwerr("game id not found")
}
var matches = local.getmath(args.id)
var querykey = local.get("gameid", args)
var matches = local.query("gameid", querykey, "", 0, 1)
if (!matches) {
matches = []
}
var n = -1
for (var i = 0; i < RAND_MAX; i ++) {
if (sha256(args.randstr + i) == game.randhash) {
for (var i = 0; i < RAND_MAX; i++) {
if (Sha256(args.randstr + i) == game.randhash) {
n = i
}
}
......@@ -85,7 +91,7 @@ Exec.prototype.CloseGame = function(args) {
}
//必须可以让用户可以有一个区块的竞猜时间
if (this.context.height - game.height < MIN_WAIT_BLOCK) {
throwerr("close game must wait 2 block")
throwerr("close game must wait "+MIN_WAIT_BLOCK+" block")
}
for (var i = 0; i < matches.length; i++) {
var match = matches[i]
......@@ -158,27 +164,22 @@ Exec.prototype.ForceCloseGame = function(args) {
}
ExecLocal.prototype.NewGame = function(args) {
var local = MatchGameTable(this.kvc)
local.addlogs(this.logs)
local.save()
return this.kvc.receipt()
return localprocess.call(this, args)
}
ExecLocal.prototype.Guess = function(args) {
var local = MatchGameTable(this.kvc)
local.addlogs(this.logs)
local.save()
return this.kvc.receipt()
return localprocess.call(this, args)
}
ExecLocal.prototype.CloseGame = function(args) {
var local = MatchGameTable(this.kvc)
local.addlogs(this.logs)
local.save()
return this.kvc.receipt()
return localprocess.call(this, args)
}
ExecLocal.prototype.ForceCloseGame = function(args) {
return localprocess.call(this, args)
}
function localprocess(args) {
var local = MatchGameTable(this.kvc)
local.addlogs(this.logs)
local.save()
......@@ -187,16 +188,16 @@ ExecLocal.prototype.ForceCloseGame = function(args) {
Query.prototype.ListGameByAddr = function(args) {
var local = GameLocalTable(this.kvc)
return local.query("addr", args.addr, args.primaryKey, args.count, args.direction)
var q = local.query("addr", args.addr, args.primaryKey, args.count, args.direction)
return querytojson(q)
}
/*
game ->(1 : n) match
game.gameid -> primary
Query.prototype.ListMatchByAddr = function(args) {
var local = MatchGameTable(this.kvc)
var q= local.query("addr#status", args["addr#status"], args.primaryKey, args.count, args.direction)
return querytojson(q)
}
match.gameid -> fk
match.id -> primary
*/
function GameLocalTable(kvc) {
this.config = {
"#tablename" : "game",
......
package executor_test
import (
"encoding/json"
"fmt"
"math/rand"
"testing"
......@@ -134,12 +135,33 @@ func TestJsGame(t *testing.T) {
block = mocker.GetLastBlock()
balance = mocker.GetExecAccount(block.StateHash, "user.jsvm."+contractName, mocker.GetHotAddress()).Balance
assert.Equal(t, 100*types.Coin, balance)
reqtx = &rpctypes.CreateTx{
To: address.ExecAddress("user.jsvm." + contractName),
Amount: 100 * types.Coin,
Note: "12312",
IsWithdraw: false,
IsToken: false,
TokenSymbol: "",
ExecName: "user.jsvm." + contractName,
}
err = mocker.GetJSONC().Call("Chain33.CreateRawTransaction", reqtx, &txhex)
assert.Nil(t, err)
hash, err = mocker.SendAndSign(mocker.GetGenesisKey(), txhex)
assert.Nil(t, err)
txinfo, err = mocker.WaitTx(hash)
assert.Nil(t, err)
assert.Equal(t, txinfo.Receipt.Ty, int32(2))
block = mocker.GetLastBlock()
balance = mocker.GetExecAccount(block.StateHash, "user.jsvm."+contractName, mocker.GetGenesisAddress()).Balance
assert.Equal(t, 100*types.Coin, balance)
t.Log(mocker.GetGenesisAddress())
//2.2 调用 hello 函数(随机数,用nonce)
privhash := common.Sha256(mocker.GetHotKey().Bytes())
nonce := rand.Int63()
num := rand.Int63() % 10
realhash := common.Sha256([]byte(string(privhash) + ":" + fmt.Sprint(nonce)))
myhash := common.ToHex(common.Sha256([]byte(string(realhash) + fmt.Sprint(num))))
realhash := common.ToHex(common.Sha256([]byte(string(privhash) + ":" + fmt.Sprint(nonce))))
myhash := common.ToHex(common.Sha256([]byte(realhash + fmt.Sprint(num))))
call := &jsproto.Call{
Funcname: "NewGame",
......@@ -153,14 +175,71 @@ func TestJsGame(t *testing.T) {
}
err = mocker.GetJSONC().Call("Chain33.CreateTransaction", req, &txhex)
assert.Nil(t, err)
t.Log(mocker.GetHotAddress())
hash, err = mocker.SendAndSignNonce(mocker.GetHotKey(), txhex, nonce)
assert.Nil(t, err)
txinfo, err = mocker.WaitTx(hash)
assert.Nil(t, err)
assert.Equal(t, txinfo.Receipt.Ty, int32(2))
gameid := txinfo.Height*100000 + txinfo.Index
//2.3 guess a number (win)
call = &jsproto.Call{
Funcname: "Guess",
Name: contractName,
Args: fmt.Sprintf(`{"bet": %d, "gameid" : "%d", "num" : %d}`, 1*types.Coin, gameid, num),
}
req = &rpctypes.CreateTxIn{
Execer: "user." + ptypes.JsX + "." + contractName,
ActionName: "Call",
Payload: types.MustPBToJSON(call),
}
err = mocker.GetJSONC().Call("Chain33.CreateTransaction", req, &txhex)
assert.Nil(t, err)
hash, err = mocker.SendAndSignNonce(mocker.GetGenesisKey(), txhex, nonce)
assert.Nil(t, err)
txinfo, err = mocker.WaitTx(hash)
assert.Nil(t, err)
assert.Equal(t, txinfo.Receipt.Ty, int32(2))
//3. query 函数查询
//2.4 guess a num (failed)
call = &jsproto.Call{
Funcname: "Guess",
Name: contractName,
Args: fmt.Sprintf(`{"bet": %d, "gameid" : "%d", "num" : %d}`, 1*types.Coin, gameid, num+1),
}
req = &rpctypes.CreateTxIn{
Execer: "user." + ptypes.JsX + "." + contractName,
ActionName: "Call",
Payload: types.MustPBToJSON(call),
}
err = mocker.GetJSONC().Call("Chain33.CreateTransaction", req, &txhex)
assert.Nil(t, err)
t.Log(mocker.GetHotAddress())
hash, err = mocker.SendAndSignNonce(mocker.GetGenesisKey(), txhex, nonce)
assert.Nil(t, err)
txinfo, err = mocker.WaitTx(hash)
assert.Nil(t, err)
assert.Equal(t, txinfo.Receipt.Ty, int32(2))
//2.5 close the game
call = &jsproto.Call{
Funcname: "CloseGame",
Name: contractName,
Args: fmt.Sprintf(`{"gameid":%d, "randstr":"%s"}`, gameid, realhash),
}
req = &rpctypes.CreateTxIn{
Execer: "user." + ptypes.JsX + "." + contractName,
ActionName: "Call",
Payload: types.MustPBToJSON(call),
}
err = mocker.GetJSONC().Call("Chain33.CreateTransaction", req, &txhex)
assert.Nil(t, err)
t.Log(mocker.GetHotAddress())
hash, err = mocker.SendAndSignNonce(mocker.GetHotKey(), txhex, nonce)
assert.Nil(t, err)
txinfo, err = mocker.WaitTx(hash)
assert.Nil(t, err)
assert.Equal(t, txinfo.Receipt.Ty, int32(2))
//3.1 query game 函数查询
call = &jsproto.Call{
Funcname: "ListGameByAddr",
Name: contractName,
......@@ -175,4 +254,35 @@ func TestJsGame(t *testing.T) {
err = mocker.GetJSONC().Call("Chain33.Query", query, &queryresult)
assert.Nil(t, err)
t.Log(queryresult.Data)
//3.2 query match -> status 函数
call = &jsproto.Call{
Funcname: "JoinKey",
Name: contractName,
Args: fmt.Sprintf(`{"left":"%s", "right" : "%s"}`, mocker.GetGenesisAddress(), "2"),
}
query = &rpctypes.Query4Jrpc{
Execer: "user." + ptypes.JsX + "." + contractName,
FuncName: "Query",
Payload: types.MustPBToJSON(call),
}
err = mocker.GetJSONC().Call("Chain33.Query", query, &queryresult)
assert.Nil(t, err)
joinkey := queryresult.Data
reqjson := make(map[string]interface{})
reqjson["addr#status"] = joinkey
reqdata, _ := json.Marshal(reqjson)
call = &jsproto.Call{
Funcname: "ListMatchByAddr",
Name: contractName,
Args: string(reqdata),
}
query = &rpctypes.Query4Jrpc{
Execer: "user." + ptypes.JsX + "." + contractName,
FuncName: "Query",
Payload: types.MustPBToJSON(call),
}
err = mocker.GetJSONC().Call("Chain33.Query", query, &queryresult)
assert.Nil(t, err)
t.Log(queryresult.Data)
}
......@@ -29,11 +29,14 @@ Table.prototype.joinkey = function(left, right) {
}
Table.prototype.get = function(key, row) {
if (!isstring(row)) {
row = tojson(row)
}
return table_get(this.id, key, row)
}
Table.prototype.query = function(indexName, prefix, primaryKey, count, direction) {
if (!count) {
function query_list(indexName, prefix, primaryKey, count, direction) {
if (count !== 0 && !count) {
count = 20
}
if (!direction) {
......@@ -49,7 +52,14 @@ Table.prototype.query = function(indexName, prefix, primaryKey, count, direction
indexName = ""
}
var q = table_query(this.id, indexName, prefix, primaryKey, count, direction)
return tojson(q)
if (q.err) {
return null
}
return q
}
Table.prototype.query = function(indexName, prefix, primaryKey, count, direction) {
return query_list.call(this, indexName, prefix, primaryKey, count, direction)
}
Table.prototype.replace = function(obj) {
......@@ -106,12 +116,31 @@ function print(obj) {
JoinTable.prototype.save = function() {
var ret = table_save(this.id)
print(ret)
if (this.kvc) {
this.kvc.save(ret)
}
return ret
}
JoinTable.prototype.get = function(key, row) {
if (!isstring(row)) {
row = tojson(row)
}
return table_get(this.id, key, row)
}
JoinTable.prototype.query = function(indexName, prefix, primaryKey, count, direction) {
return query_list.call(this, indexName, prefix, primaryKey, count, direction)
}
function querytojson(data) {
if (!data) {
return "[]"
}
return tojson(data)
}
JoinTable.prototype.close = function() {
table_close(this.lefttable.id)
table_close(this.righttable.id)
......@@ -421,6 +450,10 @@ function Query(context) {
}
}
Query.prototype.JoinKey = function(args) {
return table_joinkey(args.left, args.right).value
}
function throwerr(err) {
if (err) {
throw new Error(err)
......
......@@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"regexp"
"strconv"
"strings"
"github.com/33cn/chain33/common/db"
......@@ -468,28 +469,34 @@ func (row *JSONRow) SetPayload(data types.Message) error {
//Get value of row
func (row *JSONRow) Get(key string) ([]byte, error) {
v, err := row.get(key)
return v, err
}
func (row *JSONRow) get(key string) ([]byte, error) {
if format, ok := row.config[key]; ok {
if data, ok := row.data[key]; ok {
if n, ok := data.(json.Number); ok {
if row.isint.Match([]byte(format)) { //ini
num, err := n.Int64()
if row.isint.Match([]byte(format)) { //int
s := fmt.Sprint(data)
num, err := strconv.ParseInt(s, 10, 64)
if err != nil {
return nil, err
}
return []byte(fmt.Sprintf(format, num)), nil
} else if row.isfloat.Match([]byte(format)) {
num, err := n.Float64()
} else if row.isfloat.Match([]byte(format)) { //float
s := fmt.Sprint(data)
num, err := strconv.ParseFloat(s, 64)
if err != nil {
return nil, err
}
return []byte(fmt.Sprintf(format, num)), nil
} else {
s := n.String()
return []byte(fmt.Sprintf(format, s)), nil
} else { //string
if n, ok := data.(json.Number); ok {
data = n.String()
}
}
return []byte(fmt.Sprintf(format, data)), nil
}
}
return nil, types.ErrNotFound
return nil, errors.New("get key " + key + "from data err")
}
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