This commit is contained in:
sk 2024-04-12 10:35:47 +08:00
parent fec1e4441d
commit 9405ae091e
842 changed files with 193371 additions and 91 deletions

6
.gitattribute Normal file
View File

@ -0,0 +1,6 @@
*.go text eol=lf
*.json text eol=lf
*.dat text eol=lf
*.bin text eol=lf
*.proto text eol=lf
*.xml text eol=lf

43
.gitignore vendored Normal file
View File

@ -0,0 +1,43 @@
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.exe~
*.test
*.log
*.log.*
.idea
.vscode
*.ts
**/.DS_Store
# linux可执行文件
/dbproxy/dbproxy
/mgrsrv/mgrsrv
/gatesrv/gatesrv
/gamesrv/gamesrv
/worldsrv/worldsrv
/robot/robot
/schedulesrv/schedulesrv
/ranksrv/ranksrv
/bin/*
**/backup

0
CHANGELOG.md Normal file
View File

View File

@ -1,93 +1,4 @@
# game
## win88
服务端业务代码
## Getting started
To make it easy for you to get started with GitLab, here's a list of recommended next steps.
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
## Add your files
- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
```
cd existing_repo
git remote add origin https://git.pogorockgames.com/mango-games/server/game.git
git branch -M main
git push -uf origin main
```
## Integrate with your tools
- [ ] [Set up project integrations](https://git.pogorockgames.com/mango-games/server/game/-/settings/integrations)
## Collaborate with your team
- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
- [ ] [Set auto-merge](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
## Test and Deploy
Use the built-in continuous integration in GitLab.
- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
***
# Editing this README
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template.
## Suggestions for a good README
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
## Name
Choose a self-explaining name for your project.
## Description
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
## Badges
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
## Visuals
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
## Installation
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
## Usage
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
## Support
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
## Roadmap
If you have ideas for releases in the future, it is a good idea to list them in the README.
## Contributing
State if you are open to contributions and what your requirements are for accepting them.
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
## Authors and acknowledgment
Show your appreciation to those who have contributed to the project.
## License
For open source projects, say how it is licensed.
## Project status
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.

79
api3th/common.go Normal file
View File

@ -0,0 +1,79 @@
package api3th
import "bytes"
// 牌数据转换
// 1 2 3 4 5 6 7 8 9 10 11 12 13 52 53 =>
// A 2 3 4 5 6 7 8 9 T J Q K B C
func CardValueToShowCard(cards []int32) string {
ret := bytes.NewBuffer([]byte{})
for _, v := range cards {
ret.WriteString(AIRecordMap[GetPoint(v)])
}
return ret.String()
}
// 扑克牌点数
func GetPoint(v int32) int32 {
if v >= 52 {
return v
}
return v%13 + 1
}
var AIRecordMap = map[int32]string{
53: "C",
52: "B",
1: "A",
2: "2",
3: "3",
4: "4",
5: "5",
6: "6",
7: "7",
8: "8",
9: "9",
10: "T",
11: "J",
12: "Q",
13: "K",
}
var AIPointMap = map[string]int32{
"D": 53,
"X": 52,
"C": 53,
"B": 52,
"A": 1,
"2": 2,
"3": 3,
"4": 4,
"5": 5,
"6": 6,
"7": 7,
"8": 8,
"9": 9,
"T": 10,
"J": 11,
"Q": 12,
"K": 13,
}
// 德州扑克接入的机器人接口需要的牌定义
// SHDC 黑红梅方
// 0:2S 1:3S ... 11:13S 12:1S
// 13:2H 14:3H ... 24:13H 25:1H
// 26:2D 27:3D ... 37:13D 38:1D
// 39:2C 40:3C ... 50:13C 51:1C
func DZPCardToAICard(card int32) int32 {
var ret int32
// 点数
if card%13 == 0 {
ret += 12
} else {
ret = card%13 - 1
}
// 花色
ret += (3 - card/13) * 13
return ret
}

240
api3th/config.go Normal file
View File

@ -0,0 +1,240 @@
package api3th
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"github.com/cihub/seelog"
"github.com/google/go-querystring/query"
"io"
"mongo.games.com/game/common"
"net/http"
"strings"
"sync"
"sync/atomic"
"time"
)
const (
// 智能机器人接口
APITypeAI = 0
// 智能化运营接口
APITypeSmart = 1
)
type BaseConfig struct {
sync.Once
methods map[string]string
urlNames map[string]string
seqNo uint64 // 日志序号
IPAddr string
AuthKey string // 接口认证秘钥
TimeoutDuration time.Duration // 请求超时时长
Name string // 游戏名称
ApiType int // 接口类型
}
func (c *BaseConfig) LogName() string {
return fmt.Sprint(c.Name, "Logger")
}
func (c *BaseConfig) Log() seelog.LoggerInterface {
return common.GetLoggerInstanceByName(c.LogName())
}
func (c *BaseConfig) OrderNum() uint64 {
return atomic.AddUint64(&c.seqNo, 1)
}
func (c *BaseConfig) Register(method, name, urlName string) {
if method == "" {
method = "POST"
}
if _, ok := c.urlNames[name]; ok {
panic(fmt.Sprintf("api3th registered name:%s urlName:%s", name, urlName))
}
c.urlNames[name] = urlName
c.methods[name] = method
}
func (c *BaseConfig) Do(name string, req interface{}, args ...time.Duration) (resp []byte, err error) {
// 加载配置
c.Once.Do(func() {
c.AuthKey = common.CustomConfig.GetString(fmt.Sprintf("%sApiKey", c.Name))
c.TimeoutDuration = time.Duration(common.CustomConfig.GetInt(fmt.Sprintf("%sApi3thTimeout", c.Name))) * time.Second
})
timeout := time.Duration(-1)
if len(args) > 0 {
timeout = args[0]
}
url, ok := c.urlNames[name]
if !ok {
return nil, errors.New(fmt.Sprintf("api3th no register %s", name))
}
var code int
method := strings.ToUpper(c.methods[name])
switch method {
case "POST":
code, resp, err = c.Post(url, req, timeout)
case "POSTFORM":
code, resp, err = c.PostForm(url, req)
case "POSTFORMTIMEOUT":
code, resp, err = c.PostFormTimeOut(url, req, timeout)
default:
err = errors.New(fmt.Sprintf("api3th method error %s", c.methods[name]))
}
if code != http.StatusOK {
err = errors.New(fmt.Sprint("error code ", code))
}
return
}
func (c *BaseConfig) Post(url string, req interface{}, timeout time.Duration) (int, []byte, error) {
logger := c.Log()
data, err := json.Marshal(req)
if err != nil {
logger.Error("json.Marshal() error ", err)
return 0, nil, err
}
seqNo := c.OrderNum()
logger.Tracef("%s PostRequest[%d] Url %s Param: %s", c.Name, seqNo, fmt.Sprint(c.IPAddr, url), string(data))
r, err := http.NewRequest("POST", fmt.Sprint(c.IPAddr, url), bytes.NewBuffer(data))
if err != nil {
logger.Errorf("%s PostRequest[%d] http.NewRequest() error: %v", c.Name, seqNo, err)
return 0, nil, err
}
r.Header.Set("Content-Type", "application/json")
if c.AuthKey != "" {
r.Header.Set("Ocp-Apim-Subscription-Key", c.AuthKey)
}
cli := http.Client{}
if timeout >= 0 {
cli.Timeout = timeout
} else {
cli.Timeout = c.TimeoutDuration
}
resp, err := cli.Do(r)
if err != nil {
logger.Errorf("%s PostRequest[%d] httpClient.Do() error: %v", c.Name, seqNo, err)
return 0, nil, err
}
defer resp.Body.Close()
respBytes, err := io.ReadAll(resp.Body)
if err != nil {
logger.Errorf("%s PostRequest[%d] io.ReadAll() error: %v", c.Name, seqNo, err)
return 0, nil, err
}
logger.Tracef("%s PostRequest[%d] StatusCode=%d Body=%s", c.Name, seqNo, resp.StatusCode, string(respBytes))
return resp.StatusCode, respBytes, nil
}
func (c *BaseConfig) PostFormTimeOut(url string, req interface{}, timeout time.Duration) (int, []byte, error) {
logger := c.Log()
data, err := json.Marshal(req)
if err != nil {
logger.Error("json.Marshal() error ", err)
return 0, nil, err
}
seqNo := c.OrderNum()
logger.Tracef("%s PostRequest[%d] Url %s Param: %s", c.Name, seqNo, fmt.Sprint(c.IPAddr, url), string(data))
params, query_err := query.Values(req)
if query_err != nil {
logger.Errorf("(c *BaseConfig) PostForm query.Values %v", query_err)
return 0, nil, query_err
}
rp := strings.NewReader(params.Encode())
r, err := http.NewRequest("POST", fmt.Sprint(c.IPAddr, url), rp)
if err != nil {
logger.Errorf("%s PostRequest[%d] http.NewRequest() error: %v", c.Name, seqNo, err)
return 0, nil, err
}
r.Header.Set("Content-Type", "application/x-www-form-urlencoded")
if c.AuthKey != "" {
r.Header.Set("Ocp-Apim-Subscription-Key", c.AuthKey)
}
cli := http.Client{}
if timeout >= 0 {
cli.Timeout = timeout
} else {
cli.Timeout = c.TimeoutDuration
}
resp, err := cli.Do(r)
if err != nil {
//logger.Errorf("%s PostRequest[%d] httpClient.Do() error: %v", c.Name, seqNo, err)
return 0, nil, err
}
defer resp.Body.Close()
respBytes, err := io.ReadAll(resp.Body)
if err != nil {
logger.Errorf("%s PostRequest[%d] io.ReadAll() error: %v", c.Name, seqNo, err)
return 0, nil, err
}
logger.Tracef("%s PostRequest[%d] StatusCode=%d Body=%s", c.Name, seqNo, resp.StatusCode, string(respBytes))
return resp.StatusCode, respBytes, nil
}
func (c *BaseConfig) PostForm(url1 string, req interface{}) (int, []byte, error) {
logger := c.Log()
data, err := json.Marshal(req)
if err != nil {
logger.Error("json.Marshal() error ", err)
return 0, nil, err
}
c.Log().Info(fmt.Sprint(c.IPAddr, url1), string(data))
params, query_err := query.Values(req)
if query_err != nil {
logger.Errorf("(c *BaseConfig) PostForm query.Values %v", query_err)
return 0, nil, query_err
}
//c.Log().Info(fmt.Sprint(c.IPAddr, url1),params.Encode())
//fmt.Println(vals.Encode())
//
//params := req.(url.Values)
res, err := http.PostForm(fmt.Sprint(c.IPAddr, url1), params)
if err != nil {
logger.Errorf("(c *BaseConfig) PostForm http.PostForm %v", err)
return 0, nil, err
}
defer res.Body.Close()
body, err := io.ReadAll(res.Body)
if err != nil {
logger.Errorf("(c *BaseConfig) PostForm io.ReadAll %v", err)
return 0, nil, err
}
//println(url, " ret:", string(body[:]))
//result := make(map[string]interface{})
//json.Unmarshal(body, &result)
return http.StatusOK, body, err
}
func (c *BaseConfig) Switch() bool {
switch c.ApiType {
case 1: // 智能化运营
return common.CustomConfig.GetBool(fmt.Sprintf("Use%sSmartApi3th", c.Name))
default: // ai
return common.CustomConfig.GetBool(fmt.Sprintf("Use%sRobotApi3th", c.Name))
}
}
func NewBaseConfig(name string, apiType int) *BaseConfig {
ret := new(BaseConfig)
ret.methods = make(map[string]string)
ret.urlNames = make(map[string]string)
ret.Name = name
ret.ApiType = apiType
return ret
}

32
api3th/doc.go Normal file
View File

@ -0,0 +1,32 @@
package api3th
/*
1.三方接口接入方法参考推饼(智能化运营)和十点半(智能ai)
新增智能ai配置 config.json
"costum": {
"UseSDBRobotApi3th":true,
"SDBApi3thTimeout": 10,
"SDBApi3thAddr":"https://api.vonabcs.com",
"SDBApiKey": "284672e9733249c69a4d1558b9080f1e",
}
新增智能化运营配置 config.json
"costum": {
"UseTBSmartApi3th": true,
"TBApi3thTimeout": 10,
"TBApi3thAddr":"https://api.vonabcs.com",
"TBApiKey": "a8c38779-41e0-4a78-b996-8964e752a4d3",
}
2.智能化运营配置在mode/gameparam.go 中的GameParam结构体中新增配置参考百人炸金花和对战场21点
新增配置 data/gameparam.json
"SmartHZJH": {
"SwitchPlatform": ["1"],
"SwitchABTestTailFilter": [],
"SwitchABTestSnIdFilter": [],
"ABTestTick":0 ,
"SwitchPlatformABTestTick": [] ,
"SwitchPlatformABTestTickSnIdFilter": []
}
3.在具体游戏中添加代码实现智能化运营或智能ai
*/

64
api3th/simlog.go Normal file
View File

@ -0,0 +1,64 @@
package api3th
import (
"fmt"
"github.com/cihub/seelog"
)
type TestLog struct {
seelog.LoggerInterface
}
func (this *TestLog) Tracef(format string, params ...interface{}) {
fmt.Printf(format+"\n", params...)
}
func (this *TestLog) Debugf(format string, params ...interface{}) {
fmt.Printf(format+"\n", params...)
}
func (this *TestLog) Infof(format string, params ...interface{}) {
fmt.Printf(format+"\n", params...)
}
func (this *TestLog) Warnf(format string, params ...interface{}) error {
fmt.Printf(format+"\n", params...)
return nil
}
func (this *TestLog) Errorf(format string, params ...interface{}) error {
fmt.Printf(format+"\n", params...)
return nil
}
func (this *TestLog) Criticalf(format string, params ...interface{}) error {
fmt.Printf(format+"\n", params...)
return nil
}
func (this *TestLog) Trace(v ...interface{}) {
fmt.Println(v...)
}
func (this *TestLog) Debug(v ...interface{}) {
fmt.Println(v...)
}
func (this *TestLog) Info(v ...interface{}) {
fmt.Println(v...)
}
func (this *TestLog) Warn(v ...interface{}) error {
fmt.Println(v...)
return nil
}
func (this *TestLog) Error(v ...interface{}) error {
fmt.Println(v...)
return nil
}
func (this *TestLog) Critical(v ...interface{}) error {
fmt.Println(v...)
return nil
}
func (this *TestLog) Close() {
}
func (this *TestLog) Flush() {
}
func (this *TestLog) Closed() bool {
return true
}
func (this *TestLog) SetAdditionalStackDepth(depth int) error {
return nil
}

View File

@ -0,0 +1,66 @@
package tienlen
import "mongo.games.com/game/api3th"
var Config = api3th.NewBaseConfig("TIENLEN", api3th.APITypeSmart)
const (
Predict = "predict"
Legal = "legal"
)
func init() {
Config.Register("PostFormTimeOut", Predict, "/predict")
Config.Register("PostFormTimeOut", Legal, "/legal")
}
type PredictRequest struct {
Bomb_num int `url:"bomb_num" form:"bomb_num"`
Card_play_action_seq string `url:"card_play_action_seq" form:"card_play_action_seq"`
Last_move_0 string `url:"last_move_0" form:"last_move_0"`
Last_move_1 string `url:"last_move_1" form:"last_move_1"`
Last_move_2 string `url:"last_move_2" form:"last_move_2"`
Last_move_3 string `url:"last_move_3" form:"last_move_3"`
Num_cards_left_0 int `url:"num_cards_left_0" form:"num_cards_left_0"`
Num_cards_left_1 int `url:"num_cards_left_1" form:"num_cards_left_1"`
Num_cards_left_2 int `url:"num_cards_left_2" form:"num_cards_left_2"`
Num_cards_left_3 int `url:"num_cards_left_3" form:"num_cards_left_3"`
Other_hand_cards string `url:"other_hand_cards" form:"other_hand_cards"`
Played_cards_0 string `url:"played_cards_0" form:"played_cards_0"`
Played_cards_1 string `url:"played_cards_1" form:"played_cards_1"`
Played_cards_2 string `url:"played_cards_2" form:"played_cards_2"`
Played_cards_3 string `url:"played_cards_3" form:"played_cards_3"`
Player_hand_cards string `url:"player_hand_cards" form:"player_hand_cards"`
Player_position int `url:"player_position" form:"player_position"`
}
type PredictResponse struct {
Message string `json:"message"`
Status int `json:"status"`
Result map[string]string `json:"result"`
WinRates map[string]string `json:"win_rates"`
}
type LegalRequest struct {
Player_hand_cards int `url:"player_hand_cards" form:"player_hand_cards"`
Rival_move string `url:"rival_move" form:"rival_move"`
}
type LegalResponse struct {
Legal_action string `json:"legal_action"`
Message string `json:"message"`
Status int `json:"status"`
}
var CardToAiCard = map[int32]int32{
-1: -1, 0: 2, 1: 3, 2: 4, 3: 5, 4: 6, 5: 7, 6: 8, 7: 9, 8: 10, 9: 11, 10: 12, 11: 0, 12: 1,
13: 15, 14: 16, 15: 17, 16: 18, 17: 19, 18: 20, 19: 21, 20: 22, 21: 23, 22: 24, 23: 25, 24: 13, 25: 14,
26: 28, 27: 29, 28: 30, 29: 31, 30: 32, 31: 33, 32: 34, 33: 35, 34: 36, 35: 37, 36: 38, 37: 26, 38: 27,
39: 41, 40: 42, 41: 43, 42: 44, 43: 45, 44: 46, 45: 47, 46: 48, 47: 49, 48: 50, 49: 51, 50: 39, 51: 40,
}
var AiCardToCard = map[int32]int32{
-1: -1, 2: 0, 3: 1, 4: 2, 5: 3, 6: 4, 7: 5, 8: 6, 9: 7, 10: 8, 11: 9, 12: 10, 0: 11, 1: 12,
15: 13, 16: 14, 17: 15, 18: 16, 19: 17, 20: 18, 21: 19, 22: 20, 23: 21, 24: 22, 25: 23, 13: 24, 14: 25,
28: 26, 29: 27, 30: 28, 31: 29, 32: 30, 33: 31, 34: 32, 35: 33, 36: 34, 37: 35, 38: 36, 26: 37, 27: 38,
41: 39, 42: 40, 43: 41, 44: 42, 45: 43, 46: 44, 47: 45, 48: 46, 49: 47, 50: 48, 51: 49, 39: 50, 40: 51,
}

View File

@ -0,0 +1,76 @@
package tienlen
import "mongo.games.com/game/api3th"
var Config = api3th.NewBaseConfig("TIENLEN", api3th.APITypeSmart)
const (
Predict = "predict"
Legal = "legal"
)
func init() {
Config.Register("PostFormTimeOut", Predict, "/predict")
Config.Register("PostFormTimeOut", Legal, "/legal")
}
type PredictRequest struct {
Bomb_num int `url:"bomb_num" form:"bomb_num"`
Card_play_action_seq string `url:"card_play_action_seq" form:"card_play_action_seq"`
Last_move_0 string `url:"last_move_0" form:"last_move_0"`
Last_move_1 string `url:"last_move_1" form:"last_move_1"`
Last_move_2 string `url:"last_move_2" form:"last_move_2"`
Last_move_3 string `url:"last_move_3" form:"last_move_3"`
Num_cards_left_0 int `url:"num_cards_left_0" form:"num_cards_left_0"`
Num_cards_left_1 int `url:"num_cards_left_1" form:"num_cards_left_1"`
Num_cards_left_2 int `url:"num_cards_left_2" form:"num_cards_left_2"`
Num_cards_left_3 int `url:"num_cards_left_3" form:"num_cards_left_3"`
Other_hand_cards string `url:"other_hand_cards" form:"other_hand_cards"`
Played_cards_0 string `url:"played_cards_0" form:"played_cards_0"`
Played_cards_1 string `url:"played_cards_1" form:"played_cards_1"`
Played_cards_2 string `url:"played_cards_2" form:"played_cards_2"`
Played_cards_3 string `url:"played_cards_3" form:"played_cards_3"`
Player_hand_cards string `url:"player_hand_cards" form:"player_hand_cards"`
Player_position int `url:"player_position" form:"player_position"`
IsTienLenYule bool `url:"isTienLenYule" form:"isTienLenYule"`
IsFirstHand bool `url:"isFirstHand" form:"isFirstHand"`
Cards_left_0 []int32 `url:"cards_left_0" form:"cards_left_0"`
Cards_left_1 []int32 `url:"cards_left_1" form:"cards_left_1"`
Cards_left_2 []int32 `url:"cards_left_2" form:"cards_left_2"`
Cards_left_3 []int32 `url:"cards_left_3" form:"cards_left_3"`
Last_pos int32 `url:"last_pos" form:"last_pos"`
IsEnd bool `url:"isend" form:"isend"`
WinSnids []int32 `url:"winsnids" form:"winsnids"`
IsWin bool `url:"iswin" form:"iswin"`
}
type PredictResponse struct {
Message string `json:"message"`
Status int `json:"status"`
Result map[string]string `json:"result"`
WinRates map[string]string `json:"win_rates"`
}
type LegalRequest struct {
Player_hand_cards int `url:"player_hand_cards" form:"player_hand_cards"`
Rival_move string `url:"rival_move" form:"rival_move"`
}
type LegalResponse struct {
Legal_action string `json:"legal_action"`
Message string `json:"message"`
Status int `json:"status"`
}
var CardToAiCard = map[int32]int32{
-1: -1, 0: 2, 1: 3, 2: 4, 3: 5, 4: 6, 5: 7, 6: 8, 7: 9, 8: 10, 9: 11, 10: 12, 11: 0, 12: 1,
13: 15, 14: 16, 15: 17, 16: 18, 17: 19, 18: 20, 19: 21, 20: 22, 21: 23, 22: 24, 23: 25, 24: 13, 25: 14,
26: 28, 27: 29, 28: 30, 29: 31, 30: 32, 31: 33, 32: 34, 33: 35, 34: 36, 35: 37, 36: 38, 37: 26, 38: 27,
39: 41, 40: 42, 41: 43, 42: 44, 43: 45, 44: 46, 45: 47, 46: 48, 47: 49, 48: 50, 49: 51, 50: 39, 51: 40,
}
var AiCardToCard = map[int32]int32{
-1: -1, 2: 0, 3: 1, 4: 2, 5: 3, 6: 4, 7: 5, 8: 6, 9: 7, 10: 8, 11: 9, 12: 10, 0: 11, 1: 12,
15: 13, 16: 14, 17: 15, 18: 16, 19: 17, 20: 18, 21: 19, 22: 20, 23: 21, 24: 22, 25: 23, 13: 24, 14: 25,
28: 26, 29: 27, 30: 28, 31: 29, 32: 30, 33: 31, 34: 32, 35: 33, 36: 34, 37: 35, 38: 36, 26: 37, 27: 38,
41: 39, 42: 40, 43: 41, 44: 42, 45: 43, 46: 44, 47: 45, 48: 46, 49: 47, 50: 48, 51: 49, 39: 50, 40: 51,
}

11
build-sub.bat Normal file
View File

@ -0,0 +1,11 @@
@echo off
echo Build %1 task!
cd %1
go fmt
go vet
go build -v
echo errorlevel:%errorlevel%
if "%errorlevel%"=="0" exit
if not "%errorlevel%"=="0" echo %1 build failed!
pause
exit

29
build.bat Normal file
View File

@ -0,0 +1,29 @@
go env -w GO111MODULE=off
@echo "go fmt common..."
cd common
go fmt
@echo "go fmt api3th..."
cd ../api3th
go fmt
@echo "go fmt model..."
cd ../model
go fmt
@echo "go fmt webapi..."
cd ../webapi
go fmt
@echo "go fmt lib complete!"
cd ..
start build-sub.bat dbproxy
start build-sub.bat mgrsrv
start build-sub.bat gatesrv
start build-sub.bat worldsrv
start build-sub.bat gamesrv
start build-sub.bat robot
start build-sub.bat ranksrv
@echo "Wait all build task complete!"
pause

31
build_linux.bat Normal file
View File

@ -0,0 +1,31 @@
set CGO_ENABLED=0
set GOOS=linux
set GOARCH=amd64
go env -w GO111MODULE=off
cd gatesrv
go fmt
go build
cd ../mgrsrv
go fmt
go build
cd ../worldsrv
go fmt
go build
cd ../gamesrv
go fmt
go build
rem cd ../minigame
rem go fmt
rem go build
cd ../robot
go fmt
go build
cd ../dbproxy
go fmt
go build
cd ../ranksrv
go fmt
go build
cd ..
@echo "complete"
pause

31
build_mac.bat Normal file
View File

@ -0,0 +1,31 @@
set CGO_ENABLED=0
set GOOS=darwin
set GOARCH=amd64
go env -w GO111MODULE=off
cd routesrv
go fmt
go build
cd ../gatesrv
go fmt
go build
cd ../mgrsrv
go fmt
go build
cd ../worldsrv
go fmt
go build
cd ../gamesrv
go fmt
go build
cd ../robot
go fmt
go build
cd ../datasrv
go fmt
go build
cd ../schedulesrv
go fmt
go build
cd ..
@echo "complete"
pause

14
clean.bat Normal file
View File

@ -0,0 +1,14 @@
del /F/S gatesrv\gatesrv
del /F/S gatesrv\gatesrv.exe
del /F/S gamesrv\gamesrv
del /F/S gamesrv\gamesrv.exe
del /F/S mgrsrv\mgrsrv
del /F/S mgrsrv\mgrsrv.exe
del /F/S worldsrv\worldsrv
del /F/S worldsrv\worldsrv.exe
del /F/S robot\robot
del /F/S robot\robot.exe
del /F/S dbproxy\dbproxy
del /F/S dbproxy\dbproxy.exe
del /F/S minigame\minigame
del /F/S minigame\minigame.exe

9
close.bat Normal file
View File

@ -0,0 +1,9 @@
TASKKILL /F /IM gatesrv.exe
TASKKILL /F /IM mgrsrv.exe
TASKKILL /F /IM worldsrv.exe
TASKKILL /F /IM gamesrv.exe
TASKKILL /F /IM robot.exe
TASKKILL /F /IM minigame.exe
TASKKILL /F /IM dbproxy.exe
TASKKILL /F /IM ranksrv.exe
clrlogs.bat

14
clrlogs.bat Normal file
View File

@ -0,0 +1,14 @@
del /F/S gatesrv\*.log
del /F/S gatesrv\*.log.*
del /F/S mgrsrv\*.log
del /F/S mgrsrv\*.log.*
del /F/S worldsrv\*.log
del /F/S worldsrv\*.log.*
del /F/S gamesrv\*.log
del /F/S gamesrv\*.log.*
del /F/S dbproxy\*.log
del /F/S dbproxy\*.log.*
del /F/S minigame\*.log
del /F/S minigame\*.log.*
del /F/S robot\*.log
del /F/S robot\*.log.*

54
common/action.go Normal file
View File

@ -0,0 +1,54 @@
package common
import (
"mongo.games.com/goserver/core/logger"
)
const (
A_USER_BLACK = 1 //增加黑名单
)
type Action struct {
ActionID int //执行id
ActionParamInt64 []int //整形参数
ActionParamFloat []float64 //浮点参数
ActionParamString []string //字符串参数
}
var ActionMgrSington = &ActionMgr{
pool: make(map[int]ActionBase),
}
func init() {
}
type ActionMgr struct {
pool map[int]ActionBase
}
func (this *ActionMgr) ActionGroup(need interface{}, action []*Action) bool {
for i := 0; i < len(action); i++ {
this.action(need, action[i])
}
return true
}
func (this *ActionMgr) action(need interface{}, action *Action) bool {
a, ok := this.pool[action.ActionID]
if !ok {
logger.Logger.Warnf("no this action %v", action.ActionID)
return false
}
return a.Action(need, action)
}
func (this *ActionMgr) Register(cid int, c ActionBase) {
this.pool[cid] = c
}
type ActionBase interface {
Action(need interface{}, action *Action) bool
}

54
common/action_srvctrl.go Normal file
View File

@ -0,0 +1,54 @@
package common
import (
"mongo.games.com/game/protocol/server"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/module"
"mongo.games.com/goserver/core/netlib"
)
type GameSessState int
const (
GAME_SESS_STATE_OFF GameSessState = iota //关闭状态
GAME_SESS_STATE_ON //开启状态
)
var ServerCtrlCallback func(int32)
func RegisteServerCtrlCallback(cb func(int32)) {
ServerCtrlCallback = cb
}
type ServerCtrlPacketFactory struct {
}
type ServerCtrlHandler struct {
}
func (this *ServerCtrlPacketFactory) CreatePacket() interface{} {
pack := &server.ServerCtrl{}
return pack
}
func (this *ServerCtrlHandler) Process(s *netlib.Session, packetid int, data interface{}) error {
if sc, ok := data.(*server.ServerCtrl); ok {
logger.Logger.Trace("ServerCtrlHandler.Process== ", *sc)
switch sc.GetCtrlCode() {
case SrvCtrlCloseCode:
module.Stop()
}
//回调
if ServerCtrlCallback != nil {
ServerCtrlCallback(sc.GetCtrlCode())
}
}
return nil
}
func init() {
netlib.RegisterHandler(int(server.SSPacketID_PACKET_MS_SRVCTRL), &ServerCtrlHandler{})
netlib.RegisterFactory(int(server.SSPacketID_PACKET_MS_SRVCTRL), &ServerCtrlPacketFactory{})
}

172
common/aes.go Normal file
View File

@ -0,0 +1,172 @@
package common
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"fmt"
"mongo.games.com/goserver/core/logger"
"regexp"
"strconv"
)
var key = []byte("kjh-vgjhhionoommmkokmokoo$%JH")
// 加密
func EnCrypt(orig []byte) (str string) {
defer func() {
err := recover()
if err != nil {
logger.Logger.Errorf("EnCrypt %v Error %v", string(orig), err)
str = string(orig)
}
}()
//将秘钥中的每个字节累加,通过sum实现orig的加密工作
sum := 0
for i := 0; i < len(key); i++ {
sum += int(key[0])
}
//给明文补码
var pkcs_code = PKCS5Padding(orig, 8)
//通过秘钥,对补码后的明文进行加密
for j := 0; j < len(pkcs_code); j++ {
pkcs_code[j] += byte(sum)
}
//base64.URLEncoding.EncodeToString()
return base64.URLEncoding.EncodeToString(pkcs_code)
}
// 补码
func PKCS5Padding(orig []byte, size int) []byte {
//计算明文的长度
length := len(orig)
padding := size - length%size
//向byte类型的数组中重复添加padding
repeats := bytes.Repeat([]byte{byte(padding)}, padding)
return append(orig, repeats...)
}
// 解密
func DeCrypt(text string) (str string) {
defer func() {
err := recover()
if err != nil {
logger.Logger.Errorf("DeCrypt %v Error %v", text, err)
str = text
}
}()
//orig, err := base64.StdEncoding.DecodeString(text)
orig, err := base64.URLEncoding.DecodeString(text)
if err != nil {
return "密文类型错误"
}
sum := 0
for i := 0; i < len(key); i++ {
sum += int(key[0])
}
//解密
for j := 0; j < len(orig); j++ {
orig[j] -= byte(sum)
}
//去码
var pkcs_unCode = PKCS5UnPadding(orig)
return string(pkcs_unCode)
}
// 去码
func PKCS5UnPadding(orig []byte) []byte {
//获取最后一位补码的数字
var tail = int(orig[len(orig)-1])
return orig[:(len(orig) - tail)]
}
var aesRule, _ = regexp.Compile(`^[0-9]+$`)
const (
aeskey = "DoNotEditThisKeyDoNotEditThisKey" // 加密的密钥,绝不可以更改
)
// 下面的字符串,也绝不可以更改
var defaultLetters = []rune("idjGfiRogsFnkdKgokdfgdow07u6978uxcvvLiPiDfjafOd2fuFJYYGBJuykbvfk")
func AesEncrypt(origDataStr string) (str string) {
defer func() {
err := recover()
if err != nil {
logger.Logger.Errorf("AesEncrypt %v Error %v", origDataStr, err)
str = origDataStr
}
}()
strlen := len(origDataStr)
b := aesRule.MatchString(origDataStr)
//不全是数字,或长度为零,不加密
if !b || strlen == 0 {
return origDataStr
}
phonenum, errint := strconv.Atoi(origDataStr)
if errint != nil {
return origDataStr
}
text := []byte(origDataStr)
//指定加密、解密算法为AES返回一个AES的Block接口对象
block, err := aes.NewCipher([]byte(aeskey))
if err != nil {
panic(err)
}
//指定计数器,长度必须等于block的块尺寸
iv := string(defaultLetters[phonenum%(len(defaultLetters))])
count := []byte(fmt.Sprintf("%016v", iv))
//指定分组模式
blockMode := cipher.NewCTR(block, count)
//执行加密、解密操作
message := make([]byte, len(text))
blockMode.XORKeyStream(message, text)
//返回明文或密文
return fmt.Sprintf("%v%v", iv, base64.StdEncoding.EncodeToString(message))
//return base64.StdEncoding.EncodeToString(message)
}
func AesDecrypt(cryptedstr string) (str string) {
defer func() {
err := recover()
if err != nil {
logger.Logger.Errorf("AesDecrypt %v Error %v", cryptedstr, err)
str = cryptedstr
}
}()
strlen := len(cryptedstr)
b := aesRule.MatchString(cryptedstr)
//全是数字,或长度为零,不解密
if b || strlen == 0 {
return cryptedstr
}
iv := cryptedstr[:1]
str = cryptedstr[1:]
text, err := base64.StdEncoding.DecodeString(str)
if err != nil {
logger.Logger.Errorf("AesDecrypt %v Err:%v", cryptedstr, err)
return cryptedstr
}
//指定加密、解密算法为AES返回一个AES的Block接口对象
block, err := aes.NewCipher([]byte(aeskey))
if err != nil {
panic(err)
}
//指定计数器,长度必须等于block的块尺寸
count := []byte(fmt.Sprintf("%016v", iv))
//指定分组模式
blockMode := cipher.NewCTR(block, count)
//执行加密、解密操作
message := make([]byte, len(text))
blockMode.XORKeyStream(message, text)
//返回明文或密文
return string(message)
}

11
common/clientparam.go Normal file
View File

@ -0,0 +1,11 @@
package common
const (
ClientSessionAttribute_State int = iota
ClientSessionAttribute_GameServer
ClientSessionAttribute_Buf
ClientSessionAttribute_WorldServer
ClientSessionAttribute_PlayerData
ClientSessionAttribute_GroupTag
ClientSessionAttribute_RankServer
)

