-
Notifications
You must be signed in to change notification settings - Fork 109
/
exec_del_local.go
160 lines (134 loc) · 4.46 KB
/
exec_del_local.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package executor
import (
"fmt"
"github.com/33cn/chain33/common/db/table"
"github.com/33cn/chain33/types"
gty "github.com/33cn/plugin/plugin/dapp/guess/types"
)
func (g *Guess) rollbackGame(game *gty.GuessGame, log *gty.ReceiptGuessGame) {
if game == nil || log == nil {
return
}
//如果状态发生了变化,则需要将游戏状态恢复到前一状态
if log.StatusChange {
game.Status = log.PreStatus
game.Index = log.PreIndex
//玩家信息中的index回滚
for i := 0; i < len(game.Plays); i++ {
player := game.Plays[i]
player.Bet.Index = player.Bet.PreIndex
}
}
//如果下注了,则需要把下注回滚
if log.Bet {
//统计信息回滚
game.BetStat.TotalBetTimes--
game.BetStat.TotalBetsNumber -= log.BetsNumber
for i := 0; i < len(game.BetStat.Items); i++ {
item := game.BetStat.Items[i]
if item.Option == log.Option {
item.BetsTimes--
item.BetsNumber -= log.BetsNumber
break
}
}
//玩家下注信息回滚
for i := 0; i < len(game.Plays); i++ {
player := game.Plays[i]
if player.Addr == log.Addr && player.Bet.Index == log.Index {
game.Plays = append(game.Plays[:i], game.Plays[i+1:]...)
break
}
}
}
}
func (g *Guess) rollbackIndex(log *gty.ReceiptGuessGame) (kvs []*types.KeyValue, err error) {
userTable := gty.NewGuessUserTable(g.GetLocalDB())
gameTable := gty.NewGuessGameTable(g.GetLocalDB())
tableJoin, err := table.NewJoinTable(userTable, gameTable, []string{"addr#status"})
if err != nil {
return nil, err
}
if log.Status == gty.GuessGameStatusStart {
//新创建游戏回滚,game表删除记录
err = gameTable.Del([]byte(fmt.Sprintf("%018d", log.StartIndex)))
if err != nil {
return nil, err
}
kvs, err = tableJoin.Save()
return kvs, err
} else if log.Status == gty.GuessGameStatusBet {
//下注阶段,需要更新游戏信息,回滚下注信息
game := log.Game
log.Game = nil
//先回滚游戏信息,再进行更新
g.rollbackGame(game, log)
err = tableJoin.MustGetTable("game").Replace(game)
if err != nil {
return nil, err
}
err = tableJoin.MustGetTable("user").Del([]byte(fmt.Sprintf("%018d", log.Index)))
if err != nil {
return nil, err
}
kvs, err = tableJoin.Save()
if err != nil {
return nil, err
}
} else if log.StatusChange {
//如果是其他状态下仅发生了状态变化,则需要恢复游戏状态,并更新游戏记录。
game := log.Game
log.Game = nil
//先回滚游戏信息,再进行更新
g.rollbackGame(game, log)
err = tableJoin.MustGetTable("game").Replace(game)
if err != nil {
return nil, err
}
kvs, err = tableJoin.Save()
if err != nil {
return nil, err
}
}
return kvs, nil
}
func (g *Guess) execDelLocal(receipt *types.ReceiptData) (*types.LocalDBSet, error) {
dbSet := &types.LocalDBSet{}
if receipt.GetTy() != types.ExecOk {
return dbSet, nil
}
for _, log := range receipt.Logs {
switch log.GetTy() {
case gty.TyLogGuessGameStart, gty.TyLogGuessGameBet, gty.TyLogGuessGameStopBet, gty.TyLogGuessGameAbort, gty.TyLogGuessGamePublish, gty.TyLogGuessGameTimeout:
receiptGame := >y.ReceiptGuessGame{}
if err := types.Decode(log.Log, receiptGame); err != nil {
return nil, err
}
kv, err := g.rollbackIndex(receiptGame)
if err != nil {
return nil, err
}
dbSet.KV = append(dbSet.KV, kv...)
}
}
return dbSet, nil
}
//ExecDelLocal_Start Guess执行器Start交易撤销
func (g *Guess) ExecDelLocal_Start(payload *gty.GuessGameStart, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return g.execLocal(receiptData)
}
//ExecDelLocal_Bet Guess执行器Bet交易撤销
func (g *Guess) ExecDelLocal_Bet(payload *gty.GuessGameBet, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return g.execLocal(receiptData)
}
//ExecDelLocal_Publish Guess执行器Publish交易撤销
func (g *Guess) ExecDelLocal_Publish(payload *gty.GuessGamePublish, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return g.execLocal(receiptData)
}
//ExecDelLocal_Abort Guess执行器Abort交易撤销
func (g *Guess) ExecDelLocal_Abort(payload *gty.GuessGameAbort, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return g.execLocal(receiptData)
}