Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d640be472 | ||
|
|
cc08e830d3 | ||
|
|
696f1bcbdb | ||
|
|
5c45ddb80b | ||
|
|
14de836089 | ||
|
|
1c4f804738 | ||
|
|
5fbe4d5dcf | ||
|
|
4963780a32 | ||
|
|
70ebaae3d2 | ||
|
|
9cd286fd92 |
@@ -1,7 +1,8 @@
|
||||
package aycache
|
||||
|
||||
import (
|
||||
"github.com/ayflying/utility_go/package/aycache/drive"
|
||||
"github.com/ayflying/utility_go/pkg/aycache/drive"
|
||||
drive2 "github.com/ayflying/utility_go/pkg/aycache/drive"
|
||||
"github.com/gogf/gf/v2/os/gcache"
|
||||
)
|
||||
|
||||
@@ -13,7 +14,7 @@ type Mod struct {
|
||||
// return pgk.Cache
|
||||
//}
|
||||
|
||||
// Deprecated: Use pgk.Cache()
|
||||
// Deprecated:弃用,改用 pgk.Cache()
|
||||
func New(_name ...string) gcache.Adapter {
|
||||
|
||||
var cacheAdapterObj gcache.Adapter
|
||||
@@ -23,11 +24,11 @@ func New(_name ...string) gcache.Adapter {
|
||||
}
|
||||
switch name {
|
||||
case "cache":
|
||||
cacheAdapterObj = NewAdapterMemory()
|
||||
cacheAdapterObj = drive2.NewAdapterMemory()
|
||||
case "redis":
|
||||
cacheAdapterObj = NewAdapterRedis()
|
||||
cacheAdapterObj = drive2.NewAdapterRedis()
|
||||
case "file":
|
||||
cacheAdapterObj = NewAdapterFile("runtime/cache")
|
||||
cacheAdapterObj = drive2.NewAdapterFile("runtime/cache")
|
||||
case "es":
|
||||
cacheAdapterObj = drive.NewAdapterElasticsearch([]string{"http://127.0.0.1:9200"})
|
||||
}
|
||||
@@ -2,7 +2,6 @@ package act{id}
|
||||
|
||||
import (
|
||||
service2 "github.com/ayflying/utility_go/service"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
)
|
||||
|
||||
type sAct{id} struct {
|
||||
@@ -14,7 +13,7 @@ func New() *sAct{id} {
|
||||
|
||||
var (
|
||||
ActId = {id}
|
||||
ctx = gctx.New()
|
||||
Name = ""
|
||||
)
|
||||
|
||||
type Data struct {
|
||||
|
||||
@@ -9,7 +9,7 @@ type s{name} struct {
|
||||
}
|
||||
|
||||
var (
|
||||
ctx = gctx.New()
|
||||
|
||||
)
|
||||
|
||||
func New() *s{name} {
|
||||
|
||||
@@ -62,9 +62,9 @@ func MiddlewareAdmin(r *ghttp.Request) {
|
||||
ip := r.GetClientIp()
|
||||
r.SetCtxVar("ip", ip)
|
||||
|
||||
get := r.Cookie.Get("uid")
|
||||
getUid := r.Cookie.Get("uid")
|
||||
|
||||
if get == nil {
|
||||
if getUid == nil {
|
||||
//调试模式允许不验证用户名
|
||||
debug, _ := g.Cfg().GetWithEnv(nil, "debug")
|
||||
if !debug.Bool() {
|
||||
@@ -82,7 +82,13 @@ func MiddlewareAdmin(r *ghttp.Request) {
|
||||
|
||||
}
|
||||
|
||||
uid := get.Int()
|
||||
uid := getUid.Int()
|
||||
|
||||
//获取所有请求的信息
|
||||
get := r.GetRequestMapStrStr()
|
||||
if _, ok := get["uid"]; ok {
|
||||
r.SetCtxVar("uid", get["uid"])
|
||||
}
|
||||
|
||||
r.Middleware.Next()
|
||||
|
||||
|
||||
14
go.mod
14
go.mod
@@ -10,14 +10,15 @@ require (
|
||||
github.com/go-pay/gopay v1.5.109
|
||||
github.com/go-pay/util v0.0.4
|
||||
github.com/goccy/go-json v0.10.4
|
||||
github.com/gogf/gf/contrib/config/apollo/v2 v2.8.3
|
||||
github.com/gogf/gf/v2 v2.8.3
|
||||
github.com/gogf/gf/contrib/config/apollo/v2 v2.9.0
|
||||
github.com/gogf/gf/v2 v2.9.0
|
||||
github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20241220152942-06eb5c6e8230
|
||||
github.com/minio/minio-go/v7 v7.0.85
|
||||
github.com/xuri/excelize/v2 v2.9.0
|
||||
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602
|
||||
google.golang.org/api v0.44.0
|
||||
google.golang.org/protobuf v1.26.0
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -68,10 +69,10 @@ require (
|
||||
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d // indirect
|
||||
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 // indirect
|
||||
go.opencensus.io v0.23.0 // indirect
|
||||
go.opentelemetry.io/otel v1.28.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.28.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.28.0 // indirect
|
||||
go.opentelemetry.io/otel v1.32.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.32.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.32.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.32.0 // indirect
|
||||
golang.org/x/crypto v0.33.0 // indirect
|
||||
golang.org/x/net v0.33.0 // indirect
|
||||
golang.org/x/sys v0.30.0 // indirect
|
||||
@@ -80,7 +81,6 @@ require (
|
||||
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect
|
||||
google.golang.org/grpc v1.38.0 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df // indirect
|
||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
|
||||
35
go.sum
35
go.sum
@@ -122,10 +122,10 @@ github.com/go-pay/xtime v0.0.2/go.mod h1:W1yRbJaSt4CSBcdAtLBQ8xajiN/Pl5hquGczUcU
|
||||
github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM=
|
||||
github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogf/gf/contrib/config/apollo/v2 v2.8.3 h1:KU51l3uaU7Mxq+FSoLjROyDERUGKCMo4qExxPEgA7KQ=
|
||||
github.com/gogf/gf/contrib/config/apollo/v2 v2.8.3/go.mod h1:Uo6f/Pr6zVHSbdP2Lj9iToEMuh/TzU/bE2E5SJlquEk=
|
||||
github.com/gogf/gf/v2 v2.8.3 h1:h9Px3lqJnnH6It0AqHRz4/1hx0JmvaSf1IvUir5x1rA=
|
||||
github.com/gogf/gf/v2 v2.8.3/go.mod h1:n++xPYGUUMadw6IygLEgGZqc6y6DRLrJKg5kqCrPLWY=
|
||||
github.com/gogf/gf/contrib/config/apollo/v2 v2.9.0 h1:BewnDc3gq2iqYzPH56FtOelmT9F9WcAm6nnlOVgw3J8=
|
||||
github.com/gogf/gf/contrib/config/apollo/v2 v2.9.0/go.mod h1:uNjaJcnMvMl7bkcoL0amxwcrOM+Q5XGADKKwKTY+8MY=
|
||||
github.com/gogf/gf/v2 v2.9.0 h1:semN5Q5qGjDQEv4620VzxcJzJlSD07gmyJ9Sy9zfbHk=
|
||||
github.com/gogf/gf/v2 v2.9.0/go.mod h1:sWGQw+pLILtuHmbOxoe0D+0DdaXxbleT57axOLH2vKI=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
@@ -300,8 +300,8 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
|
||||
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
@@ -329,8 +329,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/tevid/gohamcrest v1.1.1 h1:ou+xSqlIw1xfGTg1uq1nif/htZ2S3EzRqLm2BP+tYU0=
|
||||
@@ -357,14 +357,14 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||
go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
|
||||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||
go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo=
|
||||
go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4=
|
||||
go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q=
|
||||
go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s=
|
||||
go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw=
|
||||
go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg=
|
||||
go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g=
|
||||
go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
|
||||
go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
|
||||
go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg=
|
||||
go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M=
|
||||
go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8=
|
||||
go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4=
|
||||
go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU=
|
||||
go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM=
|
||||
go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||
@@ -699,8 +699,9 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"fmt"
|
||||
"github.com/ayflying/utility_go/internal/model/do"
|
||||
"github.com/ayflying/utility_go/internal/model/entity"
|
||||
"github.com/ayflying/utility_go/package/aycache"
|
||||
"github.com/ayflying/utility_go/pgk"
|
||||
"github.com/ayflying/utility_go/pkg"
|
||||
service2 "github.com/ayflying/utility_go/service"
|
||||
"github.com/ayflying/utility_go/tools"
|
||||
"github.com/gogf/gf/v2/container/gset"
|
||||
@@ -70,8 +70,8 @@ func (s *sGameAct) Info(uid int64, actId int) (data *g.Var, err error) {
|
||||
// 将查询到的活动信息保存到Redis缓存中
|
||||
_, err = g.Redis().Set(ctx, keyCache, data)
|
||||
|
||||
var ActUidUpdateTimeCacheKey = fmt.Sprintf("act:update:%d", uid)
|
||||
aycache.New("redis").Set(ctx, ActUidUpdateTimeCacheKey, uid, time.Hour*24*3)
|
||||
var CacheKey = fmt.Sprintf("act:update:%d", uid)
|
||||
pkg.Cache("redis").Set(ctx, CacheKey, uid, time.Hour*24*1)
|
||||
|
||||
return
|
||||
}
|
||||
@@ -137,29 +137,22 @@ func (s *sGameAct) Save(actId int) (err error) {
|
||||
}
|
||||
|
||||
cacheGet, _ := g.Redis().Get(ctx, cacheKey)
|
||||
//最后删除key
|
||||
delKey = append(delKey, cacheKey)
|
||||
|
||||
if uid == 0 {
|
||||
//跳过为空的用户缓存
|
||||
continue
|
||||
}
|
||||
if cacheGet.IsEmpty() {
|
||||
//空数据也不巴保存
|
||||
//空数据也不保存
|
||||
continue
|
||||
}
|
||||
|
||||
var ActUidUpdateTimeCacheKey = fmt.Sprintf("act:update:%d", uid)
|
||||
//如果有活跃,跳过持久化
|
||||
if getBool, _ := aycache.New("redis").Contains(ctx, ActUidUpdateTimeCacheKey); getBool {
|
||||
if getBool, _ := pkg.Cache("redis").Contains(ctx,
|
||||
fmt.Sprintf("act:update:%d", uid)); getBool {
|
||||
continue
|
||||
}
|
||||
|
||||
////如果1天没有活跃,跳过
|
||||
//user, _ := service.MemberUser().Info(uid)
|
||||
//if user.UpdatedAt.Seconds < gtime.Now().Add(consts.ActSaveTime).Unix() {
|
||||
// continue
|
||||
//}
|
||||
|
||||
//获取数据库数据
|
||||
var data *entity.GameAct
|
||||
// 从数据库中查询活动信息
|
||||
@@ -184,7 +177,8 @@ func (s *sGameAct) Save(actId int) (err error) {
|
||||
data.Action = actionData
|
||||
add = append(add, data)
|
||||
}
|
||||
|
||||
//最后删除key
|
||||
delKey = append(delKey, cacheKey)
|
||||
}
|
||||
|
||||
//批量写入数据库
|
||||
|
||||
125
internal/logic/gameKv/gameKv.go
Normal file
125
internal/logic/gameKv/gameKv.go
Normal file
@@ -0,0 +1,125 @@
|
||||
package gameKv
|
||||
|
||||
import (
|
||||
"github.com/ayflying/utility_go/service"
|
||||
"github.com/ayflying/utility_go/tools"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
ctx = gctx.New()
|
||||
Name = "game_kv"
|
||||
)
|
||||
|
||||
type sGameKv struct {
|
||||
Lock sync.Mutex
|
||||
}
|
||||
|
||||
func New() *sGameKv {
|
||||
return &sGameKv{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
service.RegisterGameKv(New())
|
||||
|
||||
//支付钩子
|
||||
//task.Task.Trigger(tasks.TaskType_PAY, service.GameKv().HookPay)
|
||||
//task.Task.Trigger(tasks.TaskType_WARDROBE_LEVEL, service.GameKv().HookLevelRwd)
|
||||
}
|
||||
|
||||
// SavesV1 方法
|
||||
//
|
||||
// @Description: 保存用户KV数据列表。
|
||||
// @receiver s: sGameKv的实例。
|
||||
// @return err: 错误信息,如果操作成功,则为nil。
|
||||
func (s *sGameKv) SavesV1() (err error) {
|
||||
// 从Redis列表中获取所有用户KV索引的键
|
||||
//keys, err := utils.RedisScan("user:kv:*")
|
||||
err = tools.Redis.RedisScanV2("user:kv:*", func(keys []string) (err error) {
|
||||
// 定义用于存储用户数据的结构体
|
||||
type ListData struct {
|
||||
Uid int64 `json:"uid"`
|
||||
Kv interface{} `json:"kv"`
|
||||
}
|
||||
var list []*ListData
|
||||
// 初始化列表,长度与keys数组一致
|
||||
list = make([]*ListData, 0)
|
||||
//需要删除的key
|
||||
var delKey []string
|
||||
// 遍历keys,获取每个用户的数据并填充到list中
|
||||
for _, cacheKey := range keys {
|
||||
//g.Log().Infof(ctx, "保存用户kv数据%v", v)
|
||||
//uid := v.Int64()
|
||||
//cacheKey = "user:kv:" + strconv.FormatInt(uid, 10)
|
||||
result := strings.Split(cacheKey, ":")
|
||||
var uid int64
|
||||
uid, err = strconv.ParseInt(result[2], 10, 64)
|
||||
if err != nil {
|
||||
g.Log().Error(ctx, err)
|
||||
g.Redis().Del(ctx, cacheKey)
|
||||
continue
|
||||
}
|
||||
|
||||
////如果1天没有活跃,跳过
|
||||
//user, _ := service.MemberUser().Info(uid)
|
||||
//if user.UpdatedAt.Seconds < gtime.Now().Add(consts.ActSaveTime).Unix() {
|
||||
// continue
|
||||
//}
|
||||
|
||||
get, _ := g.Redis().Get(ctx, cacheKey)
|
||||
var data interface{}
|
||||
get.Scan(&data)
|
||||
list = append(list, &ListData{
|
||||
Uid: int64(uid),
|
||||
Kv: data,
|
||||
})
|
||||
|
||||
delKey = append(delKey, cacheKey)
|
||||
}
|
||||
|
||||
// 将列表数据保存到数据库
|
||||
if len(list) > 0 {
|
||||
_, err2 := g.Model("game_kv").Batch(30).Data(list).Save()
|
||||
list = make([]*ListData, 0)
|
||||
if err2 != nil {
|
||||
g.Log().Error(ctx, err2)
|
||||
return
|
||||
}
|
||||
|
||||
//批量删除key
|
||||
for _, v := range delKey {
|
||||
_, err2 = g.Redis().Del(ctx, v)
|
||||
if err2 != nil {
|
||||
g.Log().Errorf(ctx, "删除存档错误:%v,err=%v", v, err2)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
delKey = make([]string, 0)
|
||||
|
||||
}
|
||||
if err != nil {
|
||||
g.Log().Error(ctx, "当前kv数据入库失败: %v", err)
|
||||
}
|
||||
|
||||
return
|
||||
})
|
||||
|
||||
//if err != nil {
|
||||
// return err
|
||||
//}
|
||||
////跳过
|
||||
//if len(keys) == 0 {
|
||||
// return
|
||||
//}
|
||||
////一次最多处理10w条
|
||||
//if len(keys) > 10000 {
|
||||
// keys = keys[:10000]
|
||||
//}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -6,6 +6,7 @@ package logic
|
||||
|
||||
import (
|
||||
_ "github.com/ayflying/utility_go/internal/logic/gameAct"
|
||||
_ "github.com/ayflying/utility_go/internal/logic/gameKv"
|
||||
_ "github.com/ayflying/utility_go/internal/logic/ip2region"
|
||||
_ "github.com/ayflying/utility_go/internal/logic/logData"
|
||||
_ "github.com/ayflying/utility_go/internal/logic/systemCron"
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
v1 "github.com/ayflying/utility_go/api/pgk/v1"
|
||||
"github.com/ayflying/utility_go/pgk/notice"
|
||||
"github.com/ayflying/utility_go/pkg/notice"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/gclient"
|
||||
)
|
||||
|
||||
@@ -1,134 +0,0 @@
|
||||
package aycache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/v2/container/gvar"
|
||||
"github.com/gogf/gf/v2/os/gcache"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type AdapterFile struct {
|
||||
FilePath string
|
||||
}
|
||||
|
||||
func (a AdapterFile) Set(ctx context.Context, key interface{}, value interface{}, duration time.Duration) error {
|
||||
//defer a.handleLruKey(ctx, key)
|
||||
//expireTime := a.getInternalExpire(duration)
|
||||
//a.data.Set(key, memoryDataItem{
|
||||
// a: value,
|
||||
// a: expireTime,
|
||||
//})
|
||||
//c.eventList.PushBack(&adapterMemoryEvent{
|
||||
// k: key,
|
||||
// e: expireTime,
|
||||
//})
|
||||
|
||||
arr := strings.Split(":", gconv.String(key))
|
||||
fileName := path.Join(arr...)
|
||||
return gfile.PutBytes(fileName, gconv.Bytes(value))
|
||||
}
|
||||
|
||||
func (a AdapterFile) SetMap(ctx context.Context, data map[interface{}]interface{}, duration time.Duration) error {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) SetIfNotExist(ctx context.Context, key interface{}, value interface{}, duration time.Duration) (ok bool, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) SetIfNotExistFunc(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (ok bool, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) SetIfNotExistFuncLock(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (ok bool, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) Get(ctx context.Context, key interface{}) (*gvar.Var, error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) GetOrSet(ctx context.Context, key interface{}, value interface{}, duration time.Duration) (result *gvar.Var, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) GetOrSetFunc(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (result *gvar.Var, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) GetOrSetFuncLock(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (result *gvar.Var, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) Contains(ctx context.Context, key interface{}) (bool, error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) Size(ctx context.Context) (size int, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) Data(ctx context.Context) (data map[interface{}]interface{}, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) Keys(ctx context.Context) (keys []interface{}, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) Values(ctx context.Context) (values []interface{}, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) Update(ctx context.Context, key interface{}, value interface{}) (oldValue *gvar.Var, exist bool, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) UpdateExpire(ctx context.Context, key interface{}, duration time.Duration) (oldDuration time.Duration, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) GetExpire(ctx context.Context, key interface{}) (time.Duration, error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) Remove(ctx context.Context, keys ...interface{}) (lastValue *gvar.Var, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) Clear(ctx context.Context) error {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterFile) Close(ctx context.Context) error {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func NewAdapterFile(filePath string) gcache.Adapter {
|
||||
return &AdapterFile{
|
||||
FilePath: filePath,
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package aycache
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/os/gcache"
|
||||
)
|
||||
|
||||
var adapterMemoryClient = gcache.New()
|
||||
|
||||
// NewAdapterMemory 创建并返回一个新的内存缓存对象。
|
||||
func NewAdapterMemory() gcache.Adapter {
|
||||
//if adapterMemoryClient == nil {
|
||||
// adapterMemoryClient = gcache.New()
|
||||
//}
|
||||
return adapterMemoryClient
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
package aycache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/v2/container/gvar"
|
||||
"github.com/gogf/gf/v2/database/gredis"
|
||||
"github.com/gogf/gf/v2/os/gcache"
|
||||
"time"
|
||||
)
|
||||
|
||||
// AdapterRedis is the gcache adapter implements using Redis server.
|
||||
type AdapterMemcached struct {
|
||||
//redis *gredis.Redis
|
||||
//client
|
||||
}
|
||||
|
||||
func (a AdapterMemcached) Set(ctx context.Context, key interface{}, value interface{}, duration time.Duration) error {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterMemcached) SetMap(ctx context.Context, data map[interface{}]interface{}, duration time.Duration) error {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterMemcached) SetIfNotExist(ctx context.Context, key interface{}, value interface{}, duration time.Duration) (ok bool, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterMemcached) SetIfNotExistFunc(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (ok bool, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterMemcached) SetIfNotExistFuncLock(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (ok bool, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterMemcached) Get(ctx context.Context, key interface{}) (*gvar.Var, error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterMemcached) GetOrSet(ctx context.Context, key interface{}, value interface{}, duration time.Duration) (result *gvar.Var, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterMemcached) GetOrSetFunc(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (result *gvar.Var, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterMemcached) GetOrSetFuncLock(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (result *gvar.Var, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterMemcached) Contains(ctx context.Context, key interface{}) (bool, error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterMemcached) Size(ctx context.Context) (size int, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterMemcached) Data(ctx context.Context) (data map[interface{}]interface{}, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterMemcached) Keys(ctx context.Context) (keys []interface{}, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterMemcached) Values(ctx context.Context) (values []interface{}, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterMemcached) Update(ctx context.Context, key interface{}, value interface{}) (oldValue *gvar.Var, exist bool, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterMemcached) UpdateExpire(ctx context.Context, key interface{}, duration time.Duration) (oldDuration time.Duration, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterMemcached) GetExpire(ctx context.Context, key interface{}) (time.Duration, error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterMemcached) Remove(ctx context.Context, keys ...interface{}) (lastValue *gvar.Var, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterMemcached) Clear(ctx context.Context) error {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterMemcached) Close(ctx context.Context) error {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
// NewAdapterRedis creates and returns a new memory cache object.
|
||||
func NewAdapterMemcached(redis *gredis.Redis) gcache.Adapter {
|
||||
return &AdapterMemcached{}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package aycache
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gcache"
|
||||
)
|
||||
|
||||
var adapterRedisClient gcache.Adapter
|
||||
var adapterRedisCache = gcache.New()
|
||||
|
||||
func NewAdapterRedis() gcache.Adapter {
|
||||
|
||||
if adapterRedisClient == nil {
|
||||
adapterRedisClient = gcache.NewAdapterRedis(g.Redis("default"))
|
||||
adapterRedisCache.SetAdapter(adapterRedisClient)
|
||||
}
|
||||
return adapterRedisCache
|
||||
}
|
||||
@@ -69,6 +69,10 @@ func (s *Excel) ExcelLoad(ctx context.Context, fileItem *FileItem, mainPath stri
|
||||
fileBytes := gfile.GetBytes(filepath)
|
||||
arr, _ := gjson.DecodeToJson(fileBytes)
|
||||
list := arr.Array()
|
||||
|
||||
//排除注释行
|
||||
list = s.RemoveComments(list, fileItem.Json)
|
||||
|
||||
//格式化item格式
|
||||
if len(fileItem.Items) > 0 {
|
||||
list = s.itemsFormat(list, fileItem.Items)
|
||||
@@ -98,105 +102,193 @@ func (s *Excel) ExcelLoad(ctx context.Context, fileItem *FileItem, mainPath stri
|
||||
return
|
||||
}
|
||||
|
||||
//排除配置中注释行
|
||||
func (s *Excel) RemoveComments(list []interface{}, json []string) []interface{} {
|
||||
var temp = make([]interface{}, 0)
|
||||
// 遍历列表中的每个元素
|
||||
for _, v2 := range list {
|
||||
var add = true
|
||||
// 遍历当前元素的每个键值对
|
||||
for _, v3 := range v2.(g.Map) {
|
||||
// 如果字符串中存在//则跳过不写入temp
|
||||
if gstr.Contains(gconv.String(v3), "//") {
|
||||
//delKey = append(delKey, k2)
|
||||
add = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if add {
|
||||
temp = append(temp, v2)
|
||||
}
|
||||
|
||||
}
|
||||
return temp
|
||||
}
|
||||
|
||||
// itemsFormat 格式化列表中的道具字段
|
||||
// 参数:
|
||||
// - list: 待处理的列表,包含多个元素,每个元素是一个 g.Map 类型
|
||||
// - Items: 包含需要处理的道具字段名称的切片
|
||||
// 返回值:
|
||||
// - 处理后的列表
|
||||
func (s *Excel) itemsFormat(list []interface{}, Items []string) []interface{} {
|
||||
// 遍历列表中的每个元素
|
||||
for k2, v2 := range list {
|
||||
// 遍历当前元素的每个键值对
|
||||
for k3, v3 := range v2.(g.Map) {
|
||||
// 检查当前键是否在需要处理的道具字段列表中
|
||||
if gstr.InArray(Items, k3) {
|
||||
// 检查当前值是否为字符串类型
|
||||
if _, ok := v3.(string); ok {
|
||||
// 如果是字符串类型,调用 Spilt2Item 函数将其转换为 [][]int64 类型,并更新到列表中
|
||||
list[k2].(g.Map)[k3] = Spilt2Item(v3.(string))
|
||||
} else {
|
||||
// 如果不是字符串类型,记录错误日志
|
||||
g.Log().Errorf(gctx.New(), "当前类型断言失败:%v,list=%v", v3, v2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 返回处理后的列表
|
||||
return list
|
||||
}
|
||||
|
||||
// itemsMapFormat 将列表中指定字段的道具信息转换为映射格式
|
||||
// 参数:
|
||||
// - list: 待处理的列表,包含多个元素,每个元素是一个 g.Map 类型
|
||||
// - Items: 包含需要处理的道具字段名称的切片
|
||||
// 返回值:
|
||||
// - 处理后的列表
|
||||
func (s *Excel) itemsMapFormat(list []interface{}, Items []string) []interface{} {
|
||||
// 遍历列表中的每个元素
|
||||
for k2, v2 := range list {
|
||||
// 遍历当前元素的每个键值对
|
||||
for k3, v3 := range v2.(g.Map) {
|
||||
// 检查当前键是否在需要处理的道具字段列表中
|
||||
if gstr.InArray(Items, k3) {
|
||||
// 检查当前值是否为字符串类型
|
||||
if _, ok := v3.(string); ok {
|
||||
// 如果是字符串类型,调用 Spilt2Item 函数将其转换为 [][]int64 类型
|
||||
get := Spilt2Item(v3.(string))
|
||||
// 调用 Items2Map 函数将 [][]int64 类型的数据转换为映射格式,并更新到列表中
|
||||
list[k2].(g.Map)[k3] = s.Items2Map(get)
|
||||
} else {
|
||||
// 如果不是字符串类型,记录错误日志
|
||||
g.Log().Errorf(gctx.New(), "当前类型断言失败:%v,list=%v", v3, v2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 返回处理后的列表
|
||||
return list
|
||||
}
|
||||
|
||||
// sliceFormat 格式化列表中指定字段为切片格式
|
||||
// 参数:
|
||||
// - list: 待处理的列表,包含多个元素,每个元素是一个 g.Map 类型
|
||||
// - Slice: 一个映射,键为需要处理的字段名,值为目标类型(如 "int", "int64", "float64")
|
||||
// 返回值:
|
||||
// - 处理后的列表
|
||||
func (s *Excel) sliceFormat(list []interface{}, Slice map[string]string) []interface{} {
|
||||
// 遍历 Slice 映射中的每个键值对
|
||||
for s1, s2 := range Slice {
|
||||
// 遍历列表中的每个元素
|
||||
for k2, v2 := range list {
|
||||
// 遍历当前元素的每个键值对
|
||||
for k3, v3 := range v2.(g.Map) {
|
||||
//判断是否存在
|
||||
// 判断当前键是否与 Slice 中的键匹配
|
||||
if s1 != k3 {
|
||||
// 不匹配则跳过当前循环
|
||||
continue
|
||||
}
|
||||
// 检查当前值是否为空字符串
|
||||
if gconv.String(v3) == "" {
|
||||
// 若为空,则将该字段设置为空字符串切片
|
||||
list[k2].(g.Map)[k3] = []string{}
|
||||
// 跳过当前循环
|
||||
continue
|
||||
}
|
||||
// 用于存储分割后的字符串切片
|
||||
var parts []string
|
||||
//断言是否成功
|
||||
// 断言当前值是否为字符串类型
|
||||
if get, ok := v3.(string); !ok {
|
||||
//g.Log().Errorf(gctx.New(), "当前类型断言失败:%v", v3)
|
||||
// 若断言失败,将当前值转换为字符串并作为唯一元素存入 parts
|
||||
parts = []string{gconv.String(v3)}
|
||||
|
||||
} else {
|
||||
// 若为字符串类型,将字符串中的特殊字符替换为 "|"
|
||||
for _, v := range shadiao {
|
||||
get = strings.ReplaceAll(get, v, "|")
|
||||
}
|
||||
parts = strings.Split(get, "|") // 分割字符串
|
||||
// 按 "|" 分割字符串
|
||||
parts = strings.Split(get, "|")
|
||||
}
|
||||
|
||||
// 根据 Slice 映射中的值进行类型转换
|
||||
switch s2 {
|
||||
case "int":
|
||||
// 创建一个长度为 parts 的 int 切片
|
||||
var temp = make([]int, len(parts))
|
||||
// 遍历 parts 切片,将每个元素转换为 int 类型
|
||||
for k, v := range parts {
|
||||
temp[k], _ = strconv.Atoi(v)
|
||||
}
|
||||
// 将转换后的切片存入列表中
|
||||
list[k2].(g.Map)[k3] = temp
|
||||
case "int64":
|
||||
// 创建一个长度为 parts 的 int64 切片
|
||||
var temp = make([]int64, len(parts))
|
||||
// 遍历 parts 切片,将每个元素转换为 int64 类型
|
||||
for k, v := range parts {
|
||||
temp[k], _ = strconv.ParseInt(v, 10, 64)
|
||||
}
|
||||
case "float64":
|
||||
// 创建一个长度为 parts 的 float64 切片
|
||||
var temp = make([]float64, len(parts))
|
||||
// 遍历 parts 切片,将每个元素转换为 float64 类型
|
||||
for k, v := range parts {
|
||||
temp[k], _ = strconv.ParseFloat(v, 64)
|
||||
}
|
||||
// 将转换后的切片存入列表中
|
||||
list[k2].(g.Map)[k3] = temp
|
||||
default:
|
||||
// 若未匹配到指定类型,直接将 parts 存入列表中
|
||||
list[k2].(g.Map)[k3] = parts
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 返回处理后的列表
|
||||
return list
|
||||
}
|
||||
|
||||
// jsonFormat 将列表中指定字段的 JSON 字符串解析为 Go 数据结构
|
||||
// 参数:
|
||||
// - list: 待处理的列表,包含多个元素,每个元素是一个 g.Map 类型
|
||||
// - Items: 包含需要处理的 JSON 字段名称的切片
|
||||
// 返回值:
|
||||
// - 处理后的列表
|
||||
func (s *Excel) jsonFormat(list []interface{}, Items []string) []interface{} {
|
||||
// 遍历列表中的每个元素
|
||||
for k2, v2 := range list {
|
||||
// 遍历当前元素的每个键值对
|
||||
for k3, v3 := range v2.(g.Map) {
|
||||
// 检查当前键是否在需要处理的 JSON 字段列表中
|
||||
if gstr.InArray(Items, k3) {
|
||||
// 检查当前值是否为字符串类型
|
||||
if _, ok := v3.(string); ok {
|
||||
// 用于存储解析后的 JSON 数据
|
||||
var get interface{}
|
||||
// 将字符串解析为 JSON 数据
|
||||
json.Unmarshal([]byte(v3.(string)), &get)
|
||||
// 将解析后的 JSON 数据更新到列表中
|
||||
list[k2].(g.Map)[k3] = get
|
||||
} else {
|
||||
// 如果不是字符串类型,记录错误日志
|
||||
g.Log().Errorf(gctx.New(), "当前类型断言失败:%v,list=%v", v3, v2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 返回处理后的列表
|
||||
return list
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//Deprecated: 使用新的 pkg.Pay()
|
||||
package pay
|
||||
|
||||
import (
|
||||
@@ -27,6 +28,7 @@ type WechatPay struct {
|
||||
PrivateKey string
|
||||
}
|
||||
|
||||
// Deprecated: pkg.Pay().Wechat()
|
||||
func Wechat() *WechatPay {
|
||||
var pay = &WechatPay{}
|
||||
var err error
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
package drive
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/v2/container/gvar"
|
||||
"github.com/gogf/gf/v2/os/gcache"
|
||||
"time"
|
||||
)
|
||||
|
||||
type AdapterElasticsearch struct {
|
||||
//FilePath string
|
||||
Addresses []string
|
||||
}
|
||||
|
||||
func (a AdapterElasticsearch) Set(ctx context.Context, key interface{}, value interface{}, duration time.Duration) error {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterElasticsearch) SetMap(ctx context.Context, data map[interface{}]interface{}, duration time.Duration) error {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterElasticsearch) SetIfNotExist(ctx context.Context, key interface{}, value interface{}, duration time.Duration) (ok bool, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterElasticsearch) SetIfNotExistFunc(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (ok bool, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterElasticsearch) SetIfNotExistFuncLock(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (ok bool, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterElasticsearch) Get(ctx context.Context, key interface{}) (*gvar.Var, error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterElasticsearch) GetOrSet(ctx context.Context, key interface{}, value interface{}, duration time.Duration) (result *gvar.Var, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterElasticsearch) GetOrSetFunc(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (result *gvar.Var, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterElasticsearch) GetOrSetFuncLock(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (result *gvar.Var, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterElasticsearch) Contains(ctx context.Context, key interface{}) (bool, error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterElasticsearch) Size(ctx context.Context) (size int, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterElasticsearch) Data(ctx context.Context) (data map[interface{}]interface{}, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterElasticsearch) Keys(ctx context.Context) (keys []interface{}, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterElasticsearch) Values(ctx context.Context) (values []interface{}, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterElasticsearch) Update(ctx context.Context, key interface{}, value interface{}) (oldValue *gvar.Var, exist bool, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterElasticsearch) UpdateExpire(ctx context.Context, key interface{}, duration time.Duration) (oldDuration time.Duration, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterElasticsearch) GetExpire(ctx context.Context, key interface{}) (time.Duration, error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterElasticsearch) Remove(ctx context.Context, keys ...interface{}) (lastValue *gvar.Var, err error) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterElasticsearch) Clear(ctx context.Context) error {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (a AdapterElasticsearch) Close(ctx context.Context) error {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func NewAdapterElasticsearch(addresses []string) gcache.Adapter {
|
||||
return &AdapterElasticsearch{
|
||||
Addresses: addresses,
|
||||
}
|
||||
}
|
||||
12
pgk/pgk.go
12
pgk/pgk.go
@@ -2,29 +2,33 @@ package pgk
|
||||
|
||||
import (
|
||||
v1 "github.com/ayflying/utility_go/api/pgk/v1"
|
||||
"github.com/ayflying/utility_go/pgk/aycache"
|
||||
"github.com/ayflying/utility_go/pgk/notice"
|
||||
"github.com/ayflying/utility_go/pgk/rank"
|
||||
"github.com/ayflying/utility_go/pgk/s3"
|
||||
"github.com/ayflying/utility_go/pkg/aycache"
|
||||
"github.com/ayflying/utility_go/pkg/notice"
|
||||
"github.com/ayflying/utility_go/pkg/rank"
|
||||
"github.com/ayflying/utility_go/pkg/s3"
|
||||
"github.com/gogf/gf/v2/os/gcache"
|
||||
)
|
||||
|
||||
var ()
|
||||
|
||||
// 统一调用
|
||||
// Deprecated: 请使用 pkg.Notice() 方法替代。
|
||||
func Notice(typ v1.NoticeType, host string) notice.MessageV1 {
|
||||
return notice.New(typ, host)
|
||||
}
|
||||
|
||||
// 统一调用cache
|
||||
// Deprecated: 请使用 pkg.Cache() 方法替代。
|
||||
func Cache(_name ...string) gcache.Adapter {
|
||||
return aycache.New(_name...)
|
||||
}
|
||||
|
||||
// Deprecated: 请使用 pkg.S3() 方法替代。
|
||||
func S3(_name ...string) *s3.Mod {
|
||||
return s3.New(_name...)
|
||||
}
|
||||
|
||||
// Deprecated: 请使用 pkg.Rank() 方法替代。
|
||||
func Rank() *rank.Mod {
|
||||
return rank.New()
|
||||
}
|
||||
|
||||
@@ -46,6 +46,8 @@ func (s *Mod) Load() {
|
||||
// 返回值:
|
||||
//
|
||||
// *F64CountRank: 返回一个指向新创建的F64CountRank实例的指针
|
||||
|
||||
// Deprecated: pgk.Rnak().CreateF64CountRank("赛季")
|
||||
func (s *Mod) CreateF64CountRank(name string) *F64CountRank {
|
||||
// 初始化F64CountRank实例的name和updateTs字段
|
||||
// name字段用于标识排行榜的名称,格式为"rank:<name>:score"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package aycache
|
||||
|
||||
import (
|
||||
"github.com/ayflying/utility_go/package/aycache/drive"
|
||||
drive2 "github.com/ayflying/utility_go/pgk/aycache/drive"
|
||||
"github.com/ayflying/utility_go/pkg/aycache/drive"
|
||||
drive2 "github.com/ayflying/utility_go/pkg/aycache/drive"
|
||||
"github.com/gogf/gf/v2/os/gcache"
|
||||
)
|
||||
|
||||
@@ -2,7 +2,7 @@ package notice
|
||||
|
||||
import (
|
||||
v1 "github.com/ayflying/utility_go/api/pgk/v1"
|
||||
"github.com/ayflying/utility_go/pgk/notice/drive"
|
||||
"github.com/ayflying/utility_go/pkg/notice/drive"
|
||||
)
|
||||
|
||||
type MessageV1 interface {
|
||||
35
pkg/pkg.go
Normal file
35
pkg/pkg.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package pkg
|
||||
|
||||
import (
|
||||
v1 "github.com/ayflying/utility_go/api/pgk/v1"
|
||||
"github.com/ayflying/utility_go/pkg/aycache"
|
||||
"github.com/ayflying/utility_go/pkg/notice"
|
||||
"github.com/ayflying/utility_go/pkg/rank"
|
||||
"github.com/ayflying/utility_go/pkg/s3"
|
||||
"github.com/ayflying/utility_go/pkg/websocket"
|
||||
"github.com/gogf/gf/v2/os/gcache"
|
||||
)
|
||||
|
||||
var ()
|
||||
|
||||
// 统一调用
|
||||
func Notice(typ v1.NoticeType, host string) notice.MessageV1 {
|
||||
return notice.New(typ, host)
|
||||
}
|
||||
|
||||
// 统一调用cache
|
||||
func Cache(_name ...string) gcache.Adapter {
|
||||
return aycache.New(_name...)
|
||||
}
|
||||
|
||||
func S3(_name ...string) *s3.Mod {
|
||||
return s3.New(_name...)
|
||||
}
|
||||
|
||||
func Rank() *rank.Mod {
|
||||
return rank.New()
|
||||
}
|
||||
|
||||
func Websocket() *websocket.SocketV1 {
|
||||
return websocket.NewV1()
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package rank
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
v1 "github.com/ayflying/utility_go/api/pgk/v1"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/database/gredis"
|
||||
@@ -21,14 +22,14 @@ type F64CountRank struct {
|
||||
updateTs string // 更新时间key
|
||||
}
|
||||
|
||||
type RankData struct {
|
||||
Id int64
|
||||
Score int64
|
||||
Rank int32
|
||||
UpdateTs int64
|
||||
}
|
||||
//
|
||||
//type RankData struct {
|
||||
// Id int64
|
||||
// Score int64
|
||||
// Rank int32
|
||||
// UpdateTs int64
|
||||
//}
|
||||
|
||||
// Deprecated:Use pgk.Rank()
|
||||
func New() *Mod {
|
||||
return &Mod{}
|
||||
}
|
||||
@@ -45,8 +46,6 @@ func (s *Mod) Load() {
|
||||
// 返回值:
|
||||
//
|
||||
// *F64CountRank: 返回一个指向新创建的F64CountRank实例的指针
|
||||
//
|
||||
// Deprecated:Use pgk.Rank().CreateF64CountRank(fmt.Sprintf("rank:%v", 1))
|
||||
func (s *Mod) CreateF64CountRank(name string) *F64CountRank {
|
||||
// 初始化F64CountRank实例的name和updateTs字段
|
||||
// name字段用于标识排行榜的名称,格式为"rank:<name>:score"
|
||||
@@ -321,7 +320,7 @@ func (r *F64CountRank) UpdateScore(id int64, score int64) (err error) {
|
||||
//
|
||||
// list - 排名信息列表
|
||||
// err - 错误信息,如果执行过程中遇到错误
|
||||
func (r *F64CountRank) GetRankInfosNotTs(offset, count int) (list []*RankData, err error) {
|
||||
func (r *F64CountRank) GetRankInfosNotTs(offset, count int) (list []*v1.RankData, err error) {
|
||||
// 初始化存储成员ID的切片
|
||||
var members []int64
|
||||
|
||||
@@ -341,7 +340,7 @@ func (r *F64CountRank) GetRankInfosNotTs(offset, count int) (list []*RankData, e
|
||||
}
|
||||
|
||||
// 根据获取的成员ID数量初始化排名信息列表
|
||||
list = make([]*RankData, len(members))
|
||||
list = make([]*v1.RankData, len(members))
|
||||
for i := range members {
|
||||
// 获取当前成员ID
|
||||
id := members[i]
|
||||
@@ -361,9 +360,9 @@ func (r *F64CountRank) GetRankInfosNotTs(offset, count int) (list []*RankData, e
|
||||
// 返回值:
|
||||
//
|
||||
// rankInfo - 包含id的分数和排名信息的指针,如果没有找到,则返回nil
|
||||
func (r *F64CountRank) GetIdRankNotTs(id int64) (rankInfo *RankData) {
|
||||
func (r *F64CountRank) GetIdRankNotTs(id int64) (rankInfo *v1.RankData) {
|
||||
// 初始化rankInfo结构体,设置id,其他字段将通过查询填充
|
||||
rankInfo = &RankData{Id: id}
|
||||
rankInfo = &v1.RankData{Id: id}
|
||||
|
||||
// 查询有序集合中指定id的分数
|
||||
score, err := g.Redis().ZScore(ctx, r.name, id)
|
||||
16
pkg/websocket/registerer.go
Normal file
16
pkg/websocket/registerer.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package websocket
|
||||
|
||||
import "context"
|
||||
|
||||
// 定义一个处理方法的类型
|
||||
type Handler func(ctx context.Context, req any) (err error)
|
||||
|
||||
// 路由器的处理映射
|
||||
var (
|
||||
handlers = make(map[int]Handler)
|
||||
)
|
||||
|
||||
// 注册方法,将某个消息路由器ID和对应的处理方法关联起来
|
||||
func (s *SocketV1) RegisterRouter(cmd int, handler Handler) {
|
||||
handlers[cmd] = handler
|
||||
}
|
||||
179
pkg/websocket/socket_new.go
Normal file
179
pkg/websocket/socket_new.go
Normal file
@@ -0,0 +1,179 @@
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/v2/container/gmap"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/gogf/gf/v2/os/glog"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"github.com/google/uuid"
|
||||
"github.com/gorilla/websocket"
|
||||
"sync"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
)
|
||||
|
||||
type SocketV1 struct{}
|
||||
|
||||
var (
|
||||
//ctx = gctx.New()
|
||||
//Conn map[uuid.UUID]*WebsocketData
|
||||
lock sync.Mutex
|
||||
|
||||
m = gmap.New(true)
|
||||
)
|
||||
|
||||
type WebsocketData struct {
|
||||
Ws *websocket.Conn
|
||||
Uuid uuid.UUID
|
||||
Uid int64
|
||||
Ctx context.Context
|
||||
}
|
||||
|
||||
func NewV1() *SocketV1 {
|
||||
return &SocketV1{}
|
||||
}
|
||||
|
||||
type SocketInterface interface {
|
||||
OnConnect(*websocket.Conn)
|
||||
OnMessage(*WebsocketData, []byte, int)
|
||||
Send(uuid.UUID, []byte) (err error)
|
||||
SendAll(data []byte)
|
||||
OnClose(conn *websocket.Conn)
|
||||
}
|
||||
|
||||
func (s *SocketV1) Load(serv *ghttp.Server, prefix string) {
|
||||
//websocket服务启动
|
||||
serv.Group(prefix, func(group *ghttp.RouterGroup) {
|
||||
|
||||
var websocketCfg = websocket.Upgrader{
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 1024,
|
||||
}
|
||||
group.Bind(
|
||||
func(r *ghttp.Request) {
|
||||
ctx := r.Context()
|
||||
ws, err := websocketCfg.Upgrade(r.Response.Writer, r.Request, nil)
|
||||
if err != nil {
|
||||
glog.Error(ctx, err)
|
||||
r.Exit()
|
||||
}
|
||||
|
||||
//ws联机触发器
|
||||
NewV1().OnConnect(ctx, ws)
|
||||
},
|
||||
)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
// OnConnect
|
||||
//
|
||||
// @Description:
|
||||
// @receiver s
|
||||
// @param conn
|
||||
func (s *SocketV1) OnConnect(ctx context.Context, conn *websocket.Conn) {
|
||||
//lock.Lock()
|
||||
//defer lock.Unlock()
|
||||
|
||||
defer conn.Close()
|
||||
id, _ := uuid.NewUUID()
|
||||
ip := conn.RemoteAddr().String()
|
||||
|
||||
data := &WebsocketData{
|
||||
Uuid: id,
|
||||
Ws: conn,
|
||||
Ctx: ctx,
|
||||
}
|
||||
m.Set(id, data)
|
||||
|
||||
//defer delete(Conn, id)
|
||||
|
||||
//to := fmt.Sprintf("创建连接:%v,ip=%v", id, ip)
|
||||
//s.Send(id, []byte(to))
|
||||
|
||||
for {
|
||||
//进入当前连接线程拥堵
|
||||
msgType, msg, err := conn.ReadMessage()
|
||||
if err != nil {
|
||||
//客户端断开返回错误,断开当前连接
|
||||
break
|
||||
}
|
||||
s.OnMessage(m.Get(id).(*WebsocketData), msg, msgType)
|
||||
}
|
||||
//关闭连接触发
|
||||
s.OnClose(id, conn)
|
||||
g.Log().Debugf(ctx, "断开连接:uuid=%v,ip=%v", id, ip)
|
||||
}
|
||||
|
||||
// OnMessage
|
||||
//
|
||||
// @Description:
|
||||
// @receiver s
|
||||
// @param msg
|
||||
// @param msgType
|
||||
func (s *SocketV1) OnMessage(conn *WebsocketData, req []byte, msgType int) {
|
||||
//g.Log().Debugf(ctx, "收到消息:%v,type=%v,conn=%v", string(req), msgType, conn)
|
||||
//s.Send(conn.Uuid, msg)
|
||||
//s.SendAll(msg)
|
||||
msgStr := string(req)
|
||||
msg := msgStr[8:]
|
||||
cmd := gconv.Int(msgStr[:8])
|
||||
//GetRouter(cmd, conn.Uid, msg)
|
||||
handler, exist := handlers[cmd]
|
||||
if exist {
|
||||
//匹配上路由器
|
||||
handler(conn.Ctx, msg)
|
||||
} else {
|
||||
//fmt.Println("未注册的路由器ID:", cmd)
|
||||
s.Send(conn.Uuid, []byte("未注册的协议号:"+msgStr[:8]))
|
||||
s.OnClose(conn.Uuid, conn.Ws)
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Send
|
||||
//
|
||||
// @Description:
|
||||
// @receiver s
|
||||
// @param uid
|
||||
// @param data
|
||||
// @return err
|
||||
func (s *SocketV1) Send(id uuid.UUID, data []byte) (err error) {
|
||||
if !m.Contains(id) {
|
||||
return
|
||||
}
|
||||
|
||||
conn := m.Get(id).(*WebsocketData)
|
||||
conn.Ws.WriteMessage(1, data)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 批量发送
|
||||
func (s *SocketV1) SendAll(data []byte) {
|
||||
m.Iterator(func(k interface{}, v interface{}) bool {
|
||||
//fmt.Printf("%v:%v ", k, v)
|
||||
conn := v.(*WebsocketData)
|
||||
conn.Ws.WriteMessage(1, data)
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
// OnClose
|
||||
//
|
||||
// @Description:
|
||||
// @receiver s
|
||||
// @param conn
|
||||
func (s *SocketV1) OnClose(id uuid.UUID, conn *websocket.Conn) {
|
||||
// 在此处编写断开连接后的处理逻辑
|
||||
g.Log().Debugf(gctx.New(), "WebSocket connection from %s has been closed.", conn.RemoteAddr())
|
||||
|
||||
// 可能的后续操作:
|
||||
// 1. 更新连接状态或从连接池移除
|
||||
// 2. 发送通知或清理关联资源
|
||||
// 3. 执行特定于业务的断开处理
|
||||
m.Remove(id)
|
||||
conn.Close()
|
||||
}
|
||||
32
service/game_kv.go
Normal file
32
service/game_kv.go
Normal file
@@ -0,0 +1,32 @@
|
||||
// ================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// You can delete these comments if you wish manually maintain this interface file.
|
||||
// ================================================================================
|
||||
|
||||
package service
|
||||
|
||||
type (
|
||||
IGameKv interface {
|
||||
// SavesV1 方法
|
||||
//
|
||||
// @Description: 保存用户KV数据列表。
|
||||
// @receiver s: sGameKv的实例。
|
||||
// @return err: 错误信息,如果操作成功,则为nil。
|
||||
SavesV1() (err error)
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
localGameKv IGameKv
|
||||
)
|
||||
|
||||
func GameKv() IGameKv {
|
||||
if localGameKv == nil {
|
||||
panic("implement not found for interface IGameKv, forgot register?")
|
||||
}
|
||||
return localGameKv
|
||||
}
|
||||
|
||||
func RegisterGameKv(i IGameKv) {
|
||||
localGameKv = i
|
||||
}
|
||||
52
tools/random.go
Normal file
52
tools/random.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
Rand *randMod
|
||||
)
|
||||
|
||||
type randMod struct {
|
||||
}
|
||||
|
||||
// RandomAll 按权重随机选取 N 个不重复的元素
|
||||
func (m *randMod) RandomAll(data map[int]int, n int) []int {
|
||||
if n > len(data) {
|
||||
n = len(data)
|
||||
}
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
// 复制权重映射,避免修改原始数据
|
||||
remainingWeights := make(map[int]int)
|
||||
for k, v := range data {
|
||||
remainingWeights[k] = v
|
||||
}
|
||||
result := make([]int, 0, n)
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
totalWeight := 0
|
||||
// 计算剩余元素的总权重
|
||||
for _, weight := range remainingWeights {
|
||||
totalWeight += weight
|
||||
}
|
||||
if totalWeight == 0 {
|
||||
break
|
||||
}
|
||||
// 生成一个 0 到总权重之间的随机数
|
||||
randomNum := rand.Intn(totalWeight)
|
||||
currentWeight := 0
|
||||
for key, weight := range remainingWeights {
|
||||
currentWeight += weight
|
||||
if randomNum < currentWeight {
|
||||
// 将选中的元素添加到结果切片中
|
||||
result = append(result, key)
|
||||
// 从剩余权重映射中移除选中的元素
|
||||
delete(remainingWeights, key)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -124,11 +124,11 @@ func (m *tools) Items2Map(items [][]int64) (list map[int64]int64) {
|
||||
// 该函数通过遍历切片,从后向前检查每个元素,如果找到与指定值相等的元素,则将其从切片中移除。
|
||||
// 这种从后向前的遍历方法可以避免因移除元素而导致的数组重新排列带来的额外计算。
|
||||
// RemoveSlice 删除切片中的某个值
|
||||
func RemoveSlice[t Number](slice []t, value t) []t {
|
||||
func RemoveSlice[t Number](slice []t, value ...t) []t {
|
||||
// 从后向前遍历切片
|
||||
for i := len(slice) - 1; i >= 0; i-- {
|
||||
// 检查当前元素是否等于需要移除的值
|
||||
if slice[i] == value {
|
||||
if InArray(slice[i], value) {
|
||||
// 如果相等,移除该元素
|
||||
// 使用append和切片操作符来实现移除操作,将i之前和i之后的元素合并到一起
|
||||
slice = append(slice[:i], slice[i+1:]...)
|
||||
@@ -223,3 +223,33 @@ func ReverseSlice[T comparable](s []T) []T {
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// 道具数量合并
|
||||
func (m *tools) ItemsMerge(_items ...[][]int64) [][]int64 {
|
||||
var items [][]int64
|
||||
for _, v := range _items {
|
||||
items = append(items, v...)
|
||||
}
|
||||
if len(items) == 0 {
|
||||
return [][]int64{}
|
||||
}
|
||||
var temp = make(map[int64]int64)
|
||||
for _, v := range items {
|
||||
if len(v) < 2 {
|
||||
g.Log().Errorf(ctx, "分解的物品格式不对:%v", v)
|
||||
continue
|
||||
}
|
||||
if _, ok := temp[v[0]]; !ok {
|
||||
temp[v[0]] = 0
|
||||
}
|
||||
temp[v[0]] += v[1]
|
||||
}
|
||||
|
||||
items = make([][]int64, len(temp))
|
||||
i := 0
|
||||
for k, v := range temp {
|
||||
items[i] = []int64{k, v}
|
||||
i++
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user