19
common/clientstate.go Normal file
View File

@ -0,0 +1,19 @@
package common
const (
ClientState_WaitBindBundle int = iota
ClientState_WaitLogin
ClientState_Logined
ClientState_WaiteGetPlayerInfo
ClientState_CreatePlayer
ClientState_GetPlayerInfo
ClientState_EnterGame
ClientState_EnterMap
ClientState_EnterFight
ClientState_WaitLogout
ClientState_Logouted
ClientState_Dropline
ClientState_Droplined
ClientState_WaitRehold
ClientState_Reholded
)

90
common/comm.go Normal file
View File

@ -0,0 +1,90 @@
package common
import (
rawproto "google.golang.org/protobuf/proto"
"mongo.games.com/game/proto"
protocol_game "mongo.games.com/game/protocol/server"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/netlib"
"mongo.games.com/goserver/srvlib"
"mongo.games.com/goserver/srvlib/protocol"
)
type WGCoinSceneChange struct {
SnId int32
SceneId int32
}
type WGAddCoin struct {
SnId int32
Coin int64
GainWay int32
Oper string
Remark string
Broadcast bool
WriteLog bool
}
func createMulticastPacket(packetid int, data interface{}, sis ...*protocol.MCSessionUnion) (rawproto.Message, error) {
pack := &protocol.SSPacketMulticast{
Sessions: sis,
PacketId: proto.Int(packetid),
}
if byteData, ok := data.([]byte); ok {
pack.Data = byteData
} else {
byteData, err := netlib.MarshalPacket(packetid, data)
if err == nil {
pack.Data = byteData
} else {
logger.Logger.Info("MulticastPacketFactory.CreateMulticastPacket err:", err)
return nil, err
}
}
proto.SetDefaults(pack)
return pack, nil
}
func SendToGate(sid int64, packetid int, rawpack interface{}, s *netlib.Session) bool {
if s == nil || rawpack == nil || sid == 0 {
return false
}
pack, err := createMulticastPacket(packetid, rawpack,
&protocol.MCSessionUnion{
Mccs: &protocol.MCClientSession{
SId: proto.Int64(sid)}})
if err == nil && pack != nil {
if d, err := netlib.MarshalPacket(int(protocol.SrvlibPacketID_PACKET_SS_MULTICAST), pack); err == nil {
return s.Send(int(protocol.SrvlibPacketID_PACKET_SS_MULTICAST), d, true)
} else {
logger.Logger.Warn("SendToGate err:", err)
}
}
return false
}
func SendToActThrSrv(packetid int, rawpack interface{}) bool {
if rawpack == nil {
return false
}
replaySess := srvlib.ServerSessionMgrSington.GetSession(GetSelfAreaId(), ActThrServerType, ActThrServerID)
if replaySess != nil {
return replaySess.Send(int(packetid), rawpack)
}
return false
}
func TransmitToServer(sid int64, packetid int, rawpack interface{}, s *netlib.Session) bool {
if d, err := netlib.MarshalPacket(packetid, rawpack); err == nil {
pack := &protocol_game.SSTransmit{
PacketData: d,
SessionId: sid,
}
proto.SetDefaults(pack)
return s.Send(int(protocol_game.TransmitPacketID_PACKET_SS_PACKET_TRANSMIT), pack, true)
} else {
logger.Logger.Warn("TransmitToServer err:", err)
}
return false
}

192
common/condition.go Normal file
View File

@ -0,0 +1,192 @@
package common
import (
"math"
"strings"
)
const (
CMP_OP_EQ = 0
CMP_OP_GT = 1
CMP_OP_LT = 2
CMP_OP_GTE = 3
CMP_OP_LTE = 4
CMP_OP_NEQ = 5
)
type Condition struct {
ConditionID int //条件id
ConditionCMP int //比较类型
ConditionParamInt64 int64 //整形参数
ConditionParamFloat64 float64 //浮点参数
ConditionParamString string //字符串参数
}
func (this *Condition) CmpInt(n int64) bool {
switch this.ConditionCMP {
case CMP_OP_EQ:
if n == this.ConditionParamInt64 {
return true
}
case CMP_OP_GT:
if n > this.ConditionParamInt64 {
return true
}
case CMP_OP_LT:
if n < this.ConditionParamInt64 {
return true
}
case CMP_OP_GTE:
if n >= this.ConditionParamInt64 {
return true
}
case CMP_OP_LTE:
if n <= this.ConditionParamInt64 {
return true
}
case CMP_OP_NEQ:
if n != this.ConditionParamInt64 {
return true
}
}
return false
}
func (this *Condition) CmpFloat64(n float64) bool {
switch this.ConditionCMP {
case CMP_OP_EQ:
if n == this.ConditionParamFloat64 {
return true
}
case CMP_OP_GT:
if n > this.ConditionParamFloat64 {
return true
}
case CMP_OP_LT:
if n < this.ConditionParamFloat64 {
return true
}
case CMP_OP_GTE:
if n >= this.ConditionParamFloat64 {
return true
}
case CMP_OP_LTE:
if n <= this.ConditionParamFloat64 {
return true
}
case CMP_OP_NEQ:
if math.Abs(n-this.ConditionParamFloat64) > 0.00001 {
return true
}
}
return false
}
func (this *Condition) CmpString(n string) bool {
switch this.ConditionCMP {
case CMP_OP_EQ:
if strings.Compare(n, this.ConditionParamString) == 0 {
return true
}
case CMP_OP_NEQ:
if strings.Compare(n, this.ConditionParamString) != 0 {
return true
}
case CMP_OP_GT:
if strings.Compare(n, this.ConditionParamString) > 0 {
return true
}
case CMP_OP_LT:
if strings.Compare(n, this.ConditionParamString) < 0 {
return true
}
case CMP_OP_GTE:
if strings.Compare(n, this.ConditionParamString) >= 0 {
return true
}
case CMP_OP_LTE:
if strings.Compare(n, this.ConditionParamString) <= 0 {
return true
}
}
return false
}
func (this *Condition) CmpBool(n bool) bool {
cmpBool := false
if this.ConditionParamInt64 > 0 {
cmpBool = true
}
switch this.ConditionCMP {
case CMP_OP_EQ:
if n == cmpBool {
return true
}
case CMP_OP_NEQ:
if n != cmpBool {
return true
}
}
return false
}
//todo 检查参数,临时处理,暂时没想到更好的办法
var ConditionMgrSington = &ConditionMgr{
pool: make(map[int]CheckBase),
}
type ConditionMgr struct {
pool map[int]CheckBase
}
func (this *ConditionMgr) CheckGroup(need interface{}, con [][]*Condition) bool {
if len(con) <= 0 {
return false
}
//组内或,组间与
for i := 0; i < len(con); i++ {
cArray := con[i]
isOk := false
for j := 0; j < len(cArray); j++ {
if this.check(need, cArray[j]) {
isOk = true
break
}
}
if !isOk {
return false
}
}
return true
}
func (this *ConditionMgr) check(need interface{}, con *Condition) bool {
c, ok := this.pool[con.ConditionID]
if !ok {
return false
}
return c.Check(need, con)
}
func (this *ConditionMgr) Register(cid int, c CheckBase) {
this.pool[cid] = c
}
type CheckBase interface {
Check(need interface{}, condition *Condition) bool
}
// ////////////////////////////////////////////////////////////
const (
C_USER_PROMOTER = 1 //判定用户推广员
C_USER_ISNEW = 2 //是否新用户
C_USER_ISHAVETEL = 3 //是否正式用户
C_USER_ISFIRST = 4 //是否首充
C_USER_ISDAYFIRST = 5 //是否当日首充
C_USER_PAYEXCHANGE = 6 //充值提现比
C_USER_PAYNNUM = 7 //充值额度
)

121
common/config.go Normal file
View File

@ -0,0 +1,121 @@
package common
import (
"encoding/json"
"mongo.games.com/goserver/core"
)
var Config = Configuration{}
type Configuration struct {
AppId string
SrvId string
IsDevMode bool
}
func (this *Configuration) Name() string {
return "common"
}
func (this *Configuration) Init() error {
return nil
}
func (this *Configuration) Close() error {
return nil
}
func init() {
core.RegistePackage(&Config)
core.RegistePackage(&CustomConfig)
}
var CustomConfig = make(CustomConfiguration)
type CustomConfiguration map[string]interface{}
func (this *CustomConfiguration) Name() string {
return "costum"
}
func (this *CustomConfiguration) Init() error {
return nil
}
func (this *CustomConfiguration) Close() error {
return nil
}
func (this *CustomConfiguration) GetString(key string) string {
if v, exist := (*this)[key]; exist {
if str, ok := v.(string); ok {
return str
}
}
return ""
}
func (this *CustomConfiguration) GetStrings(key string) (strs []string) {
if v, exist := (*this)[key]; exist {
if vals, ok := v.([]interface{}); ok {
for _, s := range vals {
if str, ok := s.(string); ok {
strs = append(strs, str)
}
}
return
}
}
return
}
func (this *CustomConfiguration) GetCustomCfgs(key string) (strs []*CustomConfiguration) {
if v, exist := (*this)[key]; exist {
if vals, ok := v.([]interface{}); ok {
for _, s := range vals {
if data, ok := s.(map[string]interface{}); ok {
var pkg *CustomConfiguration
modelBuff, _ := json.Marshal(data)
err := json.Unmarshal(modelBuff, &pkg)
if err == nil {
strs = append(strs, pkg)
}
}
}
return
}
}
return
}
func (this *CustomConfiguration) GetInts(key string) (strs []int) {
if v, exist := (*this)[key]; exist {
if vals, ok := v.([]interface{}); ok {
for _, s := range vals {
if str, ok := s.(float64); ok {
strs = append(strs, int(str))
}
}
return
}
}
return
}
func (this *CustomConfiguration) GetInt(key string) int {
if v, exist := (*this)[key]; exist {
if val, ok := v.(float64); ok {
return int(val)
}
}
return 0
}
func (this *CustomConfiguration) GetBool(key string) bool {
if v, exist := (*this)[key]; exist {
if val, ok := v.(bool); ok {
return val
}
}
return false
}

119
common/configencryptor.go Normal file
View File

@ -0,0 +1,119 @@
package common
const (
aa uint = 0x7E
bb = 0x33
cc = 0xA1
ENCRYPT_KEY1 = 0xa61fce5e // A = 0x20, B = 0xFD, C = 0x07, first = 0x1F, key = a61fce5e
ENCRYPT_KEY2 = 0x443ffc04 // A = 0x7A, B = 0xCF, C = 0xE5, first = 0x3F, key = 443ffc04
ENCRYPT_KEY3 = 0x12345678
)
var ConfigFE = &ConfigFileEncryptor{}
type ConfigFileEncryptor struct {
m_nPos1 int
m_nPos2 int
m_nPos3 int
m_cGlobalEncrypt EncryptCode
}
type EncryptCode struct {
m_bufEncrypt1 [256]uint8
m_bufEncrypt2 [256]uint8
m_bufEncrypt3 [256]uint8
}
func (this *EncryptCode) init(key1, key2, key3 uint) {
var a1, b1, c1, fst1 uint
a1 = ((key1 >> 0) & 0xFF) ^ aa
b1 = ((key1 >> 8) & 0xFF) ^ bb
c1 = ((key1 >> 24) & 0xFF) ^ cc
fst1 = (key1 >> 16) & 0xFF
var a2, b2, c2, fst2 uint
a2 = ((key2 >> 0) & 0xFF) ^ aa
b2 = ((key2 >> 8) & 0xFF) ^ bb
c2 = ((key2 >> 24) & 0xFF) ^ cc
fst2 = (key2 >> 16) & 0xFF
i := 0
nCode := uint8(fst1)
for i = 0; i < 256; i++ {
this.m_bufEncrypt1[i] = nCode
nCode = (uint8(a1)*nCode*nCode + uint8(b1)*nCode + uint8(c1)) & 0xFF
}
nCode = uint8(fst2)
for i = 0; i < 256; i++ {
this.m_bufEncrypt2[i] = nCode
nCode = (uint8(a2)*nCode*nCode + uint8(b2)*nCode + uint8(c2)) & 0xFF
}
for i = 0; i < 256; i++ {
this.m_bufEncrypt3[i] = uint8(((key3 >> uint(i%4)) ^ uint(i)) & 0xff)
}
}
func (this *ConfigFileEncryptor) init(key1, key2, key3 uint) {
this.m_cGlobalEncrypt.init(key1, key2, key3)
}
func (this *ConfigFileEncryptor) IsCipherText(buf []byte) bool {
size := len(buf)
if size < 4 {
return false
}
//0x1b454e43
if buf[size-1] == 0x43 && buf[size-2] == 0x4e && buf[size-3] == 0x45 && buf[size-4] == 0x1b {
return true
}
return false
}
func (this *ConfigFileEncryptor) Encrypt(buf []byte) []byte {
size := len(buf)
oldPos1, oldPos2, oldPos3 := this.m_nPos1, this.m_nPos2, this.m_nPos3
for i := 0; i < size; i++ {
buf[i] ^= this.m_cGlobalEncrypt.m_bufEncrypt1[this.m_nPos1]
buf[i] ^= this.m_cGlobalEncrypt.m_bufEncrypt2[this.m_nPos2]
buf[i] ^= this.m_cGlobalEncrypt.m_bufEncrypt3[this.m_nPos3]
this.m_nPos1++
if this.m_nPos1 >= 256 {
this.m_nPos1 = 0
this.m_nPos2++
if this.m_nPos2 >= 256 {
this.m_nPos2 = 0
}
}
this.m_nPos3++
if this.m_nPos3 >= 256 {
this.m_nPos3 = 0
}
}
this.m_nPos1, this.m_nPos2, this.m_nPos3 = oldPos1, oldPos2, oldPos3
buf = append(buf, 0x1b, 0x45, 0x4e, 0x43)
return buf
}
func (this *ConfigFileEncryptor) Decrtypt(buf []byte) []byte {
size := len(buf) - 4
oldPos1, oldPos2, oldPos3 := this.m_nPos1, this.m_nPos2, this.m_nPos3
for i := 0; i < size; i++ {
buf[i] ^= this.m_cGlobalEncrypt.m_bufEncrypt1[this.m_nPos1]
buf[i] ^= this.m_cGlobalEncrypt.m_bufEncrypt2[this.m_nPos2]
buf[i] ^= this.m_cGlobalEncrypt.m_bufEncrypt3[this.m_nPos3]
this.m_nPos1++
if this.m_nPos1 >= 256 {
this.m_nPos1 = 0
this.m_nPos2++
if this.m_nPos2 >= 256 {
this.m_nPos2 = 0
}
}
this.m_nPos3++
if this.m_nPos3 >= 256 {
this.m_nPos3 = 0
}
}
this.m_nPos1, this.m_nPos2, this.m_nPos3 = oldPos1, oldPos2, oldPos3
return buf[:size]
}
func init() {
ConfigFE.init(ENCRYPT_KEY1, ENCRYPT_KEY2, ENCRYPT_KEY3)
}

782
common/constant.go Normal file
View File

@ -0,0 +1,782 @@
package common
import (
"fmt"
"strings"
)
// todo
// 游戏模式ID
// 多个id会属于同一个游戏需要判断游戏类型时添加一个方法
// 例如:判断是否是象棋游戏
// func IsChess(id int) bool {
// switch id {
// case GameId_Chesstitians,
// GameId_ChesstitiansMakruk,
// GameId_ChesstitiansCambodian,
// GameId_ChesstitiansCambodianRobot:
// return true
// }
// return false
//}
const (
GameId_Unknow int = iota
__GameId_Hundred_Min__ = 100 //################百人类################
GameId_HundredDZNZ = 101 //德州牛仔
GameId_HundredYXX = 102 //鱼虾蟹
GameId_Baccarat = 103 //百家乐
GameId_RollPoint = 104 //骰宝
GameId_Roulette = 105 //轮盘
GameId_DragonVsTiger = 106 //龙虎斗
GameId_RedVsBlack = 107 //红黑大战
GameId_RollCoin = 108 //奔驰宝马
GameId_RollAnimals = 109 //飞禽走兽
GameId_RollColor = 110 //森林舞会
GameId_RedPack = 111 //红包扫雷
GameId_Crash = 112 //碰撞游戏
__GameId_VS_Min__ = 200 //################对战类################
GameId_DezhouPoker = 201 //德州扑克
GameId_DezhouPoker_5To2 = 202 //德州扑克5选2
GameId_OmahaPoker = 203 //奥马哈
GameId_TenHalf = 204 //十点半
GameId_FiveCardStud = 205 //梭哈
GameId_BlackJack = 206 //21点
GameId_TienLen = 207 // tienlen自由桌经典版
GameId_TienLen_yl = 208 // tienlen自由桌娱乐版
GameId_TienLen_toend = 209 // tienlen自由桌经典版打到底
GameId_TienLen_yl_toend = 210 // tienlen自由桌娱乐版打到底
GameId_TienLen_m = 807 // tienlen经典比赛场
GameId_TienLen_m_toend = 808 // tienlen经典比赛场打到底
GameId_TaLa = 220 //tala
GameId_SamLoc = 230 //samloc
GameId_TienLenSelect = 240 // tienlen经典版
GameId_TienLenSelect_yl = 241 // tienlen娱乐版
GameId_TienLenRank = 242 // tienlen排位赛经典
GameId_TienLenRank_yl = 243 // tienlen排位赛娱乐
GameId_TienLenSelect_toend = 244 // tienlen经典版打到底
GameId_TienLenSelect_yl_toend = 245 // tienlen娱乐版打到底
GameId_TienLenRank_toend = 246 // tienlen排位赛经典打到底
GameId_TienLenRank_yl_toend = 247 // tienlen排位赛娱乐打到底
GameId_Chesstitians = 501 //国际象棋
GameId_ChesstitiansMakruk = 511 //国际象棋变体 (Makruk 泰国象棋)
GameId_ChesstitiansCambodian = 521 // 柬埔寨象棋 (Cambodian 柬埔寨象棋)
GameId_ChesstitiansCambodianRobot = 522 // 柬埔寨象棋人机对战
GameID_Thirteen4 = 211 // 十三张(四人场)
GameID_Thirteen8 = 212 // 十三张(八人场)
GameID_ThirteenFree = 213 // 十三张(自由场经典场)
GameID_ThirteenFreeLaiZi = 214 // 十三张(自由场癞子场)
__GameId_Slot_Min__ = 300 //################拉霸类################
GameId_CaiShen = 301 //财神
GameId_Avengers = 302 //复仇者联盟
GameId_EasterIsland = 303 //复活岛
GameId_IceAge = 304 //冰河世纪
GameId_TamQuoc = 305 //百战成神
GameId_Fruits = 306 //水果拉霸
GameId_Richblessed = 307 //多福多财
__GameId_Fishing_Min__ = 400 //################捕鱼类################
GameId_HFishing = 401 //欢乐捕鱼
GameId_TFishing = 402 //天天捕鱼
__GameId_Casual_Min__ = 500 //################休闲类################
__GameId_MiniGame_Min__ = 600 //################小游类################
GameId_Candy = 601 //糖果小游戏
GameId_MiniPoker = 602 //MiniPoker
GameId_BOOM = 603 //卡丁车
GameId_LuckyDice = 604 //幸运筛子
GameId_CaoThap = 605 //CaoThap
GameId_AngerUncle = 606 // 愤怒大叔
GameId_SmallRoket = 607 // 小火箭
__GameId_ThrGame_Min__ = 700 //################三方类################
GameId_Thr_Dg = 701 //DG Game
GameId_Thr_XHJ = 901 //DG Game
)
// IsTienLen TienLen游戏
func IsTienLen(gameId int) bool {
return InSliceInt32(GetTienlenGameID(), int32(gameId))
}
func GetTienlenGameID() []int32 {
//todo 还要维护游戏id,好麻烦,还容易忘
return []int32{
GameId_TienLen, GameId_TienLen_yl,
GameId_TienLen_toend, GameId_TienLen_yl_toend,
GameId_TienLen_m, GameId_TienLen_m_toend,
GameId_TienLenSelect, GameId_TienLenSelect_toend,
GameId_TienLenSelect_yl, GameId_TienLenSelect_yl_toend,
GameId_TienLenRank, GameId_TienLenRank_toend,
GameId_TienLenRank_yl, GameId_TienLenRank_yl_toend,
}
}
// IsTienLenYuLe TienLen娱乐
func IsTienLenYuLe(gameId int) bool {
switch gameId {
case GameId_TienLen_yl,
GameId_TienLen_yl_toend,
GameId_TienLenSelect_yl,
GameId_TienLenRank_yl,
GameId_TienLenSelect_yl_toend,
GameId_TienLenRank_yl_toend:
return true
}
return false
}
// IsTienLenToEnd TienLen打到底
func IsTienLenToEnd(gameId int) bool {
switch gameId {
case GameId_TienLen_toend,
GameId_TienLen_yl_toend,
GameId_TienLen_m_toend,
GameId_TienLenSelect_toend,
GameId_TienLenSelect_yl_toend,
GameId_TienLenRank_toend,
GameId_TienLenRank_yl_toend:
return true
}
return false
}
// IsChess 象棋游戏
func IsChess(gameId int) bool {
switch gameId {
case GameId_Chesstitians,
GameId_ChesstitiansMakruk,
GameId_ChesstitiansCambodian,
GameId_ChesstitiansCambodianRobot:
return true
}
return false
}
// IsThirteen 十三张游戏
func IsThirteen(gameId int) bool {
switch gameId {
case GameID_Thirteen4,
GameID_Thirteen8,
GameID_ThirteenFree,
GameID_ThirteenFreeLaiZi:
return true
}
return false
}
// IsThirteen 十三张游戏
func IsSmallRocket(gameId int) bool {
switch gameId {
case GameId_SmallRoket:
return true
}
return false
}
// IsLocalGame 自动分场模式的游戏
// 根据 DB_Createroom.xlsx 给玩家分场或创建房间
func IsLocalGame(gameId int) bool {
switch gameId {
case GameId_TienLen, GameId_TienLen_yl,
GameId_TienLen_toend, GameId_TienLen_yl_toend,
GameId_TaLa,
GameId_SamLoc,
GameID_ThirteenFree, GameID_ThirteenFreeLaiZi:
return true
}
return false
}
// IsPlayerPool 需要统计在个人水池的游戏
func IsPlayerPool(gameId int) bool {
if IsTienLen(gameId) || IsThirteen(gameId) {
return true
}
return false
}
// 房间编号区间
const (
PrivateSceneStartId = 10000000
PrivateSceneMaxId = 99999999
MatchSceneStartId = 100000000
MatchSceneMaxId = 199999999
HundredSceneStartId = 200000000
HundredSceneMaxId = 299999999
HallSceneStartId = 300000000
HallSceneMaxId = 399999999
MiniGameSceneStartId = 400000000
MiniGameSceneMaxId = 409999999
CoinSceneStartId = 1000000000 //区间预留大点,因为队列匹配比较耗id,假定一天100w牌局,那么这个id区间够用1000天
CoinSceneMaxId = 1999999999
DgSceneId = 99
)
// 房间模式
const (
SceneMode_Public = iota //公共房间
SceneMode_Club //俱乐部房间
SceneMode_Private //私人房间
SceneMode_Match //赛事房间
SceneMode_Thr //三方房间
)
// 场景级别
//const (
// SceneLvl_Test = -1 // 试玩场(不要钱)
// SceneLvl_Experience = 0 // 体验场(花小钱)
// SceneLvl_Primary = 1 // 初级场
// SceneLvl_Middle = 2 // 中级场
// SceneLvl_Senior = 3 // 高级场
// SceneLvl_Professor = 4 // 专家场
//)
// 房费选项
//const (
// RoomFee_Owner int32 = iota //房主
// RoomFee_AA //AA
// RoomFee_Max
//)
const (
Platform_Rob = "__$G_P$__"
Platform_Sys = "0"
Channel_Rob = "$${ROBOT}$$"
PMCmd_SplitToken = "-"
PMCmd_AddCoin = "addcoin"
PMCmd_Privilege = "setprivilege"
DeviceOS_Android = "android"
DeviceOS_IOS = "ios"
)
const (
GainWay_NewPlayer int32 = 0 //0.新建角色
GainWay_Pay = 1 //1.后台增加(主要是充值)
GainWay_ByPMCmd = 2 //2.pm命令
GainWay_MatchBreakBack = 3 //3.退赛退还
GainWay_MatchSystemSupply = 4 //4.比赛奖励
GainWay_Exchange = 5 //5.兑换
GainWay_ServiceFee = 6 //6.桌费
GainWay_CoinSceneWin = 7 //7.金豆场赢取
GainWay_CoinSceneLost = 8 //8.金豆场输
GainWay_CoinSceneEnter = 9 //9.进入金币场预扣
GainWay_ShopBuy = 10 //10.商城购买或者兑换
GainWay_CoinSceneLeave = 11 //11.金豆场回兑
GainWay_HundredSceneWin = 12 //12.万人场赢取
GainWay_HundredSceneLost = 13 //13.万人场输
GainWay_MessageAttach = 14 //14.邮件
GainWay_SafeBoxSave = 15 //15.保险箱存入
GainWay_SafeBoxTakeOut = 16 //16.保险箱取出
GainWay_Fishing = 17 //17.捕鱼
GainWay_CoinSceneExchange = 18 //18.金豆场兑换
GainWay_UpgradeAccount = 19 //19.升级账号
GainWay_API_AddCoin = 20 //20.API操作钱包
GainWay_GoldCome = 21 //21.财神降临
GainWay_Transfer_System2Thrid = 22 //22.系统平台转入到第三方平台的金币
GainWay_Transfer_Thrid2System = 23 //23.第三方平台转入到系统平台的金币
GainWay_RebateTask = 24 //24.返利获取
GainWay_IOSINSTALLSTABLE = 25 //25.ios安装奖励
GainWay_VirtualChange = 26 //26.德州虚拟账变
GainWay_CreatePrivateScene = 27 //27.创建私有房间
GainWay_PrivateSceneReturn = 28 //28.解散私有房间返还
GainWay_OnlineRandCoin = 29 //29.红包雨
GainWay_Expire = 30 //30.到期清理
GainWay_PromoterBind = 31 //31.手动绑定推广员
GainWay_GradeShopReturn = 32 //32.积分商城撤单退还积分
GainWay_Api_In = 33 //33.转移金币
GainWay_Api_Out = 34 //34.转移金币
GainWay_Shop_Buy = 35 //35.购买记录
GainWay_MAIL_MTEM = 36 //36.邮件领取道具
GainWay_Item_Sale = 37 //37.道具出售
GainWay_ReliefFund = 38 //38.领取救济金
GainWay_Shop_Revoke = 39 //39.撤单
GainWay_ActSign = 40 //40.签到
GainWay_MatchSignup = 41 //比赛报名费用
GainWay_MatchSeason = 42 //比赛赛季奖励
GainWay_ActSignNew = 43 //43.新签到
GainWay_ActTurnplate = 44 //44.轮盘
GainWay_ActBlindBox = 45 //45.盲盒
GainWay_ActFirstPay = 46 //46.首充
GainWay_VIPGift = 47 //47.vip礼包
GainWay_ActContinuousPay = 48 //48.连续充值
GainWay_ActJybAward = 49 //49.礼包码兑换
GainWay_LeaveDeduct = 50 //50.离开扣分
GainWay_LeaveCombat = 51 //51.离开补偿
GainWay_RankMatch = 52 //52.排位赛段位奖励
GainWay_AddBag = 53 //53 增加背包接口调用
GainWay_SmallRocket = 54 //54.小火箭收入
GainWay_BindTel = 55 //55.绑定手机号
GainWay_ReliefFund2 = 56 //56.救济金看视频双倍领取
GainWay_ActTurnplate2 = 57 //57.轮盘看视频双倍领取
GainWay_ActSignNew2 = 58 //58.签到看视频双倍领取
GainWay_ItemUse = 59 //59.道具使用
GainWay_PhoneScore = 60 //60.积分抽奖活动
GainWay_RankReward = 61 //61.段位奖励
GainWay_TaskReward = 62 //62.任务奖励
GainWay_Interact = 63 //63.房间内互动效果
GainWay_Collect = 64 //64.集卡活动
)
// 后台选择 金币变化类型 的充值 类型id号起始
//const GainWaySort_Api = 1000
// 自定义局数起始索引
//const CUSTOM_PER_GAME_INDEX_BEG int32 = 10
const (
ClientRole_Agentor int = iota
ClientRole_Player
ClientRole_GM
ClientRole_Max
)
const (
CoinSceneOp_Enter int32 = iota //进入
CoinSceneOp_Leave //离开
CoinSceneOp_Change //换桌
CoinSceneOp_AudienceEnter //观众进入
CoinSceneOp_AudienceLeave //观众离开
CoinSceneOp_AudienceChange //观众换桌
CoinSceneOP_Server
)
// 玩家离开原因
const (
PlayerLeaveReason_Normal int = iota //主动离开
PlayerLeaveReason_Bekickout //钱不够被踢出
PlayerLeaveReason_OnDestroy //房间销毁强制退出
PlayerLeaveReason_CoinScene //玩家暂离金豆自由场
PlayerLeaveReason_ChangeCoinScene //玩家换桌
PlayerLeaveReason_OnBilled //结算完毕
PlayerLeaveReason_DropLine //掉线离开
PlayerLeaveReason_LongTimeNoOp //长时间未操作
PlayerLeaveReason_GameTimes //超过游戏次数强制离开
PlayerLeaveReason_RoomFull //房间人数已达上限
PlayerLeaveReason_RoomClose //房间已解散
PlayerLeaveReason_RoomMaxCoin //超出房间限制金币范围
PlayerLeaveReason_AutoState //托管状态踢出房间
)
// 万分比
const RATE_BASE_VALUE int32 = 10000
const (
SceneState_Normal int = iota
SceneState_Fishing //鱼潮
)
const (
PlayerType_Rob int32 = 0
PlayerType_Undefine = 1
PlayerType_Black = -1
PlayerType_White = -2
)
const (
CoinPoolAIModel_Default int32 = iota //默认
CoinPoolAIModel_Normal //正常模式
CoinPoolAIModel_ShouFen //收分模式
CoinPoolAIModel_ZheZhong //折中模式
CoinPoolAIModel_TuFen //吐分
CoinPoolAIModel_Max //
)
const (
RobotServerType int = 9
RobotServerId = 901
DataServerType int = 10
DataServerId = 1001
AIServerType = 11
AIServerId = 1101
ActThrServerType int = 12
ActThrServerID = 1201
)
// 踢号原因
const (
KickReason_Unknow int32 = iota
KickReason_OtherLogin //顶号
KickReason_Freeze //冻结
KickReason_ResLow = 5 //资源
KickReason_AppLow = 6 //App版本
KickReason_CheckCodeErr = 7 //校验错误
KickReason_TaskErr = 8 //任务错误
KickReason_CantFindAcc = 9 //查找sid acc错误
KickReason_DBLoadAcc = 10 //数据库登录错误
KickReason_Logining //登陆中
KickReason_Disconnection = 99 //网络断开
)
// 游戏类型
const (
GameType_Unknow int32 = iota
GameType_Hundred // 百人类
GameType_PVP // 对战类
GameType_Slot // 拉霸类
GameType_Fishing // 捕鱼类
GameType_Casual // 休闲类
GameType_Mini // 小游戏类
GameType_Thr // 三方类
)
func IsHundredType(gt int32) bool {
return gt == GameType_Hundred || gt == GameType_Slot || gt == GameType_Casual
}
func IsCoinSceneType(gt int32) bool {
return gt == GameType_PVP || gt == GameType_Fishing
}
const PreCreateSceneAudienceNum = 20
const (
HorseRaceLampPriority_Coin int = iota //根据玩家输赢金额大小设置优先级(在最大最小限额的基础上)
HorseRaceLampPriority_Rand //随机(在最大最小限额的基础上)
)
// 设备
const (
Web = 0
Android = 1
IOS = 2
WebStr = "h5"
AndroidStr = "android"
IOSStr = "ios"
)
var DeviceName = map[int]string{
Web: WebStr,
Android: AndroidStr,
IOS: IOSStr,
}
var DeviceNum = map[string]int{
WebStr: Web,
AndroidStr: Android,
IOSStr: IOS,
}
const (
MatchTrueMan_Forbid int32 = -1 //禁止匹配真人
MatchTrueMan_Unlimited = 0 //不限制
MatchTrueMan_Priority = 1 //优先匹配真人
)
const (
SingleAdjustModeNormal = 0
SingleAdjustModeWin = 1
SingleAdjustModeLose = 2
)
// 自动化标签(程序里产生的全部<0)
const (
AutomaticTag_QZNN_Smart int32 = -1
)
const (
SceneParamEx_DbGameFreeId = 0
SceneParamEx_CanStartNum = 1 //游戏开始的要求人数
)
// 比赛参数
const (
PlayerIParam_MatchRank int = iota
PlayerIParam_IsQuit
PlayerIParam_MatchWeaken
PlayerIParam_TotalOfGames
)
const (
PARAMEX_GAMEFREEID int = iota //游戏id
PARAMEX_MATCH_COPYID //比赛副本id
PARAMEX_MATCH_ID //比赛id
PARAMEX_MATCH_PHASEIDX //赛程阶段idx
PARAMEX_MATCH_MMTYPE //赛制
PARAMEX_MATCH_BASESCORE //底分
PARAMEX_MATCH_NUMOFGAME //局数
PARAMEX_MATCH_OUTSCORE //出局分数
PARAMEX_MATCH_RESTPLAYERNUM //剩余人数
PARAMEX_MATCH_STARTNUM //本轮开始人数
//PARAMEX_MATCH_RANK //我的排名,构建房间消息时,额外补充,每个玩家不同
)
const (
MaxLoopNum = 1000
DefaultResult = 0
)
const (
CodeTypeSMS = 0 // 短信验证码
CodeTypeStr = 1 // 字符串验证码
CodeTypeHuaKuai = 2 // 滑块验证码
CodeTypeNo = 3 // 不使用验证码
)
const (
ActId_Share int = iota //0.微信分享
ActId_OnlineReward //1.在线奖励
ActId_UpgradeAccount //2.升级账号
ActId_GoldTask //3.财神任务
ActId_GoldCome //4.财神降临
ActId_LuckyTurntable //5.转盘活动
ActId_Yeb //6.余额宝
ActId_Card //7.周卡月卡
ActId_RebateTask //8.返利获取
ActId_IOSINSTALLSTABLE //9.ios安装奖励
ActId_VipLevelBonus //10.vip日周月等级奖励
ActId_LoginRandCoin //11.登录红包
ActId_OnlineRandCoin //12.红包雨
ActId_MatchSwitch //13.比赛开关
ActId_PromoterBind //14.手动绑定推广员
ActId_Lottery //15.彩金池
ActId_Task //16.活跃任务
ActId_PROMOTER //17.全民推广
ActId_Activity //18.活动界面
ActId_NewYear //19.新年暗号红包活动
ActId_Guess //20.猜灯谜活动
ActId_Sign //21.七日签到
ExchangeId_Alipay //22.兑换到支付宝
ExchangeId_Bank //23.兑换到银行卡
ExchangeId_Wechat //24.兑换到微信
ActId_Max
)
// 匹配模式
const (
MatchMode_Normal int32 = iota //普通匹配
MatchMode_Quene //队列匹配
)
const (
SCENE_BIGWINHISTORY_MAXNUMBER = 40 // 爆奖记录最大数量
SCENE_BIGWINHISTORY_LIMITNUMBER = 10 // 假数据生成临界值
SCENE_BIGWINHISTORY_TIMEINTERVAL = 2 // 假数据生成定点时间间隔,单位:小时(实际时间 = 定点时间 + 随机时间)
)
const (
OrderColumnInvalid = 0 // 默认
OrderColumnCoinPayTotal = 1 // 充值
OrderColumnCoinExchangeTotal = 2 // 提现
OrderColumnTaxTotal = 3 // 税收
OrderColumnRegisterTime = 4 // 注册时间
OrderColumnRoomNumber = 5 // 游戏房间号
OrderColumnLose = 6 // 输次数
OrderColumnWin = 7 // 赢次数
OrderColumnDraw = 8 // 平次数
OrderColumnWinCoin = 9 // 赢分
OrderColumnLoseCoin = 10 // 输分
)
const (
LoginTypeGuest = 0 // 游客登录
LoginTypeAccount = 1 // 账号登录
LoginTypeTelCode = 2 // 手机号验证码登录
LoginTypeTelegram = 5 // telegram登录
LoginTypeGoogle = 6 // google,facebook 登录
RegisterTypeTel = 3 // 手机号注册
RegisterTypeName = 4 // 账号注册
)
const (
// 账号判断状态码
LoginTypeNoExist = -1
LoginError = 0
LoginOk = 1
LoginNew = 2
LoginPasswordError = 3
LoginFreeze = 4
LoginTelExist = 8
LoginTelCodeExpire = 9 // 手机号验证码登录过期
RegisterNotExist = 6
RegisterExist = 7
// 创建账号状态码
InsertAccountOk = 9
)
const TelLoginValidDays = 7 // 手机号登录有效期,天
const (
LoginLogTypeLogin int32 = iota // 登录
LoginLogTypeLogout // 登出
LoginLogTypeRehold // 重连
LoginLogTypeDrop // 掉线
)
// 道具ID
const (
ItemIDCoin = 100001 // 金币对应的itemId
ItemIDDiamond = 100002 // 钻石对应的itemId
ItemIDMoneyPond = 100003 // 玩家金币池对应物品Id
ItemIDVipExp = 100005 // VIP经验对应的物品Id
ItemIDPhoneScore = 100006 // 手机抽奖积分
ItemIDWeekScore = 100004 // 周活跃积分
ItemIDGiftBox = 50001 // 碎片礼盒
)
func ToItemId(id int32) int32 {
switch id {
case 1:
return ItemIDCoin
case 2:
return ItemIDDiamond
}
return id
}
// 道具类型
const (
ItemTypePetFragments = 1 //宠物碎片
ItemTypeCharacterFragments = 2 //角色碎片
ItemTypeChangeCard = 3 //兑换卡
ItemTypeOther = 4 //其他
ItemTypeCoin = 5 //金币
ItemTypeDiamond = 6 //钻石
ItemTypeFishPower = 7 //捕鱼炮台
ItemTypeMoneyPond = 8 //玩家金币池
ItemTypePhoneCode = 9 //话费兑换卡
ItemTypeVipExp = 10 //VIP经验
ItemTypeShopScore = 11 //积分
ItemTypeInteract = 12 // 互动表情
)
func GetKeyNoviceGameId(gameId int) string {
return fmt.Sprintf("novice-%v", gameId)
}
func GetKeyGameType(gameType int) string {
return fmt.Sprintf("gametype-%v", gameType)
}
// 账变类型
const (
BillTypeCoin = 0 // 金币
BillTypeDiamond = 1 // 钻石
)
// 验证码类型
const (
SMSCodeTelBind = 1 // 绑定手机号验证码
SMSCodeTelLogin = 2 // 手机号登录验证码
)
// 账号类型
const (
AccountTypeGoogle = 1 // 谷歌
AccountTypeFacebook = 2 // facebook
AccountTypeTel = 3 // 手机号
)
func GetTelLoginCodeKey(platform, tel string) string {
return fmt.Sprintf("%v.%v.%v", SMSCodeTelLogin, platform, tel)
}
func GetBindTelCodeKey(platform, tel string) string {
return fmt.Sprintf("%v.%v.%v", SMSCodeTelBind, platform, tel)
}
func GetImageCodeKey(key string) string {
return fmt.Sprintf("%v.%v", "Image", key)
}
const (
SMSCodeValidTime = 60 // 访问频率限制
SMSCodeValidTimeTelBind = 60 // 绑定手机号验证码有效期,单位秒
SMSCodeValidTimeTelLogin = 600 // 手机号登录验证码有效期,单位秒
)
// 活动,任务类型
const (
TaskTypeAdv = 1 // 看广告次数
TaskTypeBuyCoin = 2 // 买金币次数
TaskTypeLogin = 3 // 登录次数
TaskTypeWinTimes = 4 // 赢游戏次数
TaskTypePlayTimes = 5 // 玩游戏次数
TaskTypeRankMatchTimes = 6 // 排位赛次数
TaskTypePay = 7 // 充值金额
TaskTypeWinOrLose = 8 // 游戏输赢金币数量
TaskTypeTienlenCount = 9 // tienlen游戏场次
TaskTypeBindInviter = 10 // 绑定邀请人数量
TaskTypeWinCoin = 11 // 赢取金币数量
TaskTypeTienlenWinTimes = 12 // tienlen游戏赢取次数
TaskTypeInviteScore = 13 // 邀请积分
TaskTypeActivityScore = 14 // 周活跃积分数量
TaskTypeFirstLogin = 15 // 每日首次登录
TaskTypeInviteNum = 16 // 邀请绑定数量
)
const (
TaskGameTypeTienlen = 1 // tienlen
TaskGameTypeThirteen = 2 // 十三张
TaskGameTypeChess = 3 // 象棋
TaskGameTypeSmallRocket = 4 // 小火箭
)
const (
TaskActivityTypeEveryDay = 1 // 每日任务
TaskActivityTypeWeek = 2 // 每周任务
TaskActivityTypeNovice = 3 // 新手任务
TaskActivityTypeInvite = 4 // 邀请任务
)
const HeadRange = 3 // 机器人头像id范围
const (
InviteScoreTypeBind = 1 // 绑定邀请码
InviteScoreTypeLogin = 2 // 每日登录
InviteScoreTypePlayTimes = 3 // 每日参与任意游戏
InviteScoreTypeRecharge = 4 // 充值
InviteScoreTypeGameTimes = 5 // 每局游戏
)
const TaskIDInvitePlayGame = 1000001
const TaskIDInviteRecharge = 1000002
const TaskIDInviteFirstLogin = 1000003
func InMatchChannel(ls []string, n string) bool {
if n == "" || len(ls) == 0 {
return false
}
if n == Channel_Rob {
return true
}
if InSliceString(ls, n) {
return true
}
if InSliceString(ls, "Official") && strings.ToLower(n) == "main" { // 兼容
return true
}
return false
}
// 渠道名称
const (
ChannelDefault = ChannelOfficial
ChannelGooglePlay = "GooglePlay"
ChannelWeb = "Web"
ChannelOfficial = "Official"
)
// 角色id
const (
DefaultRoleId = RoleIDGirl // 默认角色
RoleIDGirl = 2000001
RoleIDBoy = 2000002
RoleIDMagic = 2000003
)
var RolesIDs = []int32{RoleIDGirl, RoleIDBoy, RoleIDMagic}
// 角色加成类型
const (
RoleAddADV = 1 // 看视频加成
RoleAddCoin = 2 // 商城购买金币加成
RoleAddRankScore = 3 // 排位积分加成
)
// 宠物id
const (
DefaultPetId = PetIDChicken // 默认宠物
PetIDChicken = 3000001
)
var PetIDs = []int32{PetIDChicken}

