Commit e23d2a79 authored by vipwzw's avatar vipwzw Committed by 33cn

add table query

parent e650737b
......@@ -8,6 +8,9 @@ function Init(context) {
return this.kvc.receipt()
}
var MIN_WAIT_BLOCK = 2
var RAND_MAX = 10
function ExecInit(execthis) {
execthis.acc = new account(this.kvc, "coins", "bty")
}
......@@ -24,13 +27,13 @@ Exec.prototype.NewGame = function(args) {
game.status = 1 //open
//最大值是 9000万,否则js到 int 会溢出
if (game.bet < 10 * COINS || game.bet > 10000000 * COINS) {
throw new Error("bet low than 10 or hight than 10000000")
throwerr("bet low than 10 or hight than 10000000")
}
var err = this.acc.execFrozen(this.name, this.context.from, game.bet)
throwerr(err)
this.kvc.add(game.id, game)
this.kvc.addlog(game)
return this.kvc.receipt()
return this.kvc.receipt()
}
Exec.prototype.Guess = function(args) {
......@@ -41,19 +44,19 @@ Exec.prototype.Guess = function(args) {
match.addr = this.context.from
var game = this.kvc.get(match.gameid)
if (!game) {
throw new Error("game id not found")
throwerr("game id not found")
}
if (game.status != 1) {
throw new Error("game status not open")
throwerr("game status not open")
}
if (match.bet < 1 * COINS || match.bet > game.bet/10) {
throw new Error("match bet litte than 1 or big than game.bet/10")
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)
throwerr(err)
this.kvc.add(match.id, match)
this.kvc.addlog(match)
return this.kvc.receipt()
return this.kvc.receipt()
}
Exec.prototype.CloseGame = function(args) {
......@@ -67,7 +70,7 @@ Exec.prototype.CloseGame = function(args) {
matches = []
}
var n = -1
for (var i = 0; i < 10; i ++) {
for (var i = 0; i < RAND_MAX; i ++) {
if (sha256(args.randstr + i) == game.randhash) {
n = i
}
......@@ -75,8 +78,9 @@ Exec.prototype.CloseGame = function(args) {
if (n == -1) {
throwerr("err rand str")
}
if (this.context.height - game.height < 10) {
throwerr("close game must wait 10 block")
//必须可以让用户可以有一个区块的竞猜时间
if (this.context.height - game.height < MIN_WAIT_BLOCK) {
throwerr("close game must wait 2 block")
}
for (var i = 0; i < matches.length; i++) {
var match = matches[i]
......@@ -95,11 +99,11 @@ Exec.prototype.CloseGame = function(args) {
game.status = 2
this.kvc.add(game.id, game)
this.kvc.addlog(game)
return this.kvc.receipt()
return this.kvc.receipt()
}
function win(this, game, match) {
var amount = 9 * match.bet
var amount = (RAND_MAX - 1) * match.bet
if (game.bet - amount < 0) {
amount = game.bet
}
......@@ -145,28 +149,28 @@ Exec.prototype.ForceCloseGame = function(args) {
game.status = 2
this.kvc.add(game.id, game)
this.kvc.addlog(game)
return this.kvc.receipt()
return this.kvc.receipt()
}
ExecLocal.prototype.NewGame = function(args) {
var local = new MatchGameTable(this.kvc)
local.add(this.logs)
local.table.save()
return this.kvc.receipt()
return this.kvc.receipt()
}
ExecLocal.prototype.Guess = function(args) {
var local = new MatchGameTable(this.kvc)
local.add(this.logs)
local.table.save()
return this.kvc.receipt()
return this.kvc.receipt()
}
ExecLocal.prototype.CloseGame = function(args) {
var local = new MatchGameTable(this.kvc)
local.add(this.logs)
local.table.save()
return this.kvc.receipt()
return this.kvc.receipt()
}
ExecLocal.prototype.ForceCloseGame = function(args) {
......@@ -188,7 +192,6 @@ game.id -> primary
match.gameid -> fk
match.id -> primary
*/
function GameLocalTable(kvc) {
this.config = {
"#tablename" : "game",
......
......@@ -2,6 +2,7 @@ package executor
import (
"encoding/json"
"errors"
"fmt"
"strings"
"sync"
......@@ -121,9 +122,9 @@ func getTable(id int64) (*table.Table, error) {
return nil, types.ErrNotFound
}
func getSaver(id int64) (saver, error) {
func getTabler(id int64) (tabler, error) {
if value, ok := globalTableHandle.Load(id); ok {
return value.(saver), nil
return value.(tabler), nil
}
return nil, types.ErrNotFound
}
......@@ -135,6 +136,24 @@ func registerTableFunc(vm *otto.Otto) {
tableCloseFunc(vm)
tableSave(vm)
tableJoinFunc(vm)
tableQueryFunc(vm)
tableGetFunc(vm)
tableJoinKeyFunc(vm)
}
func tableJoinKeyFunc(vm *otto.Otto) {
vm.Set("table_joinkey", func(call otto.FunctionCall) otto.Value {
left, err := call.Argument(0).ToString()
if err != nil {
return errReturn(vm, err)
}
right, err := call.Argument(1).ToString()
if err != nil {
return errReturn(vm, err)
}
key := table.JoinKey([]byte(left), []byte(right))
return okReturn(vm, string(key))
})
}
func tableAddFunc(vm *otto.Otto) {
......@@ -203,7 +222,37 @@ func tableDelFunc(vm *otto.Otto) {
})
}
type saver interface {
func tableGetFunc(vm *otto.Otto) {
vm.Set("table_get", func(call otto.FunctionCall) otto.Value {
id, err := call.Argument(0).ToInteger()
if err != nil {
return errReturn(vm, err)
}
tab, err := getTabler(id)
if err != nil {
return errReturn(vm, err)
}
key, err := call.Argument(1).ToString()
if err != nil {
return errReturn(vm, err)
}
row, err := call.Argument(2).ToString()
if err != nil {
return errReturn(vm, err)
}
meta := tab.GetMeta()
meta.SetPayload(&jsproto.JsLog{Data: row})
result, err := meta.Get(key)
if err != nil {
return errReturn(vm, err)
}
return okReturn(vm, string(result))
})
}
type tabler interface {
GetMeta() table.RowMeta
ListIndex(indexName string, prefix []byte, primaryKey []byte, count, direction int32) (rows []*table.Row, err error)
Save() (kvs []*types.KeyValue, err error)
}
......@@ -213,7 +262,7 @@ func tableSave(vm *otto.Otto) {
if err != nil {
return errReturn(vm, err)
}
tab, err := getSaver(id)
tab, err := getTabler(id)
if err != nil {
return errReturn(vm, err)
}
......@@ -239,6 +288,86 @@ func tableCloseFunc(vm *otto.Otto) {
})
}
func tableQueryFunc(vm *otto.Otto) {
vm.Set("table_query", func(call otto.FunctionCall) otto.Value {
id, err := call.Argument(0).ToInteger()
if err != nil {
return errReturn(vm, err)
}
tab, err := getTabler(id)
if err != nil {
return errReturn(vm, err)
}
//参数
//List(indexName string, data types.Message, primaryKey []byte, count, direction int32) (rows []*Row, err error)
indexName, err := call.Argument(1).ToString()
if err != nil {
return errReturn(vm, err)
}
prefix, err := call.Argument(2).ToString()
if err != nil {
return errReturn(vm, err)
}
primaryKey, err := call.Argument(3).ToString()
if err != nil {
return errReturn(vm, err)
}
count, err := call.Argument(4).ToInteger()
if err != nil {
return errReturn(vm, err)
}
direction, err := call.Argument(5).ToInteger()
if err != nil {
return errReturn(vm, err)
}
bprefix := []byte(prefix)
if prefix == "" {
bprefix = nil
}
bprimaryKey := []byte(primaryKey)
if primaryKey == "" {
bprimaryKey = nil
}
rows, err := tab.ListIndex(indexName, bprefix, bprimaryKey, int32(count), int32(direction))
if err != nil {
return errReturn(vm, err)
}
_, isjoin := tab.(*table.JoinTable)
querylist := make([]*otto.Object, len(rows))
for i := 0; i < len(rows); i++ {
if isjoin {
joindata, ok := rows[i].Data.(*table.JoinData)
if !ok {
return errReturn(vm, errors.New("jointable has no joindata"))
}
leftdata, ok := joindata.Left.(*jsproto.JsLog)
if !ok {
return errReturn(vm, errors.New("leftdata is not JsLog"))
}
rightdata, ok := joindata.Right.(*jsproto.JsLog)
if !ok {
return errReturn(vm, errors.New("rightdata is not jslog"))
}
obj := newObject(vm).setValue("left", leftdata.Data)
obj.setValue("right", rightdata.Data)
querylist[i] = obj.object()
} else {
leftdata, ok := rows[i].Data.(*jsproto.JsLog)
if !ok {
return errReturn(vm, errors.New("data is not JsLog"))
}
obj := newObject(vm).setValue("left", leftdata.Data)
querylist[i] = obj.object()
}
}
retvalue, err := vm.ToValue(querylist)
if err != nil {
return errReturn(vm, err)
}
return retvalue
})
}
func tableJoinFunc(vm *otto.Otto) {
vm.Set("new_join_table", func(call otto.FunctionCall) otto.Value {
left, err := call.Argument(0).ToInteger()
......
......@@ -312,6 +312,16 @@ func (table *Table) getPrimaryFromData(data types.Message) (primaryKey []byte, e
return
}
//ListIndex list table index
func (table *Table) ListIndex(indexName string, prefix []byte, primaryKey []byte, count, direction int32) (rows []*Row, err error) {
kvdb, ok := table.kvdb.(db.KVDB)
if !ok {
return nil, errors.New("list only support KVDB interface")
}
query := &Query{table: table, kvdb: kvdb}
return query.ListIndex(indexName, prefix, primaryKey, count, direction)
}
//Replace 如果有重复的,那么替换
func (table *Table) Replace(data types.Message) error {
if err := table.checkIndex(data); err != nil {
......@@ -602,8 +612,15 @@ func (table *Table) getModify(row, oldrow *Row, index string) ([]byte, []byte, b
return indexkey, oldkey, true, nil
}
//GetQuery 获取查询结构
//GetQuery 获取查询结构(允许传入 kvdb 为nil)
func (table *Table) GetQuery(kvdb db.KVDB) *Query {
if kvdb == nil {
var ok bool
kvdb, ok = table.kvdb.(db.KVDB)
if !ok {
return nil
}
}
return &Query{table: table, kvdb: kvdb}
}
......@@ -611,6 +628,11 @@ func (table *Table) getMeta() RowMeta {
return table.meta
}
//GetMeta 获取meta
func (table *Table) GetMeta() RowMeta {
return table.getMeta()
}
func (table *Table) getOpt() *Option {
return table.opt
}
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