8
common/ctrlcode.go Normal file
View File

@ -0,0 +1,8 @@
package common
const (
SrvCtrlNilCode int32 = iota
SrvCtrlCloseCode
SrvCtrlStateSwitchCode
SrvCtrlResetMgoSession
)

47
common/encryptor.go Normal file
View File

@ -0,0 +1,47 @@
package common
import (
"crypto/md5"
"encoding/hex"
"fmt"
"io"
)
type Encryptor struct {
buf1 [256]uint8
buf2 [256]uint8
}
func (e *Encryptor) Init(appId, key string, ts int32) {
h1 := md5.New()
io.WriteString(h1, fmt.Sprintf("%v;%v;%v", appId, key, ts))
raw1 := hex.EncodeToString(h1.Sum(nil))
n1 := len(raw1)
for i := 0; i < 256; i++ {
e.buf1[i] = uint8((raw1[i%n1] ^ uint8(i)) & 0xff)
}
h2 := md5.New()
io.WriteString(h2, key)
raw2 := hex.EncodeToString(h2.Sum(nil))
n2 := len(raw2)
for i := 0; i < 256; i++ {
e.buf2[i] = uint8((raw2[i%n2] ^ uint8(i)) & 0xff)
}
}
func (e *Encryptor) Encrypt(buf []byte, size int) {
var pos1, pos2 int
for i := 0; i < size; i++ {
buf[i] ^= e.buf1[pos1]
buf[i] ^= e.buf2[pos2]
pos1++
if pos1 == 255 {
pos1 = 0
pos2++
if pos2 == 255 {
pos2 = 0
}
}
}
}

172
common/esayfunc.go Normal file
View File

@ -0,0 +1,172 @@
package common
import (
"crypto/md5"
"encoding/hex"
"io"
"math/rand"
"os"
"regexp"
"encoding/json"
"math"
"mongo.games.com/goserver/core/netlib"
"mongo.games.com/goserver/srvlib"
)
const (
RankServerType = 15
)
var seed int64 = 1
func GetSelfSrvType() int {
return netlib.Config.SrvInfo.Type
}
func GetSelfSrvId() int {
return netlib.Config.SrvInfo.Id
}
func GetSelfAreaId() int {
return netlib.Config.SrvInfo.AreaID
}
func GetAccountSrvId() int {
return srvlib.ServerSessionMgrSington.GetServerId(GetSelfAreaId(), srvlib.AccountServerType)
}
func GetGameSrvId() int {
return srvlib.ServerSessionMgrSington.GetServerId(GetSelfAreaId(), srvlib.GameServerType)
}
func GetGameSrvIds() []int {
return srvlib.ServerSessionMgrSington.GetServerIds(GetSelfAreaId(), srvlib.GameServerType)
}
func GetWorldSrvId() int {
return srvlib.ServerSessionMgrSington.GetServerId(GetSelfAreaId(), srvlib.WorldServerType)
}
func GetRankSrvId() int {
return srvlib.ServerSessionMgrSington.GetServerId(GetSelfAreaId(), srvlib.RankServerType)
}
func GetAppId() string {
return Config.AppId
}
func GetClientSessionId(s *netlib.Session) srvlib.SessionId {
param := s.GetAttribute(srvlib.SessionAttributeClientSession)
if sid, ok := param.(srvlib.SessionId); ok {
return sid
}
return srvlib.SessionId(0)
}
func GetRandInt(max int) int {
seed++
rand.Seed(seed)
return rand.Intn(max)
}
func Md5String(str string) string {
h := md5.New()
io.WriteString(h, str)
return hex.EncodeToString(h.Sum(nil))
}
func MakeMd5String(strs ...string) string {
buff := md5.New()
for _, value := range strs {
io.WriteString(buff, value)
}
return hex.EncodeToString(buff.Sum(nil))
}
func SetIntegerBit(num int32, index int32) int32 {
return num | (1 << uint(index-1))
}
func GetIntegerBit(num int32, index int32) bool {
if num&(1<<uint(index-1)) > 0 {
return true
} else {
return false
}
}
// 校验身份证是否合法
var IDReg, _ = regexp.Compile(`(^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)|(^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{2}$)`)
var REGEXP_IPRule, _ = regexp.Compile(`^(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|[1-9])\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)$`)
var ClubNameRule, _ = regexp.Compile("^[\u4e00-\u9fa5a-zA-Z-z0-9]+$")
func IsValidID(id string) bool {
if IDReg != nil {
return IDReg.Match([]byte(id))
}
return false
}
func IsValidIP(Ip string) bool {
const UNKNOWIP = "0.0.0.0"
if Ip == "" || Ip == UNKNOWIP {
return false
}
if !REGEXP_IPRule.MatchString(Ip) {
return false
}
return true
}
func JsonToStr(v interface{}) string {
buff, _ := json.Marshal(v)
return string(buff)
}
func PathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
func MinI64(l int64, r int64) int64 {
if l < r {
return l
} else {
return r
}
}
func AbsI64(l int64) int64 {
if l >= 0 {
return l
} else {
return -l
}
}
// 如果结果为负,说明是玩家亏钱,结果为正,玩家赢钱。
// 图像上是一个分段函数绝对值极值为1
func GetWinLossRate(win int64, loss int64) float64 {
ret := float64(0)
if win > loss {
ret = float64(loss) / float64(win)
} else {
ret = -float64(win) / float64(loss)
}
return ret
}
// 得到一个初段慢,高段变快数
func GetSoftMaxNum(cur float64, maxValue float64) float64 {
if cur > maxValue {
return maxValue
}
return cur * math.Sin((cur/maxValue)*math.Pi/2)
}

26
common/exchangecode.go Normal file
View File

@ -0,0 +1,26 @@
package common
import (
"bytes"
"crypto/rc4"
"encoding/base32"
"encoding/binary"
"math/rand"
)
const encodeHex = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ"
var rc4Key = []byte{0x12, 0x57, 0xb8, 0xd8, 0x60, 0xae, 0x4c, 0xbd}
var HexEncoding = base32.NewEncoding(encodeHex)
var Rc4Cipher, _ = rc4.NewCipher(rc4Key)
// 生成兑换码
func GeneExchangeCode(seq int32) string {
buf := bytes.NewBuffer(nil)
binary.Write(buf, binary.BigEndian, seq)
buf.WriteByte(byte(rand.Intn(0xff)))
var dst [5]byte
Rc4Cipher.XORKeyStream(dst[:], buf.Bytes())
return HexEncoding.EncodeToString(dst[:])
}

48
common/handler.go Normal file
View File

@ -0,0 +1,48 @@
package common
import (
"fmt"
"reflect"
"mongo.games.com/goserver/core/netlib"
)
var handlers = make(map[int]Handler)
type Handler interface {
Process(s *netlib.Session, packetid int, data interface{}, sid int64) error
}
type HandlerWrapper func(s *netlib.Session, packetid int, data interface{}, sid int64) error
func (hw HandlerWrapper) Process(s *netlib.Session, packetid int, data interface{}, sid int64) error {
return hw(s, packetid, data, sid)
}
func RegisterHandler(packetId int, h Handler) {
if _, ok := handlers[packetId]; ok {
panic(fmt.Sprintf("repeate register handler: %v Handler type=%v", packetId, reflect.TypeOf(h)))
}
handlers[packetId] = h
}
func GetHandler(packetId int) Handler {
if h, ok := handlers[packetId]; ok {
return h
}
return nil
}
func Register(mainId int, msgType interface{}, h func(s *netlib.Session, packetId int, data interface{}, sid int64) error) {
RegisterHandler(mainId, HandlerWrapper(h))
f := func() interface{} {
tp := reflect.TypeOf(msgType)
if tp.Kind() == reflect.Ptr {
tp = tp.Elem()
}
return reflect.New(tp).Interface()
}
netlib.RegisterFactory(mainId, netlib.PacketFactoryWrapper(f))
}

27
common/imagecode.go Normal file
View File

@ -0,0 +1,27 @@
package common
import (
"github.com/mojocn/base64Captcha"
"strings"
)
var ImageStore = base64Captcha.DefaultMemStore
func ImageCode() (b64s string, answer string, err error) {
driver := &base64Captcha.DriverString{
Height: 50,
Width: 100,
NoiseCount: 0,
ShowLineOptions: base64Captcha.OptionShowHollowLine | base64Captcha.OptionShowSlimeLine,
Length: 5,
Source: "123456789qwertyuiopasdfghjklzxcvb",
}
var id string
c := base64Captcha.NewCaptcha(driver, ImageStore)
id, b64s, answer, err = c.Generate()
ImageStore.Verify(id, answer, true)
b64s = strings.TrimPrefix(b64s, "data:image/png;base64,")
return b64s, answer, err
}

78
common/intconvert.go Normal file
View File

@ -0,0 +1,78 @@
package common
import (
"math"
)
/*
整型安全转换
*/
const (
// MaxInt32 int32最大值
MaxInt32 int32 = math.MaxInt32
// MinInt32 int32最小值
MinInt32 = math.MinInt32
)
const (
// MaxUInt32 uint32最大值
MaxUInt32 uint32 = math.MaxUint32
)
const (
// MaxInt64 int64最大值
MaxInt64 int64 = math.MaxInt64
// MinInt64 int64最小值
MinInt64 = math.MinInt64
)
const (
// MaxUInt64 uint64最大值
MaxUInt64 uint64 = math.MaxUint64
)
// MakeU64 将两个uint32拼凑为uint64 lo为低字节 hi为高字节
func MakeU64(lo, hi uint32) uint64 {
return uint64(hi)<<32 | uint64(lo)
}
// LowU32 返回uint64低字节(后uint32)
func LowU32(n uint64) uint32 {
return uint32(n & 0xffffffff)
}
// HighU32 返回uint64高字节(前uint32)
func HighU32(n uint64) uint32 {
return uint32(n >> 32)
}
// LowAndHighUI32 分别返回uint64低字节,高字节
func LowAndHighUI32(n uint64) (uint32, uint32) {
return uint32(n & 0xffffffff), uint32(n >> 32)
}
// MakeI64 将两个int32拼凑为int64 lo为低字节 hi为高字节
func MakeI64(lo, hi int32) int64 {
return int64(hi)<<32 | int64(lo)
}
// LowI32 返回int64低字节(后int32)
func LowI32(n int64) int32 {
return int32(n & 0xffffffff)
}
// HighI32 返回int64高字节(前int32)
func HighI32(n int64) int32 {
return int32(n >> 32)
}
// LowAndHighI32 分别返回int64低字节,高字节
func LowAndHighI32(n int64) (int32, int32) {
return int32(n & 0xffffffff), int32(n >> 32)
}
// LowAndHighI32 分别返回int64低字节,高字节
func LowAndHighI64(n int64) (int64, int64) {
return n & 0xffffffff, n >> 32
}

77
common/log.go Normal file
View File

@ -0,0 +1,77 @@
package common
import (
"os"
"path/filepath"
"github.com/howeyc/fsnotify"
"mongo.games.com/goserver/core"
"mongo.games.com/goserver/core/basic"
"mongo.games.com/goserver/core/logger"
)
var LastModifyConfig int64
func init() {
core.RegisteHook(core.HOOK_BEFORE_START, func() error {
var err error
workDir, err := os.Getwd()
if err != nil {
return err
}
watcher, err := fsnotify.NewWatcher()
if err != nil {
return err
}
// Process events
go func() {
defer func() {
if err := recover(); err != nil {
logger.Logger.Warn("watch logger.xml modify goroutine err:", err)
}
}()
for {
select {
case ev, ok := <-watcher.Event:
if ok && ev != nil {
if ev.IsModify() {
obj := core.CoreObject()
if filepath.Base(ev.Name) == "logger.xml" {
if obj != nil {
obj.SendCommand(&loggerParamModifiedCommand{fileName: ev.Name}, false)
}
}
}
} else {
return
}
case err := <-watcher.Error:
logger.Logger.Warn("fsnotify error:", err)
}
}
logger.Logger.Warn("logger.xml watcher quit!")
}()
watcher.Watch(workDir)
return nil
})
}
type loggerParamModifiedCommand struct {
fileName string
}
func (lmc *loggerParamModifiedCommand) Done(o *basic.Object) error {
logger.Logger.Info("===reload ", lmc.fileName)
data, err := os.ReadFile(lmc.fileName)
if err != nil {
return err
}
if len(data) != 0 {
err = logger.Reload(lmc.fileName)
if err != nil {
logger.Logger.Warn("===reload ", lmc.fileName, err)
}
}
return err
}

132
common/log_mgr.go Normal file
View File

@ -0,0 +1,132 @@
package common
/////////////////////////////////////////////////////////////
//使用方法
//1、定义自己日志模块名字
//const(
// BaccaratLogger = "BaccaratLogger"
// )
//2、通过自己定义的日志名获得日志实例调用方式参考如下
//-------getLoggerInstanceByName(BaccaratLogger).Trace(time.Now().String())
//-------getLoggerInstanceByName(BaccaratLogger).Warn(time.Now().String())
//-------getLoggerInstanceByName(BaccaratLogger).Error(time.Now().String())
//-------getLoggerInstanceByName(BaccaratLogger).Debug(time.Now().String())
//-------getLoggerInstanceByName(BaccaratLogger).Info(time.Now().String())
//-------getLoggerInstanceByName(BaccaratLogger).Flush()
//3、如果自己定义的日志名在配置文件中没有找到则使用默认的全局日志
//4、可动态添加自己的日志配置添加后即可生效
//5、注意确保自己定义的日志模块名与配置日志的文件名一样
//6、同时确保自己配置日志的文件中输出日志的文件名参考如下
// ..........
// .......... ↓↓↓这个日志输出的文件名
// <rollingfile formatid="all" type="size" filename="./all.log"
// ..........
// ..........
//////////////////////////////////////////////////////////////
import (
"github.com/cihub/seelog"
"github.com/howeyc/fsnotify"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/utils"
"os"
"path"
"strings"
"sync"
)
var g_LogSet sync.Map
// 获得日志实例
func GetLoggerInstanceByName(name string) (log seelog.LoggerInterface) {
if v, ok := g_LogSet.Load(name); ok {
return v.(seelog.LoggerInterface)
}
return logger.Logger
}
func init() {
go utils.CatchPanic(watchFile)
}
func watchFile() {
watch, err := fsnotify.NewWatcher()
if err != nil {
logger.Error(err)
return
}
defer watch.Close()
var workingDir string
workDir, workingDirError := os.Getwd()
if workingDirError != nil {
workingDir = string(os.PathSeparator)
logger.Error(workingDirError)
return
}
workingDir = workDir + string(os.PathSeparator)
err = watch.Watch(workingDir)
if err != nil {
logger.Error(err)
return
}
dir_list, e := os.ReadDir(workingDir)
if e != nil {
logger.Error("read dir error")
return
}
for _, v := range dir_list {
if strings.Contains(v.Name(), ".xml") && v.Name() != "logger.xml" {
log, err := seelog.LoggerFromConfigAsFile(v.Name())
if err != nil {
logger.Error(err)
break
}
g_LogSet.Store(strings.TrimRight(v.Name(), ".xml"), log)
}
}
for {
select {
case ev := <-watch.Event:
if path.Ext(ev.Name) != ".xml" {
break
}
fileName := getFileName(ev.Name)
//logger.log过滤掉
if fileName == "logger" {
break
}
{
if ev.IsCreate() {
log, err := seelog.LoggerFromConfigAsFile(ev.Name)
if err != nil {
logger.Error(err)
break
}
g_LogSet.Store(fileName, log)
}
if ev.IsModify() {
log, err := seelog.LoggerFromConfigAsFile(ev.Name)
if err != nil {
logger.Error(err)
break
}
g_LogSet.Store(fileName, log)
}
if ev.IsDelete() {
g_LogSet.Delete(fileName)
}
if ev.IsRename() {
g_LogSet.Delete(fileName)
}
}
case err := <-watch.Error:
{
logger.Error("error : ", err)
return
}
}
}
}
func getFileName(fullPath string) string {
p := path.Base(strings.Replace(fullPath, "\\", "/", -1))
return strings.TrimSuffix(p, ".xml")
}

22
common/logger.xml Normal file
View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8" ?>
<seelog type="adaptive" mininterval="2000000" maxinterval="100000000" critmsgcount="500" minlevel="trace">
<exceptions>
<exception filepattern="test*" minlevel="error"/>
</exceptions>
<outputs formatid="all">
<rollingfile formatid="all" type="size" filename="./all.log" maxsize="50000000" maxrolls="5" />
<filter levels="info,trace,warn">
<console formatid="fmtinfo"/>
</filter>
<filter levels="error,critical" formatid="fmterror">
<console/>
<file path="errors.log"/>
</filter>
</outputs>
<formats>
<format id="fmtinfo" format="[%Date][%Time] [%Level] %Msg%n"/>
<format id="fmterror" format="[%Date][%Time] [%LEVEL] [%FuncShort @ %File.%Line] %Msg%n"/>
<format id="all" format="[%Date][%Time] [%Level] [@ %File.%Line] %Msg%n"/>
<format id="criticalemail" format="Critical error on our server!\n %Time %Date %RelFile %Func %Msg \nSent by Seelog"/>
</formats>
</seelog>

23
common/logmgr_test.go Normal file
View File

@ -0,0 +1,23 @@
package common
import (
"testing"
"time"
)
const (
BaccaratLogger = "BaccaratLogger"
)
func TestLogMgr(t *testing.T) {
go func() {
for {
time.Sleep(time.Second)
GetLoggerInstanceByName(BaccaratLogger).Info(time.Now().String())
GetLoggerInstanceByName(BaccaratLogger).Error(time.Now().String())
GetLoggerInstanceByName(BaccaratLogger).Debug(time.Now().String())
GetLoggerInstanceByName(BaccaratLogger).Trace(time.Now().String())
GetLoggerInstanceByName(BaccaratLogger).Warn(time.Now().String())
}
}()
}

85
common/pbutils.go Normal file
View File

@ -0,0 +1,85 @@
package common
import (
"math/rand"
)
// /////////////////////////////////////a2b
func MapToint32(a map[int]bool) (b []int32) {
b = make([]int32, len(a))
i := 0
for k, _ := range a {
b[i] = int32(k)
i++
}
return
}
func Int32Toint(a []int32) (b []int) {
b = make([]int, len(a))
for k, v := range a {
b[k] = int(v)
}
return
}
func ThreeTonullArray(a [3]int) (b []int32) {
b = make([]int32, len(a), len(a))
for i := 0; i < len(a); i++ {
b[i] = int32(a[i])
}
return
}
func RandInSliceIndex(pool []int) int {
var total int
for _, v := range pool {
total += v
}
val := int(rand.Int31n(int32(total)))
total = 0
for index, v := range pool {
total += v
if total >= val {
return index
}
}
return 0
}
func IntToInt64(a []int) []int64 {
c := make([]int64, len(a), len(a))
for k, v := range a {
c[k] = int64(v)
}
return c
}
func Int64Toint(a []int64) []int {
c := make([]int, len(a), len(a))
for k, v := range a {
c[k] = int(v)
}
return c
}
func Int64ToInt32(a []int64) []int32 {
c := make([]int32, len(a), len(a))
for k, v := range a {
c[k] = int32(v)
}
return c
}
// 将数组类型转化为int切片类型的值
func Int32SliceToInt(arr []int32) []int {
s := make([]int, 0)
for _, v := range arr {
s = append(s, int(v))
}
return s
}
// 将数组类型转化为int切片类型的值
func IntSliceToInt32(arr []int) []int32 {
s := make([]int32, 0)
for _, v := range arr {
s = append(s, int32(v))
}
return s
}

123
common/poker.go Normal file
View File

@ -0,0 +1,123 @@
package common
import (
"fmt"
"strings"
)
//牌序- K, Q, J,10, 9, 8, 7, 6, 5, 4, 3, 2, A
// 52 53
//黑桃-51,50,49,48,47,46,45,44,43,42,41,40,39
//红桃-38,37,36,35,34,33,32,31,30,29,28,27,26
//梅花-25,24,23,22,21,20,19,18,17,16,15,14,13
//方片-12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
// cards 将癞子牌转点数牌时使用
var cards = [][]int32{
{0, 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},
}
// GetPoint 获取牌点数
func GetPoint(val int32) int32 {
switch {
case val == 52:
return 16
case val == 53:
return 17
default:
return val%13 + 1
}
}
// PointValue: 13 12 11 10 9 8 7 6 5 4 3 2 1
// LogicValue: 13 12 11 10 9 8 7 6 5 4 3 15 14
var pointLogic = [18]int32{
1: 14, 2: 15,
3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10, 11: 11, 12: 12, 13: 13,
14: 1, 15: 2,
16: 16, 17: 17,
}
// GetLogic 获取逻辑值
func GetLogic(val int32) int32 {
return pointLogic[GetPoint(val)]
}
// PointToLogic 根据点数获取逻辑值
func PointToLogic(point int32) int32 {
return pointLogic[point]
}
// LogicToPoint 根据逻辑值获取点数
func LogicToPoint(logic int32) int32 {
return pointLogic[logic]
}
// GetColor 获取花色
func GetColor(val int32) int32 {
switch {
case val >= 0 && val <= 12:
return 0
case val >= 13 && val <= 25:
return 1
case val >= 26 && val <= 38:
return 2
case val >= 39 && val <= 51:
return 3
default:
return val
}
}
// CreatCard 根据点数和花色生成牌
func CreatCard(point int32, color int32, defaultColor int32) int32 {
if point == 16 {
return 52
}
if point == 17 {
return 53
}
if color < 0 || color > 3 {
color = defaultColor
}
if color < 0 || color > 3 {
color = 0
}
return cards[int(color)][point-1]
}
var color = [4]string{"♦", "♣", "♥", "♠"}
func String(val int32) string {
switch {
case val == -1:
return ""
case val == 52:
return "小王"
case val == 53:
return "大王"
default:
return fmt.Sprint(GetPoint(val), color[GetColor(val)])
}
}
func StringCards(cards []int32) string {
s := strings.Builder{}
for _, v := range cards {
s.WriteString(String(v))
s.WriteString(" ")
}
return s.String()
}
func StringCardsInt(cards []int) string {
s := strings.Builder{}
for _, v := range cards {
s.WriteString(String(int32(v)))
s.WriteString(" ")
}
return s.String()
}

350
common/random.go Normal file
View File

@ -0,0 +1,350 @@
package common
import (
"fmt"
"math"
"math/rand"
"time"
)
const (
RAND32_M int32 = 2147483647
RAND32_A = 48271
RAND32_Q = RAND32_M / RAND32_A
RAND32_R = RAND32_M % RAND32_A
)
type RandomGenerator struct {
rand32_state int32
}
func (this *RandomGenerator) RandomSeed(seed int32) {
this.rand32_state = seed
}
func (this *RandomGenerator) Random() int32 {
hi := this.rand32_state / RAND32_Q
lo := this.rand32_state % RAND32_Q
test := RAND32_A*lo - RAND32_R*hi
if test > 0 {
this.rand32_state = test
} else {
this.rand32_state = test + RAND32_M
}
return this.rand32_state - 1
}
func (this *RandomGenerator) Rand32(max int32) int32 {
return this.Random() % max
}
func (this *RandomGenerator) GetRandomSeed() int32 {
return this.rand32_state
}
// [l..u)
func RandInt(args ...int) int {
switch len(args) {
case 0:
return rand.Int()
case 1:
if args[0] > 0 {
return rand.Intn(args[0])
} else {
return 0
}
default:
l := args[0]
u := args[1]
switch {
case l == u:
{
return l
}
case l > u:
{
return u + rand.Intn(l-u)
}
default:
{
return l + rand.Intn(u-l)
}
}
}
}
func RandItemByAvg(s1 []int64) int64 {
if len(s1)%2 != 0 {
return 0
}
rates := []int64{}
for i := 0; i < len(s1); i = i + 2 {
rates = append(rates, s1[i+1])
}
index := RandInt(0, len(rates))
return s1[index*2]
}
func RandItemByWight(s1 []int64) int64 {
if len(s1)%2 != 0 {
return 0
}
rates := []int64{}
for i := 0; i < len(s1); i = i + 2 {
rates = append(rates, s1[i+1])
}
index := RandSliceIndexByWight(rates)
return s1[index*2]
}
func RandSliceIndexByWight(s1 []int64) int {
total := int64(0)
for _, v := range s1 {
total += v
}
if total <= 0 {
return 0
}
random := rand.Int63n(total)
total = 0
for i, v := range s1 {
total += v
if random < total {
return i
}
}
return 0
}
func RandSliceIndexByWight31N(s1 []int32) int {
total := int32(0)
for _, v := range s1 {
total += v
}
if total <= 0 {
return 0
}
random := rand.Int31n(total)
total = 0
for i, v := range s1 {
total += v
if random < total {
return i
}
}
return 0
}
func RandSliceIndexByWightN(s1 []int) int {
total := 0
for _, v := range s1 {
total += v
}
if total <= 0 {
return 0
}
random := rand.Intn(total)
total = 0
for i, v := range s1 {
total += v
if random < total {
return i
}
}
return 0
}
func RandNFromSlice(source []int, n int) []int {
if len(source) == 0 {
return source
}
if n > len(source) {
cycle := n / len(source)
rem := n % len(source)
for i := 0; i < cycle; i++ {
source = append(source, source...)
}
source = append(source, source[:rem]...)
}
idxs := rand.Perm(len(source))
ret := make([]int, len(source))
for i := 0; i < len(source); i++ {
ret[i] = source[idxs[i]]
}
return ret[:n]
}
func RandInt32Slice(source []int32) int32 {
if len(source) == 0 {
return 0
}
return source[rand.Intn(len(source))]
}
func RandFromRange(minValue, maxValue int32) int32 {
if minValue < 0 || maxValue < 0 {
return 0
}
if minValue >= maxValue {
return minValue
}
return rand.Int31n(maxValue-minValue+1) + minValue
}
func RandFromRangeInt64(minValue, maxValue int64) int64 {
if minValue < 0 || maxValue < 0 {
return 0
}
if minValue >= maxValue {
return minValue
}
return rand.Int63n(maxValue-minValue+1) + minValue
}
func RandSmsCode() string {
//seed := rand.Int()
//code := seed % 999999
//return strconv.Itoa(code)
return fmt.Sprintf("%06v", rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(1000000))
}
func RandSlice(n int) []int {
return rand.Perm(n)
}
func RandValueByRang(value int, l, u int) int {
r := RandInt(l, u)
return int(float64(value) * float64(r) / 100)
}
// 随机一个索引,最大的是 中间索引
func RandMaxMiddle(arrLen int) int {
if arrLen <= 0 {
return 0
}
if arrLen%2 == 0 {
return rand.Intn(arrLen / 2)
} else {
return rand.Intn(arrLen/2 + 1)
}
}
// 随机一个索引,最小的是 中间索引
func RandLastMiddle(arrLen int) int {
if arrLen <= 0 {
return 0
}
if arrLen%2 == 0 {
return rand.Intn(arrLen/2) + arrLen/2
} else {
return rand.Intn(arrLen/2+1) + arrLen/2
}
}
// 获得一个线性的随机概率是否满足
func RandLineInt64(curvalue, minValue, maxValue int64) bool {
ret := RandFromRangeInt64(minValue, maxValue)
if curvalue > ret {
return true
}
return false
}
// 获得一个正态分布的随机概率是否满足 cur max 都需要传入正值,用法不太对
func RandNormInt64(cur int64, max int64) bool {
t := math.Abs(rand.NormFloat64()) / 3
if t > 1 {
t = 1
}
if cur >= max {
return true
}
return cur > int64(t*float64(max))
}
// 获得最小公倍数
func GetMinCommonRate(array []int64) int64 {
ret := nlcm(array, len(array))
return ret
}
func gcd(a int64, b int64) int64 {
if a < b {
a, b = b, a
}
if b == 0 {
return a
} else {
return gcd(b, a%b)
}
}
func ngcd(array []int64, n int) int64 {
if n == 1 {
return array[0]
}
return gcd(array[n-1], ngcd(array, n-1))
}
func lcm(a int64, b int64) int64 {
return a * b / gcd(a, b)
}
func nlcm(array []int64, n int) int64 {
if n == 1 {
return array[0]
} else {
return lcm(array[n-1], nlcm(array, n-1))
}
}
// 随机生成遍历的数组列表
func GetRandomList(num int) []int {
var ret []int
for i := 0; i < num; i++ {
ret = append(ret, i)
r := RandInt(len(ret))
ret[i], ret[r] = ret[r], ret[i]
}
return ret
}
// 从A中随机出B个数字
func GetBNumFromA(A []int32, B int) []int32 {
if B >= len(A) {
return A
}
var ret []int32
var rate []int
for {
index := rand.Intn(len(A))
if !InSliceInt(rate, index) {
rate = append(rate, index)
ret = append(ret, A[index])
if len(ret) >= B {
return ret
}
}
}
}
func GetBElementFromA(A []interface{}, B int) []interface{} {
if B >= len(A) {
return A
}
var ret []interface{}
var rate []int
for {
index := rand.Intn(len(A))
if !InSliceInt(rate, index) {
rate = append(rate, index)
ret = append(ret, A[index])
if len(ret) >= B {
return ret
}
}
}
}

43
common/random_test.go Normal file
View File

@ -0,0 +1,43 @@
package common
import (
"testing"
)
func TestRandom(t *testing.T) {
r := &RandomGenerator{}
r.RandomSeed(1000)
for i := 0; i < 100; i++ {
t.Log(r.Rand32(100))
}
}
func TestRandMaxMiddle(t *testing.T) {
testData := [][]int{
{0},
{0, 1},
{0, 1, 2},
{0, 1, 2, 3},
}
for _, value := range testData {
index := RandMaxMiddle(len(value))
if index >= len(value) || index < 0 {
t.Error("Data", value)
t.Fatal("Error check in TestRandMaxMiddle")
}
}
}
func TestRandLastMiddle(t *testing.T) {
testData := [][]int{
{0},
{0, 1},
{0, 1, 2},
{0, 1, 2, 3},
}
for _, value := range testData {
index := RandMaxMiddle(len(value))
if index >= len(value) || index < 0 {
t.Error("Data", value)
t.Fatal("Error check in TestRandLastMiddle")
}
}
}

155
common/rangerandid.go Normal file
View File

@ -0,0 +1,155 @@
package common
import (
"math/rand"
"time"
)
const (
MAX_TRY_RAND_CNT = 10
RANDID_INVALID = -1
)
type BitPool struct {
flag []uint64
cnt int
}
func (bp *BitPool) Init(cnt int) {
bp.cnt = cnt/64 + 1
bp.flag = make([]uint64, bp.cnt, bp.cnt)
}
func (bp *BitPool) Mark(n int) bool {
idx := n / 64
off := n % 64
if idx < 0 || idx >= bp.cnt {
return false
}
bp.flag[idx] |= 1 << uint(off)
return true
}
func (bp *BitPool) Unmark(n int) bool {
idx := n / 64
off := n % 64
if idx < 0 || idx >= bp.cnt {
return false
}
bp.flag[idx] &= ^(1 << uint(off))
return true
}
func (bp *BitPool) IsMark(n int) bool {
idx := n / 64
off := n % 64
if idx < 0 || idx >= bp.cnt {
return false
}
return (bp.flag[idx] & (1 << uint(off))) != 0
}
type RandDistinctId struct {
rand *rand.Rand
bp BitPool
min int
max int
cap int
}
func NewRandDistinctId(min, max int) *RandDistinctId {
var id RandDistinctId
id.Init(min, max)
return &id
}
func (rid *RandDistinctId) Init(min, max int) {
rid.min = min
rid.max = max
rid.cap = max - min
rid.bp.Init(rid.cap)
rid.rand = rand.New(rand.NewSource(time.Now().UnixNano()))
}
func (rid *RandDistinctId) Alloc(id int) bool {
if !rid.bp.IsMark(id) {
rid.bp.Mark(id)
return true
}
return false
}
func (rid *RandDistinctId) Free(id int) bool {
if rid.bp.IsMark(id) {
rid.bp.Unmark(id)
return true
}
return false
}
func (rid *RandDistinctId) RandOne() int {
for i := 0; i < MAX_TRY_RAND_CNT; i++ {
pos := rid.rand.Intn(rid.cap)
if !rid.bp.IsMark(pos) {
rid.bp.Mark(pos)
return pos + rid.min
}
}
//try one by one
rpos := rid.rand.Intn(rid.cap)
if rpos < rid.cap/2 {
for i := rpos; i >= 0; i-- {
if !rid.bp.IsMark(i) {
rid.bp.Mark(i)
return i + rid.min
}
}
} else {
for i := rpos; i < rid.cap; i++ {
if !rid.bp.IsMark(i) {
rid.bp.Mark(i)
return i + rid.min
}
}
}
return RANDID_INVALID
}
//func memConsumed() uint64 {
// runtime.GC() //GC排除对象影响
// var memStat runtime.MemStats
// runtime.ReadMemStats(&memStat)
// return memStat.Sys
//}
//func main() {
// var idPool RandDistinctId
// before := memConsumed()
// idPool.Init(MIN, MAX)
// after := memConsumed()
//
// idMap := make(map[int]bool)
// for i := 0; i < 1000000; i++ {
// id := idPool.RandId()
// if id != -1 {
// idMap[id] = true
// }
// }
//
// start := time.Now()
// for i := 0; i < 10000; i++ {
// id := idPool.RandId()
// if id != -1 {
// fmt.Println(i, "->", id)
// idMap[id] = true
// }
//
// }
//
// fmt.Println("total take:", time.Now().Sub(start), " len:", len(idMap))
// fmt.Println(fmt.Sprintf("new %v pool consume %.3f MB", MAX-MIN, float64(after-before)/1024/1024))
//}

128
common/responseresult.go Normal file
View File

@ -0,0 +1,128 @@
package common
import (
"encoding/json"
"fmt"
"net/http"
"strings"
"mongo.games.com/goserver/core/admin"
"mongo.games.com/goserver/core/logger"
)
const (
ResponseTag_Ok int = iota //0
ResponseTag_ParamError //1
ResponseTag_NoFindService //2
ResponseTag_NoFindUser //3
ResponseTag_DataMarshalError //4
ResponseTag_TransactYield //5
ResponseTag_Unsupport //6
ResponseTag_NoFindRoom //7
ResponseTag_NoData //8
ResponseTag_NoFindClub //9
ResponseTag_ClubHadCreated //10
ResponseTag_SrcCardCntNotEnough //11
ResponseTag_SrcPlayerNotExist //12
ResponseTag_DestPlayerNotExist //13
ResponseTag_TransferCardFailed //14
ResponseTag_OpFailed //15
ResponseTag_InviterNotExist //16
ResponseTag_HadSetInviter //17
ResponseTag_CreateNewPlayerFailed //18
ResponseTag_ClubAdminCountReachLimit //19
ResponseTag_OnlyBeClubMember //20
ResponseTag_FetchNiceIdFail //21
ResponseTag_MoneyNotEnough //22
ResponseTag_TransferMoneyFailed //23
ResponseTag_SrcMoneyCntNotEnough //24
ResponseTag_CoinNotEnough //25
ResponseTag_CoinInUse //26
ResponseTag_RMBNotEnough //27
ResponseTag_AgentNotExist //28
)
type HttpResult struct {
Tag int
Msg interface{}
}
func ResponseMsg(req *http.Request, res http.ResponseWriter, tag int, msg interface{}) bool {
result := &HttpResult{
Tag: tag,
Msg: msg,
}
data, err := json.Marshal(&result)
if err != nil {
logger.Logger.Info(req.RemoteAddr, " Marshal error:", err)
return false
}
fmt.Println(string(data[:]))
dataLen := len(data)
res.Header().Set("Content-Length", fmt.Sprintf("%v", dataLen))
res.Header().Set("Access-Control-Allow-Origin", "*")
res.WriteHeader(http.StatusOK)
pos := 0
for pos < dataLen {
writeLen, err := res.Write(data[pos:])
if err != nil {
logger.Logger.Info(req.RemoteAddr, " SendData error:", err)
return false
}
pos += writeLen
}
return true
}
func responseMsg2(req *http.Request, res http.ResponseWriter, params map[string]interface{}) bool {
data, err := json.Marshal(params)
if err != nil {
logger.Logger.Info(req.RemoteAddr, " Marshal error:", err)
return false
}
fmt.Println(string(data[:]))
dataLen := len(data)
res.Header().Set("Content-Length", fmt.Sprintf("%v", dataLen))
res.Header().Set("Access-Control-Allow-Origin", "*")
res.WriteHeader(http.StatusOK)
pos := 0
for pos < dataLen {
writeLen, err := res.Write(data[pos:])
if err != nil {
logger.Logger.Info(req.RemoteAddr, " SendData error:", err)
return false
}
pos += writeLen
}
return true
}
func RequestCheck(req *http.Request, whitelist []string) bool {
strs := strings.Split(req.RemoteAddr, ":")
if len(strs) != 2 {
return false
}
if len(admin.Config.WhiteHttpAddr) > 0 {
for _, value := range admin.Config.WhiteHttpAddr {
if value == strs[0] {
return true
}
}
}
if len(whitelist) > 0 {
for _, value := range whitelist {
if value == strs[0] {
return true
}
}
}
//都没设置也让过
return len(whitelist) == 0 && len(admin.Config.WhiteHttpAddr) == 0
}

103
common/serializable.go Normal file
View File

@ -0,0 +1,103 @@
package common
import (
"bytes"
"encoding/binary"
"errors"
"hash/crc32"
"os"
)
const (
MDUMP_MAGIC_CODE uint32 = 0xdeadfee1
MDUMP_FILEHEAD_LEN = 16
MDUMP_VERSION_LASTEST = 1
)
var (
errMdumpEmpty = errors.New(".mdump empty")
errMdumpFormat = errors.New(".mdump format error")
errMdumpCheckSum = errors.New(".mdump checksum error")
errMdumpTruncation = errors.New(".mdump truncation error")
)
// 对象序列化接口
type Serializable interface {
//序列化
Marshal() ([]byte, error)
//反序列化
Unmarshal([]byte, interface{}) error
}
// 内存dump文件头
type MDumpFileHead struct {
MagicCode uint32 //mdump文件标记
Version uint32 //版本号
DataLen uint32 //数据区长度
CheckSum uint32 //校验和
}
func ReadMDumpFile(fileName string) (head *MDumpFileHead, data []byte, err error) {
buf, err := os.ReadFile(fileName)
if err != nil {
return
}
os.Remove(fileName)
//解析文件头
head = &MDumpFileHead{}
err = binary.Read(bytes.NewReader(buf), binary.BigEndian, head)
if err != nil {
return
}
if head.MagicCode != MDUMP_MAGIC_CODE {
err = errMdumpFormat
return
}
data = buf[MDUMP_FILEHEAD_LEN:]
if uint32(len(data)) != head.DataLen {
err = errMdumpTruncation
return
}
checkSum := crc32.ChecksumIEEE(data)
if checkSum != head.CheckSum {
err = errMdumpCheckSum
return
}
return
}
func WriteMDumpFile(fileName string, data []byte) error {
if len(data) == 0 {
return errMdumpEmpty
}
checkSum := crc32.ChecksumIEEE(data)
head := MDumpFileHead{
MagicCode: MDUMP_MAGIC_CODE,
Version: MDUMP_VERSION_LASTEST,
DataLen: uint32(len(data)),
CheckSum: checkSum,
}
file, err := os.Create(fileName)
if err != nil {
return err
}
defer file.Close()
//写文件头
err = binary.Write(file, binary.BigEndian, &head)
if err != nil {
return err
}
//写数据
_, err = file.WriteAt(data, int64(MDUMP_FILEHEAD_LEN))
if err != nil {
return err
}
return err
}

View File

@ -0,0 +1,10 @@
package common
import "testing"
func TestWriteMDumpFile(t *testing.T) {
err := WriteMDumpFile("test.mdump", []byte("hello world!"))
if err != nil {
t.Fatal("WriteMDumpFile fail", err)
}
}

470
common/slice.go Normal file
View File

@ -0,0 +1,470 @@
package common
import (
"fmt"
"math"
"sort"
"strconv"
"strings"
)
func CopySliceInt32(s []int32) []int32 {
n := len(s)
if n != 0 {
temp := make([]int32, n, n)
copy(temp, s)
return temp
}
return nil
}
func CopySliceInt64(s []int64) []int64 {
n := len(s)
if n != 0 {
temp := make([]int64, n, n)
copy(temp, s)
return temp
}
return nil
}
func CopySliceIntToInt32(s []int) []int32 {
n := len(s)
if n != 0 {
temp := make([]int32, n, n)
for i := 0; i < n; i++ {
temp[i] = int32(s[i])
}
return temp
}
return nil
}
func CopySliceInt32ToInt(s []int32) []int {
n := len(s)
if n != 0 {
temp := make([]int, n, n)
for i := 0; i < n; i++ {
temp[i] = int(s[i])
}
return temp
}
return nil
}
func CopySliceInt32ToInt64(s []int32) []int64 {
n := len(s)
if n != 0 {
temp := make([]int64, n, n)
for i := 0; i < n; i++ {
temp[i] = int64(s[i])
}
return temp
}
return nil
}
func InSliceInt32(sl []int32, v int32) bool {
for _, vv := range sl {
if vv == v {
return true
}
}
return false
}
func InSliceInt32Slice(sl []int32, sub []int32) bool {
for _, vv := range sub {
if !InSliceInt32(sl, vv) {
return false
}
}
return true
}
func DelSliceInt32(sl []int32, v int32) []int32 {
index := -1
for key, value := range sl {
if value == v {
index = key
break
}
}
if index != -1 {
sl = append(sl[:index], sl[index+1:]...)
}
return sl
}
func DelSliceInt64(sl []int64, v int64) []int64 {
index := -1
for key, value := range sl {
if value == v {
index = key
}
}
if index != -1 {
sl = append(sl[:index], sl[index+1:]...)
}
return sl
}
func DelSliceInt64s(cards []int64, sl []int64) []int64 {
c := make([]int64, len(cards))
s := make([]int64, len(sl))
copy(c, cards)
copy(s, sl)
for i := 0; i < len(sl); i++ {
for k, v := range c {
isF := false
for m, n := range s {
if v == n {
c = append(c[:k], c[k+1:]...)
s = append(s[:m], s[m+1:]...)
isF = true
break
}
}
if isF {
break
}
}
}
return c
}
// Data. Predict: ["4"]
// a := []string{"1","2","3","4"}
// b := []string{"0","1","2","3"}
func GetASliceInt32NotInB(a []int32, b []int32) []int32 {
var c []int32
temp := map[int32]struct{}{}
for _, val := range b {
if _, ok := temp[val]; !ok {
temp[val] = struct{}{} // 空struct 不占内存空间
}
}
for _, val := range a {
if _, ok := temp[val]; !ok {
c = append(c, val)
}
}
return c
}
func DelSliceIn32s(cards []int32, sl []int32) []int32 {
c := make([]int32, len(cards))
s := make([]int32, len(sl))
copy(c, cards)
copy(s, sl)
for i := 0; i < len(sl); i++ {
for k, v := range c {
isF := false
for m, n := range s {
if v == n {
c = append(c[:k], c[k+1:]...)
s = append(s[:m], s[m+1:]...)
isF = true
break
}
}
if isF {
break
}
}
}
return c
}
func DelSliceInt(sl []int, v int) []int {
index := -1
for key, value := range sl {
if value == v {
index = key
break
}
}
if index != -1 {
sl = append(sl[:index], sl[index+1:]...)
}
return sl
}
func DelSliceString(sl []string, v string) ([]string, bool) {
index := -1
for key, value := range sl {
if value == v {
index = key
break
}
}
if index != -1 {
sl = append(sl[:index], sl[index+1:]...)
}
return sl, index != -1
}
func InSliceInt32Index(sl []int32, v int32) int {
for idx, vv := range sl {
if vv == v {
return idx
}
}
return -1
}
func InSliceInt64Index(sl []int64, v int64) int {
for idx, vv := range sl {
if vv == v {
return idx
}
}
return -1
}
func IntSliceEqual(left []int, right []int) bool {
if len(left) != len(right) {
return false
}
for i := 0; i < len(left); i++ {
if left[i] != right[i] {
return false
}
}
return true
}
func Int32SliceEqual(left []int32, right []int32) bool {
if len(left) != len(right) {
return false
}
for i := 0; i < len(left); i++ {
if left[i] != right[i] {
return false
}
}
return true
}
func InSliceInt64(sl []int64, v int64) bool {
for _, vv := range sl {
if vv == v {
return true
}
}
return false
}
func InSliceInt(sl []int, v int) bool {
for _, vv := range sl {
if vv == v {
return true
}
}
return false
}
func InSliceString(sl []string, v string) bool {
for _, vv := range sl {
if vv == v {
return true
}
}
return false
}
func InSliceInterface(sl []interface{}, v interface{}) bool {
for _, vv := range sl {
if vv == v {
return true
}
}
return false
}
func InsertValueToSlice(index int, value int, arr []int) []int {
arr[index] = value
playerRandData := arr[index]
arr = append(arr[:index], arr[index+1:]...)
var coinRandDataSort = make([]int, 0, len(arr))
isEnd := true
for i := 0; i < len(arr); i++ {
if arr[i] < playerRandData {
coinRandDataSort = append(coinRandDataSort, arr[:i]...)
coinRandDataSort = append(coinRandDataSort, playerRandData)
coinRandDataSort = append(coinRandDataSort, arr[i:]...)
isEnd = false
break
}
}
if isEnd {
coinRandDataSort = append(arr, playerRandData)
}
return coinRandDataSort
}
func IsLadderSlice(sl []int) bool {
sort.Ints(sl)
switch len(sl) {
case 0:
return false
case 1:
return true
default:
for i := 0; i < len(sl)-1; i++ {
if sl[i] < sl[i+1] {
return false
}
}
return true
}
}
func IsSameSliceStr(dst []string, src []string) bool {
if len(dst) != len(src) {
return false
}
for i := 0; i < len(dst); i++ {
if dst[i] != src[i] {
return false
}
}
return true
}
func StrSliceInt(str string, sep string) ([]int, error) {
var err error
t := strings.Split(str, sep)
var ret []int
for i := 0; i < len(t); i++ {
if n, ok := strconv.Atoi(t[i]); ok == nil {
ret = append(ret, n)
} else {
ret = append(ret, 0)
err = ok
}
}
return ret, err
}
func SliceIntEqual(dst []int, src []int) bool {
if len(dst) != len(src) {
return false
}
for i := 0; i < len(dst); i++ {
if dst[i] != src[i] {
return false
}
}
return true
}
func SliceInt64Equal(dst []int64, src []int64) bool {
if len(dst) != len(src) {
return false
}
for i := 0; i < len(dst); i++ {
if dst[i] != src[i] {
return false
}
}
return true
}
func SliceInt32Equal(dst []int32, src []int32) bool {
if len(dst) != len(src) {
return false
}
for i := 0; i < len(dst); i++ {
if dst[i] != src[i] {
return false
}
}
return true
}
func SliceNoRepeate(data []int) []int {
var newData []int
for _, value := range data {
repeate := false
for _, n := range newData {
if n == value {
repeate = true
}
}
if !repeate {
newData = append(newData, value)
}
}
return newData
}
func SliceInterfaceToInt32(data []interface{}) []int32 {
cnt := len(data)
if cnt > 0 {
val := make([]int32, 0, cnt)
for _, f := range data {
val = append(val, int32(int32(f.(float64))))
}
return val
}
return nil
}
func SliceMaxValue(sl []int) int {
maxValue := math.MinInt32
for _, value := range sl {
if value > maxValue {
maxValue = value
}
}
return maxValue
}
func SliceMinValue(sl []int) int {
minValue := math.MaxInt32
for _, value := range sl {
if value < minValue {
minValue = value
}
}
return minValue
}
func SliceValueCount(sl []int, value int) int {
var count int
for _, v := range sl {
if v == value {
count++
}
}
return count
}
func SliceValueWeight(sl []int, index int) float64 {
if index < 0 || index > len(sl) {
return 0
}
value := sl[index]
totle := 0
for _, v := range sl {
totle += v
}
return float64(value) / float64(totle)
}
type Int32Slice []int32
func (p Int32Slice) Len() int { return len(p) }
func (p Int32Slice) Less(i, j int) bool { return p[i] < p[j] }
func (p Int32Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p Int32Slice) Sort() { sort.Sort(p) }
type Int64Slice []int64
func (p Int64Slice) Len() int { return len(p) }
func (p Int64Slice) Less(i, j int) bool { return p[i] < p[j] }
func (p Int64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p Int64Slice) Sort() { sort.Sort(p) }
type Float64Slice []float64
func (p Float64Slice) Len() int { return len(p) }
func (p Float64Slice) Less(i, j int) bool { return p[i] < p[j] }
func (p Float64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p Float64Slice) Sort() { sort.Sort(p) }
func Int32SliceToString(a []int32, delim string) string {
return strings.Trim(strings.Join(strings.Fields(fmt.Sprint(a)), delim), "[]")
}
func StringSliceToString(a []string, delim string) string {
return strings.Trim(strings.Join(strings.Fields(fmt.Sprint(a)), delim), "[]")
}

114
common/slice_test.go Normal file
View File

@ -0,0 +1,114 @@
package common
import (
"math/rand"
"sort"
"testing"
)
func TestInsertValueToSlice(t *testing.T) {
type InsertValueToSliceTestCase struct {
arr []int
index int
value int
}
testData := []InsertValueToSliceTestCase{
{arr: []int{100, 90, 80, 70, 60, 50, 40, 30, 20, 10}, index: 0, value: 110},
{arr: []int{100, 90, 80, 70, 60, 50, 40, 30, 20, 10}, index: 0, value: 1},
{arr: []int{100, 90, 80, 70, 60, 50, 40, 30, 20, 10}, index: 0, value: 55},
{arr: []int{100, 90, 80, 70, 60, 50, 40, 30, 20, 10}, index: 5, value: 110},
{arr: []int{100, 90, 80, 70, 60, 50, 40, 30, 20, 10}, index: 5, value: 1},
{arr: []int{100, 90, 80, 70, 60, 50, 40, 30, 20, 10}, index: 5, value: 55},
{arr: []int{100, 90, 80, 70, 60, 50, 40, 30, 20, 10}, index: 9, value: 110},
{arr: []int{100, 90, 80, 70, 60, 50, 40, 30, 20, 10}, index: 9, value: 1},
{arr: []int{100, 90, 80, 70, 60, 50, 40, 30, 20, 10}, index: 9, value: 55},
}
for _, value := range testData {
newArr := InsertValueToSlice(value.index, value.value, value.arr)
if !IsLadderSlice(newArr) || len(newArr) != len(value.arr) {
t.Log(value)
t.Failed()
}
}
}
func TestSliceNoRepeate(t *testing.T) {
type TestCase struct {
Src []int
Dest []int
}
var testData = []TestCase{
TestCase{Src: []int{}, Dest: []int{}},
TestCase{Src: []int{1}, Dest: []int{1}},
TestCase{Src: []int{1, 1}, Dest: []int{1}},
TestCase{Src: []int{1, 1, 1}, Dest: []int{1}},
TestCase{Src: []int{1, 2, 1}, Dest: []int{1, 2}},
TestCase{Src: []int{1, 2, 3}, Dest: []int{1, 2, 3}},
TestCase{Src: []int{1, 2, 3, 3}, Dest: []int{1, 2, 3}},
TestCase{Src: []int{1, 2, 3, 3, 5}, Dest: []int{1, 2, 3, 5}},
TestCase{Src: []int{1, 2, 3, 3, 5, 5}, Dest: []int{1, 2, 3, 5}},
TestCase{Src: []int{1, 2, 3, 3, 5, 5, 6}, Dest: []int{1, 2, 3, 5, 6}},
TestCase{Src: []int{1, 2, 3, 3, 5, 6, 6}, Dest: []int{1, 2, 3, 5, 6}},
TestCase{Src: []int{1, 2, 3, 3, 5, 6, 7}, Dest: []int{1, 2, 3, 5, 6, 7}},
}
for _, value := range testData {
dest := SliceNoRepeate(value.Src)
equal := SliceIntEqual(dest, value.Dest)
if !equal {
t.Error(value)
t.Error(dest)
t.Fatal()
}
}
for i := 0; i < 1000; i++ {
length := rand.Intn(100) + 1
src := rand.Perm(length)
dest := make([]int, length)
copy(dest, src)
e := rand.Intn(50)
for s := 0; s < e; s++ {
src = append(src, rand.Intn(length))
}
norepeate := SliceNoRepeate(src)
equal := SliceIntEqual(norepeate, dest)
if !equal {
sort.Ints(src)
sort.Ints(dest)
sort.Ints(norepeate)
t.Error(src)
t.Error(dest)
t.Error(norepeate)
t.Fatal()
}
}
}
func TestSliceDelValue(t *testing.T) {
type DelTestData struct {
Arr []int32
Del int32
}
var TestCase = []DelTestData{
{Arr: []int32{1, 2, 3, 4, 5}, Del: 1},
{Arr: []int32{1, 2, 3, 4, 5}, Del: 3},
{Arr: []int32{1, 2, 3, 4, 5}, Del: 5},
{Arr: []int32{1, 2, 3, 4, 5}, Del: 6},
{Arr: []int32{1, 2, 3, 4, 5}, Del: 0},
}
for i := 0; i < len(TestCase); i++ {
randArr := DelSliceInt32(TestCase[i].Arr, TestCase[i].Del)
if InSliceInt32(randArr, TestCase[i].Del) {
t.Log(randArr)
t.Log(TestCase[i].Del)
t.Fatal("Slice del value failed.")
}
}
for i := 0; i < 1000; i++ {
randArr := rand.Perm(rand.Intn(1000))
delValue := rand.Intn(1000)
randArr = DelSliceInt(randArr, delValue)
if InSliceInt(randArr, delValue) {
t.Log(randArr)
t.Log(delValue)
t.Fatal("Slice del value failed.")
}
}
}

25
common/sortobject.go Normal file
View File

@ -0,0 +1,25 @@
package common
import "sort"
type SortObjectSlice []SortObject
type SortObject struct {
SortValue int
ObjectValue int
RoomId int
}
func (so SortObjectSlice) Len() int {
return len(so)
}
func (so SortObjectSlice) Less(i, j int) bool {
return so[i].SortValue > so[j].SortValue
}
func (so SortObjectSlice) Swap(i, j int) {
so[i], so[j] = so[j], so[i]
}
func Sort(data SortObjectSlice) {
sort.Sort(data)
}

60
common/srvmsg.go Normal file
View File

@ -0,0 +1,60 @@
package common
import (
"fmt"
"mongo.games.com/game/proto"
"mongo.games.com/game/protocol/player"
)
const (
SRVMSG_CODE_DEFAULT int32 = iota
)
type SrvMsgSender interface {
SendToClient(packetid int, rawpack interface{}) bool
}
func SendSrvMsg(sender SrvMsgSender, msgId int32, params ...interface{}) bool {
pack := CreateSrvMsg(msgId, params)
return sender.SendToClient(int(player.PlayerPacketID_PACKET_SC_SRVMSG), pack)
}
func CreateSrvMsg(msgId int32, params ...interface{}) *player.SCSrvMsg {
pack := &player.SCSrvMsg{
MsgId: msgId,
}
for _, p := range params {
switch d := p.(type) {
case string:
pack.Params = append(pack.Params, &player.SrvMsgParam{StrParam: d})
case int:
pack.Params = append(pack.Params, &player.SrvMsgParam{IntParam: int32(d)})
case int8:
pack.Params = append(pack.Params, &player.SrvMsgParam{IntParam: int32(d)})
case int16:
pack.Params = append(pack.Params, &player.SrvMsgParam{IntParam: int32(d)})
case int32:
pack.Params = append(pack.Params, &player.SrvMsgParam{IntParam: d})
case int64:
pack.Params = append(pack.Params, &player.SrvMsgParam{IntParam: int32(d)})
case uint:
pack.Params = append(pack.Params, &player.SrvMsgParam{IntParam: int32(d)})
case uint8:
pack.Params = append(pack.Params, &player.SrvMsgParam{IntParam: int32(d)})
case uint16:
pack.Params = append(pack.Params, &player.SrvMsgParam{IntParam: int32(d)})
case uint32:
pack.Params = append(pack.Params, &player.SrvMsgParam{IntParam: int32(d)})
case uint64:
pack.Params = append(pack.Params, &player.SrvMsgParam{IntParam: int32(d)})
case float32:
pack.Params = append(pack.Params, &player.SrvMsgParam{IntParam: int32(d)})
case float64:
pack.Params = append(pack.Params, &player.SrvMsgParam{IntParam: int32(d)})
default:
pack.Params = append(pack.Params, &player.SrvMsgParam{StrParam: fmt.Sprintf("%v", p)})
}
}
proto.SetDefaults(pack)
return pack
}

86
common/sstransmit.go Normal file
View File

@ -0,0 +1,86 @@
package common
import (
"fmt"
rawproto "google.golang.org/protobuf/proto"
"mongo.games.com/game/proto"
"mongo.games.com/game/protocol/server"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/netlib"
"mongo.games.com/goserver/core/profile"
"mongo.games.com/goserver/core/utils"
)
var (
TransmitMaker = &SSTransmitPacketFactory{}
)
type SSTransmitPacketFactory struct {
}
type SSTransmitHandler struct {
}
func (this *SSTransmitPacketFactory) CreatePacket() interface{} {
pack := &server.SSTransmit{}
return pack
}
func (this *SSTransmitPacketFactory) CreateTransmitPacket(packetid int, data interface{}, sid int64) (rawproto.Message, error) {
pack := &server.SSTransmit{
SessionId: sid,
}
if byteData, ok := data.([]byte); ok {
pack.PacketData = byteData
if byteData == nil || len(byteData) == 0 {
logger.Logger.Info("SSTransmitPacketFactory.CreateTransmitPacket PacketData is empty")
}
} else {
byteData, err := netlib.MarshalPacket(packetid, data)
if err == nil {
pack.PacketData = byteData
if byteData == nil || len(byteData) == 0 {
logger.Logger.Info("SSTransmitPacketFactory.CreateTransmitPacket PacketData is empty")
}
} else {
logger.Logger.Info("SSTransmitPacketFactory.CreateTransmitPacket err:", err)
return nil, err
}
}
proto.SetDefaults(pack)
return pack, nil
}
func (this *SSTransmitHandler) Process(s *netlib.Session, packetid int, data interface{}) error {
//logger.Logger.Trace("SSTransmitHandler Process recv ", data)
if transmitPack, ok := data.(*server.SSTransmit); ok {
pd := transmitPack.GetPacketData()
sid := transmitPack.GetSessionId()
packetid, packet, err := netlib.UnmarshalPacket(pd)
if err == nil {
h := GetHandler(packetid)
if h != nil {
utils.DumpStackIfPanic(fmt.Sprintf("SSTransmitHandler.Process error, packetid:%v", packetid))
watch := profile.TimeStatisticMgr.WatchStart(fmt.Sprintf("/action/packet:%v", packetid), profile.TIME_ELEMENT_ACTION)
err := h.Process(s, packetid, packet, sid)
if watch != nil {
watch.Stop()
}
if err != nil {
logger.Logger.Tracef("Packet [%d] error:", packetid, err)
}
return err
} else {
logger.Logger.Tracef("Packet %v not find handler.", packetid)
}
} else {
logger.Logger.Trace("SSTransmitHandler process err:", err)
}
}
return nil
}
func init() {
netlib.RegisterHandler(int(server.TransmitPacketID_PACKET_SS_PACKET_TRANSMIT), &SSTransmitHandler{})
netlib.RegisterFactory(int(server.TransmitPacketID_PACKET_SS_PACKET_TRANSMIT), TransmitMaker)
}

7
common/sysmsg.go Normal file
View File

@ -0,0 +1,7 @@
package common
// 系统消息编号
const (
SYSMSG_BEGIN int = iota
SYSMSG_PASSHU //因过胡规则,此牌不能胡
)

30
common/temp.txt Normal file
View File

@ -0,0 +1,30 @@
GainWay_NewPlayer int32 = iota //0.新建角色 新建账号,系统赠送房卡%s张|新建账号,系统赠送金币%s个 remark:无
GainWay_Pay //1.后台增加(主要是充值) %s获得d%张房卡剩余d%张 remark:充值X元
GainWay_Transfer_In //2.俱乐部转移(转入) s%赠送您房卡d%张剩余d%张 remark:玩家名称
GainWay_AgentReturn //3.代创房间返还 -
GainWay_DrawPrize //4.领取奖励 领取奖励房卡d%张,剩余%d张 remark:无
GainWay_Share //5.每日分享 每日分享活动奖励d%房卡剩余d%房卡 remark:无
GainWay_Activty //6.活动获得 s%活动奖励d%金币剩余d%金币 remark:活动名称
GainWay_Game //7.玩游戏消耗 开房间房卡-d%张剩余d%张 remark:无
GainWay_Task //8.任务 完成%s任务奖励房卡d%张剩余d%张 remark:任务名称
GainWay_ByPMCmd //9.pm命令 -
GainWay_MatchSignup //10.比赛报名 -
GainWay_MatchPlay //11.比赛回兑 -
GainWay_MatchAdd //12.比赛补充 -
GainWay_MatchBreakBack //13.退赛退还 -
GainWay_MatchSystemSupply //14.系统补给 -
GainWay_Exchange //15.兑换 兑换%s红包%d分剩余红包%d分 remark:房卡x张
GainWay_Contribute //16.贡献 -
GainWay_ClubMoneySceneFee //17.俱乐部钻石场房费 -
GainWay_Transfer_Out //18.俱乐部转移(转出) 赠送给s%房卡d%张剩余d%张 remark:玩家名称
GainWay_ServiceFee //19.桌费 扣除桌费d%金币剩余d%金币 remark:无
GainWay_CoinSceneWin //20.金豆场赢取 参与游戏赢取d%金币剩余d%金币 remark:无
GainWay_CoinSceneLost //21.金豆场输 参与游戏输掉d%金币剩余d%金币 remark:无
GainWay_BindTel //22.绑定手机 绑定手机,获得房卡%d张剩余%d张 remark:无
GainWay_PlayerShare //23.隶属玩家每日分享 每日分享活动,领取房卡%d张剩余%d张 remark:无
GainWay_Invite //24.邀请玩家 邀请玩家,获得红包%d分剩余%d分 remark:无
GainWay_LoginSign //25.签到奖励
GainWay_OnlineGift //26.签到奖励
GainWay_CoinSceneEnter //27.进入金币场预扣
GainWay_ShopBuy //28.商城购买或者兑换 使用%s购买金币%d剩余%d remark:房卡x张
GainWay_CoinSceneLeave //29.离开金币场回兑

145
common/time.go Normal file
View File

@ -0,0 +1,145 @@
package common
import (
"time"
"mongo.games.com/goserver/core/timer"
)
type WGDayTimeChange struct {
LastMin int
LastHour int
LastDay int
LastWeek int
LastMonth int
}
func InSameDay(tNow, tPre time.Time) bool {
if tPre.IsZero() {
return true
}
if tNow.Day() != tPre.Day() {
return false
}
if tNow.Sub(tPre) < time.Hour*24 {
return true
}
return false
}
func InSameDayNoZero(tNow, tPre time.Time) bool {
if tNow.Day() != tPre.Day() {
return false
}
if tNow.Sub(tPre) < time.Hour*24 {
return true
}
return false
}
func TsInSameDay(tsNow, tsPre int64) bool {
tNow := time.Unix(tsNow, 0)
tPre := time.Unix(tsPre, 0)
return InSameDay(tNow, tPre)
}
func IsContinueDay(tNow, tPre time.Time) bool {
if tPre.IsZero() {
return true
}
tNext := tPre.AddDate(0, 0, 1)
if InSameDay(tNow, tNext) {
return true
}
return false
}
func InSameMonth(tNow, tPre time.Time) bool {
if tPre.IsZero() {
return true
}
if tNow.Month() != tPre.Month() {
return false
}
if tNow.Year() == tPre.Year() {
return true
}
return false
}
func InSameWeek(tNow, tPre time.Time) bool {
if tPre.IsZero() {
return true
}
preYear, preWeek := tPre.ISOWeek()
nowYear, nowWeek := tNow.ISOWeek()
if preYear == nowYear && preWeek == nowWeek {
return true
}
return false
}
func TsInSameWeek(tsNow, tsPre int64) bool {
tNow := time.Unix(tsNow, 0)
tPre := time.Unix(tsPre, 0)
return InSameWeek(tNow, tPre)
}
func DiffDay(tNow, tPre time.Time) int { // AddDate(0, 0, -1) 会显示差0天
y, m, d := tPre.Date()
tStart := time.Date(y, m, d, 0, 0, 0, 0, tPre.Location())
return int(tNow.Sub(tStart) / (time.Hour * 24))
}
func DiffDaybyTs(tNowts, tPrets int64) int {
tNow := time.Unix(tNowts, 0)
tPre := time.Unix(tPrets, 0)
y, m, d := tPre.Date()
tStart := time.Date(y, m, d, 0, 0, 0, 0, tPre.Location())
return int(tNow.Sub(tStart) / (time.Hour * 24))
}
func DiffMonth(tNow, tPre time.Time) int {
y1, m1, _ := tNow.Date()
y2, m2, _ := tPre.Date()
diffMonth := (y1-y2)*12 + (int(m1) - int(m2))
return int(diffMonth)
}
func DelayInvake(method func(), ud interface{}, delay time.Duration, times int) (timer.TimerHandle, bool) {
return timer.StartTimer(timer.TimerActionWrapper(func(h timer.TimerHandle, ud interface{}) bool {
if method != nil {
method()
}
return true
}), ud, delay, times)
}
func StrTimeToTs(strTime string) int64 {
rTime, err := time.ParseInLocation("2006-01-02 15:04:05", strTime, time.Local)
if err != nil {
return 0
}
return rTime.Unix()
}
func TsToStrTime(tc int64) string {
//return time.Now().Format("2018-07-02 19:14:00")
return time.Unix(tc, 0).Format("2006-01-02 15:04:05")
}
func TsToStrDateTime(tc int64) string {
//return time.Now().Format("2018-07-02 19:14:00")
return time.Unix(tc, 0).Format("2006-01-02")
}
func InTimeRange(beginHour, beginMinute, endHour, endMinute, checkHour, checkMinute int32) bool {
beginTime := beginHour*100 + beginMinute
endTime := endHour*100 + endMinute
checkTime := checkHour*100 + checkMinute
return beginTime <= checkTime && checkTime <= endTime
}

129
common/time_test.go Normal file
View File

@ -0,0 +1,129 @@
package common
import (
"testing"
"time"
)
type TimeTestCaseData struct {
t1 time.Time
t2 time.Time
expectResult bool
}
func TestInSameDay(t *testing.T) {
testCases := []*TimeTestCaseData{
&TimeTestCaseData{
t1: time.Date(2016, time.May, 17, 15, 12, 15, 0, time.Local),
t2: time.Date(2016, time.May, 16, 15, 12, 15, 0, time.Local),
expectResult: false,
},
&TimeTestCaseData{
t1: time.Date(2016, time.May, 16, 23, 59, 59, 0, time.Local),
t2: time.Date(2016, time.May, 16, 15, 12, 15, 0, time.Local),
expectResult: true,
},
&TimeTestCaseData{
t1: time.Date(2017, time.May, 16, 23, 59, 59, 0, time.Local),
t2: time.Date(2016, time.May, 16, 15, 12, 15, 0, time.Local),
expectResult: false,
},
}
for i := 0; i < len(testCases); i++ {
tc := testCases[i]
if InSameDay(tc.t1, tc.t2) != tc.expectResult {
t.Fatal("IsSameDay(", tc.t1, tc.t2, ") expect result is ", tc.expectResult)
}
}
}
func TestIsContinueDay(t *testing.T) {
testCases := []*TimeTestCaseData{
&TimeTestCaseData{
t1: time.Date(2016, time.May, 17, 15, 12, 15, 0, time.Local),
t2: time.Date(2016, time.May, 16, 15, 12, 15, 0, time.Local),
expectResult: true,
},
&TimeTestCaseData{
t1: time.Date(2016, time.May, 16, 23, 59, 59, 0, time.Local),
t2: time.Date(2016, time.May, 16, 15, 12, 15, 0, time.Local),
expectResult: false,
},
&TimeTestCaseData{
t1: time.Date(2017, time.May, 17, 23, 59, 59, 0, time.Local),
t2: time.Date(2016, time.May, 16, 15, 12, 15, 0, time.Local),
expectResult: false,
},
}
for i := 0; i < len(testCases); i++ {
tc := testCases[i]
if IsContinueDay(tc.t1, tc.t2) != tc.expectResult {
t.Fatal("IsContinueDay(", tc.t1, tc.t2, ") expect result is ", tc.expectResult)
}
}
}
func TestInSameMonth(t *testing.T) {
testCases := []*TimeTestCaseData{
&TimeTestCaseData{
t1: time.Date(2016, time.May, 17, 15, 12, 15, 0, time.Local),
t2: time.Date(2016, time.May, 16, 15, 12, 15, 0, time.Local),
expectResult: true,
},
&TimeTestCaseData{
t1: time.Date(2016, time.June, 1, 23, 59, 59, 0, time.Local),
t2: time.Date(2016, time.May, 31, 15, 12, 15, 0, time.Local),
expectResult: false,
},
&TimeTestCaseData{
t1: time.Date(2017, time.May, 17, 23, 59, 59, 0, time.Local),
t2: time.Date(2016, time.May, 16, 15, 12, 15, 0, time.Local),
expectResult: false,
},
}
for i := 0; i < len(testCases); i++ {
tc := testCases[i]
if InSameMonth(tc.t1, tc.t2) != tc.expectResult {
t.Fatal("InSameMonth(", tc.t1, tc.t2, ") expect result is ", tc.expectResult)
}
}
}
func TestInSameWeek(t *testing.T) {
testCases := []*TimeTestCaseData{
&TimeTestCaseData{
t1: time.Date(2016, time.May, 17, 15, 12, 15, 0, time.Local),
t2: time.Date(2016, time.May, 16, 15, 12, 15, 0, time.Local),
expectResult: true,
},
&TimeTestCaseData{
t1: time.Date(2016, time.May, 16, 23, 59, 59, 0, time.Local),
t2: time.Date(2016, time.May, 15, 15, 12, 15, 0, time.Local),
expectResult: false,
},
&TimeTestCaseData{
t1: time.Date(2016, time.January, 1, 23, 59, 59, 0, time.Local),
t2: time.Date(2015, time.December, 31, 15, 12, 15, 0, time.Local),
expectResult: true,
},
&TimeTestCaseData{
t1: time.Date(2024, time.March, 17, 23, 59, 59, 0, time.Local),
t2: time.Date(2024, time.March, 18, 15, 12, 15, 0, time.Local),
expectResult: false,
},
}
for i := 0; i < len(testCases); i++ {
tc := testCases[i]
if InSameWeek(tc.t1, tc.t2) != tc.expectResult {
t.Fatal("InSameWeek(", tc.t1, tc.t2, ") expect result is ", tc.expectResult)
}
}
}

108
common/transtype.go Normal file
View File

@ -0,0 +1,108 @@
package common
import (
"mongo.games.com/goserver/core/transact"
)
const (
TransType_Login transact.TransType = 1000
TransType_Logout = 1001
TransType_WebTrascate = 1002
TransType_AddCoin = 1003
TransType_ViewData = 1004
TransType_DayTimeChange = 1005
TransType_CoinSceneChange = 1006
TransType_WebApi = 1007
TransType_WebApi_ForRank = 1101
TransType_GameSrvWebApi = 1008
TransType_QueryCoinPool = 1009
TransType_StopServer = 1010
TransType_QueryAllCoinPool = 1011
TransType_ActThrSrvWebApi = 1012
TransType_MatchSceneChange = 1013
TransType_MiniGameAddCoin = 1014
TransType_ServerCtrl = 1015
)
type M2GWebTrascate struct {
Tag int
Param string
}
type M2GWebApiRequest struct {
Path string
RawQuery string
ReqIp string
Body []byte
}
type M2GWebApiResponse struct {
Body []byte
}
type W2GQueryCoinPool struct {
GameId int32
GameMode int32
Platform string
GroupId int32
}
type PlatformStates struct {
Platform string
GamesVal map[int32]*CoinPoolStatesInfo
}
type GamesIndex struct {
GameFreeId int32
GroupId int32
}
type QueryGames struct {
Index map[string][]*GamesIndex
}
// 单个平台各游戏水池信息概况
type CoinPoolStatesInfo struct {
GameId int32 //当前游戏id
GameFreeId int32 //游戏id
LowerLimit int32 //库存下限
UpperLimit int32 //库存上限
CoinValue int32 //当前库存值
States int32 //水池状态
}
type CoinPoolSetting struct {
Platform string //平台id
GameFreeId int32 //游戏id
ServerId int32 //服务器id
GroupId int32 //组id
InitValue int32 //初始库存值
LowerLimit int32 //库存下限
UpperLimit int32 //库存上限
UpperOffsetLimit int32 //上限偏移值
MaxOutValue int32 //最大吐钱数
ChangeRate int32 //库存变化速度
MinOutPlayerNum int32 //最少吐钱人数
UpperLimitOfOdds int32 //赔率上限(万分比)
CoinValue int64 //当前库存值
PlayerNum int32 //当前在线人数
BaseRate int32 //基础赔率
CtroRate int32 //调节赔率
HardTimeMin int32 //收分调节频率下限
HardTimeMax int32 //收分调节频率上限
NormalTimeMin int32 //正常调节频率下限
NormalTimeMax int32 //正常调节频率上限
EasyTimeMin int32 //放分调节频率下限
EasyTimeMax int32 //放分调节频率上限
EasrierTimeMin int32 //吐分调节频率下限
EasrierTimeMax int32 //吐分分调节频率上限
CpCangeType int32
CpChangeInterval int32
CpChangeTotle int32
CpChangeLower int32
CpChangeUpper int32
ProfitRate int32 //收益比例
ProfitPool int64 //当前收益池
CoinPoolMode int32 //当前池模式
ResetTime int32
ProfitAutoRate int32
ProfitManualRate int32
ProfitUseManual bool
}

3
dbproxy/README Normal file
View File

@ -0,0 +1,3 @@
1.动态数据库连接配置文件修改立刻更新数据库连接或收到etcd通知
2.rabbitmq消费端日志游戏记录等异步写入数据库
3.提供数据库rpc调用

61
dbproxy/config.json Normal file
View File

@ -0,0 +1,61 @@
{
"tx": {
"TxSkeletonName": "mongo.games.com/goserver/srvlib/txcommskeleton"
},
"module": {
"Options": {
"QueueBacklog": 1024,
"MaxDone": 1024,
"Interval": 100
}
},
"executor": {
"Options": {
"QueueBacklog": 1024,
"MaxDone": 1024,
"Interval": 31004
},
"Worker": {
"WorkerCnt": 8,
"Options": {
"QueueBacklog": 1024,
"MaxDone": 1024,
"Interval": 0
}
}
},
"timer": {
"Options": {
"QueueBacklog": 1024,
"MaxDone": 1024,
"Interval": 100
}
},
"cmdline": {
"SupportCmdLine": true
},
"signal": {
"SupportSignal": true
},
"cmgo": {
"CfgFile": "./etc/mgo.json"
},
"common": {
"AppId": "5c56d1644966f078bfb90c71",
"IsDevMode": true
},
"costum": {
"MgoRpcCliNet": "tcp",
"MgoRpcCliAddr": "127.0.0.1:8999",
"RabbitMQURL": "amqp://win88:123456@127.0.0.1:5672/win88",
"RMQExchange": "win88",
"RMQQosPrefetchCount": 2,
"RMQQosPrefetchSize": 0,
"RMQQosGlobal": true,
"etcdurl": [
"127.0.0.1:2379"
],
"etcduser": "",
"etcdpwd": ""
}
}

102
dbproxy/etc/mgo.json Normal file
View File

@ -0,0 +1,102 @@
{
"Global":{
"user":{
"HostName":"127.0.0.1",
"HostPort":27017,
"Database":"win88_global",
"Username":"",
"Password":"",
"Options":"",
"CfgSign":"",
"CfgVer":0
},
"log":{
"HostName":"127.0.0.1",
"HostPort":27017,
"Database":"win88_log",
"Username":"",
"Password":"",
"Options":"",
"CfgSign":"",
"CfgVer":0
},
"monitor":{
"HostName":"127.0.0.1",
"HostPort":27017,
"Database":"win88_monitor",
"Username":"",
"Password":"",
"Options":"",
"CfgSign":"",
"CfgVer":0
}
},
"Platforms":{
"0":{
"user":{
"HostName":"127.0.0.1",
"HostPort":27017,
"Database":"win88_user_plt_000",
"Username":"",
"Password":"",
"Options":"",
"CfgSign":"",
"CfgVer":0
},
"log":{
"HostName":"127.0.0.1",
"HostPort":27017,
"Database":"win88_log_plt_000",
"Username":"",
"Password":"",
"Options":"",
"CfgSign":"",
"CfgVer":0
}
},
"1":{
"user":{
"HostName":"127.0.0.1",
"HostPort":27017,
"Database":"win88_user_plt_001",
"Username":"",
"Password":"",
"Options":"",
"CfgSign":"",
"CfgVer":0
},
"log":{
"HostName":"127.0.0.1",
"HostPort":27017,
"Database":"win88_log_plt_001",
"Username":"",
"Password":"",
"Options":"",
"CfgSign":"",
"CfgVer":0
}
},
"12":{
"user":{
"HostName":"127.0.0.1",
"HostPort":27017,
"Database":"win88_user_plt_012",
"Username":"",
"Password":"",
"Options":"",
"CfgSign":"",
"CfgVer":0
},
"log":{
"HostName":"127.0.0.1",
"HostPort":27017,
"Database":"win88_log_plt_012",
"Username":"",
"Password":"",
"Options":"",
"CfgSign":"",
"CfgVer":0
}
}
}
}

37
dbproxy/etcd.go Normal file
View File

@ -0,0 +1,37 @@
package main
import (
"strings"
"go.etcd.io/etcd/client/v3"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/game/dbproxy/mongo"
"mongo.games.com/game/etcd"
"mongo.games.com/game/protocol/webapi"
)
func init() {
etcd.Register(etcd.ETCDKEY_SYS_PLT_DBCFG_PREFIX, webapi.PlatformDbConfig{}, func(completeKey string, isInit bool, event *clientv3.Event, data interface{}) {
if event.Type == clientv3.EventTypeDelete {
return
}
config, ok := data.(*webapi.PlatformDbConfig)
if !ok {
logger.Logger.Errorf("etcd completeKey:%s, data type error", completeKey)
return
}
s := strings.TrimPrefix(completeKey, etcd.ETCDKEY_SYS_PLT_DBCFG_PREFIX)
arr := strings.Split(s, "/")
if len(arr) >= 1 {
pltId := arr[0]
//用户库
mongo.MgoSessionMgrSington.UptCfgWithEtcd(pltId, "user", config.MongoDb)
//日志库
mongo.MgoSessionMgrSington.UptCfgWithEtcd(pltId, "log", config.MongoDbLog)
}
})
}

22
dbproxy/logger.xml Normal file
View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8" ?>
<seelog type="adaptive" mininterval="2000000" maxinterval="100000000" critmsgcount="500" minlevel="trace">
<exceptions>
<exception filepattern="test*" minlevel="error"/>
</exceptions>
<outputs formatid="all">
<rollingfile formatid="all" type="size" filename="./all.log" maxsize="50000000" maxrolls="5" />
<filter levels="info,trace,warn">
<console formatid="fmtinfo"/>
</filter>
<filter levels="error,critical" formatid="fmterror">
<console/>
<file path="errors.log"/>
</filter>
</outputs>
<formats>
<format id="fmtinfo" format="[%Date][%Time] [%Level] %Msg%n"/>
<format id="fmterror" format="[%Date][%Time] [%LEVEL] [%FuncShort @ %File.%Line] %Msg%n"/>
<format id="all" format="[%Date][%Time] [%Level] [@ %File.%Line] %Msg%n"/>
<format id="criticalemail" format="Critical error on our server!\n %Time %Date %RelFile %Func %Msg \nSent by Seelog"/>
</formats>
</seelog>

59
dbproxy/main.go Normal file
View File

@ -0,0 +1,59 @@
package main
import (
"log"
"net"
"net/http"
"net/rpc"
"mongo.games.com/goserver/core"
"mongo.games.com/goserver/core/broker/rabbitmq"
"mongo.games.com/goserver/core/module"
_ "games.yol.com/win88"
_ "mongo.games.com/game/dbproxy/mq"
"mongo.games.com/game/common"
"mongo.games.com/game/dbproxy/svc"
"mongo.games.com/game/model"
"mongo.games.com/game/mq"
)
var rabbitMqConsumer *mq.RabbitMQConsumer
func init() {
core.RegisteHook(core.HOOK_BEFORE_START, func() error {
model.InitGameParam()
rabbitMqConsumer = mq.NewRabbitMQConsumer(common.CustomConfig.GetString("RabbitMQURL"), rabbitmq.Exchange{Name: common.CustomConfig.GetString("RMQExchange"), Durable: true})
if rabbitMqConsumer != nil {
rabbitMqConsumer.Start()
}
//尝试初始化
svc.GetOnePlayerIdFromBucket()
return nil
})
core.RegisteHook(core.HOOK_AFTER_STOP, func() error {
if rabbitMqConsumer != nil {
rabbitMqConsumer.Stop()
}
model.ShutdownRPClient()
return nil
})
}
func main() {
defer core.ClosePackages()
core.LoadPackages("config.json")
rpc.HandleHTTP() // 采用http协议作为rpc载体
lis, err := net.Listen(common.CustomConfig.GetString("MgoRpcCliNet"), common.CustomConfig.GetString("MgoRpcCliAddr"))
if err != nil {
log.Fatalln("fatal error: ", err)
}
go http.Serve(lis, nil)
waitor := module.Start()
waitor.Wait("main()")
}

70
dbproxy/mongo/config.go Normal file
View File

@ -0,0 +1,70 @@
package mongo
import (
"github.com/howeyc/fsnotify"
"mongo.games.com/goserver/core"
"mongo.games.com/goserver/core/logger"
)
/*
当数据库配置文件修改后实时更新mongo数据库连接
*/
type Configuration struct {
CfgFile string // 数据库配置文件路径
watcher *fsnotify.Watcher
}
func (c *Configuration) Name() string {
return "cmgo"
}
func (c *Configuration) Init() error {
MgoSessionMgrSington.LoadConfig(c.CfgFile)
var err error
c.watcher, err = fsnotify.NewWatcher()
if err != nil {
logger.Logger.Warnf("%s NewWatcher err:%v", c.CfgFile, err)
return err
}
err = c.watcher.Watch(c.CfgFile)
if err != nil {
logger.Logger.Warnf("%s Watch err:%v", c.CfgFile, err)
return err
}
go func() {
defer func() {
if err := recover(); err != nil {
logger.Logger.Warnf("%s watch modify goroutine err:%v", c.CfgFile, err)
}
}()
for {
select {
case ev, ok := <-c.watcher.Event:
if ok && ev != nil {
if ev.IsModify() {
MgoSessionMgrSington.LoadConfig(c.CfgFile)
}
} else {
return
}
case err := <-c.watcher.Error:
logger.Logger.Info("fsnotify error:", err)
}
}
logger.Logger.Warnf("%s watcher quit!", c.CfgFile)
}()
return nil
}
func (c *Configuration) Close() error {
c.watcher.Close()
MgoSessionMgrSington.Close()
return nil
}
func init() {
core.RegistePackage(&Configuration{})
}

326
dbproxy/mongo/sessionmgr.go Normal file
View File

@ -0,0 +1,326 @@
package mongo
import (
"encoding/json"
"fmt"
"github.com/globalsign/mgo"
webapi_proto "mongo.games.com/game/protocol/webapi"
"mongo.games.com/goserver/core/logger"
"os"
"sync"
"time"
)
const (
G_P = "__$G_P$__"
)
var MgoSessionMgrSington = &MgoSessionMgr{
pltCfgs: new(sync.Map),
pltMgos: make(map[string]*PlatformSession),
}
type MgoCfg struct {
HostName string
HostPort int32
Database string
Username string
Password string
Options string
CfgVer int32
WithEtcd bool
}
type Config struct {
Global map[string]*MgoCfg
Platforms map[string]map[string]*MgoCfg // 平台:内部库名称:数据库名称
}
type Collection struct {
*mgo.Collection
}
type Database struct {
sync.RWMutex
*mgo.Database
mc map[string]*Collection
}
func (db *Database) C(name string) (*Collection, bool) {
db.RLock()
c, ok := db.mc[name]
if ok {
db.RUnlock()
return c, false
}
db.RUnlock()
db.Lock()
c, ok = db.mc[name]
if ok {
db.Unlock()
return c, false
}
cc := &Collection{Collection: db.Database.C(name)}
db.mc[name] = cc
db.Unlock()
return cc, true
}
type Session struct {
sync.RWMutex
*mgo.Session
db *Database
cfg *MgoCfg
}
func (s *Session) DB() *Database {
s.RLock()
if s.db != nil {
s.RUnlock()
return s.db
}
s.RUnlock()
s.Lock()
s.db = &Database{Database: s.Session.DB(s.cfg.Database), mc: make(map[string]*Collection)}
s.Unlock()
return s.db
}
type PlatformSession struct {
sync.RWMutex
sesses map[string]*Session // 内部库名称
}
func (ps *PlatformSession) GetSession(name string) (*Session, bool) {
ps.RLock()
s, ok := ps.sesses[name]
ps.RUnlock()
return s, ok
}
func (ps *PlatformSession) SetSession(name string, s *Session) {
ps.Lock()
ps.sesses[name] = s
ps.Unlock()
}
func (ps *PlatformSession) DiscardSession(name string, s *Session) {
ps.Lock()
old, ok := ps.sesses[name]
delete(ps.sesses, name)
ps.Unlock()
if ok && old != nil && old == s {
//1分钟后释放防止有pending的任务在执行
time.AfterFunc(time.Minute, func() {
old.Close()
})
}
}
type MgoSessionMgr struct {
sync.RWMutex
pltCfgs *sync.Map
pltMgos map[string]*PlatformSession // 平台名称
}
func newMgoSession(user, password, host string, port int32, options string) (s *mgo.Session, err error) {
login := ""
if user != "" {
login = user + ":" + password + "@"
}
if host == "" {
host = "localhost"
}
if port == 0 {
port = 27017
}
if options != "" {
options = "?" + options
}
// http://goneat.org/pkg/labix.org/v2/mgo/#Session.Mongo
// [mongodb://][user:pass@]host1[:port1][,host2[:port2],...][/database][?options]
url := fmt.Sprintf("mongodb://%s%s:%d/admin%s", login, host, port, options)
//fmt.Println(url)
session, err := mgo.Dial(url)
if err != nil {
return nil, err
}
session.SetSafe(&mgo.Safe{})
return session, nil
}
func (msm *MgoSessionMgr) LoadConfig(cfgFile string) error {
data, err := os.ReadFile(cfgFile)
if err != nil {
logger.Logger.Errorf("MgoSessionMgr.LoadConfig ReadFile err:%v", err)
return err
}
var cfg Config
err = json.Unmarshal(data, &cfg)
if err != nil {
logger.Logger.Errorf("MgoSessionMgr.LoadConfig Unmarshal err:%v", err)
return err
}
//全局配置
for key, cfg := range cfg.Global {
if _, ok := msm.UptCfg(G_P, key, cfg); ok {
if ps, olds, ok := msm.HasPltMgoSession(G_P, key); ok {
if olds.cfg.CfgVer < cfg.CfgVer {
ps.DiscardSession(key, olds)
}
}
}
}
//平台配置
for plt, cfgs := range cfg.Platforms {
for key, cfg := range cfgs {
if _, ok := msm.UptCfg(plt, key, cfg); ok {
if ps, olds, ok := msm.HasPltMgoSession(plt, key); ok {
if olds.cfg.CfgVer < cfg.CfgVer {
ps.DiscardSession(key, olds)
}
}
}
}
}
return nil
}
func (msm *MgoSessionMgr) GetPlt(plt string) (*PlatformSession, bool) {
msm.RLock()
ps, ok := msm.pltMgos[plt]
msm.RUnlock()
return ps, ok
}
func (msm *MgoSessionMgr) HasPltMgoSession(plt, key string) (*PlatformSession, *Session, bool) {
ps, ok := msm.GetPlt(plt)
if !ok {
return nil, nil, false
}
s, ok := ps.GetSession(key)
return ps, s, ok
}
func (msm *MgoSessionMgr) GetPltMgoSession(plt, key string) *Session {
ps, ok := msm.GetPlt(plt)
if !ok {
msm.Lock()
ps, ok = msm.pltMgos[plt]
if !ok {
ps = &PlatformSession{
sesses: make(map[string]*Session),
}
msm.pltMgos[plt] = ps
}
msm.Unlock()
}
if ps == nil {
return nil
}
if s, ok := ps.GetSession(key); ok {
return s
}
ps.Lock()
defer ps.Unlock()
s, ok := ps.sesses[key]
if ok {
return s
}
if c, ok := msm.GetCfg(plt, key); ok {
s, err := newMgoSession(c.Username, c.Password, c.HostName, c.HostPort, c.Options)
if s == nil || err != nil {
logger.Logger.Error("GetPltMgoSession(%s,%s) err:%v", plt, key, err)
return nil
}
ss := &Session{Session: s, cfg: c}
ps.sesses[key] = ss
return ss
}
return nil
}
func (msm *MgoSessionMgr) GetGlobal(key string) *Session {
return msm.GetPltMgoSession(G_P, key)
}
func (msm *MgoSessionMgr) GetCfg(plt, key string) (*MgoCfg, bool) {
if val, ok := msm.pltCfgs.Load(plt); ok {
if cfgs, ok := val.(*sync.Map); ok {
if cfg, ok := cfgs.Load(key); ok {
if c, ok := cfg.(*MgoCfg); ok {
return c, true
}
}
}
}
return nil, false
}
func (msm *MgoSessionMgr) UptCfg(plt, key string, cfg *MgoCfg) (*MgoCfg, bool) {
if val, ok := msm.pltCfgs.Load(plt); ok {
cfgs, _ := val.(*sync.Map)
if old, ok := cfgs.Load(key); ok {
cfgs.Store(key, cfg)
return old.(*MgoCfg), true
} else {
cfgs.Store(key, cfg)
return nil, false
}
} else {
cfgs := new(sync.Map)
msm.pltCfgs.Store(plt, cfgs)
cfgs.Store(key, cfg)
return nil, false
}
}
func (msm *MgoSessionMgr) UptCfgWithEtcd(plt, key string, cfg *webapi_proto.MongoDbSetting) {
//文件配置优先级高于etcd
if oldCfg, exist := msm.GetCfg(plt, key); exist && !oldCfg.WithEtcd {
return
}
newcfg := &MgoCfg{
HostName: cfg.HostName,
HostPort: cfg.HostPort,
Database: cfg.Database,
Username: cfg.Username,
Password: cfg.Password,
Options: cfg.Options,
CfgVer: cfg.CfgVer,
WithEtcd: true,
}
if _, ok := msm.UptCfg(plt, key, newcfg); ok {
if ps, olds, ok := msm.HasPltMgoSession(plt, key); ok {
if olds.cfg.CfgVer < cfg.CfgVer {
ps.DiscardSession(key, olds)
}
}
}
return
}
func (msm *MgoSessionMgr) Close() {
msm.RLock()
defer msm.RUnlock()
for _, plt := range msm.pltMgos {
plt.RLock()
for _, s := range plt.sesses {
s.Close()
}
plt.RUnlock()
}
}

40
dbproxy/mq/c_apilog.go Normal file
View File

@ -0,0 +1,40 @@
package mq
import (
"encoding/json"
"mongo.games.com/game/dbproxy/svc"
"mongo.games.com/game/model"
"mongo.games.com/game/mq"
"mongo.games.com/goserver/core/broker"
"mongo.games.com/goserver/core/broker/rabbitmq"
)
func init() {
mq.RegisterSubscriber(model.APILogCollName, func(e broker.Event) (err error) {
msg := e.Message()
if msg != nil {
defer func() {
if err != nil {
mq.BackUp(e, err)
}
e.Ack()
recover()
}()
var log model.APILog
err = json.Unmarshal(msg.Body, &log)
if err != nil {
return
}
c := svc.APILogsCollection()
if c != nil {
err = c.Insert(log)
}
return
}
return nil
}, broker.Queue(model.APILogCollName), broker.DisableAutoAck(), rabbitmq.DurableQueue())
}

56
dbproxy/mq/c_clientlog.go Normal file
View File

@ -0,0 +1,56 @@
package mq
func init() {
//mq.RegisteSubscriber(model.ClientLogCollName, func(e broker.Event) (err error) {
// msg := e.Message()
// if msg != nil {
// defer func() {
// if err != nil {
// mq.BackUp(e, err)
// }
//
// e.Ack()
//
// recover()
// }()
//
// var log model.ClientLog
// err = json.Unmarshal(msg.Body, &log)
// if err != nil {
// logger.Logger.Errorf("[mq] %s %v", model.ClientLogCollName, err)
// return
// }
//
// logger.Logger.Tracef("[mq] %s %v", model.ClientLogCollName, string(msg.Body))
//
// data := map[string]interface{}{}
// err = json.Unmarshal([]byte(log.Data), &data)
// if err != nil {
// logger.Logger.Errorf("[mq] %s %v", model.ClientLogCollName, err)
// return
// }
//
// // 获取平台id
// platform := log.Platform
// if log.Platform == "" {
// id, ok := data["platform"]
// if ok {
// platform = string(id.([]byte))
// }
// }
//
// data["ts"] = log.Ts
// if log.Snid > 0 {
// data["snid"] = log.Snid
// }
//
// c := svc.ClientLogStartCollection(platform)
// if c != nil {
// err = c.Insert(data)
// }
//
// return
// }
// return nil
//}, broker.Queue(model.ClientLogCollName), broker.DisableAutoAck(), rabbitmq.DurableQueue())
}

View File

@ -0,0 +1,40 @@
package mq
import (
"encoding/json"
"mongo.games.com/game/dbproxy/svc"
"mongo.games.com/game/model"
"mongo.games.com/game/mq"
"mongo.games.com/goserver/core/broker"
"mongo.games.com/goserver/core/broker/rabbitmq"
)
func init() {
mq.RegisterSubscriber(model.CoinGiveLogCollName, func(e broker.Event) (err error) {
msg := e.Message()
if msg != nil {
defer func() {
if err != nil {
mq.BackUp(e, err)
}
e.Ack()
recover()
}()
var log model.CoinGiveLog
err = json.Unmarshal(msg.Body, &log)
if err != nil {
return
}
c := svc.CoinGiveLogCollection(log.Platform)
if c != nil {
err = c.Insert(log)
}
return
}
return nil
}, broker.Queue(model.CoinGiveLogCollName), broker.DisableAutoAck(), rabbitmq.DurableQueue())
}

50
dbproxy/mq/c_coinlog.go Normal file
View File

@ -0,0 +1,50 @@
package mq
import (
"encoding/json"
"mongo.games.com/game/dbproxy/svc"
"mongo.games.com/game/model"
"mongo.games.com/game/mq"
"mongo.games.com/goserver/core/broker"
"mongo.games.com/goserver/core/broker/rabbitmq"
)
func init() {
mq.RegisterSubscriber(model.CoinLogCollName, func(e broker.Event) (err error) {
msg := e.Message()
if msg != nil {
defer func() {
if err != nil {
mq.BackUp(e, err)
}
e.Ack()
recover()
}()
var log model.CoinLog
err = json.Unmarshal(msg.Body, &log)
if err != nil {
return
}
if log.Count == 0 { //玩家冲账探针
RabbitMQPublisher.Send(model.TopicProbeCoinLogAck, log)
} else {
c := svc.CoinLogsCollection(log.Platform)
if c != nil {
err = c.Insert(log)
if err == nil {
err = svc.InsertCoinWAL(log.Platform, model.NewCoinWAL(log.SnId, log.Count, log.LogType, log.InGame, log.CoinType, log.RoomId, log.Time.UnixNano()))
if err != nil {
return
}
}
}
}
return
}
return nil
}, broker.Queue(model.CoinLogCollName), broker.DisableAutoAck(), rabbitmq.DurableQueue())
}

View File

@ -0,0 +1,36 @@
package mq
import (
"encoding/json"
"mongo.games.com/game/dbproxy/svc"
"mongo.games.com/game/model"
"mongo.games.com/game/mq"
"mongo.games.com/goserver/core/broker"
"mongo.games.com/goserver/core/broker/rabbitmq"
)
func init() {
mq.RegisterSubscriber(model.FriendRecordLogCollName, func(e broker.Event) (err error) {
msg := e.Message()
if msg != nil {
defer func() {
if err != nil {
mq.BackUp(e, err)
}
e.Ack()
recover()
}()
var log model.FriendRecord
err = json.Unmarshal(msg.Body, &log)
if err != nil {
return
}
err = svc.InsertFriendRecordLog(log)
return
}
return nil
}, broker.Queue(model.FriendRecordLogCollName), broker.DisableAutoAck(), rabbitmq.DurableQueue())
}

View File

@ -0,0 +1,44 @@
package mq
import (
"encoding/json"
"mongo.games.com/game/dbproxy/svc"
"mongo.games.com/game/model"
"mongo.games.com/game/mq"
"mongo.games.com/goserver/core/broker"
"mongo.games.com/goserver/core/broker/rabbitmq"
"mongo.games.com/goserver/core/logger"
)
func init() {
mq.RegisterSubscriber(model.GameDetailedLogCollName, func(e broker.Event) (err error) {
msg := e.Message()
if msg != nil {
defer func() {
if err != nil {
mq.BackUp(e, err)
}
e.Ack()
recover()
}()
var log model.GameDetailedLog
err = json.Unmarshal(msg.Body, &log)
if err != nil {
return
}
logger.Logger.Tracef("mq receive GameDetailedLog:%v", log)
c := svc.GameDetailedLogsCollection(log.Platform)
if c != nil {
err = c.Insert(log)
if err != nil {
logger.Logger.Tracef("c.Insert(log) err:%v", err.Error())
}
}
return
}
return nil
}, broker.Queue(model.GameDetailedLogCollName), broker.DisableAutoAck(), rabbitmq.DurableQueue())
}

View File

@ -0,0 +1,40 @@
package mq
import (
"encoding/json"
"mongo.games.com/game/dbproxy/svc"
"mongo.games.com/game/model"
"mongo.games.com/game/mq"
"mongo.games.com/goserver/core/broker"
"mongo.games.com/goserver/core/broker/rabbitmq"
)
func init() {
mq.RegisterSubscriber(model.GamePlayerListLogCollName, func(e broker.Event) (err error) {
msg := e.Message()
if msg != nil {
defer func() {
if err != nil {
mq.BackUp(e, err)
}
e.Ack()
recover()
}()
var log model.GamePlayerListLog
err = json.Unmarshal(msg.Body, &log)
if err != nil {
return
}
c := svc.GamePlayerListLogsCollection(log.Platform)
if c != nil {
err = c.Insert(log)
}
return
}
return nil
}, broker.Queue(model.GamePlayerListLogCollName), broker.DisableAutoAck(), rabbitmq.DurableQueue())
}

71
dbproxy/mq/c_invite.go Normal file
View File

@ -0,0 +1,71 @@
package mq
import (
"encoding/json"
"fmt"
"time"
"github.com/astaxie/beego/cache"
"mongo.games.com/goserver/core/broker"
"mongo.games.com/goserver/core/broker/rabbitmq"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/game/dbproxy/svc"
"mongo.games.com/game/model"
"mongo.games.com/game/mq"
)
var InviteNumCache = cache.NewMemoryCache()
func init() {
mq.RegisterSubscriber(model.EvtBindInvite, func(e broker.Event) (err error) {
msg := e.Message()
if msg != nil {
defer func() {
if err != nil {
mq.BackUp(e, err)
}
e.Ack()
recover()
}()
var log model.BindInvite
err = json.Unmarshal(msg.Body, &log)
if err != nil {
return
}
// 绑定
err = svc.BindInviteSnId(log.Platform, log.SnId, log.InviteSnId, log.Ts)
if err != nil {
logger.Logger.Errorf("BindInviteSnId error:%v", err)
return err
}
name := fmt.Sprintf("%v", log.InviteSnId)
b := InviteNumCache.Get(name)
n, _ := b.(int32)
if n > 0 {
n++
} else {
n, err = svc.GetInviteNum(log.Platform, log.InviteSnId)
if err != nil {
logger.Logger.Errorf("BindInviteSnId error:%v", err)
return err
}
}
InviteNumCache.Put(name, n, int64(time.Hour.Seconds()))
// 更新绑定数量
RabbitMQPublisher.Send(model.AckBindNum, &model.BindNum{
SnId: log.InviteSnId,
Num: n,
})
return
}
return nil
}, broker.Queue(model.EvtBindInvite), broker.DisableAutoAck(), rabbitmq.DurableQueue())
}

40
dbproxy/mq/c_itemlog.go Normal file
View File

@ -0,0 +1,40 @@
package mq
import (
"encoding/json"
"mongo.games.com/game/dbproxy/svc"
"mongo.games.com/game/model"
"mongo.games.com/game/mq"
"mongo.games.com/goserver/core/broker"
"mongo.games.com/goserver/core/broker/rabbitmq"
)
func init() {
mq.RegisterSubscriber(model.ItemLogCollName, func(e broker.Event) (err error) {
msg := e.Message()
if msg != nil {
defer func() {
if err != nil {
mq.BackUp(e, err)
}
e.Ack()
recover()
}()
var log model.ItemLog
err = json.Unmarshal(msg.Body, &log)
if err != nil {
return
}
c := svc.ItemLogsCollection(log.Platform)
if c != nil {
err = c.Insert(log)
}
return
}
return nil
}, broker.Queue(model.ItemLogCollName), broker.DisableAutoAck(), rabbitmq.DurableQueue())
}

View File

@ -0,0 +1,31 @@
package mq
//func init() {
// mq.RegisteSubscriber(model.JackPotLogCollName, func(e broker.Event) (err error) {
// msg := e.Message()
// if msg != nil {
// defer func() {
// if err != nil {
// mq.BackUp(e, err)
// }
//
// e.Ack()
//
// recover()
// }()
//
// var log model.JackPotLog
// err = json.Unmarshal(msg.Body, &log)
// if err != nil {
// return
// }
//
// c := svc.JackPotLogsCollection(log.Platform)
// if c != nil {
// _, err = c.Upsert(bson.M{"_id": log.LogId}, log)
// }
// return
// }
// return nil
// }, broker.Queue(model.JackPotLogCollName), broker.DisableAutoAck(), rabbitmq.DurableQueue())
//}

57
dbproxy/mq/c_loginlog.go Normal file
View File

@ -0,0 +1,57 @@
package mq
import (
"encoding/json"
"mongo.games.com/game/dbproxy/svc"
"mongo.games.com/game/model"
"mongo.games.com/game/mq"
"mongo.games.com/goserver/core/broker"
"mongo.games.com/goserver/core/broker/rabbitmq"
)
func init() {
mq.RegisterSubscriber(model.LoginLogCollName, func(e broker.Event) (err error) {
msg := e.Message()
if msg != nil {
defer func() {
if err != nil {
mq.BackUp(e, err)
}
e.Ack()
recover()
}()
var log model.LoginLog
err = json.Unmarshal(msg.Body, &log)
if err != nil {
return
}
c := svc.LoginLogsCollection(log.Platform)
if c != nil {
err = c.Insert(log)
}
return
}
return nil
}, broker.Queue(model.LoginLogCollName), broker.DisableAutoAck(), rabbitmq.DurableQueue())
//for test
//RegisterSubscriber(model.LoginLogCollName, func(e broker.Event) (err error) {
// msg := e.Message()
// if msg != nil {
// var log model.LoginLog
// err = json.Unmarshal(msg.Body, &log)
// if err != nil {
// return
// }
//
// logger.Logger.Trace(log)
// return
// }
// return nil
//}, broker.Queue(model.LoginLogCollName+"_echo"), rabbitmq.DurableQueue())
//for test
}

43
dbproxy/mq/c_onlinelog.go Normal file
View File

@ -0,0 +1,43 @@
package mq
import (
"encoding/json"
"mongo.games.com/goserver/core/broker"
"mongo.games.com/goserver/core/broker/rabbitmq"
"mongo.games.com/game/dbproxy/svc"
"mongo.games.com/game/model"
"mongo.games.com/game/mq"
)
func init() {
mq.RegisterSubscriber(model.OnlineLogCollName, func(e broker.Event) (err error) {
msg := e.Message()
if msg != nil {
defer func() {
if err != nil {
mq.BackUp(e, err)
}
e.Ack()
recover()
}()
var log model.OnlineLog
err = json.Unmarshal(msg.Body, &log)
if err != nil {
return
}
c := new(svc.OnlineLogSvc)
if c != nil {
ret := false
err = c.InsertSignleOnlineLog(&log, &ret)
}
return
}
return nil
}, broker.Queue(model.OnlineLogCollName), broker.DisableAutoAck(), rabbitmq.DurableQueue())
}

85
dbproxy/mq/c_rank.go Normal file
View File

@ -0,0 +1,85 @@
package mq
import (
"encoding/json"
"mongo.games.com/game/dbproxy/svc"
"mongo.games.com/game/model"
"mongo.games.com/game/mq"
"mongo.games.com/goserver/core"
"mongo.games.com/goserver/core/basic"
"mongo.games.com/goserver/core/broker"
"mongo.games.com/goserver/core/broker/rabbitmq"
"mongo.games.com/goserver/core/logger"
)
func init() {
// 排位排行榜
mq.RegisterSubscriber(model.MQRankSeason, func(e broker.Event) (err error) {
msg := e.Message()
if msg != nil {
defer func() {
if err != nil {
mq.BackUp(e, err)
}
e.Ack()
recover()
}()
var log model.PlayerRankScore
err = json.Unmarshal(msg.Body, &log)
if err != nil {
return
}
logger.Logger.Tracef("SubscriberPlayerRankScore: %+v", log)
core.CoreObject().SendCommand(basic.CommandWrapper(func(o *basic.Object) error {
err := svc.RankSeasonUpsert(&log)
if err != nil {
logger.Logger.Errorf("RankSeasonUpsert err: %v", err)
}
return nil
}), true)
return
}
return nil
}, broker.Queue(model.MQRankSeason), broker.DisableAutoAck(), rabbitmq.DurableQueue())
// 金币榜
mq.RegisterSubscriber(model.MQRankPlayerCoin, func(e broker.Event) (err error) {
msg := e.Message()
if msg != nil {
defer func() {
if err != nil {
mq.BackUp(e, err)
}
e.Ack()
recover()
}()
var log model.RankPlayerCoin
err = json.Unmarshal(msg.Body, &log)
if err != nil {
return
}
logger.Logger.Tracef("SubscriberRankPlayerCoin: %+v", log)
core.CoreObject().SendCommand(basic.CommandWrapper(func(o *basic.Object) error {
err := svc.RankPlayerCoinUpsert(&log)
if err != nil {
logger.Logger.Errorf("RankPlayerCoinUpsert err: %v", err)
}
return nil
}), true)
return
}
return nil
}, broker.Queue(model.MQRankPlayerCoin), broker.DisableAutoAck(), rabbitmq.DurableQueue())
}

View File

@ -0,0 +1,40 @@
package mq
import (
"encoding/json"
"mongo.games.com/game/dbproxy/svc"
"mongo.games.com/game/model"
"mongo.games.com/game/mq"
"mongo.games.com/goserver/core/broker"
"mongo.games.com/goserver/core/broker/rabbitmq"
)
func init() {
mq.RegisterSubscriber(model.SceneCoinLogCollName, func(e broker.Event) (err error) {
msg := e.Message()
if msg != nil {
defer func() {
if err != nil {
mq.BackUp(e, err)
}
e.Ack()
recover()
}()
var log model.SceneCoinLog
err = json.Unmarshal(msg.Body, &log)
if err != nil {
return
}
c := svc.SceneCoinLogsCollection(log.Platform)
if c != nil {
err = c.Insert(log)
}
return
}
return nil
}, broker.Queue(model.SceneCoinLogCollName), broker.DisableAutoAck(), rabbitmq.DurableQueue())
}

View File

@ -0,0 +1,41 @@
package mq
import (
"encoding/json"
"mongo.games.com/game/dbproxy/svc"
"mongo.games.com/game/model"
"mongo.games.com/game/mq"
"mongo.games.com/goserver/core/broker"
"mongo.games.com/goserver/core/broker/rabbitmq"
)
func init() {
mq.RegisterSubscriber(model.WelfareLogCollName, func(e broker.Event) (err error) {
msg := e.Message()
if msg != nil {
defer func() {
if err != nil {
mq.BackUp(e, err)
}
e.Ack()
recover()
}()
var log model.WelfareLog
err = json.Unmarshal(msg.Body, &log)
if err != nil {
return
}
c := svc.WelfareLogsCollection(log.Platform)
if c != nil {
err = c.Insert(log)
}
return
}
return nil
}, broker.Queue(model.WelfareLogCollName), broker.DisableAutoAck(), rabbitmq.DurableQueue())
}

33
dbproxy/mq/publisher.go Normal file
View File

@ -0,0 +1,33 @@
package mq
import (
"mongo.games.com/game/common"
"mongo.games.com/game/mq"
"mongo.games.com/goserver/core"
"mongo.games.com/goserver/core/broker/rabbitmq"
)
var RabbitMQPublisher *mq.RabbitMQPublisher
func init() {
////首先加载游戏配置
core.RegisteHook(core.HOOK_BEFORE_START, func() error {
//rabbitmq打开链接
RabbitMQPublisher = mq.NewRabbitMQPublisher(common.CustomConfig.GetString("RabbitMQURL"), rabbitmq.Exchange{Name: common.CustomConfig.GetString("RMQExchange"), Durable: true}, common.CustomConfig.GetInt("RMQPublishBacklog"))
if RabbitMQPublisher != nil {
err := RabbitMQPublisher.Start()
if err != nil {
panic(err)
}
}
return nil
})
core.RegisteHook(core.HOOK_AFTER_STOP, func() error {
//关闭rabbitmq连接
if RabbitMQPublisher != nil {
RabbitMQPublisher.Stop()
}
return nil
})
}

View File

@ -0,0 +1,71 @@
package svc
import (
"github.com/globalsign/mgo"
"github.com/globalsign/mgo/bson"
"mongo.games.com/game/dbproxy/mongo"
"mongo.games.com/game/model"
"mongo.games.com/goserver/core/logger"
"net/rpc"
)
var (
CrashHashDBName = "user"
CrashHashCollName = "user_crashhash"
ErrHashDBNotOpen = model.NewDBError(CrashHashDBName, CrashHashCollName, model.NOT_OPEN)
)
func CrashHashCollection() *mongo.Collection {
s := mongo.MgoSessionMgrSington.GetPltMgoSession(mongo.G_P, CrashHashDBName)
if s != nil {
c, first := s.DB().C(CrashHashCollName)
if first {
c.EnsureIndex(mgo.Index{Key: []string{"wheel"}, Background: true, Sparse: true})
}
return c
}
return nil
}
type CrashHashSvc struct {
}
func (svc *CrashHashSvc) InsertCrashHash(args *model.CrashHash, ret *model.HashRet) error {
ccrashhashs := CrashHashCollection()
if ccrashhashs == nil {
ret.Tag = 4
return ErrHashDBNotOpen
}
err := ccrashhashs.Insert(args)
if err != nil {
logger.Logger.Info("InsertCrashHash error:", err)
ret.Tag = 4
return nil
}
ret.Hash = nil
ret.Tag = 5
return nil
}
func (svc *CrashHashSvc) GetCrashHash(args *model.HashIdArg, ret *model.HashRet) error {
cat := CrashHashCollection()
if cat == nil {
return nil
}
//err := cat.Find(bson.M{"wheel": args.Wheel}).All(&ret.Hash)
err := cat.Find(bson.M{}).All(&ret.Hash)
if err != nil {
logger.Logger.Error("Get model.GetCrashHash data eror.", err)
ret.Tag = 4
return err
}
return nil
}
var _CrashHashSvc = &CrashHashSvc{}
func init() {
rpc.Register(_CrashHashSvc)
}

View File

@ -0,0 +1,71 @@
package svc
import (
"github.com/globalsign/mgo"
"github.com/globalsign/mgo/bson"
"mongo.games.com/game/dbproxy/mongo"
"mongo.games.com/game/model"
"mongo.games.com/goserver/core/logger"
"net/rpc"
)
var (
CrashHashAtomDBName = "user"
CrashHashAtomCollName = "user_crashhashatom"
ErrHashAtomDBNotOpen = model.NewDBError(CrashHashAtomDBName, CrashHashAtomCollName, model.NOT_OPEN)
)
func CrashHashAtomCollection() *mongo.Collection {
s := mongo.MgoSessionMgrSington.GetPltMgoSession(mongo.G_P, CrashHashAtomDBName)
if s != nil {
c, first := s.DB().C(CrashHashAtomCollName)
if first {
c.EnsureIndex(mgo.Index{Key: []string{"wheel"}, Background: true, Sparse: true})
}
return c
}
return nil
}
type CrashHashAtomSvc struct {
}
func (svc *CrashHashAtomSvc) InsertCrashHashAtom(args *model.CrashHashAtom, ret *model.HashRet) error {
ccrashhashatoms := CrashHashAtomCollection()
if ccrashhashatoms == nil {
ret.Tag = 4
return ErrHashDBNotOpen
}
err := ccrashhashatoms.Insert(args)
if err != nil {
logger.Logger.Info("InsertCrashHashAtom error:", err)
ret.Tag = 4
return nil
}
ret.Hash = nil
ret.Tag = 5
return nil
}
func (svc *CrashHashAtomSvc) GetCrashHashAtom(args *model.HashIdArg, ret *model.HashRet) error {
cat := CrashHashAtomCollection()
if cat == nil {
return nil
}
//err := cat.Find(bson.M{"wheel": args.Wheel}).All(&ret.Hash)
err := cat.Find(bson.M{}).All(&ret.Hash)
if err != nil {
logger.Logger.Error("Get model.GetCrashHashAtom data eror.", err)
ret.Tag = 4
return err
}
return nil
}
var _CrashHashAtomSvc = &CrashHashAtomSvc{}
func init() {
rpc.Register(_CrashHashAtomSvc)
}

51
dbproxy/svc/l_apilog.go Normal file
View File

@ -0,0 +1,51 @@
package svc
import (
"net/rpc"
"time"
"github.com/globalsign/mgo"
"github.com/globalsign/mgo/bson"
"mongo.games.com/game/dbproxy/mongo"
"mongo.games.com/game/model"
"mongo.games.com/goserver/core/logger"
)
func APILogsCollection() *mongo.Collection {
s := mongo.MgoSessionMgrSington.GetGlobal(model.APILogDBName)
if s != nil {
c_apilogrec, first := s.DB().C(model.APILogCollName)
if first {
c_apilogrec.EnsureIndex(mgo.Index{Key: []string{"path"}, Background: true, Sparse: true})
c_apilogrec.EnsureIndex(mgo.Index{Key: []string{"time"}, Background: true, Sparse: true})
}
return c_apilogrec
}
return nil
}
type APILogSvc struct {
}
func (svc *APILogSvc) InsertAPILog(log *model.APILog, ret *bool) (err error) {
clog := APILogsCollection()
if clog == nil {
return
}
err = clog.Insert(log)
if err != nil {
logger.Logger.Warn("InsertAPILog error:", err)
return
}
*ret = true
return
}
func (svc *APILogSvc) RemoveAPILog(ts int64, chged **mgo.ChangeInfo) (err error) {
*chged, err = APILogsCollection().RemoveAll(bson.M{"time": bson.M{"$lte": time.Unix(ts, 0)}})
return
}
func init() {
rpc.Register(new(APILogSvc))
}

52
dbproxy/svc/l_bankbind.go Normal file
View File

@ -0,0 +1,52 @@
package svc
import (
"errors"
"net/rpc"
"github.com/globalsign/mgo"
"mongo.games.com/game/dbproxy/mongo"
"mongo.games.com/game/model"
)
var (
BankBindLogDBErr = errors.New("log_bankbind db open failed.")
)
func BankBindCollection(plt string) *mongo.Collection {
s := mongo.MgoSessionMgrSington.GetPltMgoSession(plt, model.BankBindDBName)
if s != nil {
c, first := s.DB().C(model.BankBindCollName)
if first {
c.EnsureIndex(mgo.Index{Key: []string{"snid"}, Background: true, Sparse: true})
c.EnsureIndex(mgo.Index{Key: []string{"bankname"}, Background: true, Sparse: true})
c.EnsureIndex(mgo.Index{Key: []string{"bankcard"}, Background: true, Sparse: true})
}
return c
}
return nil
}
func InsertBankBindLog(log *model.BankBindLog) error {
clog := BankBindCollection(log.Platform)
if clog == nil {
return BankBindLogDBErr
}
return clog.Insert(log)
}
type BankBindLogSvc struct {
}
func (svc *BankBindLogSvc) InsertBankBindLog(log *model.BankBindLog, ret *bool) error {
err := InsertBankBindLog(log)
if err == nil {
*ret = true
}
return err
}
func init() {
rpc.Register(new(BankBindLogSvc))
}

View File

@ -0,0 +1,102 @@
package svc
import (
"errors"
"github.com/globalsign/mgo"
"github.com/globalsign/mgo/bson"
"mongo.games.com/game/dbproxy/mongo"
"mongo.games.com/game/model"
"mongo.games.com/goserver/core/logger"
"net/rpc"
)
var (
BlackWhiteCoinLogDBName = "log"
BlackWhiteCoinLogCollName = "log_blackwhitelist"
BlackWhiteCoinLogErr = errors.New("User blackwhite log open failed.")
)
func BlackWhiteCoinLogsCollection(plt string) *mongo.Collection {
s := mongo.MgoSessionMgrSington.GetPltMgoSession(plt, BlackWhiteCoinLogDBName)
if s != nil {
c_blackwhiterec, first := s.DB().C(BlackWhiteCoinLogCollName)
if first {
c_blackwhiterec.EnsureIndex(mgo.Index{Key: []string{"snid"}, Background: true, Sparse: true})
c_blackwhiterec.EnsureIndex(mgo.Index{Key: []string{"platform"}, Background: true, Sparse: true})
}
return c_blackwhiterec
}
return nil
}
type BlackWhiteCoinSvc struct {
}
func (svc *BlackWhiteCoinSvc) InsertBlackWhiteCoinLogs(logs []*model.BlackWhiteCoinLog, ret *model.BlackWhiteCoinRet) (err error) {
if len(logs) == 0 {
return errors.New("len(logs) == 0")
}
clog := BlackWhiteCoinLogsCollection(logs[0].Platform)
if clog == nil {
return
}
switch len(logs) {
case 0:
return errors.New("no data")
case 1:
err = clog.Insert(logs[0])
default:
docs := make([]interface{}, 0, len(logs))
for _, log := range logs {
docs = append(docs, log)
}
err = clog.Insert(docs...)
}
if err != nil {
logger.Logger.Warn("svc.InsertBlackWhiteCoinLog error:", err)
ret.Err = err
return
}
return
}
func (svc *BlackWhiteCoinSvc) InsertBlackWhiteCoinLog(log *model.BlackWhiteCoinLog, ret *model.BlackWhiteCoinRet) error {
if log == nil {
return errors.New("log == nil")
}
clog := BlackWhiteCoinLogsCollection(log.Platform)
if clog == nil {
return BlackWhiteCoinLogErr
}
err := clog.Insert(log)
if err != nil {
logger.Logger.Error("svc.InsertBlackWhiteCoinLog error", err)
ret.Err = err
return err
}
return nil
}
func (svc *BlackWhiteCoinSvc) RemoveBlackWhiteCoinLog(args *model.BlackWhiteCoinArg, ret *model.BlackWhiteCoinRet) error {
clog := BlackWhiteCoinLogsCollection(args.Platform)
if clog == nil {
return BlackWhiteCoinLogErr
}
ret.Err = clog.RemoveId(args.Id)
return ret.Err
}
func (svc *BlackWhiteCoinSvc) GetBlackWhiteCoinLogByBillNo(args *model.BlackWhiteCoinArg, ret *model.BlackWhiteCoinRet) error {
clog := BlackWhiteCoinLogsCollection(args.Platform)
if clog == nil {
return BlackWhiteCoinLogErr
}
err := clog.Find(bson.M{"snid": args.SnId, "billno": args.BillNo}).One(ret.Data)
if err != nil {
logger.Logger.Error("svc.GetBlackWhiteCoinLogByBillNo error", err)
return err
}
return nil
}
func init() {
rpc.Register(&BlackWhiteCoinSvc{})
}

View File

@ -0,0 +1,56 @@
package svc
import (
"github.com/globalsign/mgo"
"github.com/globalsign/mgo/bson"
"mongo.games.com/game/dbproxy/mongo"
"mongo.games.com/game/model"
"mongo.games.com/goserver/core/logger"
"net/rpc"
)
func BurstJackpotCoinLogsCollection(plt string) *mongo.Collection {
s := mongo.MgoSessionMgrSington.GetPltMgoSession(plt, model.BurstJackpotLogDBName)
if s != nil {
c_burstjackpot, first := s.DB().C(model.BurstJackpotLogCollName)
if first {
c_burstjackpot.EnsureIndex(mgo.Index{Key: []string{"platform"}, Background: true, Sparse: true})
c_burstjackpot.EnsureIndex(mgo.Index{Key: []string{"gameid"}, Background: true, Sparse: true})
c_burstjackpot.EnsureIndex(mgo.Index{Key: []string{"gamefreeid"}, Background: true, Sparse: true})
c_burstjackpot.EnsureIndex(mgo.Index{Key: []string{"ts"}, Background: true, Sparse: true})
}
return c_burstjackpot
}
return nil
}
type BurstJackpotSvc struct {
}
func (svc *BurstJackpotSvc) GetBurstJackpotLog(arg *model.BurstJackpotArg, ret *[]model.BurstJackpotLog) (err error) {
clog := BurstJackpotCoinLogsCollection(arg.Platform)
if clog == nil {
return
}
err = clog.Find(bson.M{"gameid": arg.GameId}).Limit(80).Sort("-ts").All(ret)
if err != nil {
logger.Logger.Error("GetBurstJackpotLog err:", err)
}
return
}
func (svc *BurstJackpotSvc) InsertBurstJackpotLogs(log *model.BurstJackpotLog, ret *bool) (err error) {
clog := BurstJackpotCoinLogsCollection(log.Platform)
if clog == nil {
return
}
err = clog.Insert(log)
if err != nil {
logger.Logger.Warn("svc.InsertBurstJackpotLogs error:", err)
return
}
*ret = true
return
}
func init() {
rpc.Register(&BurstJackpotSvc{})
}

78
dbproxy/svc/l_chat.go Normal file
View File

@ -0,0 +1,78 @@
package svc
import (
"errors"
"github.com/globalsign/mgo"
"github.com/globalsign/mgo/bson"
"mongo.games.com/game/dbproxy/mongo"
"mongo.games.com/game/model"
"mongo.games.com/goserver/core/logger"
"net/rpc"
)
var (
ChatDBName = "log"
ChatCollName = "log_chat"
ChatColError = errors.New("chat collection open failed")
)
func ChatCollection(plt string) *mongo.Collection {
s := mongo.MgoSessionMgrSington.GetPltMgoSession(plt, ChatDBName)
if s != nil {
c, first := s.DB().C(ChatCollName)
if first {
c.EnsureIndex(mgo.Index{Key: []string{"bindsnid"}, Background: true, Sparse: true})
}
return c
}
return nil
}
type ChatSvc struct {
}
func (svc *ChatSvc) UpsertChat(args *model.ChatByKey, ret *model.ChatRet) error {
cc := ChatCollection(args.Platform)
if cc == nil {
return ChatColError
}
_, err := cc.Upsert(bson.M{"bindsnid": args.BindSnId}, args.C)
if err != nil && err != mgo.ErrNotFound {
logger.Logger.Error("UpsertChat is err: ", err)
return err
}
ret.C = args.C
return nil
}
func (svc *ChatSvc) QueryChatByKey(args *model.ChatByKey, ret *model.ChatRet) error {
fc := ChatCollection(args.Platform)
if fc == nil {
return ChatColError
}
err := fc.Find(bson.M{"bindsnid": args.BindSnId}).One(&ret.C)
if err != nil && err != mgo.ErrNotFound {
logger.Logger.Error("QueryChatByKey is err: ", err)
return err
}
return nil
}
func (svc *ChatSvc) DelChat(args *model.ChatByKey, ret *bool) error {
cc := ChatCollection(args.Platform)
if cc == nil {
return ChatColError
}
err := cc.Remove(bson.M{"bindsnid": args.BindSnId})
if err != nil {
logger.Logger.Error("DelChat is err: ", err)
return err
}
return nil
}
var _ChatSvc = &ChatSvc{}
func init() {
rpc.Register(_ChatSvc)
}

View File

@ -0,0 +1,21 @@
package svc
import (
"mongo.games.com/game/dbproxy/mongo"
"mongo.games.com/game/model"
)
func ClientLogStartCollection(platform string) *mongo.Collection {
if platform == "" {
platform = mongo.G_P
}
s := mongo.MgoSessionMgrSington.GetPltMgoSession(platform, model.ClientLogDBName)
if s != nil {
c_coinlogrec, first := s.DB().C(model.ClientLogCollName)
if first {
//c_coinlogrec.EnsureIndex(mgo.Index{Key: []string{"ts"}, Background: true, Sparse: true})
}
return c_coinlogrec
}
return nil
}

View File

@ -0,0 +1,141 @@
package svc
import (
"errors"
"net/rpc"
"github.com/globalsign/mgo"
"github.com/globalsign/mgo/bson"
"mongo.games.com/game/dbproxy/mongo"
"mongo.games.com/game/model"
"mongo.games.com/goserver/core/logger"
)
var (
CoinGiveLogErr = errors.New("log coingive log open failed.")
)
func CoinGiveLogCollection(plt string) *mongo.Collection {
s := mongo.MgoSessionMgrSington.GetPltMgoSession(plt, model.CoinGiveLogDBName)
if s != nil {
c_coinGiveLogRec, first := s.DB().C(model.CoinGiveLogCollName)
if first {
c_coinGiveLogRec.EnsureIndex(mgo.Index{Key: []string{"snid"}, Background: true, Sparse: true})
c_coinGiveLogRec.EnsureIndex(mgo.Index{Key: []string{"promoter"}, Background: true, Sparse: true})
c_coinGiveLogRec.EnsureIndex(mgo.Index{Key: []string{"state"}, Background: true, Sparse: true})
c_coinGiveLogRec.EnsureIndex(mgo.Index{Key: []string{"ts"}, Background: true, Sparse: true})
c_coinGiveLogRec.EnsureIndex(mgo.Index{Key: []string{"time"}, Background: true, Sparse: true})
}
return c_coinGiveLogRec
}
return nil
}
type CoinGiveLogSvc struct {
}
func (svc *CoinGiveLogSvc) UpdateGiveCoinLastFlow(args *model.UpdateGiveCoinLastFlowArg, ret *bool) (err error) {
clog := CoinGiveLogCollection(args.Plt)
if clog == nil {
return CoinGiveLogErr
}
err = clog.Update(bson.M{"_id": bson.ObjectIdHex(args.LogId)}, bson.M{"$set": bson.M{"flow": args.Flow}})
if err != nil {
logger.Logger.Warn("svc.InsertSignleLoginLog error:", err)
return
}
*ret = true
return
}
func (svc *CoinGiveLogSvc) GetGiveCoinLastFlow(args *model.GetGiveCoinLastFlowArg, log *model.CoinGiveLog) (err error) {
clog := CoinGiveLogCollection(args.Plt)
if clog == nil {
return CoinGiveLogErr
}
err = clog.Find(bson.M{"_id": bson.ObjectIdHex(args.LogId)}).One(&log)
return
}
func (svc *CoinGiveLogSvc) GetCoinGiveLogList(args *model.GetCoinGiveLogListArg, logs *[]*model.CoinGiveLog) (err error) {
clog := CoinGiveLogCollection(args.Plt)
if clog == nil {
return CoinGiveLogErr
}
err = clog.Find(bson.M{"snid": args.SnId, "state": 0, "ts": bson.M{"$gt": args.TsStart, "$lte": args.TsEnd}, "ver": args.Ver}).All(&logs)
return
}
func (svc *CoinGiveLogSvc) GetCoinGiveLogListByState(args *model.GetCoinGiveLogListByStateArg, logs *[]*model.CoinGiveLog) (err error) {
clog := CoinGiveLogCollection(args.Plt)
if clog == nil {
return CoinGiveLogErr
}
err = clog.Find(bson.M{"snid": args.SnId, "state": args.State}).All(&logs)
return
}
func (svc *CoinGiveLogSvc) ResetCoinGiveLogList(args *model.ResetCoinGiveLogListArg, ret *bool) (err error) {
clog := CoinGiveLogCollection(args.Plt)
if clog == nil {
return CoinGiveLogErr
}
_, err = clog.UpdateAll(bson.M{"snid": args.SnId, "state": args.Ts}, bson.M{"$set": bson.M{"state": 0}})
if err != nil {
logger.Logger.Warn("svc.ResetCoinGiveLogList error:", err)
return
}
*ret = true
return
}
func (svc *CoinGiveLogSvc) SetCoinGiveLogList(args *model.SetCoinGiveLogListArg, ret *bool) (err error) {
clog := CoinGiveLogCollection(args.Plt)
if clog == nil {
return CoinGiveLogErr
}
_, err = clog.UpdateAll(bson.M{"snid": args.SnId, "state": 0, "ts": bson.M{"$gt": args.TsStart, "$lte": args.TsEnd}}, bson.M{"$set": bson.M{"state": args.State}})
if err != nil {
logger.Logger.Warn("svc.SetCoinGiveLogList error:", err)
return
}
*ret = true
return
}
func (svc *CoinGiveLogSvc) UpdateCoinLog(args *model.UpdateCoinLogArg, ret *bool) (err error) {
clog := CoinGiveLogCollection(args.Plt)
if clog == nil {
return CoinGiveLogErr
}
err = clog.Update(bson.M{"_id": bson.ObjectIdHex(args.LogId)}, bson.M{"$set": bson.M{"state": args.State}})
if err != nil {
logger.Logger.Warn("svc.UpdateCoinLog error:", err)
return
}
*ret = true
return
}
func (svc *CoinGiveLogSvc) InsertGiveCoinLog(log *model.CoinGiveLog, ret *bool) (err error) {
clog := CoinGiveLogCollection(log.Platform)
if clog == nil {
return CoinGiveLogErr
}
err = clog.Insert(log)
if err != nil {
logger.Logger.Warn("InsertCoinGiveSLog error:", err)
return
}
*ret = true
return
}
func init() {
rpc.Register(new(CoinGiveLogSvc))
}

176
dbproxy/svc/l_coinlog.go Normal file
View File

@ -0,0 +1,176 @@
package svc
import (
"errors"
"net/rpc"
"time"
"github.com/globalsign/mgo"
"github.com/globalsign/mgo/bson"
"mongo.games.com/game/dbproxy/mongo"
"mongo.games.com/game/model"
"mongo.games.com/goserver/core/logger"
)
var (
CoinLogErr = errors.New("log coinex log open failed.")
)
const CoinLogMaxLimitPerQuery = 100
func CoinLogsCollection(plt string) *mongo.Collection {
s := mongo.MgoSessionMgrSington.GetPltMgoSession(plt, model.CoinLogDBName)
if s != nil {
c_coinlogrec, first := s.DB().C(model.CoinLogCollName)
if first {
c_coinlogrec.EnsureIndex(mgo.Index{Key: []string{"snid"}, Background: true, Sparse: true})
c_coinlogrec.EnsureIndex(mgo.Index{Key: []string{"logtype"}, Background: true, Sparse: true})
c_coinlogrec.EnsureIndex(mgo.Index{Key: []string{"-time"}, Background: true, Sparse: true})
c_coinlogrec.EnsureIndex(mgo.Index{Key: []string{"oper"}, Background: true, Sparse: true})
c_coinlogrec.EnsureIndex(mgo.Index{Key: []string{"seqno"}, Background: true, Sparse: true})
c_coinlogrec.EnsureIndex(mgo.Index{Key: []string{"gamefreeid"}, Background: true, Sparse: true})
c_coinlogrec.EnsureIndex(mgo.Index{Key: []string{"cointype"}, Background: true, Sparse: true})
c_coinlogrec.EnsureIndex(mgo.Index{Key: []string{"ts"}, Background: true, Sparse: true})
}
return c_coinlogrec
}
return nil
}
type CoinLogSvc struct {
}
func GetCoinLogBySnidAndInGameAndGreaterTs(plt string, id int32, roomid int32, ts int64) (ret []model.CoinLog, err error) {
if roomid != 0 {
err = CoinLogsCollection(plt).Find(bson.M{"snid": id, "roomid": roomid, "ingame": bson.M{"$gt": 0}, "ts": bson.M{"$gt": ts}}).All(&ret)
} else {
err = CoinLogsCollection(plt).Find(bson.M{"snid": id, "ingame": bson.M{"$gt": 0}, "ts": bson.M{"$gt": ts}}).All(&ret)
}
return
}
func (svc *CoinLogSvc) GetCoinLogBySnidAndLessTs(args *model.GetCoinLogBySnidAndLessTsArg, ret *[]model.CoinLog) (err error) {
err = CoinLogsCollection(args.Plt).Find(bson.M{"snid": args.SnId, "time": bson.M{"$lt": time.Unix(args.Ts, 0)}}).Sort("-ts").Limit(CoinLogMaxLimitPerQuery).All(ret)
return
}
func (svc *CoinLogSvc) GetCoinLogBySnidAndTypeAndInRangeTsLimitByRange(args *model.GetCoinLogBySnidAndTypeAndInRangeTsLimitByRangeArg, ret *model.GetCoinLogBySnidAndTypeAndInRangeTsLimitByRangeRet) (err error) {
limitDataNum := args.ToIdx - args.FromIdx
if limitDataNum < 0 {
limitDataNum = 0
}
if limitDataNum > CoinLogMaxLimitPerQuery {
limitDataNum = CoinLogMaxLimitPerQuery
}
plt := args.Plt
startts := args.StartTs
endts := args.EndTs
logType := args.LogType
id := args.SnId
fromIndex := args.FromIdx
if (startts == 0 || endts == 0) && logType == 0 {
ret.Count, _ = CoinLogsCollection(plt).Find(bson.M{"snid": id}).Count()
err = CoinLogsCollection(plt).Find(bson.M{"snid": id}).Skip(fromIndex).Limit(limitDataNum).All(&ret.Logs)
} else if startts == 0 || endts == 0 {
ret.Count, _ = CoinLogsCollection(plt).Find(bson.M{"snid": id, "logtype": logType}).Count()
err = CoinLogsCollection(plt).Find(bson.M{"snid": id, "logtype": logType}).Skip(fromIndex).Limit(limitDataNum).All(&ret.Logs)
} else if logType == 0 {
ret.Count, _ = CoinLogsCollection(plt).Find(bson.M{"snid": id, "ts": bson.M{"$gte": startts, "$lte": endts}}).Count()
err = CoinLogsCollection(plt).Find(bson.M{"snid": id, "ts": bson.M{"$gte": startts, "$lte": endts}}).Skip(fromIndex).Limit(limitDataNum).All(&ret.Logs)
} else {
ret.Count, _ = CoinLogsCollection(plt).Find(bson.M{"snid": id, "logtype": logType, "ts": bson.M{"$gte": startts, "$lte": endts}}).Count()
err = CoinLogsCollection(plt).Find(bson.M{"snid": id, "logtype": logType, "ts": bson.M{"$gte": startts, "$lte": endts}}).Skip(fromIndex).Limit(limitDataNum).All(&ret.Logs)
}
return
}
func (svc *CoinLogSvc) GetCoinLogGame(args *model.GetCoinLogGameReq, ret *model.GetCoinLogGameRet) (err error) {
limitDataNum := args.ToIdx - args.FromIdx
if limitDataNum < 0 {
limitDataNum = 0
}
if limitDataNum > CoinLogMaxLimitPerQuery {
limitDataNum = CoinLogMaxLimitPerQuery
}
plt := args.Plt
startts := args.StartTs
endts := args.EndTs
billType := args.BillType // 0金币 1钻石
id := args.SnId
fromIndex := args.FromIdx
if (startts == 0 || endts == 0) && billType == 0 {
ret.Count, _ = CoinLogsCollection(plt).Find(bson.M{"snid": id, "gamefreeid": bson.M{"$gt": 0}}).Count()
err = CoinLogsCollection(plt).Find(bson.M{"snid": id, "gamefreeid": bson.M{"$gt": 0}}).Sort("-time").Skip(fromIndex).Limit(limitDataNum).All(&ret.Logs)
} else if startts == 0 || endts == 0 {
ret.Count, _ = CoinLogsCollection(plt).Find(bson.M{"snid": id, "cointype": billType, "gamefreeid": bson.M{"$gt": 0}}).Count()
err = CoinLogsCollection(plt).Find(bson.M{"snid": id, "cointype": billType, "gamefreeid": bson.M{"$gt": 0}}).Sort("-time").Skip(fromIndex).Limit(limitDataNum).All(&ret.Logs)
} else if billType == 0 {
ret.Count, _ = CoinLogsCollection(plt).Find(bson.M{"snid": id, "gamefreeid": bson.M{"$gt": 0}, "ts": bson.M{"$gte": startts, "$lte": endts}}).Count()
err = CoinLogsCollection(plt).Find(bson.M{"snid": id, "gamefreeid": bson.M{"$gt": 0}, "ts": bson.M{"$gte": startts, "$lte": endts}}).Sort("-time").Skip(fromIndex).Limit(limitDataNum).All(&ret.Logs)
} else {
ret.Count, _ = CoinLogsCollection(plt).Find(bson.M{"snid": id, "cointype": billType, "gamefreeid": bson.M{"$gt": 0}, "ts": bson.M{"$gte": startts, "$lte": endts}}).Count()
err = CoinLogsCollection(plt).Find(bson.M{"snid": id, "cointype": billType, "gamefreeid": bson.M{"$gt": 0}, "ts": bson.M{"$gte": startts, "$lte": endts}}).Sort("-time").Skip(fromIndex).Limit(limitDataNum).All(&ret.Logs)
}
return
}
func (svc *CoinLogSvc) InsertCoinLog(log *model.CoinLog, ret *bool) (err error) {
clog := CoinLogsCollection(log.Platform)
if clog == nil {
return
}
err = clog.Insert(log)
if err != nil {
logger.Logger.Warn("InsertCoinLog error:", err)
return
}
//err = InsertCoinWAL(log.Platform, model.NewCoinWAL(log.SnId, log.Count, log.LogType, log.InGame, log.CoinType, log.RoomId, log.Time.UnixNano()))
//if err != nil {
// logger.Logger.Warn("InsertCoinWAL error:", err)
// return
//}
*ret = true
return
}
func (svc *CoinLogSvc) RemoveCoinLog(args *model.RemoveCoinLogOneArg, chged **mgo.ChangeInfo) (err error) {
clog := CoinLogsCollection(args.Plt)
if clog == nil {
return CoinLogErr
}
*chged, err = clog.RemoveAll(bson.M{"time": bson.M{"$lte": time.Unix(args.Ts, 0)}})
return
}
func (svc *CoinLogSvc) RemoveCoinLogOne(args *model.RemoveCoinLogOneArg, ret *bool) (err error) {
clog := CoinLogsCollection(args.Plt)
if clog == nil {
return CoinLogErr
}
err = clog.RemoveId(args.Id)
if err != nil {
return
}
*ret = true
return
}
func (svc *CoinLogSvc) UpdateCoinLogRemark(args *model.UpdateCoinLogRemarkArg, ret *bool) (err error) {
clog := CoinLogsCollection(args.Plt)
if clog == nil {
return CoinLogErr
}
err = clog.UpdateId(args.Id, bson.M{"$set": bson.M{"remark": args.Remark}})
if err != nil {
return
}
*ret = true
return
}
func init() {
rpc.Register(new(CoinLogSvc))
}

120
dbproxy/svc/l_coinwal.go Normal file
View File

@ -0,0 +1,120 @@
package svc
import (
"errors"
"github.com/globalsign/mgo"
"github.com/globalsign/mgo/bson"
"mongo.games.com/game/dbproxy/mongo"
"mongo.games.com/game/model"
"mongo.games.com/goserver/core/logger"
"net/rpc"
)
var (
CoinWALErr = errors.New("log_coinwal open failed.")
)
func CoinWALCollection(plt string) *mongo.Collection {
s := mongo.MgoSessionMgrSington.GetPltMgoSession(plt, model.CoinWALDBName)
if s != nil {
c, first := s.DB().C(model.CoinWALCollName)
if first {
c.EnsureIndex(mgo.Index{Key: []string{"snid"}, Background: true, Sparse: true})
c.EnsureIndex(mgo.Index{Key: []string{"ingame"}, Background: true, Sparse: true})
c.EnsureIndex(mgo.Index{Key: []string{"sceneid"}, Background: true, Sparse: true})
c.EnsureIndex(mgo.Index{Key: []string{"logtype"}, Background: true, Sparse: true})
c.EnsureIndex(mgo.Index{Key: []string{"cointype"}, Background: true, Sparse: true})
c.EnsureIndex(mgo.Index{Key: []string{"-ts"}, Background: true, Sparse: true})
}
return c
}
return nil
}
func GetCoinWALBySnidAndInGameAndGreaterTs(plt string, id, sceneid int32, ts int64) (ret []model.CoinWAL, err error) {
cond := bson.M{"snid": id, "ingame": bson.M{"$gt": 0}, "ts": bson.M{"$gt": ts}}
if sceneid > 0 {
cond["sceneid"] = sceneid
}
err = CoinWALCollection(plt).Find(cond).All(&ret)
return
}
func GetCoinWALBySnidAndCoinTypeAndGreaterTs(plt string, id, coinType int32, ts int64) (ret []model.CoinWAL, err error) {
err = CoinWALCollection(plt).Find(bson.M{"snid": id, "ingame": 0, "cointype": coinType, "ts": bson.M{"$gt": ts}}).All(&ret)
return
}
func InsertCoinWAL(plt string, logs ...*model.CoinWAL) (err error) {
clog := CoinWALCollection(plt)
if clog == nil {
return
}
switch len(logs) {
case 0:
return errors.New("no data")
case 1:
err = clog.Insert(logs[0])
default:
docs := make([]interface{}, 0, len(logs))
for _, log := range logs {
docs = append(docs, log)
}
err = clog.Insert(docs...)
}
if err != nil {
logger.Logger.Warn("InsertCoinWAL error:", err)
return
}
return
}
func RemoveCoinWALInGame(plt string, id, sceneid int32, ts int64) (err error) {
clog := CoinWALCollection(plt)
if clog == nil {
return CoinLogErr
}
cond := bson.M{"snid": id, "ingame": bson.M{"$gt": 0}, "ts": bson.M{"$lte": ts}}
if sceneid > 0 {
cond["sceneid"] = sceneid
}
_, err = clog.RemoveAll(cond)
if err != nil {
return
}
return
}
func RemoveCoinWALByCoinType(plt string, id, cointype int32, ts int64) (err error) {
clog := CoinWALCollection(plt)
if clog == nil {
return CoinLogErr
}
_, err = clog.RemoveAll(bson.M{"snid": id, "ingame": 0, "cointype": cointype, "ts": bson.M{"$lte": ts}})
if err != nil {
return
}
return
}
type CoinWALSvc struct {
}
func (svc *CoinWALSvc) GetCoinWALBySnidAndInGameAndGreaterTs(args *model.CoinWALWithSnid_InGame_GreaterTsArgs, ret *[]model.CoinWAL) (err error) {
*ret, err = GetCoinWALBySnidAndInGameAndGreaterTs(args.Plt, args.SnId, args.RoomId, args.Ts)
return
}
func (svc *CoinWALSvc) RemoveCoinWALBySnidAndInGameAndGreaterTs(args *model.CoinWALWithSnid_InGame_GreaterTsArgs, ret *bool) (err error) {
err = RemoveCoinWALInGame(args.Plt, args.SnId, args.RoomId, args.Ts)
*ret = err == nil
return
}
func init() {
rpc.Register(new(CoinWALSvc))
}

103
dbproxy/svc/l_dbshoplog.go Normal file
View File

@ -0,0 +1,103 @@
package svc
import (
"github.com/globalsign/mgo"
"github.com/globalsign/mgo/bson"
"mongo.games.com/game/dbproxy/mongo"
"mongo.games.com/game/model"
"mongo.games.com/goserver/core/logger"
"net/rpc"
)
func DbShopLogCollection(plt string) *mongo.Collection {
s := mongo.MgoSessionMgrSington.GetPltMgoSession(plt, model.DbShopDBName)
if s != nil {
dbShopRec, first := s.DB().C(model.DbShopCollName)
if first {
dbShopRec.EnsureIndex(mgo.Index{Key: []string{"snid"}, Background: true, Sparse: true})
dbShopRec.EnsureIndex(mgo.Index{Key: []string{"pageid"}, Background: true, Sparse: true})
dbShopRec.EnsureIndex(mgo.Index{Key: []string{"state"}, Background: true, Sparse: true})
dbShopRec.EnsureIndex(mgo.Index{Key: []string{"shopid"}, Background: true, Sparse: true})
}
return dbShopRec
}
return nil
}
type DbShopLogSvc struct {
}
func (svc *DbShopLogSvc) InsertDbShopLog(args *model.DbShopLogArgs, ret *bool) (err error) {
clog := DbShopLogCollection(args.Log.Platform)
if clog == nil {
return
}
logger.Logger.Trace("DbShopLogSvc.InsertDbShopLog")
err = clog.Insert(args.Log)
if err != nil {
logger.Logger.Error("DbShopLogSvc.InsertDbShopLog error:", err)
return
}
*ret = true
return
}
func (svc *DbShopLogSvc) GetDbShopLog(args *model.DbShopLogArgs, dbShop *model.DbShop) (err error) {
clog := DbShopLogCollection(args.Log.Platform)
if clog == nil {
logger.Logger.Error("GetDbShopLog == nil")
return nil
}
logger.Logger.Trace("DbShopLogSvc.GetDbShopLog")
err = clog.Find(bson.M{"_id": args.Log.LogId}).One(dbShop)
if err != nil {
logger.Logger.Error("DbShopLogSvc.GetDbShopLog error:", err)
return nil
}
return
}
func (svc *DbShopLogSvc) UpdateDbShopState(args *model.DbShopLogArgs, ret *bool) (err error) {
clog := DbShopLogCollection(args.Log.Platform)
if clog == nil {
logger.Logger.Error("UpdateDbShopState == nil")
return nil
}
logger.Logger.Trace("DbShopLogSvc.UpdateDbShopState")
err = clog.UpdateId(args.Log.LogId, bson.M{"$set": bson.M{"state": args.Log.State}})
if err != nil {
logger.Logger.Error("DbShopLogSvc.UpdateDbShopState error:", err)
return nil
}
*ret = true
return
}
func (svc *DbShopLogSvc) GetDbShopLogsByPage(args *model.DbShopLogArgs, dbShops *[]*model.DbShop) (err error) {
clog := DbShopLogCollection(args.Log.Platform)
if clog == nil {
logger.Logger.Error("GetDbShopLogsByPage == nil")
return
}
logger.Logger.Trace("DbShopLogSvc.GetDbShopLogsByPage")
err = clog.Find(bson.M{"pageid": args.Log.PageId, "snid": args.Log.SnId}).Limit(100).Sort("-ts").All(dbShops)
if err != nil {
logger.Logger.Error("DbShopLogSvc.GetDbShopLogsByPage error:", err)
return
}
return
}
func (svc *DbShopLogSvc) GetDbShopLogsByState(args *model.DbShopLogArgs, dbShops *[]*model.DbShop) (err error) {
clog := DbShopLogCollection(args.Log.Platform)
if clog == nil {
logger.Logger.Error("GetDbShopLogsByPage == nil")
return
}
logger.Logger.Trace("DbShopLogSvc.GetDbShopLogsByPage")
err = clog.Find(bson.M{"state": args.Log.State, "snid": args.Log.SnId}).All(dbShops)
if err != nil {
logger.Logger.Error("DbShopLogSvc.GetDbShopLogsByPage error:", err)
return
}
return
}
func init() {
rpc.Register(new(DbShopLogSvc))
}

43
dbproxy/svc/l_dbviplog.go Normal file
View File

@ -0,0 +1,43 @@
package svc
import (
"github.com/globalsign/mgo"
"mongo.games.com/game/dbproxy/mongo"
"mongo.games.com/game/model"
"mongo.games.com/goserver/core/logger"
"net/rpc"
)
func DbVipLogCollection(plt string) *mongo.Collection {
s := mongo.MgoSessionMgrSington.GetPltMgoSession(plt, model.DbVipDBName)
if s != nil {
dbVipRec, first := s.DB().C(model.DbVipCollName)
if first {
dbVipRec.EnsureIndex(mgo.Index{Key: []string{"snid"}, Background: true, Sparse: true})
dbVipRec.EnsureIndex(mgo.Index{Key: []string{"type"}, Background: true, Sparse: true})
}
return dbVipRec
}
return nil
}
type DbVipLogSvc struct {
}
func (svc *DbVipLogSvc) InsertDbVipLog(args *model.DbVipLogArgs, ret *bool) (err error) {
clog := DbVipLogCollection(args.Log.Platform)
if clog == nil {
return
}
logger.Logger.Trace("DbVipLogSvc.InsertDbVipLog")
err = clog.Insert(args.Log)
if err != nil {
logger.Logger.Error("DbVipLogSvc.InsertDbVipLog error:", err)
return
}
*ret = true
return
}
func init() {
rpc.Register(new(DbVipLogSvc))
}

View File

@ -0,0 +1,55 @@
package svc
import (
"errors"
"github.com/globalsign/mgo"
"github.com/globalsign/mgo/bson"
"mongo.games.com/game/dbproxy/mongo"
"mongo.games.com/game/model"
"net/rpc"
)
var (
FishJackpotLogErr = errors.New("log fishjackpot log open failed.")
)
type FishJackLogSvc struct{}
func init() {
rpc.Register(new(FishJackLogSvc))
}
func FishJackpotLogsCollection(plt string) *mongo.Collection {
s := mongo.MgoSessionMgrSington.GetPltMgoSession(plt, model.FishJackpotLogDBName)
if s != nil {
c, first := s.DB().C(model.FishJackpotLogCollName)
if first {
c.EnsureIndex(mgo.Index{Key: []string{"snid"}, Background: true, Sparse: true})
c.EnsureIndex(mgo.Index{Key: []string{"channel"}, Background: true, Sparse: true})
c.EnsureIndex(mgo.Index{Key: []string{"promoter"}, Background: true, Sparse: true})
c.EnsureIndex(mgo.Index{Key: []string{"ts"}, Background: true, Sparse: true})
c.EnsureIndex(mgo.Index{Key: []string{"time"}, Background: true, Sparse: true})
c.EnsureIndex(mgo.Index{Key: []string{"roomid"}, Background: true, Sparse: true})
}
return c
}
return nil
}
func (svc *FishJackLogSvc) GetFishJackpotLogByPlatform(args *model.GetLogArgs, ret *model.GetLogRet) error {
c := FishJackpotLogsCollection(args.Platform)
if c == nil {
return FishJackpotLogErr
}
err := c.Find(bson.M{"platform": args.Platform}).Sort("-ts").Limit(model.FishJackpotLogMaxLimitPerQuery).All(&ret.Logs)
return err
}
func (svc *FishJackLogSvc) InsertSignleFishJackpotLog(args *model.InsertLogArgs, ret *model.InsertLogRet) error {
c := FishJackpotLogsCollection(args.Log.Platform)
if c == nil {
return FishJackpotLogErr
}
err := c.Insert(args.Log)
return err
}

View File

@ -0,0 +1,78 @@
package svc
import (
"errors"
"github.com/globalsign/mgo"
"github.com/globalsign/mgo/bson"
"mongo.games.com/game/dbproxy/mongo"
"mongo.games.com/game/model"
"mongo.games.com/goserver/core/logger"
"net/rpc"
)
var (
FriendApplyDBName = "log"
FriendApplyCollName = "log_friendapply"
FriendApplyColError = errors.New("friendapply collection open failed")
)
func FriendApplyCollection(plt string) *mongo.Collection {
s := mongo.MgoSessionMgrSington.GetPltMgoSession(plt, FriendApplyDBName)
if s != nil {
c, first := s.DB().C(FriendApplyCollName)
if first {
c.EnsureIndex(mgo.Index{Key: []string{"snid"}, Background: true, Sparse: true})
}
return c
}
return nil
}
type FriendApplySvc struct {
}
func (svc *FriendApplySvc) UpsertFriendApply(args *model.FriendApplyByKey, ret *model.FriendApplyRet) error {
cc := FriendApplyCollection(args.Platform)
if cc == nil {
return FriendApplyColError
}
_, err := cc.Upsert(bson.M{"snid": args.SnId}, args.FA)
if err != nil && err != mgo.ErrNotFound {
logger.Logger.Error("UpsertFriendApply is err: ", err)
return err
}
ret.FA = args.FA
return nil
}
func (svc *FriendApplySvc) QueryFriendApplyByKey(args *model.FriendApplyByKey, ret *model.FriendApplyRet) error {
fc := FriendApplyCollection(args.Platform)
if fc == nil {
return FriendApplyColError
}
err := fc.Find(bson.M{"snid": args.SnId}).One(&ret.FA)
if err != nil && !errors.Is(err, mgo.ErrNotFound) {
logger.Logger.Error("QueryFriendApplyByKey is err: ", err)
return err
}
return nil
}
func (svc *FriendApplySvc) DelFriendApply(args *model.FriendApplyByKey, ret *bool) error {
cc := FriendApplyCollection(args.Platform)
if cc == nil {
return FriendApplyColError
}
err := cc.Remove(bson.M{"snid": args.SnId})
if err != nil {
logger.Logger.Error("DelFriendApply is err: ", err)
return err
}
return nil
}
var _FriendApplySvc = &FriendApplySvc{}
func init() {
rpc.Register(_FriendApplySvc)
}

View File

@ -0,0 +1,111 @@
package svc
import (
"errors"
"github.com/globalsign/mgo"
"github.com/globalsign/mgo/bson"
"mongo.games.com/game/dbproxy/mongo"
"mongo.games.com/game/model"
"mongo.games.com/goserver/core/logger"
"net/rpc"
)
var (
FriendRecordLogErr = errors.New("friend record log open failed.")
)
func FriendRecordLogsCollection(plt string) *mongo.Collection {
s := mongo.MgoSessionMgrSington.GetPltMgoSession(plt, model.FriendRecordLogDBName)
if s != nil {
c_friendrecordlog, first := s.DB().C(model.FriendRecordLogCollName)
if first {
c_friendrecordlog.EnsureIndex(mgo.Index{Key: []string{"snid"}, Background: true, Sparse: true})
c_friendrecordlog.EnsureIndex(mgo.Index{Key: []string{"platform"}, Background: true, Sparse: true})
c_friendrecordlog.EnsureIndex(mgo.Index{Key: []string{"gameid"}, Background: true, Sparse: true})
c_friendrecordlog.EnsureIndex(mgo.Index{Key: []string{"ts"}, Background: true, Sparse: true})
}
return c_friendrecordlog
}
return nil
}
func InsertFriendRecordLog(log model.FriendRecord) error {
frlog := FriendRecordLogsCollection(log.Platform)
if frlog == nil {
return FriendRecordLogErr
}
count, err := frlog.Find(bson.M{"snid": log.SnId, "platform": log.Platform, "gameid": log.GameId}).Count()
if err != nil {
logger.Logger.Error("InsertFriendRecordLog: Find err: ", err)
return err
}
if count >= 50 {
var oldLogs []model.FriendRecord
err = frlog.Find(bson.M{"snid": log.SnId, "platform": log.Platform, "gameid": log.GameId}).Sort("-ts").Skip(19).All(&oldLogs)
if err != nil {
logger.Logger.Error("InsertFriendRecordLog: Find err: ", err)
return err
}
for _, oldLog := range oldLogs {
err = frlog.RemoveId(oldLog.LogId)
if err != nil {
logger.Logger.Error("InsertFriendRecordLog: RemoveId err: ", err)
return err
}
}
}
err = frlog.Insert(log)
return err
}
func (svc *FriendRecordLogSvc) GetFriendRecordLogBySnid(args *model.FriendRecordSnidArg, ret *model.FriendRecordSnidRet) error {
frlog := FriendRecordLogsCollection(args.Platform)
if frlog == nil {
return FriendRecordLogErr
}
var sql []bson.M
if args.SnId != 0 {
sql = append(sql, bson.M{"snid": args.SnId})
}
if args.Platform != "" {
sql = append(sql, bson.M{"platform": args.Platform})
}
if args.GameId != 0 {
sql = append(sql, bson.M{"gameid": args.GameId})
}
if args.Size == 0 {
return nil
}
var datas []*model.FriendRecord
err := frlog.Find(bson.M{"$and": sql}).Sort("-ts").Limit(20).All(&datas)
if err != nil {
logger.Logger.Error("FriendRecordLogSvc error: ", err)
return err
}
if datas == nil {
return nil
}
frs := []*model.FriendRecord{}
for _, data := range datas {
fr := &model.FriendRecord{
SnId: data.SnId,
GameId: data.GameId,
BaseScore: data.BaseScore,
IsWin: data.IsWin,
Platform: data.Platform,
Ts: data.Ts,
BillCoin: data.BillCoin,
MatchType: data.MatchType,
}
frs = append(frs, fr)
}
ret.FR = frs
return nil
}
type FriendRecordLogSvc struct {
}
func init() {
rpc.Register(new(FriendRecordLogSvc))
}

View File

@ -0,0 +1,126 @@
package svc
import (
"errors"
"github.com/globalsign/mgo"
"github.com/globalsign/mgo/bson"
"mongo.games.com/game/dbproxy/mongo"
"mongo.games.com/game/model"
"mongo.games.com/goserver/core/logger"
"net/rpc"
)
var (
FriendUnreadDBName = "log"
FriendUnreadCollName = "log_friendunread"
FriendUnreadColError = errors.New("friendunread collection open failed")
)
func FriendUnreadCollection(plt string) *mongo.Collection {
s := mongo.MgoSessionMgrSington.GetPltMgoSession(plt, FriendUnreadDBName)
if s != nil {
c, first := s.DB().C(FriendUnreadCollName)
if first {
c.EnsureIndex(mgo.Index{Key: []string{"snid"}, Background: true, Sparse: true})
}
return c
}
return nil
}
type FriendUnreadSvc struct {
}
func (svc *FriendUnreadSvc) UpsertFriendUnread(args *model.FriendUnreadByKey, ret *model.FriendUnreadRet) error {
cc := FriendUnreadCollection(args.Platform)
if cc == nil {
return FriendUnreadColError
}
err := cc.Find(bson.M{"snid": args.SnId}).One(&ret.FU)
if err != nil && err != mgo.ErrNotFound {
logger.Logger.Error("UpsertFriendUnread Find is err: ", err)
return err
}
if err == mgo.ErrNotFound {
fu := model.NewFriendUnread(args.SnId)
fu.UnreadSnids = append(fu.UnreadSnids, &model.FriendUnreadSnid{
SnId: args.UnreadSnid,
UnreadNum: 1,
})
err = cc.Insert(fu)
} else {
had := false
for _, unreadSnids := range ret.FU.UnreadSnids {
if unreadSnids.SnId == args.UnreadSnid {
unreadSnids.UnreadNum++
had = true
}
}
if !had {
ret.FU.UnreadSnids = append(ret.FU.UnreadSnids, &model.FriendUnreadSnid{
SnId: args.UnreadSnid,
UnreadNum: 1,
})
}
err = cc.Update(bson.M{"snid": args.SnId}, bson.M{"$set": bson.M{"unreadsnids": ret.FU.UnreadSnids}})
}
if err != nil {
logger.Logger.Error("UpsertFriendUnread is err: ", err)
return err
}
return nil
}
func (svc *FriendUnreadSvc) UpdateFriendUnread(args *model.FriendUnreadByKey, ret *model.FriendUnreadRet) error {
cc := FriendUnreadCollection(args.Platform)
if cc == nil {
return FriendUnreadColError
}
err := cc.Find(bson.M{"snid": args.SnId}).One(&ret.FU)
if err != nil && err != mgo.ErrNotFound {
logger.Logger.Error("UpdateFriendUnread Find is err: ", err)
return err
}
if err == mgo.ErrNotFound {
err = cc.Insert(args.FU)
} else {
err = cc.Update(bson.M{"snid": args.SnId}, bson.M{"$set": bson.M{"unreadsnids": args.FU.UnreadSnids}})
}
if err != nil {
logger.Logger.Error("UpdateFriendUnread is err: ", err)
return err
}
return nil
}
func (svc *FriendUnreadSvc) QueryFriendUnreadByKey(args *model.FriendUnreadByKey, ret *model.FriendUnreadRet) error {
fc := FriendUnreadCollection(args.Platform)
if fc == nil {
return FriendUnreadColError
}
err := fc.Find(bson.M{"snid": args.SnId}).One(&ret.FU)
if err != nil && err != mgo.ErrNotFound {
logger.Logger.Error("QueryFriendUnreadByKey is err: ", err)
return err
}
return nil
}
func (svc *FriendUnreadSvc) DelFriendUnread(args *model.FriendUnreadByKey, ret *bool) error {
cc := FriendUnreadCollection(args.Platform)
if cc == nil {
return FriendUnreadColError
}
err := cc.Remove(bson.M{"snid": args.SnId})
if err != nil && err != mgo.ErrNotFound {
logger.Logger.Error("DelFriendUnread is err: ", err)
return err
}
return nil
}
var _FriendUnreadSvc = &FriendUnreadSvc{}
func init() {
rpc.Register(_FriendUnreadSvc)
}

View File

@ -0,0 +1,161 @@
package svc
import (
"errors"
"math"
"net/rpc"
"time"
"github.com/globalsign/mgo"
"github.com/globalsign/mgo/bson"
"mongo.games.com/game/dbproxy/mongo"
"mongo.games.com/game/model"
"mongo.games.com/goserver/core/logger"
)
func GameDetailedLogsCollection(plt string) *mongo.Collection {
s := mongo.MgoSessionMgrSington.GetPltMgoSession(plt, model.GameDetailedLogDBName)
if s != nil {
c_gamedetailed, first := s.DB().C(model.GameDetailedLogCollName)
if first {
c_gamedetailed.EnsureIndex(mgo.Index{Key: []string{"gameid"}, Background: true, Sparse: true})
c_gamedetailed.EnsureIndex(mgo.Index{Key: []string{"gamefreeid"}, Background: true, Sparse: true})
c_gamedetailed.EnsureIndex(mgo.Index{Key: []string{"logid"}, Background: true, Sparse: true})
c_gamedetailed.EnsureIndex(mgo.Index{Key: []string{"time"}, Background: true, Sparse: true})
c_gamedetailed.EnsureIndex(mgo.Index{Key: []string{"ts"}, Background: true, Sparse: true})
}
return c_gamedetailed
}
return nil
}
type GameDetailedSvc struct {
}
func (svc *GameDetailedSvc) InsertGameDetailedLog(log *model.GameDetailedLog, ret *bool) (err error) {
clog := GameDetailedLogsCollection(log.Platform)
if clog == nil {
logger.Logger.Error("svc.InsertGameDetailedLogs clog == nil")
return
}
err = clog.Insert(log)
if err != nil {
logger.Logger.Warn("svc.InsertGameDetailedLogs error:", err)
return
}
*ret = true
return
}
func (svc *GameDetailedSvc) RemoveGameDetailedLog(args *model.RemoveGameDetailedLogArg, ret *mgo.ChangeInfo) (err error) {
clog := GameDetailedLogsCollection(args.Plt)
if clog == nil {
logger.Logger.Error("svc.RemoveGameDetailedLog clog == nil")
return errors.New("clog == nil")
}
ret, err = clog.RemoveAll(bson.M{"time": bson.M{"$lt": args.Ts}})
if err != nil {
logger.Logger.Error("svc.RemoveGameDetailedLog is error", err)
return err
}
return nil
}
func (svc *GameDetailedSvc) GetAllGameDetailedLogsByTs(args *model.GameDetailedArg, ret *[]model.GameDetailedLog) error {
gdlc := GameDetailedLogsCollection(args.Plt)
if gdlc == nil {
return nil
}
var sql = bson.M{"time": bson.M{"$gte": time.Unix(args.StartTime, 0), "$lte": time.Unix(args.EndTime, 0)}}
err := gdlc.Find(sql).All(ret)
if err != nil {
logger.Logger.Error("svc.GetAllGameDetailedLogsByTs ")
return err
}
return nil
}
func (svc *GameDetailedSvc) GetAllGameDetailedLogsByGameIdAndTs(args *model.GameDetailedGameIdAndArg, ret *[]model.GameDetailedLog) error {
gdlc := GameDetailedLogsCollection(args.Plt)
if gdlc == nil {
return nil
}
var sql = bson.M{"gameid": args.Gameid}
err := gdlc.Find(sql).Sort("-ts").Limit(args.LimitNum).All(ret)
if err != nil {
logger.Logger.Error("svc.GetAllGameDetailedLogsByGameIdAndTs ")
return err
}
return nil
}
func (svc *GameDetailedSvc) GetPlayerHistory(args *model.GetPlayerHistoryArg, ret *model.GameDetailedLog) error {
gdlc := GameDetailedLogsCollection(args.Plt)
if gdlc == nil {
return nil
}
err := gdlc.Find(bson.M{"logid": args.LogId}).One(ret)
if err != nil {
logger.Logger.Error("svc.GetPlayerHistory is error", err)
}
return nil
}
func (svc *GameDetailedSvc) GetPlayerHistoryAPI(args *model.GetPlayerHistoryAPIArg, ret *model.GameDetailedLogRet) error {
logger.Logger.Tracef("GameDetailedSvc.GetPlayerHistoryAPI=====> args:%v", args)
gdlc := GameDetailedLogsCollection(args.Platform)
if gdlc == nil {
return nil
}
var sql []bson.M
//if args.SnId != 0 {
// sql = append(sql, bson.M{"snid": args.SnId})
//}
if args.Platform != "" {
sql = append(sql, bson.M{"platform": args.Platform})
}
if args.StartTime != 0 {
sql = append(sql, bson.M{"ts": bson.M{"$gte": args.StartTime, "$lte": args.EndTime}})
}
total, err := gdlc.Find(bson.M{"$and": sql}).Count()
if err != nil {
logger.Logger.Warn("svc.GetPlayerHistoryAPI Count error: ", err)
return err
}
gdt := model.GameDetailedLogType{}
if total == 0 {
gdt.PageNo = args.PageNo
gdt.PageSize = args.PageSize
return nil
}
gdt.PageSum = int(math.Ceil(float64(total) / float64(args.PageSize)))
if args.PageNo > gdt.PageSum {
args.PageNo = gdt.PageSum
}
if args.PageNo <= 0 {
args.PageNo = 1
}
limitNum := (args.PageNo - 1) * args.PageSize
var data []*model.GameDetailedLog
err = gdlc.Find(bson.M{"$and": sql}).Sort("-ts").Limit(args.PageSize).Skip(limitNum).All(&data)
if err != nil {
logger.Logger.Warn("svc.GetPlayerHistoryAPI error: ", err)
return err
}
gdt.PageNo = args.PageNo
gdt.PageSize = args.PageSize
gdt.Data = data
ret.Gplt = gdt
logger.Logger.Tracef("GameDetailedSvc.GetPlayerHistoryAPI=====> ret:%v", ret)
return nil
}
func init() {
rpc.Register(new(GameDetailedSvc))
}

View File

@ -0,0 +1,560 @@
package svc
import (
"errors"
"math"
"net/rpc"
"time"
"github.com/globalsign/mgo"
"github.com/globalsign/mgo/bson"
"mongo.games.com/game/common"
"mongo.games.com/game/dbproxy/mongo"
"mongo.games.com/game/model"
"mongo.games.com/goserver/core/logger"
)
func GamePlayerListLogsCollection(plt string) *mongo.Collection {
s := mongo.MgoSessionMgrSington.GetPltMgoSession(plt, model.GamePlayerListLogDBName)
if s != nil {
c_gameplayerlistlog, first := s.DB().C(model.GamePlayerListLogCollName)
if first {
c_gameplayerlistlog.EnsureIndex(mgo.Index{Key: []string{"snid"}, Background: true, Sparse: true})
c_gameplayerlistlog.EnsureIndex(mgo.Index{Key: []string{"channel"}, Background: true, Sparse: true})
c_gameplayerlistlog.EnsureIndex(mgo.Index{Key: []string{"promoter"}, Background: true, Sparse: true})
c_gameplayerlistlog.EnsureIndex(mgo.Index{Key: []string{"packagetag"}, Background: true, Sparse: true})
c_gameplayerlistlog.EnsureIndex(mgo.Index{Key: []string{"gameid"}, Background: true, Sparse: true})
c_gameplayerlistlog.EnsureIndex(mgo.Index{Key: []string{"clubid"}, Background: true, Sparse: true})
c_gameplayerlistlog.EnsureIndex(mgo.Index{Key: []string{"sceneid"}, Background: true, Sparse: true})
c_gameplayerlistlog.EnsureIndex(mgo.Index{Key: []string{"gamefreeid"}, Background: true, Sparse: true})
c_gameplayerlistlog.EnsureIndex(mgo.Index{Key: []string{"gamedetailedlogid"}, Background: true, Sparse: true})
c_gameplayerlistlog.EnsureIndex(mgo.Index{Key: []string{"ts"}, Background: true, Sparse: true})
c_gameplayerlistlog.EnsureIndex(mgo.Index{Key: []string{"time"}, Background: true, Sparse: true})
c_gameplayerlistlog.EnsureIndex(mgo.Index{Key: []string{"name"}, Background: true, Sparse: true})
}
return c_gameplayerlistlog
}
return nil
}
type GamePlayerListSvc struct {
}
func (svc *GamePlayerListSvc) InsertGamePlayerListLog(log *model.GamePlayerListLog, ret *bool) (err error) {
clog := GamePlayerListLogsCollection(log.Platform)
if clog == nil {
return
}
err = clog.Insert(log)
if err != nil {
logger.Logger.Warn("GamePlayerListSvc.InsertGamePlayerListLog error:", err)
return
}
*ret = true
return
}
func (svc *GamePlayerListSvc) GetPlayerCount(args *model.GamePlayerListArg, ret *model.GamePlayerListRet) error {
gdlc := GamePlayerListLogsCollection(args.Platform)
if gdlc == nil {
logger.Logger.Error("svc.GetPlayerCount gdlc == nil")
return nil
}
var sql []bson.M
sql = append(sql, bson.M{"snid": args.SnId, "ts": bson.M{"$gte": args.StartTime, "$lte": args.EndTime}})
sql = append(sql, bson.M{"clubid": args.ClubId})
sql = append(sql, bson.M{"platform": args.Platform})
gameTotal, err := gdlc.Find(bson.M{"$and": sql}).Count()
if err != nil {
logger.Logger.Error("svc.GetPlayerCount is error", err)
return err
}
if gameTotal == 0 {
return errors.New("gameTotal==0")
}
prt := new(model.GameTotalRecord)
prt.GameTotal = int32(gameTotal)
var tc []model.TotalCoin
err = gdlc.Pipe([]bson.M{
{"$match": bson.M{
"snid": args.SnId,
"clubid": args.ClubId,
"ts": bson.M{"$gte": args.StartTime, "$lte": args.EndTime},
}},
{"$group": bson.M{
"_id": bson.M{
"snid": "$snid",
"clubid": "$clubid",
},
"totalin": bson.M{"$sum": "$totalin"},
"totalout": bson.M{"$sum": "$totalout"},
"taxcoin": bson.M{"$sum": "$taxcoin"},
"clubpumpcoin": bson.M{"$sum": "$clubpumpcoin"},
}}}).AllowDiskUse().All(&tc)
if err != nil {
logger.Logger.Error("svc.GetPlayerCount AllowDiskUse is error", err)
return err
}
if len(tc) > 0 {
d := tc[0]
prt.GameTotalCoin = int32(d.TotalIn + d.TotalOut)
prt.GameWinTotal = int32(d.TotalOut - d.TotalIn - d.TaxCoin - d.ClubPumpCoin)
}
ret.Gtr = prt
return nil
}
func (svc *GamePlayerListSvc) GetPlayerListLog(args *model.GamePlayerListArg, ret *model.GamePlayerListRet) error {
gdlc := GamePlayerListLogsCollection(args.Platform)
if gdlc == nil {
return nil
}
var sql []bson.M
if args.SnId != 0 {
sql = append(sql, bson.M{"snid": args.SnId})
}
if args.Platform != "" {
sql = append(sql, bson.M{"platform": args.Platform})
}
if args.ClubId != 0 {
sql = append(sql, bson.M{"clubid": args.ClubId})
}
if args.StartTime != 0 {
sql = append(sql, bson.M{"ts": bson.M{"$gte": args.StartTime, "$lte": args.EndTime}})
}
total, err := gdlc.Find(bson.M{"$and": sql}).Count()
if err != nil {
logger.Logger.Warn("select log_gamedetailed error: ", err)
return err
}
gdt := model.GamePlayerListType{}
if total == 0 {
gdt.PageNo = args.PageNo
gdt.PageSize = args.PageSize
return nil
}
gdt.PageSum = int(math.Ceil(float64(total) / float64(args.PageSize)))
if args.PageNo > gdt.PageSum {
args.PageNo = gdt.PageSum
}
if args.PageNo <= 0 {
args.PageNo = 1
}
limitNum := (args.PageNo - 1) * args.PageSize
var data []*model.NeedGameRecord
err = gdlc.Find(bson.M{"$and": sql}).Sort("-ts").Limit(args.PageSize).Skip(limitNum).All(&data)
if err != nil {
logger.Logger.Warn("select log_gameplayerlistlog error: ", err)
return err
}
gdt.PageNo = args.PageNo
gdt.PageSize = args.PageSize
gdt.Data = data
ret.Gplt = gdt
return nil
}
func (svc *GamePlayerListSvc) GetPlayerListByHall(args *model.GamePlayerListArg, ret *model.GamePlayerListRet) error {
gdlc := GamePlayerListLogsCollection(args.Platform)
if gdlc == nil {
return nil
}
var sql []bson.M
if args.SnId != 0 {
sql = append(sql, bson.M{"snid": args.SnId})
}
if args.Platform != "" {
sql = append(sql, bson.M{"platform": args.Platform})
}
sql = append(sql, bson.M{"roomtype": args.RoomType})
if args.StartTime != 0 {
sql = append(sql, bson.M{"ts": bson.M{"$gte": args.StartTime, "$lte": args.EndTime}})
}
if args.GameClass <= 6 {
sql = append(sql, bson.M{"gameclass": args.GameClass})
}
total, err := gdlc.Find(bson.M{"$and": sql}).Count()
if err != nil {
logger.Logger.Warn("select log_gameplayerlistlog error: ", err)
return err
}
gdt := model.GamePlayerListType{}
if total == 0 {
gdt.PageNo = args.PageNo
gdt.PageSize = args.PageSize
return nil
}
gdt.PageSum = int(math.Ceil(float64(total) / float64(args.PageSize)))
if args.PageNo > gdt.PageSum {
args.PageNo = gdt.PageSum
}
if args.PageNo <= 0 {
args.PageNo = 1
}
limitNum := (args.PageNo - 1) * args.PageSize
var data []*model.NeedGameRecord
err = gdlc.Find(bson.M{"$and": sql}).Sort("-ts").Limit(args.PageSize).Skip(limitNum).All(&data)
if err != nil {
logger.Logger.Error("svc.GetPlayerListByHall error: ", err)
return err
}
gdt.PageNo = args.PageNo
gdt.PageSize = args.PageSize
gdt.Data = data
ret.Gplt = gdt
return nil
}
func (svc *GamePlayerListSvc) GetPlayerListByHallEx(args *model.GamePlayerListArg, ret *model.GamePlayerListRet) error {
logger.Logger.Tracef("GamePlayerListSvc.GetPlayerListByHallEx=====> args:%v", args)
gdlc := GamePlayerListLogsCollection(args.Platform)
if gdlc == nil {
return nil
}
var sql []bson.M
if args.SnId != 0 {
sql = append(sql, bson.M{"snid": args.SnId})
}
if args.Platform != "" {
sql = append(sql, bson.M{"platform": args.Platform})
}
sql = append(sql, bson.M{"roomtype": args.RoomType})
sql = append(sql, bson.M{"gameid": args.GameId})
if args.StartTime != 0 {
sql = append(sql, bson.M{"ts": bson.M{"$gte": args.StartTime, "$lte": args.EndTime}})
}
if args.GameClass <= 6 {
sql = append(sql, bson.M{"gameclass": args.GameClass})
}
total, err := gdlc.Find(bson.M{"$and": sql}).Count()
if err != nil {
logger.Logger.Warn("svc.GetPlayerListByHallEx Count error: ", err)
return err
}
gdt := model.GamePlayerListType{}
if total == 0 {
gdt.PageNo = args.PageNo
gdt.PageSize = args.PageSize
return nil
}
gdt.PageSum = int(math.Ceil(float64(total) / float64(args.PageSize)))
if args.PageNo > gdt.PageSum {
args.PageNo = gdt.PageSum
}
if args.PageNo <= 0 {
args.PageNo = 1
}
limitNum := (args.PageNo - 1) * args.PageSize
var data []*model.NeedGameRecord
err = gdlc.Find(bson.M{"$and": sql}).Sort("-ts").Limit(args.PageSize).Skip(limitNum).All(&data)
if err != nil {
logger.Logger.Warn("svc.GetPlayerListByHallEx error: ", err)
return err
}
gdt.PageNo = args.PageNo
gdt.PageSize = args.PageSize
gdt.Data = data
ret.Gplt = gdt
logger.Logger.Tracef("GamePlayerListSvc.GetPlayerListByHallEx=====> ret:%v", ret)
return nil
}
func (svc *GamePlayerListSvc) GetPlayerListByHallExAPI(args *model.GamePlayerListAPIArg, ret *model.GamePlayerListRet) error {
logger.Logger.Tracef("GamePlayerListSvc.GetPlayerListByHallExAPI=====> args:%v", args)
gdlc := GamePlayerListLogsCollection(args.Platform)
if gdlc == nil {
return nil
}
var sql []bson.M
if args.SnId != 0 {
sql = append(sql, bson.M{"snid": args.SnId})
}
if args.Platform != "" {
sql = append(sql, bson.M{"platform": args.Platform})
}
if args.StartTime != 0 {
sql = append(sql, bson.M{"ts": bson.M{"$gte": args.StartTime, "$lte": args.EndTime}}) // >= StartTime <= EndTime
}
total, err := gdlc.Find(bson.M{"$and": sql}).Count()
if err != nil {
logger.Logger.Warn("svc.GetPlayerListByHallExAPI Count error: ", err)
return err
}
gdt := model.GamePlayerListType{}
if total == 0 {
gdt.PageNo = args.PageNo
gdt.PageSize = args.PageSize
return nil
}
gdt.PageSum = int(math.Ceil(float64(total) / float64(args.PageSize)))
if args.PageNo > gdt.PageSum {
args.PageNo = gdt.PageSum
}
if args.PageNo <= 0 {
args.PageNo = 1
}
limitNum := (args.PageNo - 1) * args.PageSize
var data []*model.NeedGameRecord
err = gdlc.Find(bson.M{"$and": sql}).Sort("-ts").Limit(args.PageSize).Skip(limitNum).All(&data)
if err != nil {
logger.Logger.Warn("svc.GetPlayerListByHallEx error: ", err)
return err
}
for _, v := range data {
//v.Username = "aaa"
//continue
a, err := _AccountSvc.getAccountBySnId(args.Platform, v.SnId)
if err != nil {
logger.Logger.Warnf("model.getAccountBySnId(%v) failed:%v", args.SnId, err)
return err
}
v.Username = a.UserName
}
gdt.PageNo = args.PageNo
gdt.PageSize = args.PageSize
gdt.Data = data
ret.Gplt = gdt
logger.Logger.Tracef("GamePlayerListSvc.GetPlayerListByHallEx=====> ret:%v", ret)
return nil
}
func (svc *GamePlayerListSvc) GetPlayerExistListByTs(args *model.GamePlayerExistListArg, ret *[]int64) error {
logger.Logger.Tracef("GamePlayerListSvc.GetPlayerListByHallExAPI=====> args:%v", args)
gdlc := GamePlayerListLogsCollection(args.Platform)
if gdlc == nil {
return nil
}
t := time.Unix(args.StartTime, 0) // 客户端给的是明天的零点
for i := 0; i != args.DayNum; i++ {
var sql []bson.M
if args.SnId != 0 {
sql = append(sql, bson.M{"snid": args.SnId})
}
if args.Platform != "" {
sql = append(sql, bson.M{"platform": args.Platform})
}
//startTime := time.Date(t.Year(), t.Month(), t.Day()-i, 0, 0, 0, 0, t.Location()).Unix() // 今日凌晨
startTime := t.AddDate(0, 0, -i-1).Unix()
//endTime := time.Date(t.Year(), t.Month(), t.Day()-i+1, 0, 0, 0, 0, t.Location()).Unix() // 明日凌晨
endTime := t.AddDate(0, 0, -i).Unix()
sql = append(sql, bson.M{"ts": bson.M{"$gte": startTime, "$lt": endTime}}) // >= StartTime < EndTime
total, err := gdlc.Find(bson.M{"$and": sql}).Count()
if err != nil {
logger.Logger.Warn("svc.GetPlayerListByHallExAPI Count error: ", err)
return err
}
if total == 0 {
continue
}
// 当日不为空
*ret = append(*ret, startTime)
}
logger.Logger.Tracef("GamePlayerListSvc.GetPlayerListByHallEx=====> ret:%v", ret)
return nil
}
func (svc *GamePlayerListSvc) GetRecentGame(args *model.RecentGameReq, ret *model.RecentGameRet) error {
c := GamePlayerListLogsCollection(args.Platform)
if c == nil {
logger.Logger.Error("svc.GetRecentGame c == nil")
return nil
}
endTime := time.Now()
startTime := endTime.AddDate(0, 0, -3)
var tc []model.RecentGameIDs
err := c.Pipe([]bson.M{
{"$match": bson.M{
"snid": args.SnID,
"ts": bson.M{"$gte": startTime.Unix(), "$lte": endTime.Unix()},
}},
{"$group": bson.M{
"_id": bson.M{
"gameid": "$gameid",
},
"gameid": bson.M{"$first": "$gameid"},
"ts": bson.M{"$first": "$ts"},
}},
{
"$sort": bson.M{"ts": -1},
},
{
"$limit": 3,
},
}).AllowDiskUse().All(&tc)
if err != nil {
logger.Logger.Error("svc.GetRecentGame AllowDiskUse is error", err)
return err
}
if len(tc) > 0 {
for _, v := range tc {
ret.GameID = append(ret.GameID, v.GameID)
}
return nil
}
// 最近3天无游戏记录
err = c.Pipe([]bson.M{
{"$match": bson.M{"snid": args.SnID}},
{"$group": bson.M{
"_id": bson.M{
"gameid": "$gameid",
},
"gameid": bson.M{"$first": "$gameid"},
"ts": bson.M{"$first": "$ts"},
}},
{
"$sort": bson.M{"ts": -1},
},
{
"$limit": 3,
},
}).AllowDiskUse().All(&tc)
if err != nil {
logger.Logger.Error("svc.GetRecentGame AllowDiskUse is error", err)
return err
}
if len(tc) > 0 {
for _, v := range tc {
ret.GameID = append(ret.GameID, v.GameID)
}
}
return nil
}
func (svc *GamePlayerListSvc) GetWinCoinListTienlen(args *model.FindWinCoinListArgs, ret *model.FindWinCoinListReply) error {
c := GamePlayerListLogsCollection(args.Platform)
if c == nil {
logger.Logger.Error("svc.GetWinCoinListTienlen c == nil")
return nil
}
type M struct {
SnId int32
Coin int64
}
var tc []*M
err := c.Pipe([]bson.M{
{"$match": bson.M{
"gameid": bson.M{"$in": common.GetTienlenGameID()},
"ts": bson.M{"$gte": args.StartTs, "$lte": args.EndTs},
}},
{"$group": bson.M{
"_id": bson.M{
"snid": "$snid",
},
"snid": bson.M{"$first": "$snid"},
"coin": bson.M{"$sum": "$totalout"},
}},
{
"$sort": bson.M{"coin": -1},
},
{
"$limit": model.GameParamData.RankWinCoinMaxNum,
},
}).AllowDiskUse().All(&tc)
if err != nil {
logger.Logger.Error("svc.GetWinCoinListTienlen AllowDiskUse is error", err)
return err
}
u := PlayerDataCollection(args.Platform)
if u == nil {
return PlayerColError
}
for _, v := range tc {
d := &model.PlayerBaseInfo2{}
err = u.Find(bson.M{"snid": v.SnId}).Select(bson.M{"name": 1, "roles": 1}).One(d)
if err != nil {
logger.Logger.Warnf("GetWinCoinListTienlen Find player is error:%v", err)
}
roleId := common.DefaultRoleId
if d.Roles != nil && d.Roles.ModId != 0 {
roleId = int(d.Roles.ModId)
}
ret.List = append(ret.List, &model.WinCoinInfo{
SnId: v.SnId,
Name: d.Name,
Coin: v.Coin,
ModId: int32(roleId),
})
}
return nil
}
func (svc *GamePlayerListSvc) GetWinCoinTienlen(args *model.FindWinCoinArgs, ret *model.FindWinCoinReply) error {
c := GamePlayerListLogsCollection(args.Platform)
if c == nil {
logger.Logger.Error("svc.GetWinCoinTienlen c == nil")
return nil
}
type M struct {
Coin int64
}
var tc []*M
err := c.Pipe([]bson.M{
{"$match": bson.M{
"snid": args.SnId,
"gameid": bson.M{"$in": common.GetTienlenGameID()},
"ts": bson.M{"$gte": args.StartTs, "$lte": args.EndTs},
}},
{"$group": bson.M{
"_id": nil,
"coin": bson.M{"$sum": "$totalout"},
}},
}).AllowDiskUse().All(&tc)
if err != nil {
logger.Logger.Error("svc.GetWinCoinTienlen AllowDiskUse is error", err)
return err
}
u := PlayerDataCollection(args.Platform)
if u == nil {
return PlayerColError
}
d := &model.PlayerBaseInfo2{}
err = u.Find(bson.M{"snid": args.SnId}).Select(bson.M{"name": 1, "roles": 1}).One(d)
if err != nil {
logger.Logger.Warnf("GetWinCoinTienlen Find player is error:%v", err)
}
roleId := common.DefaultRoleId
if d.Roles != nil && d.Roles.ModId != 0 {
roleId = int(d.Roles.ModId)
}
ret.List = &model.WinCoinInfo{
SnId: args.SnId,
Name: d.Name,
ModId: int32(roleId),
}
if len(tc) > 0 {
ret.List.Coin = tc[0].Coin
}
return nil
}
func init() {
rpc.Register(new(GamePlayerListSvc))
}

315
dbproxy/svc/l_gradelog.go Normal file
View File

@ -0,0 +1,315 @@
package svc
import (
"errors"
"math"
"net/rpc"
"time"
"github.com/globalsign/mgo"
"github.com/globalsign/mgo/bson"
"mongo.games.com/game/dbproxy/mongo"
"mongo.games.com/game/model"
"mongo.games.com/goserver/core/logger"
)
var (
GradeLogErr = errors.New("log_grade open failed.")
BillGradeLogErr = errors.New("User billgradelog open failed.")
)
const GradeLogMaxLimitPerQuery = 100
func GradeLogsCollection(plt string) *mongo.Collection {
s := mongo.MgoSessionMgrSington.GetPltMgoSession(plt, model.GradeLogDBName)
if s != nil {
c, first := s.DB().C(model.GradeLogCollName)
if first {
c.EnsureIndex(mgo.Index{Key: []string{"channel"}, Background: true, Sparse: true})
c.EnsureIndex(mgo.Index{Key: []string{"promoter"}, Background: true, Sparse: true})
c.EnsureIndex(mgo.Index{Key: []string{"snid"}, Background: true, Sparse: true})
c.EnsureIndex(mgo.Index{Key: []string{"inviterid"}, Background: true, Sparse: true})
c.EnsureIndex(mgo.Index{Key: []string{"time"}, Background: true, Sparse: true})
}
return c
}
return nil
}
func InsertGradeLog(log *model.GradeLog) error {
err := GradeLogsCollection(log.Platform).Insert(log)
if err != nil {
logger.Logger.Info("InsertGradeLog error:", err)
return err
}
return nil
}
func InsertGradeLogs(logs ...*model.GradeLog) (err error) {
if len(logs) == 0 {
return nil
}
clog := GradeLogsCollection(logs[0].Platform)
if clog == nil {
return
}
switch len(logs) {
case 0:
return errors.New("no data")
case 1:
err = clog.Insert(logs[0])
default:
docs := make([]interface{}, 0, len(logs))
for _, log := range logs {
docs = append(docs, log)
}
err = clog.Insert(docs...)
}
if err != nil {
logger.Logger.Warn("InsertGradeLogs error:", err)
return
}
return
}
func UpdateGradeLogStatus(plt string, id bson.ObjectId, status int32) error {
glc := GradeLogsCollection(plt)
if glc == nil {
return GradeLogErr
}
return glc.UpdateId(id, bson.M{"$set": bson.M{"status": status}})
}
func GetGradeLogByPageAndSnId(plt string, snid, pageNo, pageSize int32) (ret *model.GradeLogLog) {
clog := GradeLogsCollection(plt)
if clog == nil {
return nil
}
selecter := bson.M{"snid": snid}
//selecter := bson.M{"snid": snid, "logtype": common.GainWay_GradeMatchGet}
total, err := clog.Find(selecter).Count()
if err != nil || total == 0 {
return nil
}
ret = new(model.GradeLogLog)
ret.PageNum = int32(math.Ceil(float64(total) / float64(pageSize)))
if pageNo > ret.PageNum {
pageNo = ret.PageNum
}
if pageNo <= 0 {
pageNo = 1
}
limitNum := (pageNo - 1) * pageSize
err = clog.Find(selecter).Skip(int(limitNum)).Limit(int(pageSize)).Sort("-time").All(&ret.Logs)
if err != nil {
logger.Logger.Error("Find gradelog data eror.", err)
return nil
}
ret.PageNo = pageNo
ret.PageSize = pageSize
return
}
func RemoveGradeLog(plt string, id bson.ObjectId) error {
glc := GradeLogsCollection(plt)
if glc == nil {
return GradeLogErr
}
return glc.RemoveId(id)
}
func GetGradeLogBySnidAndLessTs(plt string, id int32, ts time.Time) (ret []model.GradeLog, err error) {
err = GradeLogsCollection(plt).Find(bson.M{"snid": id, "time": bson.M{"$lt": ts}}).Sort("-time", "-count").Limit(GradeLogMaxLimitPerQuery).All(&ret)
return
}
func BillGradeLogsCollection(plt string) *mongo.Collection {
s := mongo.MgoSessionMgrSington.GetPltMgoSession(plt, model.BillGradeLogDBName)
if s != nil {
c, first := s.DB().C(model.BillGradeLogCollName)
if first {
c.EnsureIndex(mgo.Index{Key: []string{"snid"}, Background: true, Sparse: true})
c.EnsureIndex(mgo.Index{Key: []string{"logid"}, Background: true, Sparse: true})
c.EnsureIndex(mgo.Index{Key: []string{"timestamp"}, Background: true, Sparse: true})
c.EnsureIndex(mgo.Index{Key: []string{"time"}, Background: true, Sparse: true})
}
return c
}
return nil
}
func InsertBillGradeLogs(logs ...*model.BillGradeLog) (err error) {
cpay := BillGradeLogsCollection(logs[0].Platform)
if cpay == nil {
return
}
switch len(logs) {
case 0:
return errors.New("no data")
case 1:
err = cpay.Insert(logs[0])
default:
docs := make([]interface{}, 0, len(logs))
for _, log := range logs {
docs = append(docs, log)
}
err = cpay.Insert(docs...)
}
if err != nil {
logger.Logger.Warn("InsertBillGradeLogs error:", err)
return
}
return
}
func InsertBillGradeLog(log *model.BillGradeLog) error {
cpay := BillGradeLogsCollection(log.Platform)
if cpay == nil {
return BillGradeLogErr
}
return cpay.Insert(log)
}
func RemoveBillGradeLog(plt, logid string) error {
bglc := BillGradeLogsCollection(plt)
if bglc == nil {
return BillGradeLogErr
}
return bglc.Remove(bson.M{"logid": logid})
}
func UpdateBillGradeLogStatus(plt, logId string, status int32) error {
bglc := BillGradeLogsCollection(plt)
if bglc == nil {
return BillGradeLogErr
}
var conds []bson.M
conds = append(conds, bson.M{"status": bson.M{"$ne": 3}})
conds = append(conds, bson.M{"status": bson.M{"$ne": 9}})
sql := bson.M{"logid": logId,
"$and": conds,
}
return bglc.Update(sql, bson.M{"$set": bson.M{"status": status}})
}
func GetAllBillGradeLog(plt string, snid int32, ts int64) (ret []model.BillGradeLog, err error) {
err = BillGradeLogsCollection(plt).Find(bson.M{"snid": snid, "timestamp": bson.M{"$gt": ts}}).All(&ret)
return
}
func GetBillGradeLogByLogId(plt, logId string) (ret *model.BillGradeLog, err error) {
var conds []bson.M
conds = append(conds, bson.M{"status": bson.M{"$ne": 3}})
conds = append(conds, bson.M{"status": bson.M{"$ne": 9}})
sql := bson.M{"logid": logId,
"$and": conds,
}
err = BillGradeLogsCollection(plt).Find(sql).One(&ret)
return
}
func GetBillGradeLogByBillNo(plt string, snid int32, billNo int64) (*model.BillGradeLog, error) {
var log model.BillGradeLog
err := BillGradeLogsCollection(plt).Find(bson.M{"snid": snid, "billno": billNo}).One(&log)
return &log, err
}
type GradeLogSvc struct {
}
func (svc *GradeLogSvc) InsertGradeLog(args *model.GradeLog, ret *bool) (err error) {
err = InsertGradeLog(args)
if err == nil {
*ret = true
}
return
}
func (svc *GradeLogSvc) InsertGradeLogs(args []*model.GradeLog, ret *bool) (err error) {
err = InsertGradeLogs(args...)
if err == nil {
*ret = true
}
return
}
func (svc *GradeLogSvc) UpdateGradeLogStatus(args *model.UpdateGradeLogStatusArgs, ret *bool) (err error) {
err = UpdateGradeLogStatus(args.Plt, args.Id, args.Status)
if err == nil {
*ret = true
}
return
}
func (svc *GradeLogSvc) GetGradeLogByPageAndSnId(args *model.GetGradeLogByPageAndSnIdArgs, ret **model.GradeLogLog) (err error) {
*ret = GetGradeLogByPageAndSnId(args.Plt, args.SnId, args.PageNo, args.PageSize)
return
}
func (svc *GradeLogSvc) GetGradeLogBySnidAndLessTs(args *model.GetGradeLogBySnidAndLessTsArgs, ret *[]model.GradeLog) (err error) {
*ret, err = GetGradeLogBySnidAndLessTs(args.Plt, args.SnId, args.Ts)
return
}
func (svc *GradeLogSvc) RemoveGradeLog(args *model.RemoveGradeLogArgs, ret *bool) (err error) {
err = RemoveGradeLog(args.Plt, args.Id)
if err == nil {
*ret = true
}
return
}
type BillGradeLogSvc struct {
}
func (svc *BillGradeLogSvc) InsertBillGradeLogs(args []*model.BillGradeLog, ret *bool) (err error) {
err = InsertBillGradeLogs(args...)
if err == nil {
*ret = true
}
return
}
func (svc *BillGradeLogSvc) InsertBillGradeLog(args *model.BillGradeLog, ret *bool) (err error) {
err = InsertBillGradeLog(args)
if err == nil {
*ret = true
}
return
}
func (svc *BillGradeLogSvc) RemoveBillGradeLog(args *model.RemoveBillGradeLogArgs, ret *bool) (err error) {
err = RemoveBillGradeLog(args.Plt, args.LogId)
if err == nil {
*ret = true
}
return
}
func (svc *BillGradeLogSvc) UpdateBillGradeLogStatus(args *model.UpdateBillGradeLogStatusArgs, ret *bool) (err error) {
err = UpdateBillGradeLogStatus(args.Plt, args.LogId, args.Status)
if err == nil {
*ret = true
}
return
}
func (svc *BillGradeLogSvc) GetAllBillGradeLog(args *model.GetAllBillGradeLogArgs, ret *[]model.BillGradeLog) (err error) {
*ret, err = GetAllBillGradeLog(args.Plt, args.SnId, args.Ts)
return
}
func (svc *BillGradeLogSvc) GetBillGradeLogByLogId(args *model.GetBillGradeLogByLogIdArgs, ret **model.BillGradeLog) (err error) {
*ret, err = GetBillGradeLogByLogId(args.Plt, args.LogId)
return
}
func (svc *BillGradeLogSvc) GetBillGradeLogByBillNo(args *model.GetBillGradeLogByBillNoArgs, ret **model.BillGradeLog) (err error) {
*ret, err = GetBillGradeLogByBillNo(args.Plt, args.SnId, args.BillNo)
return
}
func init() {
rpc.Register(new(GradeLogSvc))
rpc.Register(new(BillGradeLogSvc))
}

Some files were not shown because too many files have changed in this diff Show More