@@ -0,0 +1,8 @@ | |||
# 默认忽略的文件 | |||
/shelf/ | |||
/workspace.xml | |||
# 基于编辑器的 HTTP 客户端请求 | |||
/httpRequests/ | |||
# Datasource local storage ignored files | |||
/dataSources/ | |||
/dataSources.local.xml |
@@ -0,0 +1,8 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project version="4"> | |||
<component name="ProjectModuleManager"> | |||
<modules> | |||
<module fileurl="file://$PROJECT_DIR$/.idea/system_rules.iml" filepath="$PROJECT_DIR$/.idea/system_rules.iml" /> | |||
</modules> | |||
</component> | |||
</project> |
@@ -0,0 +1,9 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<module type="WEB_MODULE" version="4"> | |||
<component name="Go" enabled="true" /> | |||
<component name="NewModuleRootManager"> | |||
<content url="file://$MODULE_DIR$" /> | |||
<orderEntry type="inheritedJdk" /> | |||
<orderEntry type="sourceFolder" forTests="false" /> | |||
</component> | |||
</module> |
@@ -0,0 +1,6 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project version="4"> | |||
<component name="VcsDirectoryMappings"> | |||
<mapping directory="" vcs="Git" /> | |||
</component> | |||
</project> |
@@ -0,0 +1,35 @@ | |||
package enum | |||
// UserVirtualAmountFlowTransferType 用户虚拟币流水-类型 | |||
type UserVirtualAmountFlowTransferType int | |||
const ( | |||
EggEnergyCommunityDividends UserVirtualAmountFlowTransferType = iota + 1 | |||
EggEnergyWatchAdRewardPersonalActiveCoin | |||
EggEnergyWatchAdRewardTeamActiveCoin | |||
EggPointCoinToExchangeToPersonEggEnergy | |||
EggPointCoinToExchangeToTeamEggEnergy | |||
PersonEggGetByEnergyEggPointCoin | |||
TeamEggGetByEnergyEggPointCoin | |||
) | |||
func (kind UserVirtualAmountFlowTransferType) String() string { | |||
switch kind { | |||
case EggEnergyCommunityDividends: | |||
return "蛋蛋能量-社区分红" | |||
case EggEnergyWatchAdRewardPersonalActiveCoin: | |||
return "浏览视频" //浏览视频奖励-个人蛋蛋积分 | |||
case EggEnergyWatchAdRewardTeamActiveCoin: | |||
return "圈层奖励" //浏览视频奖励-团队蛋蛋积分 | |||
case EggPointCoinToExchangeToPersonEggEnergy: | |||
return "个人蛋蛋积分兑换" | |||
case EggPointCoinToExchangeToTeamEggEnergy: | |||
return "团队蛋蛋积分兑换" | |||
case PersonEggGetByEnergyEggPointCoin: | |||
return "个人蛋蛋积分兑换蛋蛋能量" | |||
case TeamEggGetByEnergyEggPointCoin: | |||
return "团队蛋蛋积分兑换蛋蛋能量" | |||
default: | |||
return "未知状态" | |||
} | |||
} |
@@ -0,0 +1,14 @@ | |||
module code.fnuoos.com/EggPlanet/egg_system_rules.git | |||
go 1.19 | |||
// go.mod文件中 | |||
//replace code.fnuoos.com/EggPlanet/egg_models.git => E:/company/Egg/egg_models | |||
require ( | |||
code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git v0.0.5 | |||
github.com/shopspring/decimal v1.3.1 | |||
xorm.io/xorm v1.3.1 | |||
) | |||
require code.fnuoos.com/EggPlanet/egg_models.git v0.2.1-0.20241112032738-ca9b07ba7b24 // indirect |
@@ -0,0 +1,670 @@ | |||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= | |||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= | |||
code.fnuoos.com/EggPlanet/egg_models.git v0.2.1-0.20241112032738-ca9b07ba7b24 h1:zH+UExmxPnD0vUTy2aGXG/sGH+g/oLtMXbO/c8iRDz4= | |||
code.fnuoos.com/EggPlanet/egg_models.git v0.2.1-0.20241112032738-ca9b07ba7b24/go.mod h1:Ktgi+Hk87UlF7/7wg1BvQnAbXWxGa3y+OqDXSD0AA4Q= | |||
code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git v0.0.5/go.mod h1:TTcCnFn/LhBGapnutpezlW+GXkLRNPMWkziOoCsXQqY= | |||
code.fnuoos.com/go_rely_warehouse/zyos_model.git v0.0.4-0.20241017011352-f7f92494c0f4/go.mod h1:nT2x13YFgrS3tS1fDyUR6q/GNIK+hPw7bdzZXz99SM0= | |||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= | |||
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU= | |||
gitee.com/travelliu/dm v1.8.11192/go.mod h1:DHTzyhCrM843x9VdKVbZ+GKXGRbKM2sJ4LxihRxShkE= | |||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= | |||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= | |||
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= | |||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= | |||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= | |||
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= | |||
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= | |||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= | |||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= | |||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= | |||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= | |||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= | |||
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= | |||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= | |||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= | |||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= | |||
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= | |||
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= | |||
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= | |||
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= | |||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= | |||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= | |||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= | |||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= | |||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= | |||
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= | |||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= | |||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= | |||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= | |||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= | |||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= | |||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= | |||
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= | |||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= | |||
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= | |||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= | |||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= | |||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= | |||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= | |||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= | |||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= | |||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= | |||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= | |||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= | |||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | |||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | |||
github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= | |||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= | |||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= | |||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= | |||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= | |||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= | |||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= | |||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= | |||
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= | |||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= | |||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= | |||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= | |||
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= | |||
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= | |||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= | |||
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= | |||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= | |||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= | |||
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= | |||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= | |||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= | |||
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= | |||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= | |||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= | |||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= | |||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= | |||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= | |||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= | |||
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= | |||
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= | |||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= | |||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= | |||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= | |||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= | |||
github.com/goccy/go-json v0.8.1/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= | |||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= | |||
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= | |||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= | |||
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= | |||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= | |||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= | |||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= | |||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= | |||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= | |||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= | |||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= | |||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= | |||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | |||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | |||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | |||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= | |||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= | |||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= | |||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= | |||
github.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE= | |||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= | |||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= | |||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= | |||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= | |||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= | |||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | |||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | |||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= | |||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= | |||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | |||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | |||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= | |||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= | |||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= | |||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= | |||
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= | |||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= | |||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= | |||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= | |||
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= | |||
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= | |||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= | |||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= | |||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= | |||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= | |||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= | |||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= | |||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= | |||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= | |||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= | |||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= | |||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= | |||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= | |||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= | |||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= | |||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= | |||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= | |||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= | |||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= | |||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= | |||
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= | |||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= | |||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= | |||
github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= | |||
github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= | |||
github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= | |||
github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= | |||
github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= | |||
github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= | |||
github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk= | |||
github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= | |||
github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= | |||
github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= | |||
github.com/jackc/pgconn v1.8.1/go.mod h1:JV6m6b6jhjdmzchES0drzCcYcAHS1OPD5xu3OZ/lE2g= | |||
github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= | |||
github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= | |||
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= | |||
github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= | |||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= | |||
github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= | |||
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= | |||
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= | |||
github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= | |||
github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= | |||
github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= | |||
github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= | |||
github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= | |||
github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= | |||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= | |||
github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= | |||
github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= | |||
github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= | |||
github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0= | |||
github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po= | |||
github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ= | |||
github.com/jackc/pgtype v1.7.0/go.mod h1:ZnHF+rMePVqDKaOfJVI4Q8IVvAQMryDlDkZnKOI75BE= | |||
github.com/jackc/pgtype v1.8.0/go.mod h1:PqDKcEBtllAtk/2p6z6SHdXW5UB+MhE75tUol2OKexE= | |||
github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= | |||
github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= | |||
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= | |||
github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA= | |||
github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o= | |||
github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg= | |||
github.com/jackc/pgx/v4 v4.11.0/go.mod h1:i62xJgdrtVDsnL3U8ekyrQXEwGNTRoG7/8r+CIdYfcc= | |||
github.com/jackc/pgx/v4 v4.12.0/go.mod h1:fE547h6VulLPA3kySjfnSG/e2D861g/50JlVUa/ub60= | |||
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= | |||
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= | |||
github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= | |||
github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= | |||
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= | |||
github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= | |||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= | |||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= | |||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= | |||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= | |||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= | |||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= | |||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= | |||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= | |||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= | |||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= | |||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= | |||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= | |||
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= | |||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= | |||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= | |||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= | |||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= | |||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= | |||
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= | |||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= | |||
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= | |||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= | |||
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= | |||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= | |||
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= | |||
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= | |||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= | |||
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= | |||
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= | |||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= | |||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= | |||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= | |||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= | |||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= | |||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= | |||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= | |||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= | |||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= | |||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= | |||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= | |||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= | |||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= | |||
github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= | |||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= | |||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= | |||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= | |||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= | |||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= | |||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= | |||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= | |||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= | |||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= | |||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= | |||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= | |||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= | |||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= | |||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= | |||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= | |||
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= | |||
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= | |||
github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= | |||
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= | |||
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= | |||
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= | |||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= | |||
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= | |||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= | |||
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= | |||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | |||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | |||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= | |||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= | |||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= | |||
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= | |||
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= | |||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= | |||
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= | |||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= | |||
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= | |||
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= | |||
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= | |||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= | |||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= | |||
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= | |||
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= | |||
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= | |||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= | |||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | |||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | |||
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= | |||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | |||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= | |||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= | |||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= | |||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= | |||
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= | |||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= | |||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= | |||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= | |||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= | |||
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= | |||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= | |||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= | |||
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= | |||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= | |||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= | |||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= | |||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= | |||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= | |||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= | |||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= | |||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= | |||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= | |||
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= | |||
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= | |||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= | |||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= | |||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= | |||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= | |||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= | |||
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= | |||
github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= | |||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= | |||
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= | |||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= | |||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= | |||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= | |||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= | |||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= | |||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= | |||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= | |||
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= | |||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= | |||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= | |||
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= | |||
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= | |||
github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= | |||
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= | |||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | |||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | |||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= | |||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= | |||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= | |||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= | |||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= | |||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= | |||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= | |||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | |||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | |||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= | |||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= | |||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= | |||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= | |||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= | |||
github.com/syyongx/php2go v0.9.8/go.mod h1:meN2eIhhUoxOd2nMxbpe8g6cFPXI5O9/UAAuz7oDdzw= | |||
github.com/tidwall/gjson v1.14.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= | |||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= | |||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= | |||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= | |||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= | |||
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= | |||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= | |||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= | |||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= | |||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | |||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= | |||
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= | |||
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= | |||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= | |||
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= | |||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= | |||
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= | |||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= | |||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= | |||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= | |||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= | |||
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= | |||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= | |||
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= | |||
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= | |||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= | |||
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= | |||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= | |||
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= | |||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= | |||
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= | |||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= | |||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= | |||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | |||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | |||
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= | |||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | |||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | |||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | |||
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | |||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | |||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | |||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | |||
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= | |||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= | |||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= | |||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= | |||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= | |||
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= | |||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= | |||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= | |||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= | |||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= | |||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= | |||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= | |||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= | |||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= | |||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | |||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= | |||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= | |||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | |||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | |||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | |||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | |||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | |||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | |||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | |||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | |||
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | |||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | |||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | |||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | |||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= | |||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | |||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | |||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | |||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= | |||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= | |||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= | |||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= | |||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= | |||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= | |||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= | |||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | |||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |||
golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= | |||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | |||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= | |||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= | |||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= | |||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= | |||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | |||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= | |||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | |||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | |||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | |||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= | |||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= | |||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= | |||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= | |||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= | |||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | |||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | |||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | |||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | |||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | |||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | |||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= | |||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= | |||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= | |||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= | |||
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= | |||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= | |||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= | |||
golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | |||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | |||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | |||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | |||
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= | |||
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= | |||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= | |||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= | |||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= | |||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= | |||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= | |||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= | |||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= | |||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= | |||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= | |||
google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= | |||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= | |||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= | |||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= | |||
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= | |||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= | |||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= | |||
google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= | |||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= | |||
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= | |||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= | |||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= | |||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= | |||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= | |||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | |||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | |||
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= | |||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= | |||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= | |||
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= | |||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= | |||
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= | |||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= | |||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= | |||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= | |||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= | |||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | |||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | |||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | |||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | |||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= | |||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= | |||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= | |||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= | |||
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= | |||
modernc.org/cc/v3 v3.33.6/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||
modernc.org/cc/v3 v3.33.9/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||
modernc.org/cc/v3 v3.33.11/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||
modernc.org/cc/v3 v3.34.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||
modernc.org/cc/v3 v3.35.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||
modernc.org/cc/v3 v3.35.4/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||
modernc.org/cc/v3 v3.35.5/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||
modernc.org/cc/v3 v3.35.7/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||
modernc.org/cc/v3 v3.35.8/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||
modernc.org/cc/v3 v3.35.10/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||
modernc.org/cc/v3 v3.35.15/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||
modernc.org/cc/v3 v3.35.16/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||
modernc.org/cc/v3 v3.35.17/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||
modernc.org/cc/v3 v3.35.18/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||
modernc.org/ccgo/v3 v3.9.5/go.mod h1:umuo2EP2oDSBnD3ckjaVUXMrmeAw8C8OSICVa0iFf60= | |||
modernc.org/ccgo/v3 v3.10.0/go.mod h1:c0yBmkRFi7uW4J7fwx/JiijwOjeAeR2NoSaRVFPmjMw= | |||
modernc.org/ccgo/v3 v3.11.0/go.mod h1:dGNposbDp9TOZ/1KBxghxtUp/bzErD0/0QW4hhSaBMI= | |||
modernc.org/ccgo/v3 v3.11.1/go.mod h1:lWHxfsn13L3f7hgGsGlU28D9eUOf6y3ZYHKoPaKU0ag= | |||
modernc.org/ccgo/v3 v3.11.3/go.mod h1:0oHunRBMBiXOKdaglfMlRPBALQqsfrCKXgw9okQ3GEw= | |||
modernc.org/ccgo/v3 v3.12.4/go.mod h1:Bk+m6m2tsooJchP/Yk5ji56cClmN6R1cqc9o/YtbgBQ= | |||
modernc.org/ccgo/v3 v3.12.6/go.mod h1:0Ji3ruvpFPpz+yu+1m0wk68pdr/LENABhTrDkMDWH6c= | |||
modernc.org/ccgo/v3 v3.12.8/go.mod h1:Hq9keM4ZfjCDuDXxaHptpv9N24JhgBZmUG5q60iLgUo= | |||
modernc.org/ccgo/v3 v3.12.11/go.mod h1:0jVcmyDwDKDGWbcrzQ+xwJjbhZruHtouiBEvDfoIsdg= | |||
modernc.org/ccgo/v3 v3.12.14/go.mod h1:GhTu1k0YCpJSuWwtRAEHAol5W7g1/RRfS4/9hc9vF5I= | |||
modernc.org/ccgo/v3 v3.12.18/go.mod h1:jvg/xVdWWmZACSgOiAhpWpwHWylbJaSzayCqNOJKIhs= | |||
modernc.org/ccgo/v3 v3.12.20/go.mod h1:aKEdssiu7gVgSy/jjMastnv/q6wWGRbszbheXgWRHc8= | |||
modernc.org/ccgo/v3 v3.12.21/go.mod h1:ydgg2tEprnyMn159ZO/N4pLBqpL7NOkJ88GT5zNU2dE= | |||
modernc.org/ccgo/v3 v3.12.22/go.mod h1:nyDVFMmMWhMsgQw+5JH6B6o4MnZ+UQNw1pp52XYFPRk= | |||
modernc.org/ccgo/v3 v3.12.25/go.mod h1:UaLyWI26TwyIT4+ZFNjkyTbsPsY3plAEB6E7L/vZV3w= | |||
modernc.org/ccgo/v3 v3.12.29/go.mod h1:FXVjG7YLf9FetsS2OOYcwNhcdOLGt8S9bQ48+OP75cE= | |||
modernc.org/ccgo/v3 v3.12.36/go.mod h1:uP3/Fiezp/Ga8onfvMLpREq+KUjUmYMxXPO8tETHtA8= | |||
modernc.org/ccgo/v3 v3.12.38/go.mod h1:93O0G7baRST1vNj4wnZ49b1kLxt0xCW5Hsa2qRaZPqc= | |||
modernc.org/ccgo/v3 v3.12.43/go.mod h1:k+DqGXd3o7W+inNujK15S5ZYuPoWYLpF5PYougCmthU= | |||
modernc.org/ccgo/v3 v3.12.46/go.mod h1:UZe6EvMSqOxaJ4sznY7b23/k13R8XNlyWsO5bAmSgOE= | |||
modernc.org/ccgo/v3 v3.12.47/go.mod h1:m8d6p0zNps187fhBwzY/ii6gxfjob1VxWb919Nk1HUk= | |||
modernc.org/ccgo/v3 v3.12.50/go.mod h1:bu9YIwtg+HXQxBhsRDE+cJjQRuINuT9PUK4orOco/JI= | |||
modernc.org/ccgo/v3 v3.12.51/go.mod h1:gaIIlx4YpmGO2bLye04/yeblmvWEmE4BBBls4aJXFiE= | |||
modernc.org/ccgo/v3 v3.12.53/go.mod h1:8xWGGTFkdFEWBEsUmi+DBjwu/WLy3SSOrqEmKUjMeEg= | |||
modernc.org/ccgo/v3 v3.12.54/go.mod h1:yANKFTm9llTFVX1FqNKHE0aMcQb1fuPJx6p8AcUx+74= | |||
modernc.org/ccgo/v3 v3.12.55/go.mod h1:rsXiIyJi9psOwiBkplOaHye5L4MOOaCjHg1Fxkj7IeU= | |||
modernc.org/ccgo/v3 v3.12.56/go.mod h1:ljeFks3faDseCkr60JMpeDb2GSO3TKAmrzm7q9YOcMU= | |||
modernc.org/ccgo/v3 v3.12.57/go.mod h1:hNSF4DNVgBl8wYHpMvPqQWDQx8luqxDnNGCMM4NFNMc= | |||
modernc.org/ccgo/v3 v3.12.60/go.mod h1:k/Nn0zdO1xHVWjPYVshDeWKqbRWIfif5dtsIOCUVMqM= | |||
modernc.org/ccgo/v3 v3.12.65/go.mod h1:D6hQtKxPNZiY6wDBtehSGKFKmyXn53F8nGTpH+POmS4= | |||
modernc.org/ccgo/v3 v3.12.66/go.mod h1:jUuxlCFZTUZLMV08s7B1ekHX5+LIAurKTTaugUr/EhQ= | |||
modernc.org/ccgo/v3 v3.12.67/go.mod h1:Bll3KwKvGROizP2Xj17GEGOTrlvB1XcVaBrC90ORO84= | |||
modernc.org/ccgo/v3 v3.12.73/go.mod h1:hngkB+nUUqzOf3iqsM48Gf1FZhY599qzVg1iX+BT3cQ= | |||
modernc.org/ccgo/v3 v3.12.81/go.mod h1:p2A1duHoBBg1mFtYvnhAnQyI6vL0uw5PGYLSIgF6rYY= | |||
modernc.org/ccgo/v3 v3.12.82/go.mod h1:ApbflUfa5BKadjHynCficldU1ghjen84tuM5jRynB7w= | |||
modernc.org/ccorpus v1.11.1/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= | |||
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= | |||
modernc.org/libc v1.9.8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w= | |||
modernc.org/libc v1.9.11/go.mod h1:NyF3tsA5ArIjJ83XB0JlqhjTabTCHm9aX4XMPHyQn0Q= | |||
modernc.org/libc v1.11.0/go.mod h1:2lOfPmj7cz+g1MrPNmX65QCzVxgNq2C5o0jdLY2gAYg= | |||
modernc.org/libc v1.11.2/go.mod h1:ioIyrl3ETkugDO3SGZ+6EOKvlP3zSOycUETe4XM4n8M= | |||
modernc.org/libc v1.11.5/go.mod h1:k3HDCP95A6U111Q5TmG3nAyUcp3kR5YFZTeDS9v8vSU= | |||
modernc.org/libc v1.11.6/go.mod h1:ddqmzR6p5i4jIGK1d/EiSw97LBcE3dK24QEwCFvgNgE= | |||
modernc.org/libc v1.11.11/go.mod h1:lXEp9QOOk4qAYOtL3BmMve99S5Owz7Qyowzvg6LiZso= | |||
modernc.org/libc v1.11.13/go.mod h1:ZYawJWlXIzXy2Pzghaf7YfM8OKacP3eZQI81PDLFdY8= | |||
modernc.org/libc v1.11.16/go.mod h1:+DJquzYi+DMRUtWI1YNxrlQO6TcA5+dRRiq8HWBWRC8= | |||
modernc.org/libc v1.11.19/go.mod h1:e0dgEame6mkydy19KKaVPBeEnyJB4LGNb0bBH1EtQ3I= | |||
modernc.org/libc v1.11.24/go.mod h1:FOSzE0UwookyT1TtCJrRkvsOrX2k38HoInhw+cSCUGk= | |||
modernc.org/libc v1.11.26/go.mod h1:SFjnYi9OSd2W7f4ct622o/PAYqk7KHv6GS8NZULIjKY= | |||
modernc.org/libc v1.11.27/go.mod h1:zmWm6kcFXt/jpzeCgfvUNswM0qke8qVwxqZrnddlDiE= | |||
modernc.org/libc v1.11.28/go.mod h1:Ii4V0fTFcbq3qrv3CNn+OGHAvzqMBvC7dBNyC4vHZlg= | |||
modernc.org/libc v1.11.31/go.mod h1:FpBncUkEAtopRNJj8aRo29qUiyx5AvAlAxzlx9GNaVM= | |||
modernc.org/libc v1.11.34/go.mod h1:+Tzc4hnb1iaX/SKAutJmfzES6awxfU1BPvrrJO0pYLg= | |||
modernc.org/libc v1.11.37/go.mod h1:dCQebOwoO1046yTrfUE5nX1f3YpGZQKNcITUYWlrAWo= | |||
modernc.org/libc v1.11.39/go.mod h1:mV8lJMo2S5A31uD0k1cMu7vrJbSA3J3waQJxpV4iqx8= | |||
modernc.org/libc v1.11.42/go.mod h1:yzrLDU+sSjLE+D4bIhS7q1L5UwXDOw99PLSX0BlZvSQ= | |||
modernc.org/libc v1.11.44/go.mod h1:KFq33jsma7F5WXiYelU8quMJasCCTnHK0mkri4yPHgA= | |||
modernc.org/libc v1.11.45/go.mod h1:Y192orvfVQQYFzCNsn+Xt0Hxt4DiO4USpLNXBlXg/tM= | |||
modernc.org/libc v1.11.47/go.mod h1:tPkE4PzCTW27E6AIKIR5IwHAQKCAtudEIeAV1/SiyBg= | |||
modernc.org/libc v1.11.49/go.mod h1:9JrJuK5WTtoTWIFQ7QjX2Mb/bagYdZdscI3xrvHbXjE= | |||
modernc.org/libc v1.11.51/go.mod h1:R9I8u9TS+meaWLdbfQhq2kFknTW0O3aw3kEMqDDxMaM= | |||
modernc.org/libc v1.11.53/go.mod h1:5ip5vWYPAoMulkQ5XlSJTy12Sz5U6blOQiYasilVPsU= | |||
modernc.org/libc v1.11.54/go.mod h1:S/FVnskbzVUrjfBqlGFIPA5m7UwB3n9fojHhCNfSsnw= | |||
modernc.org/libc v1.11.55/go.mod h1:j2A5YBRm6HjNkoSs/fzZrSxCuwWqcMYTDPLNx0URn3M= | |||
modernc.org/libc v1.11.56/go.mod h1:pakHkg5JdMLt2OgRadpPOTnyRXm/uzu+Yyg/LSLdi18= | |||
modernc.org/libc v1.11.58/go.mod h1:ns94Rxv0OWyoQrDqMFfWwka2BcaF6/61CqJRK9LP7S8= | |||
modernc.org/libc v1.11.70/go.mod h1:DUOmMYe+IvKi9n6Mycyx3DbjfzSKrdr/0Vgt3j7P5gw= | |||
modernc.org/libc v1.11.71/go.mod h1:DUOmMYe+IvKi9n6Mycyx3DbjfzSKrdr/0Vgt3j7P5gw= | |||
modernc.org/libc v1.11.75/go.mod h1:dGRVugT6edz361wmD9gk6ax1AbDSe0x5vji0dGJiPT0= | |||
modernc.org/libc v1.11.82/go.mod h1:NF+Ek1BOl2jeC7lw3a7Jj5PWyHPwWD4aq3wVKxqV1fI= | |||
modernc.org/libc v1.11.86/go.mod h1:ePuYgoQLmvxdNT06RpGnaDKJmDNEkV7ZPKI2jnsvZoE= | |||
modernc.org/libc v1.11.87/go.mod h1:Qvd5iXTeLhI5PS0XSyqMY99282y+3euapQFxM7jYnpY= | |||
modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= | |||
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= | |||
modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= | |||
modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= | |||
modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc= | |||
modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM= | |||
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= | |||
modernc.org/sqlite v1.14.2/go.mod h1:yqfn85u8wVOE6ub5UT8VI9JjhrwBUUCNyTACN0h6Sx8= | |||
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= | |||
modernc.org/tcl v1.8.13/go.mod h1:V+q/Ef0IJaNUSECieLU4o+8IScapxnMyFV6i/7uQlAY= | |||
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= | |||
modernc.org/z v1.2.19/go.mod h1:+ZpP0pc4zz97eukOzW3xagV/lS82IpPN9NGG5pNF9vY= | |||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= | |||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= | |||
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= | |||
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE= | |||
xorm.io/xorm v1.3.1/go.mod h1:9NbjqdnjX6eyjRRhh01GHm64r6N9shTb/8Ak3YRt8Nw= |
@@ -0,0 +1,14 @@ | |||
package egg_system_rules | |||
import ( | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/md" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/cache" | |||
) | |||
func Init(redisAddr string) (err error) { | |||
if redisAddr != "" { | |||
cache.NewRedis(redisAddr) | |||
} | |||
_, err = cache.SelectDb(md.RedisDataBase) | |||
return | |||
} |
@@ -0,0 +1,13 @@ | |||
package md | |||
const RedisDataBase = 0 //Redis 0 号库 | |||
// 缓存key统一管理 | |||
const ( | |||
EggEnergyNowPriceUpdateLock = "egg_energy_core_data_update_lock" // 当前价格(能拿到锁才能更新价格) | |||
DealEggEnergyNowPriceRequestIdPrefix = "egg_energy_core_data:%d" | |||
UserFinValidUpdateLock = "%s:user_fin_valid_update_lock:%s" // 用户余额更新锁(能拿到锁才能更新余额) | |||
UserVirtualAmountUpdateLock = "%s:user_virtual_amount_update_lock:%s" // 用户虚拟币更新锁(能拿到锁才能更新余额) | |||
) |
@@ -0,0 +1,41 @@ | |||
package md | |||
type StandardPublicPlatoonRelation struct { | |||
FatherUid1 int64 `json:"father_uid1"` | |||
FatherUid2 int64 `json:"father_uid2"` | |||
FatherUid3 int64 `json:"father_uid3"` | |||
FatherUid4 int64 `json:"father_uid4"` | |||
FatherUid5 int64 `json:"father_uid5"` | |||
FatherUid6 int64 `json:"father_uid6"` | |||
FatherUid7 int64 `json:"father_uid7"` | |||
FatherUid8 int64 `json:"father_uid8"` | |||
FatherUid9 int64 `json:"father_uid9"` | |||
Pid1 int64 `json:"pid1"` | |||
Pid2 int64 `json:"pid2"` | |||
Pid3 int64 `json:"pid3"` | |||
Pid4 int64 `json:"pid4"` | |||
Pid5 int64 `json:"pid5"` | |||
Pid6 int64 `json:"pid6"` | |||
Pid7 int64 `json:"pid7"` | |||
Pid8 int64 `json:"pid8"` | |||
Pid9 int64 `json:"pid9"` | |||
Position1 int64 `json:"position1"` | |||
Position2 int64 `json:"position2"` | |||
Position3 int64 `json:"position3"` | |||
Position4 int64 `json:"position4"` | |||
Position5 int64 `json:"position5"` | |||
Position6 int64 `json:"position6"` | |||
Position7 int64 `json:"position7"` | |||
Position8 int64 `json:"position8"` | |||
Position9 int64 `json:"position9"` | |||
Level1 int `json:"level1"` | |||
Level2 int `json:"level2"` | |||
Level3 int `json:"level3"` | |||
Level4 int `json:"level4"` | |||
Level5 int `json:"level5"` | |||
Level6 int `json:"level6"` | |||
Level7 int `json:"level7"` | |||
Level8 int `json:"level8"` | |||
Level9 int `json:"level9"` | |||
LevelTotal int `json:"level_total"` | |||
} |
@@ -0,0 +1,14 @@ | |||
package md | |||
const ( | |||
UserVirtualAmountRedisKey = "user_virtual_amount:%d:user:%d" | |||
) | |||
type DealUserVirtualCoinReq struct { | |||
Kind string `json:"kind"` | |||
Title string `json:"title"` | |||
TransferType int `json:"transfer_type"` | |||
CoinId int `json:"coin_id"` | |||
Uid int64 `json:"uid"` | |||
Amount float64 `json:"amount"` | |||
} |
@@ -0,0 +1,58 @@ | |||
package egg_energy | |||
import ( | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/enum" | |||
md2 "code.fnuoos.com/EggPlanet/egg_system_rules.git/md" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/rule" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/md" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/svc" | |||
egg_system_rules "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils" | |||
zhios_order_relate_logx "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/logx" | |||
"code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git/rabbit" | |||
"fmt" | |||
"xorm.io/xorm" | |||
) | |||
// ActivityCoinAutoExchangeEggPersonEnergy 个人蛋蛋积分【开始】兑换成个人蛋蛋能量 | |||
func ActivityCoinAutoExchangeEggPersonEnergy(engine *xorm.Engine, req md.EggEnergyStructForAutoExchangeGreenEnergy, ch *rabbit.Channel) (err error) { | |||
session := engine.NewSession() | |||
defer func() { | |||
session.Close() | |||
if err := recover(); err != nil { | |||
_ = zhios_order_relate_logx.Error(err) | |||
} | |||
}() | |||
session.Begin() | |||
eggEnergyCoreData, cb, err := svc.GetEggEnergyCoreData(engine) | |||
if err != nil { | |||
return err | |||
} | |||
if cb != nil { | |||
defer cb() // 释放锁 | |||
} | |||
//1、计算涨价公式 | |||
err1, calcPriceIncreaseFormulaResp := CalcPriceIncreaseFormula(req.AutoExchangeNumsAmount, eggEnergyCoreData) | |||
if err1 != nil { | |||
_ = session.Rollback() | |||
return err1 | |||
} | |||
//2、增加用户对应蛋蛋能量数量 | |||
err = rule.DealUserVirtualCoin(session, md2.DealUserVirtualCoinReq{ | |||
Kind: "add", | |||
Title: enum.PersonEggGetByEnergyEggPointCoin.String(), | |||
TransferType: int(enum.PersonEggGetByEnergyEggPointCoin), | |||
CoinId: req.EnergyCoinId, | |||
Uid: req.Uid, | |||
Amount: egg_system_rules.StrToFloat64(calcPriceIncreaseFormulaResp.GetEggEnergyNums), | |||
}) | |||
if err != nil { | |||
fmt.Println("ActivityCoinAutoExchangeEggPersonEnergy:::::err111:::", err) | |||
_ = session.Rollback() | |||
return | |||
} | |||
return session.Commit() | |||
} |
@@ -0,0 +1,58 @@ | |||
package egg_energy | |||
import ( | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/enum" | |||
md2 "code.fnuoos.com/EggPlanet/egg_system_rules.git/md" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/rule" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/md" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/svc" | |||
egg_system_rules "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils" | |||
zhios_order_relate_logx "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/logx" | |||
"code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git/rabbit" | |||
"fmt" | |||
"xorm.io/xorm" | |||
) | |||
// ActivityCoinAutoExchangeEggTeamEnergy 团队蛋蛋积分【开始】兑换成团队蛋蛋能量 | |||
func ActivityCoinAutoExchangeEggTeamEnergy(engine *xorm.Engine, req md.EggEnergyStructForAutoExchangeGreenEnergy, ch *rabbit.Channel) (err error) { | |||
session := engine.NewSession() | |||
defer func() { | |||
session.Close() | |||
if err := recover(); err != nil { | |||
_ = zhios_order_relate_logx.Error(err) | |||
} | |||
}() | |||
session.Begin() | |||
eggEnergyCoreData, cb, err := svc.GetEggEnergyCoreData(engine) | |||
if err != nil { | |||
return err | |||
} | |||
if cb != nil { | |||
defer cb() // 释放锁 | |||
} | |||
//1、计算涨价公式 | |||
err1, calcPriceIncreaseFormulaResp := CalcPriceIncreaseFormula(req.AutoExchangeNumsAmount, eggEnergyCoreData) | |||
if err1 != nil { | |||
_ = session.Rollback() | |||
return err1 | |||
} | |||
//2、增加用户对应蛋蛋能量数量 | |||
err = rule.DealUserVirtualCoin(session, md2.DealUserVirtualCoinReq{ | |||
Kind: "add", | |||
Title: enum.TeamEggGetByEnergyEggPointCoin.String(), | |||
TransferType: int(enum.TeamEggGetByEnergyEggPointCoin), | |||
CoinId: req.EnergyCoinId, | |||
Uid: req.Uid, | |||
Amount: egg_system_rules.StrToFloat64(calcPriceIncreaseFormulaResp.GetEggEnergyNums), | |||
}) | |||
if err != nil { | |||
fmt.Println("ActivityCoinAutoExchangeEggTeamEnergy:::::err111:::", err) | |||
_ = session.Rollback() | |||
return | |||
} | |||
return session.Commit() | |||
} |
@@ -0,0 +1,129 @@ | |||
package egg_energy | |||
import ( | |||
"code.fnuoos.com/EggPlanet/egg_models.git/src/implement" | |||
"code.fnuoos.com/EggPlanet/egg_models.git/src/model" | |||
md2 "code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/md" | |||
egg_system_rules "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils" | |||
"code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git/rabbit" | |||
"encoding/json" | |||
"errors" | |||
"fmt" | |||
"github.com/shopspring/decimal" | |||
"time" | |||
"xorm.io/xorm" | |||
) | |||
// ActivityCoinReadyExchangeEggEnergy 蛋蛋积分【准备】兑换成蛋蛋能量 | |||
func ActivityCoinReadyExchangeEggEnergy(engine *xorm.Engine, uid int64, ch *rabbit.Channel) (err error) { | |||
//1、查找`egg_energy_basic_setting` 基础设置 | |||
eggEnergyBasicSettingDb := implement.NewEggEnergyBasicSettingDb(engine) | |||
eggEnergyBasicSetting, err := eggEnergyBasicSettingDb.EggEnergyBasicSettingGetOneByParams(map[string]interface{}{ | |||
"key": "is_open", | |||
"value": 1, | |||
}) | |||
if err != nil { | |||
return | |||
} | |||
if eggEnergyBasicSetting.ExchangeRules == "" { | |||
err = errors.New("自动兑换未设置!") | |||
return | |||
} | |||
var exchangeRulesStruct *md2.ExchangeRulesStruct | |||
err = json.Unmarshal([]byte(eggEnergyBasicSetting.ExchangeRules), &exchangeRulesStruct) | |||
if err != nil { | |||
return | |||
} | |||
var videoRewardSystem *md2.VideoRewardSystemStruct | |||
err = json.Unmarshal([]byte(eggEnergyBasicSetting.VideoRewardSystem), &videoRewardSystem) | |||
if err != nil { | |||
return | |||
} | |||
if videoRewardSystem.RewardValue == "" || videoRewardSystem.RewardTotalNum == "" || videoRewardSystem.IntervalMinutes == "" || videoRewardSystem.EachRoundHour == "" { | |||
err = errors.New("视屏奖励机制设置未完全!") | |||
return | |||
} | |||
var autoExchangeNumsByPerson = egg_system_rules.StrToFloat64(exchangeRulesStruct.AutoExchangeNumsByPerson) //个人活跃积分X个自动兑换 | |||
fmt.Println("autoExchangeNumsByPerson>>>>>>>>>>>>", autoExchangeNumsByPerson) | |||
var autoExchangeNumsByTeam = egg_system_rules.StrToFloat64(exchangeRulesStruct.AutoExchangeNumsByTeam) //个人活跃积分X个自动兑换 | |||
fmt.Println("autoExchangeNumsByTeam>>>>>>>>>>>>", autoExchangeNumsByTeam) | |||
//2、获取"个人蛋蛋活跃积分" && 获取"团队蛋蛋活跃积分" | |||
var coin1, coin2 model.VirtualCoin | |||
_, err = engine.Where("id = ?", eggEnergyBasicSetting.PersonEggPointsCoinId).Get(&coin1) | |||
if err != nil { | |||
return err | |||
} | |||
_, err = engine.Where("id = ?", eggEnergyBasicSetting.TeamEggPointsCoinId).Get(&coin2) | |||
if err != nil { | |||
return err | |||
} | |||
personActivePointsCoinExchangeRatioValue, _ := decimal.NewFromString(coin1.ExchangeRatio) | |||
teamActivePointsCoinExchangeRatioValue, _ := decimal.NewFromString(coin2.ExchangeRatio) | |||
//3、当前 "个人活跃积分"可以自动兑换的用户数据 && "团队活跃积分"可以自动兑换的用户数据 | |||
var personUserVirtualAmount model.UserVirtualAmount | |||
_, err = engine.Where("coin_id = ?", eggEnergyBasicSetting.PersonEggPointsCoinId).Get(&personUserVirtualAmount) | |||
if err != nil { | |||
fmt.Println("err:::::1111", err) | |||
return | |||
} | |||
var teamUserVirtualAmount model.UserVirtualAmount | |||
_, err = engine.Where("coin_id = ?", eggEnergyBasicSetting.TeamEggPointsCoinId).Get(&teamUserVirtualAmount) | |||
if err != nil { | |||
fmt.Println("err:::::2222", err) | |||
return | |||
} | |||
if egg_system_rules.StrToFloat64(personUserVirtualAmount.Amount) < autoExchangeNumsByPerson && egg_system_rules.StrToFloat64(teamUserVirtualAmount.Amount) < autoExchangeNumsByTeam { | |||
return errors.New("当前活跃值无法发起挖掘~") | |||
} | |||
//session := engine.NewSession() | |||
//defer func() { | |||
// session.Close() | |||
// if err := recover(); err != nil { | |||
// _ = zhios_order_relate_logx.Error(err) | |||
// } | |||
//}() | |||
//session.Begin() | |||
now := time.Now() | |||
//4、计算能兑换的个人活跃积分数量 | |||
if egg_system_rules.StrToFloat64(personUserVirtualAmount.Amount) >= autoExchangeNumsByPerson { | |||
autoExchangeNumsByPersonValue, _ := decimal.NewFromString(personUserVirtualAmount.Amount) | |||
autoExchangeRateByPersonValue, _ := decimal.NewFromString(exchangeRulesStruct.AutoExchangeRateByPerson) | |||
autoExchangeNumsByPersonAmount := autoExchangeNumsByPersonValue.Mul(autoExchangeRateByPersonValue).Div(personActivePointsCoinExchangeRatioValue).String() //个人活跃积分数量*兑换百分比/兑换比例(与金额) | |||
//TODO::推入rabbitmq 异步处理 | |||
ch.Publish(md2.EggEnergyExchange, md2.EggEnergyStructForStartExchangeGreenEnergy{ | |||
Uid: uid, | |||
Amount: autoExchangeNumsByPersonValue.Mul(autoExchangeRateByPersonValue).String(), | |||
PointCoinId: coin1.Id, | |||
EnergyCoinId: eggEnergyBasicSetting.PersonEggEnergyCoinId, | |||
AutoExchangeNumsAmount: autoExchangeNumsByPersonAmount, | |||
StartExchangeTime: now.Format("2006-01-02 15:04:05"), | |||
EndExchangeTime: now.Add(time.Hour * time.Duration(egg_system_rules.StrToInt64(videoRewardSystem.EachRoundHour))).Format("2006-01-02 15:04:05"), | |||
}, md2.EggEnergyRoutKeyForStartExchangeGreenEnergyToPerson) | |||
} | |||
//5、计算能兑换的团队活跃积分数量 | |||
if egg_system_rules.StrToFloat64(teamUserVirtualAmount.Amount) >= autoExchangeNumsByTeam { | |||
autoExchangeNumsByTeamValue, _ := decimal.NewFromString(teamUserVirtualAmount.Amount) | |||
autoExchangeRateByTeamValue, _ := decimal.NewFromString(exchangeRulesStruct.AutoExchangeRateByTeam) | |||
autoExchangeNumsByTeamAmount := autoExchangeNumsByTeamValue.Mul(autoExchangeRateByTeamValue).Div(teamActivePointsCoinExchangeRatioValue).String() //团队活跃积分数量*兑换百分比/兑换比例(与金额) | |||
//TODO::推入rabbitmq 异步处理 | |||
ch.Publish(md2.EggEnergyExchange, md2.EggEnergyStructForStartExchangeGreenEnergy{ | |||
Uid: uid, | |||
Amount: autoExchangeNumsByTeamValue.Mul(autoExchangeRateByTeamValue).String(), | |||
PointCoinId: coin2.Id, | |||
EnergyCoinId: eggEnergyBasicSetting.TeamEggEnergyCoinId, | |||
AutoExchangeNumsAmount: autoExchangeNumsByTeamAmount, | |||
StartExchangeTime: now.Format("2006-01-02 15:04:05"), | |||
EndExchangeTime: now.Add(time.Hour * time.Duration(egg_system_rules.StrToInt64(videoRewardSystem.EachRoundHour))).Format("2006-01-02 15:04:05"), | |||
}, md2.EggEnergyRoutKeyForStartExchangeGreenEnergyToTeam) | |||
} | |||
return | |||
} |
@@ -0,0 +1,51 @@ | |||
package egg_energy | |||
import ( | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/enum" | |||
md2 "code.fnuoos.com/EggPlanet/egg_system_rules.git/md" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/rule" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/md" | |||
egg_system_rules "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils" | |||
zhios_order_relate_logx "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/logx" | |||
"code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git/rabbit" | |||
"fmt" | |||
"xorm.io/xorm" | |||
) | |||
// ActivityCoinStartExchangeEggPersonEnergy 个人蛋蛋积分【开始】兑换成个人蛋蛋能量 | |||
func ActivityCoinStartExchangeEggPersonEnergy(engine *xorm.Engine, req md.EggEnergyStructForStartExchangeGreenEnergy, ch *rabbit.Channel) (err error) { | |||
session := engine.NewSession() | |||
defer func() { | |||
session.Close() | |||
if err := recover(); err != nil { | |||
_ = zhios_order_relate_logx.Error(err) | |||
} | |||
}() | |||
session.Begin() | |||
//1、扣除用户对应蛋蛋活跃积分数量 | |||
err = rule.DealUserVirtualCoin(session, md2.DealUserVirtualCoinReq{ | |||
Kind: "sub", | |||
Title: enum.EggPointCoinToExchangeToPersonEggEnergy.String(), | |||
TransferType: int(enum.EggPointCoinToExchangeToPersonEggEnergy), | |||
CoinId: req.PointCoinId, | |||
Uid: req.Uid, | |||
Amount: egg_system_rules.StrToFloat64(req.Amount), | |||
}) | |||
if err != nil { | |||
fmt.Println("ActivityCoinStartExchangeEggPersonEnergy:::::err111:::", err) | |||
_ = session.Rollback() | |||
return | |||
} | |||
//TODO::推入rabbitmq 异步处理 | |||
ch.Publish(md.EggEnergyExchange, md.EggEnergyStructForAutoExchangeGreenEnergy{ | |||
Uid: req.Uid, | |||
EnergyCoinId: req.EnergyCoinId, | |||
AutoExchangeNumsAmount: req.AutoExchangeNumsAmount, | |||
StartExchangeTime: req.StartExchangeTime, | |||
EndExchangeTime: req.StartExchangeTime, | |||
}, md.EggEnergyRoutKeyForAutoExchangeGreenEnergyToPerson) | |||
return session.Commit() | |||
} |
@@ -0,0 +1,51 @@ | |||
package egg_energy | |||
import ( | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/enum" | |||
md2 "code.fnuoos.com/EggPlanet/egg_system_rules.git/md" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/rule" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/md" | |||
egg_system_rules "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils" | |||
zhios_order_relate_logx "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/logx" | |||
"code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git/rabbit" | |||
"fmt" | |||
"xorm.io/xorm" | |||
) | |||
// ActivityCoinStartExchangeEggTeamEnergy 团队蛋蛋积分【开始】兑换成团队蛋蛋能量 | |||
func ActivityCoinStartExchangeEggTeamEnergy(engine *xorm.Engine, req md.EggEnergyStructForStartExchangeGreenEnergy, ch *rabbit.Channel) (err error) { | |||
session := engine.NewSession() | |||
defer func() { | |||
session.Close() | |||
if err := recover(); err != nil { | |||
_ = zhios_order_relate_logx.Error(err) | |||
} | |||
}() | |||
session.Begin() | |||
//1、扣除用户对应蛋蛋活跃积分数量 | |||
err = rule.DealUserVirtualCoin(session, md2.DealUserVirtualCoinReq{ | |||
Kind: "sub", | |||
Title: enum.EggPointCoinToExchangeToTeamEggEnergy.String(), | |||
TransferType: int(enum.EggPointCoinToExchangeToTeamEggEnergy), | |||
CoinId: req.PointCoinId, | |||
Uid: req.Uid, | |||
Amount: egg_system_rules.StrToFloat64(req.Amount), | |||
}) | |||
if err != nil { | |||
fmt.Println("ActivityCoinStartExchangeEggTeamEnergy:::::err111:::", err) | |||
_ = session.Rollback() | |||
return | |||
} | |||
//TODO::推入rabbitmq 异步处理 | |||
ch.Publish(md.EggEnergyExchange, md.EggEnergyStructForAutoExchangeGreenEnergy{ | |||
Uid: req.Uid, | |||
EnergyCoinId: req.EnergyCoinId, | |||
AutoExchangeNumsAmount: req.AutoExchangeNumsAmount, | |||
StartExchangeTime: req.StartExchangeTime, | |||
EndExchangeTime: req.StartExchangeTime, | |||
}, md.EggEnergyRoutKeyForAutoExchangeGreenEnergyToTeam) | |||
return session.Commit() | |||
} |
@@ -0,0 +1,109 @@ | |||
package egg_energy | |||
import ( | |||
"code.fnuoos.com/EggPlanet/egg_models.git/src/implement" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/enum" | |||
md2 "code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/md" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/svc" | |||
egg_system_rules "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils" | |||
zhios_order_relate_logx "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/logx" | |||
"encoding/json" | |||
"errors" | |||
"fmt" | |||
"github.com/shopspring/decimal" | |||
"time" | |||
"xorm.io/xorm" | |||
) | |||
// AutoAdjustPrice 自动调整价格 | |||
func AutoAdjustPrice(engine *xorm.Engine) (err error) { | |||
now := time.Now() | |||
fmt.Println(now.Hour()) | |||
//1、查找 `egg_energy_core_data` && `egg_energy_basic_setting` | |||
eggEnergyCoreData, cb, err := svc.GetEggEnergyCoreData(engine) | |||
if err != nil { | |||
return | |||
} | |||
if cb != nil { | |||
defer cb() // 释放锁 | |||
} | |||
eggEnergyBasicSettingDb := implement.NewEggEnergyBasicSettingDb(engine) | |||
eggEnergyBasicSetting, err := eggEnergyBasicSettingDb.EggEnergyBasicSettingGetOneByParams(map[string]interface{}{ | |||
"key": "is_open", | |||
"value": 1, | |||
}) | |||
if err != nil { | |||
return | |||
} | |||
if eggEnergyBasicSetting == nil { | |||
err = errors.New("蛋蛋能量设置未开启!") | |||
return | |||
} | |||
var priceSettingStruct *md2.PriceSettingStruct | |||
err = json.Unmarshal([]byte(eggEnergyBasicSetting.PriceSetting), &priceSettingStruct) | |||
if err != nil { | |||
return | |||
} | |||
if priceSettingStruct.PriceHigherThanValue == "" || priceSettingStruct.MarketplaceMerchantsNumsExchangeMarketplaceMerchantsFundValue == "" || priceSettingStruct.PriceBelowValue == "" || priceSettingStruct.MarketplaceMerchantsFundExchangeMarketplaceMerchantsNumsValue == "" { | |||
err = errors.New("价格设置未完全!") | |||
return | |||
} | |||
session := engine.NewSession() | |||
defer func() { | |||
session.Close() | |||
if err := recover(); err != nil { | |||
_ = zhios_order_relate_logx.Error(err) | |||
} | |||
}() | |||
session.Begin() | |||
priceHigherThanValue, _ := decimal.NewFromString(priceSettingStruct.PriceHigherThanValue) | |||
marketplaceMerchantsNumsExchangeMarketplaceMerchantsFundValue, _ := decimal.NewFromString(priceSettingStruct.MarketplaceMerchantsNumsExchangeMarketplaceMerchantsFundValue) | |||
priceBelowValue, _ := decimal.NewFromString(priceSettingStruct.PriceBelowValue) | |||
marketplaceMerchantsFundExchangeMarketplaceMerchantsNumsValue, _ := decimal.NewFromString(priceSettingStruct.MarketplaceMerchantsFundExchangeMarketplaceMerchantsNumsValue) | |||
nowPriceValue, _ := decimal.NewFromString(eggEnergyCoreData.NowPrice) | |||
if nowPriceValue.GreaterThan(priceHigherThanValue) { | |||
//当价格涨到设置某个价格时,自动执行 市商数量 兑换 市商资金 (降价公式) | |||
err1, resp := CalcPriceReductionFormula(marketplaceMerchantsNumsExchangeMarketplaceMerchantsFundValue.String(), eggEnergyCoreData) | |||
if err1 != nil { | |||
fmt.Println("err1111:::", err1) | |||
_ = session.Rollback() | |||
return err1 | |||
} | |||
// 市商数量 减少、市商资金 增加 | |||
err = DealAvailableGreenEnergyCoin(session, int(enum.MarketplaceMerchantNumsAutoExchangeMarketplaceMerchantFunds), egg_system_rules.StrToFloat64(marketplaceMerchantsNumsExchangeMarketplaceMerchantsFundValue.String()), egg_system_rules.StrToFloat64(amount), enum.MarketplaceMerchantNumsAutoExchangeMarketplaceMerchantFunds.String(), oneCirclesGreenEnergyBasicSetting, afterPriceValue, masterId) | |||
if err != nil { | |||
fmt.Println("err:::::22222", err) | |||
_ = session.Rollback() | |||
return err | |||
} | |||
} | |||
if nowPriceValue.LessThan(priceBelowValue) { | |||
//当价格降到设置某个价格时,自动执行 市商资金 兑换 市商数量 (涨价公式) | |||
err1, resp := CalcPriceReductionFormula(marketplaceMerchantsNumsExchangeMarketplaceMerchantsFundValue.String(), eggEnergyCoreData) | |||
if err1 != nil { | |||
fmt.Println("err1111:::", err1) | |||
_ = session.Rollback() | |||
return err1 | |||
} | |||
// 市商数量 增加、市商资金 减少 | |||
err = DealAvailableGreenEnergyCoin(session, int(enum.MarketplaceMerchantFundsAutoExchangeMarketplaceMerchantNums), egg_system_rules.StrToFloat64(greenEnergy), egg_system_rules.StrToFloat64(marketplaceMerchantsFundExchangeMarketplaceMerchantsNumsValue.String()), enum.MarketplaceMerchantFundsAutoExchangeMarketplaceMerchantNums.String(), oneCirclesGreenEnergyBasicSetting, afterPriceValue, masterId) | |||
if err != nil { | |||
fmt.Println("err:::::44444", err) | |||
_ = session.Rollback() | |||
return err | |||
} | |||
} | |||
err = session.Commit() | |||
if err != nil { | |||
_ = session.Rollback() | |||
return errors.New("事务提交失败") | |||
} | |||
return | |||
} |
@@ -0,0 +1,116 @@ | |||
package egg_energy | |||
import ( | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/db" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/db/model" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/md" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/cache" | |||
zhios_order_relate_logx "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/logx" | |||
"errors" | |||
"fmt" | |||
"github.com/shopspring/decimal" | |||
"time" | |||
"xorm.io/xorm" | |||
) | |||
const LockKey = "auto_release_exchange_green_energy_lock_key" | |||
// AutoReleaseExchangeGreenEnergy 结算绿色能量自动释放成可用绿色能量 | |||
func AutoReleaseExchangeGreenEnergy(engine *xorm.Engine, masterId string) (err error) { | |||
now := time.Now() | |||
fmt.Println(now.Hour()) | |||
if !(now.Hour() > 1 && now.Hour() < 8) { | |||
//TODO::只在凌晨一点 ~ 凌晨 8 点运行 | |||
return errors.New("非运行时间") | |||
} | |||
//TODO::增加“悲观锁”防止串行 | |||
getString, _ := cache.GetString(LockKey) | |||
//if err != nil { | |||
// return err | |||
//} | |||
if getString != "" { | |||
fmt.Println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", "上一次结算未执行完") | |||
return errors.New("上一次结算未执行完") | |||
} | |||
cache.SetEx(LockKey, "running", 3600*8) //8小时 | |||
//1、查找 `one_circles_green_energy_basic_setting` 基础设置 && `one_circles_public_platoon_basic_setting` 基础设置 | |||
oneCirclesGreenEnergyBasicSetting, err := db.OneCirclesGreenEnergyBasicSettingGetOneByParams(engine, map[string]interface{}{ | |||
"key": "is_open", | |||
"value": 1, | |||
}) | |||
if err != nil { | |||
return | |||
} | |||
settlementQuantity := oneCirclesGreenEnergyBasicSetting.SettlementQuantity | |||
fmt.Println("settlementQuantity>>>>>>>>>>>>", settlementQuantity) | |||
//2、当前 "可用"绿色能量可以兑换的用户数据 | |||
var list1 []model.UserVirtualAmount | |||
err = engine.Where("coin_id = ?", oneCirclesGreenEnergyBasicSetting.TeamGreenEnergyCoinId).And("amount > ?", 0).Find(&list1) | |||
if err != nil { | |||
fmt.Println("err:::::1111", err) | |||
return | |||
} | |||
//4、处理释放 | |||
settlementQuantityRadio := decimal.NewFromFloat(100) | |||
settlementQuantityValue := decimal.NewFromInt(int64(settlementQuantity)).Div(settlementQuantityRadio) | |||
for _, v := range list1 { | |||
userAmount, _ := decimal.NewFromString(v.Amount) | |||
settlementQuantityAmount, _ := userAmount.Mul(settlementQuantityValue).Float64() | |||
if settlementQuantityAmount > 0 { | |||
session := engine.NewSession() | |||
defer func() { | |||
session.Close() | |||
if err := recover(); err != nil { | |||
_ = zhios_order_relate_logx.Error(err) | |||
} | |||
}() | |||
session.Begin() | |||
//4.2给相应的用户加上个人的绿色积分(可用数量) | |||
err = DealUserCoin(session, md.DealUserCoinReq{ | |||
Kind: "add", | |||
Mid: masterId, | |||
Title: md.OneCirclesSettlementGreenEnergyExchangeGreenEnergy, | |||
TransferType: md.OneCirclesSettlementGreenEnergyExchangeGreenEnergyForUserVirtualCoinFlow, | |||
OrdId: "", | |||
CoinId: oneCirclesGreenEnergyBasicSetting.PersonGreenEnergyCoinId, | |||
Uid: v.Uid, | |||
Amount: settlementQuantityAmount, | |||
}) | |||
if err != nil { | |||
_ = session.Rollback() | |||
fmt.Println("err:::::22222", err) | |||
continue | |||
} | |||
//4.2给相应的用户减少个人的绿色积分(结算数量) | |||
err = DealUserCoin(session, md.DealUserCoinReq{ | |||
Kind: "sub", | |||
Mid: masterId, | |||
Title: md.OneCirclesSettlementGreenEnergyExchangeTobeGreenEnergy, | |||
TransferType: md.OneCirclesSettlementGreenEnergyExchangeTobeGreenEnergyForUserVirtualCoinFlow, | |||
OrdId: "", | |||
CoinId: oneCirclesGreenEnergyBasicSetting.TeamGreenEnergyCoinId, | |||
Uid: v.Uid, | |||
Amount: settlementQuantityAmount, | |||
}) | |||
if err != nil { | |||
_ = session.Rollback() | |||
fmt.Println("err:::::33333", err) | |||
continue | |||
} | |||
err = session.Commit() | |||
if err != nil { | |||
_ = session.Rollback() | |||
continue | |||
} | |||
} | |||
} | |||
return | |||
} |
@@ -0,0 +1,51 @@ | |||
package egg_energy | |||
import ( | |||
"code.fnuoos.com/EggPlanet/egg_models.git/src/model" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/md" | |||
egg_system_rules "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils" | |||
"github.com/shopspring/decimal" | |||
) | |||
// CalcPriceIncreaseFormula 计算涨价公式(【用户资金 ÷(用户资金+星球价值)÷ 现行数量】 = 用户获得蛋蛋能量个数) | |||
func CalcPriceIncreaseFormula(userAmountValue string, eggEnergyCoreData *model.EggEnergyCoreData) (err error, resp md.CalcPriceIncreaseFormulaResp) { | |||
userAmount, _ := decimal.NewFromString(userAmountValue) //用户资金 | |||
nowPrice, _ := decimal.NewFromString(eggEnergyCoreData.NowPrice) //当前价格 | |||
nowEnergyTotalNums, _ := decimal.NewFromString(eggEnergyCoreData.NowEnergyTotalNums) //现行数量 | |||
planetTotalValue, _ := decimal.NewFromString(eggEnergyCoreData.PlanetTotalValue) //星球价值 | |||
afterPrice := (planetTotalValue.Add(userAmount)).Div(nowEnergyTotalNums).Truncate(8) //涨价后的价格 | |||
getEggEnergyNumsValue := userAmount.Div(afterPrice).Truncate(8) //用户得到绿色能量个数 | |||
afterEnergyTotalNumsValue := nowEnergyTotalNums.Add(getEggEnergyNumsValue) //变更后-现行数量 | |||
afterPlanetTotalValue := afterEnergyTotalNumsValue.Mul(afterPrice) //变更后-星球价值 | |||
resp.GetEggEnergyNums = getEggEnergyNumsValue.String() | |||
resp.BeforePrice = nowPrice.String() | |||
resp.AfterPrice = afterPrice.String() | |||
resp.BeforePlanetTotalValue = eggEnergyCoreData.PlanetTotalValue | |||
resp.AfterPlanetTotalValue = afterPlanetTotalValue.String() | |||
resp.BeforeEnergyTotalNums = eggEnergyCoreData.NowEnergyTotalNums | |||
resp.AfterEnergyTotalNums = afterEnergyTotalNumsValue.String() | |||
egg_system_rules.FilePutContents("CalcPriceIncreaseFormula", egg_system_rules.SerializeStr(resp)) | |||
return | |||
} | |||
// CalcPriceReductionFormula 计算降价公式(【用户需兑换蛋蛋能量数量*{星球价值 ÷(用户需兑换蛋蛋能量数量+现行数量} *(1 - 扣比例50% ~ 23%) = 用户获得钱) | |||
func CalcPriceReductionFormula(userExchangeNumsValue string, eggEnergyCoreData *model.EggEnergyCoreData) (err error, resp md.CalcPriceReductionFormulaResp) { | |||
userExchangeNums, _ := decimal.NewFromString(userExchangeNumsValue) //用户兑换绿色能量 | |||
nowEnergyTotalNums, _ := decimal.NewFromString(eggEnergyCoreData.NowEnergyTotalNums) //现行数量 | |||
planetTotalValue, _ := decimal.NewFromString(eggEnergyCoreData.PlanetTotalValue) //星球价值 | |||
afterPrice := planetTotalValue.Div(userExchangeNums.Add(nowEnergyTotalNums)) //降价后的价格 | |||
greenEnergyValues := userExchangeNums.Mul(afterPrice) //用户获得的钱 | |||
afterEnergyTotalNumsValue := nowEnergyTotalNums.Sub(userExchangeNums) //变更后-现行数量 | |||
afterPlanetTotalValue := afterEnergyTotalNumsValue.Mul(afterPrice) //变更后-星球价值 | |||
resp.GetEggEnergyAmount = greenEnergyValues.Truncate(8).String() | |||
resp.BeforePrice = eggEnergyCoreData.NowPrice | |||
resp.AfterPrice = afterPrice.String() | |||
resp.BeforePlanetTotalValue = eggEnergyCoreData.PlanetTotalValue | |||
resp.AfterPlanetTotalValue = afterPlanetTotalValue.String() | |||
resp.BeforeEnergyTotalNums = eggEnergyCoreData.NowEnergyTotalNums | |||
resp.AfterEnergyTotalNums = afterEnergyTotalNumsValue.String() | |||
egg_system_rules.FilePutContents("CalcPriceReductionFormula", egg_system_rules.SerializeStr(resp)) | |||
return | |||
} |
@@ -0,0 +1,106 @@ | |||
package egg_energy | |||
import ( | |||
"code.fnuoos.com/EggPlanet/egg_models.git/src/model" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/enum" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/md" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/rule" | |||
enum2 "code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/enum" | |||
egg_system_rules "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils" | |||
zhios_order_relate_logx "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/logx" | |||
"errors" | |||
"fmt" | |||
"github.com/shopspring/decimal" | |||
"time" | |||
"xorm.io/xorm" | |||
) | |||
// CommunityDividends 社区分红 | |||
func CommunityDividends(engine *xorm.Engine, masterId string) (err error) { | |||
//1、查找当前是否有待分红的记录 | |||
var m model.EggEnergyCommunityDividends | |||
has, err := engine.Where("is_over = 0").Get(&m) | |||
if err != nil { | |||
fmt.Println("err::::::1111", err.Error()) | |||
return | |||
} | |||
if has { | |||
//3、查找 `egg_energy_community_dividends_with_user` 数据 | |||
var list []model.EggEnergyCommunityDividendsWithUser | |||
err = engine.Where("1 = 1").Find(&list) | |||
totalValue := decimal.NewFromInt(int64(m.Nums)) | |||
singleValue, _ := totalValue.Div(decimal.NewFromInt(int64(len(list)))).Float64() | |||
session := engine.NewSession() | |||
defer func() { | |||
session.Close() | |||
if err := recover(); err != nil { | |||
_ = zhios_order_relate_logx.Error(err) | |||
} | |||
}() | |||
session.Begin() | |||
now := time.Now() | |||
for _, v := range list { | |||
//4、 给相应的用户加上分红权益 | |||
err = rule.DealUserVirtualCoin(session, md.DealUserVirtualCoinReq{ | |||
Kind: "add", | |||
Title: enum.EggEnergyCommunityDividends.String(), | |||
TransferType: int(enum.EggEnergyCommunityDividends), | |||
CoinId: m.CoinId, | |||
Uid: v.Uid, | |||
Amount: singleValue, | |||
}) | |||
if err != nil { | |||
_ = session.Rollback() | |||
fmt.Println("err:::::33333", err) | |||
return err | |||
} | |||
//5、增加 egg_energy_community_dividends_with_user_records 记录 | |||
_, err = session.InsertOne(&model.EggEnergyCommunityDividendsWithUserRecords{ | |||
Uid: v.Uid, | |||
Value: egg_system_rules.Float64ToStr(singleValue), | |||
RecordsId: m.Id, | |||
CoinId: m.CoinId, | |||
CreateAt: now.Format("2006-01-02 15:04:05"), | |||
UpdateAt: now.Format("2006-01-02 15:04:05"), | |||
}) | |||
if err != nil { | |||
_ = session.Rollback() | |||
fmt.Println("err:::::insert", err) | |||
return err | |||
} | |||
} | |||
//6、 增加“社区分红”钱包中的记录值 | |||
totalDividend, _ := totalValue.Float64() | |||
err = DealAvailableGreenEnergyCoin(session, int(enum2.CommunityDividends), totalDividend, 0, enum2.CommunityDividends.String(), nil, "", masterId) | |||
if err != nil { | |||
_ = session.Rollback() | |||
fmt.Println("err:::::444444", err) | |||
return err | |||
} | |||
//7、修改 egg_energy_community_dividends 记录 | |||
m.IsOver = 1 | |||
m.PersonsNum = len(list) | |||
affected, err := session.Where("id=?", m.Id).Cols("is_over", "persons_num").Update(m) | |||
if err != nil { | |||
_ = session.Rollback() | |||
fmt.Println("err:::::5555555", err) | |||
return err | |||
} | |||
if affected == 0 { | |||
_ = session.Rollback() | |||
fmt.Println("err:::::6666666", errors.New("更新 egg_energy_community_dividends 记录失败")) | |||
return err | |||
} | |||
err = session.Commit() | |||
if err != nil { | |||
_ = session.Rollback() | |||
return errors.New("事务提交失败") | |||
} | |||
} | |||
return | |||
} |
@@ -0,0 +1,493 @@ | |||
package egg_energy | |||
import ( | |||
"code.fnuoos.com/EggPlanet/egg_models.git/src/model" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/enum" | |||
md2 "code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/md" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/svc" | |||
"encoding/json" | |||
"github.com/shopspring/decimal" | |||
"time" | |||
"xorm.io/xorm" | |||
) | |||
func DealAvailableGreenEnergyCoin(session *xorm.Session, kind int, amount, amountFee float64, title string, eggEnergyCoreData *model.EggEnergyCoreData, nowPriceValue string) error { | |||
if eggEnergyCoreData == nil { | |||
// 查找 `egg_energy_core_data` 基础设置 | |||
oneCirclesGreenEnergyBasicSetting, cb, err := svc.GetEggEnergyCoreData(session.Engine()) | |||
nowPriceValue = oneCirclesGreenEnergyBasicSetting.NowPrice | |||
if err != nil { | |||
return err | |||
} | |||
if cb != nil { | |||
defer cb() // 释放锁 | |||
} | |||
chain = oneCirclesGreenEnergyBasicSetting | |||
} | |||
amountValue := decimal.NewFromFloat(amount) | |||
now := time.Now() | |||
var oneCirclesAvailableGreenEnergyPointsFlow model.OneCirclesAvailableGreenEnergyPointsFlow | |||
oneCirclesAvailableGreenEnergyPointsFlow.CoinId = chain.PersonGreenEnergyCoinId | |||
oneCirclesAvailableGreenEnergyPointsFlow.Kind = kind | |||
oneCirclesAvailableGreenEnergyPointsFlow.Title = title | |||
oneCirclesAvailableGreenEnergyPointsFlow.Amount = amountValue.RoundFloor(8).String() | |||
oneCirclesAvailableGreenEnergyPointsFlow.CreateTime = now | |||
nowPrice, _ := decimal.NewFromString(nowPriceValue) | |||
switch kind { | |||
case int(enum.PersonalActivePointRedemption): //个人活跃积分兑换 | |||
beforeOriginalQuantity, _ := decimal.NewFromString(chain.OriginalQuantityNums) | |||
oneCirclesAvailableGreenEnergyPointsFlow.Direction = 1 | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeEcologicalApplicationValues = chain.EcologicalApplication //生态应用 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterEcologicalApplicationValues = chain.EcologicalApplication | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeTechnicalTeamValues = chain.TotalTechnologyTeam //技术团队 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterTechnicalTeamValues = chain.TotalTechnologyTeam | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOperateTeamValues = chain.TotalOperateTeam //运营团队 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOperateTeamValues = chain.TotalOperateTeam | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeActiveGiveawaysValues = chain.TotalActiveGiveaways //活跃赠送 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterActiveGiveawaysValues = chain.TotalActiveGiveaways | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOriginalQuantityValues = chain.OriginalQuantityNums //原始数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOriginalQuantityValues = beforeOriginalQuantity.Sub(amountValue).RoundFloor(8).String() | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeMarketplaceMerchantValues = chain.MarketplaceMerchantNums //市商数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterMarketplaceMerchantValues = chain.MarketplaceMerchantNums | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeDevelopmentCommitteeValues = chain.DevelopmentCommittee //发展委员会 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterDevelopmentCommitteeValues = chain.DevelopmentCommittee | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforePublicWelfareAndCharityValues = chain.PublicWelfareAndCharity //公益慈善 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterPublicWelfareAndCharityValues = chain.PublicWelfareAndCharity | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeStarLevelDividendsValues = chain.StarLevelDividends //星级分红 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterStarLevelDividendsValues = chain.StarLevelDividends | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeCommunityDividends = chain.CommunityDividends //社区分红 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterCommunityDividends = chain.CommunityDividends | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeDestructionQuantityValues = chain.DestructionQuantityNums //销毁数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterDestructionQuantityValues = chain.DestructionQuantityNums | |||
amountFeeValue := decimal.NewFromFloat(amountFee) //积分价值 | |||
originalFunds, _ := decimal.NewFromString(chain.OriginalFunds) //原始资金 | |||
afterOriginalFundValues := originalFunds.Add(amountFeeValue).RoundFloor(8).String() | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOriginalQuantityFundValues = chain.OriginalFunds //原始资金 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOriginalQuantityFundValues = afterOriginalFundValues | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeMarketplaceMerchantFundValues = chain.MarketplaceMerchantFunds //市商资金 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterMarketplaceMerchantFundValues = chain.MarketplaceMerchantFunds | |||
break | |||
case int(enum.TeamActivePointRedemption): //团队活跃积分兑换 | |||
beforeOriginalQuantity, _ := decimal.NewFromString(chain.OriginalQuantityNums) | |||
oneCirclesAvailableGreenEnergyPointsFlow.Direction = 1 | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeEcologicalApplicationValues = chain.EcologicalApplication //生态应用 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterEcologicalApplicationValues = chain.EcologicalApplication | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeTechnicalTeamValues = chain.TotalTechnologyTeam //技术团队 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterTechnicalTeamValues = chain.TotalTechnologyTeam | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOperateTeamValues = chain.TotalOperateTeam //运营团队 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOperateTeamValues = chain.TotalOperateTeam | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeActiveGiveawaysValues = chain.TotalActiveGiveaways //活跃赠送 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterActiveGiveawaysValues = chain.TotalActiveGiveaways | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOriginalQuantityValues = chain.OriginalQuantityNums //原始数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOriginalQuantityValues = beforeOriginalQuantity.Sub(amountValue).RoundFloor(8).String() | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeMarketplaceMerchantValues = chain.MarketplaceMerchantNums //市商数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterMarketplaceMerchantValues = chain.MarketplaceMerchantNums | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeDevelopmentCommitteeValues = chain.DevelopmentCommittee //发展委员会 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterDevelopmentCommitteeValues = chain.DevelopmentCommittee | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforePublicWelfareAndCharityValues = chain.PublicWelfareAndCharity //公益慈善 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterPublicWelfareAndCharityValues = chain.PublicWelfareAndCharity | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeStarLevelDividendsValues = chain.StarLevelDividends //星级分红 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterStarLevelDividendsValues = chain.StarLevelDividends | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeCommunityDividends = chain.CommunityDividends //社区分红 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterCommunityDividends = chain.CommunityDividends | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeDestructionQuantityValues = chain.DestructionQuantityNums //销毁数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterDestructionQuantityValues = chain.DestructionQuantityNums | |||
amountFeeValue := decimal.NewFromFloat(amountFee) //积分价值 | |||
originalFunds, _ := decimal.NewFromString(chain.OriginalFunds) //原始资金 | |||
afterOriginalFundValues := originalFunds.Add(amountFeeValue).RoundFloor(8).String() | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOriginalQuantityFundValues = chain.OriginalFunds //原始资金 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOriginalQuantityFundValues = afterOriginalFundValues | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeMarketplaceMerchantFundValues = chain.MarketplaceMerchantFunds //市商资金 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterMarketplaceMerchantFundValues = chain.MarketplaceMerchantFunds | |||
break | |||
case int(enum.SettlementOfGreenEnergyRelease): //结算绿色能量释放 | |||
oneCirclesAvailableGreenEnergyPointsFlow.Direction = 1 | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeEcologicalApplicationValues = chain.EcologicalApplication //生态应用 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterEcologicalApplicationValues = chain.EcologicalApplication | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeTechnicalTeamValues = chain.TotalTechnologyTeam //技术团队 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterTechnicalTeamValues = chain.TotalTechnologyTeam | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOperateTeamValues = chain.TotalOperateTeam //运营团队 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOperateTeamValues = chain.TotalOperateTeam | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeActiveGiveawaysValues = chain.TotalActiveGiveaways //活跃赠送 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterActiveGiveawaysValues = chain.TotalActiveGiveaways | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOriginalQuantityValues = chain.OriginalQuantityNums //原始数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOriginalQuantityValues = chain.OriginalQuantityNums | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeMarketplaceMerchantValues = chain.MarketplaceMerchantNums //市商数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterMarketplaceMerchantValues = chain.MarketplaceMerchantNums | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeDevelopmentCommitteeValues = chain.DevelopmentCommittee //发展委员会 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterDevelopmentCommitteeValues = chain.DevelopmentCommittee | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforePublicWelfareAndCharityValues = chain.PublicWelfareAndCharity //公益慈善 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterPublicWelfareAndCharityValues = chain.PublicWelfareAndCharity | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeStarLevelDividendsValues = chain.StarLevelDividends //星级分红 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterStarLevelDividendsValues = chain.StarLevelDividends | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeCommunityDividends = chain.CommunityDividends //社区分红 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterCommunityDividends = chain.CommunityDividends | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeDestructionQuantityValues = chain.DestructionQuantityNums //销毁数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterDestructionQuantityValues = chain.DestructionQuantityNums | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOriginalQuantityFundValues = chain.OriginalFunds //原始资金 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOriginalQuantityFundValues = chain.OriginalFunds | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeMarketplaceMerchantFundValues = chain.MarketplaceMerchantFunds //市商资金 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterMarketplaceMerchantFundValues = chain.MarketplaceMerchantFunds | |||
break | |||
case int(enum.SignInReward): //签到奖励 | |||
beforeTotalActiveGiveaways, _ := decimal.NewFromString(chain.TotalActiveGiveaways) | |||
oneCirclesAvailableGreenEnergyPointsFlow.Direction = 1 | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeEcologicalApplicationValues = chain.EcologicalApplication //生态应用 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterEcologicalApplicationValues = chain.EcologicalApplication | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeTechnicalTeamValues = chain.TotalTechnologyTeam //技术团队 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterTechnicalTeamValues = chain.TotalTechnologyTeam | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOperateTeamValues = chain.TotalOperateTeam //运营团队 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOperateTeamValues = chain.TotalOperateTeam | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeActiveGiveawaysValues = chain.TotalActiveGiveaways //活跃赠送 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterActiveGiveawaysValues = beforeTotalActiveGiveaways.Sub(amountValue).RoundFloor(8).String() | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOriginalQuantityValues = chain.OriginalQuantityNums //原始数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOriginalQuantityValues = chain.OriginalQuantityNums | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeMarketplaceMerchantValues = chain.MarketplaceMerchantNums //市商数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterMarketplaceMerchantValues = chain.MarketplaceMerchantNums | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeDevelopmentCommitteeValues = chain.DevelopmentCommittee //发展委员会 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterDevelopmentCommitteeValues = chain.DevelopmentCommittee | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforePublicWelfareAndCharityValues = chain.PublicWelfareAndCharity //公益慈善 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterPublicWelfareAndCharityValues = chain.PublicWelfareAndCharity | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeStarLevelDividendsValues = chain.StarLevelDividends //星级分红 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterStarLevelDividendsValues = chain.StarLevelDividends | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeCommunityDividends = chain.CommunityDividends //社区分红 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterCommunityDividends = chain.CommunityDividends | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeDestructionQuantityValues = chain.DestructionQuantityNums //销毁数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterDestructionQuantityValues = chain.DestructionQuantityNums | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeMarketplaceMerchantFundValues = chain.MarketplaceMerchantFunds //市商资金 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterMarketplaceMerchantFundValues = chain.MarketplaceMerchantFunds | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOriginalQuantityFundValues = chain.OriginalFunds //原始资金 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOriginalQuantityFundValues = chain.OriginalFunds | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeMarketplaceMerchantFundValues = chain.MarketplaceMerchantFunds //市商资金 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterMarketplaceMerchantFundValues = chain.MarketplaceMerchantFunds | |||
break | |||
case int(enum.AccountBalanceExchange): //账户余额兑换 | |||
beforeOriginalQuantity, _ := decimal.NewFromString(chain.OriginalQuantityNums) | |||
oneCirclesAvailableGreenEnergyPointsFlow.Direction = 1 | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeEcologicalApplicationValues = chain.EcologicalApplication //生态应用 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterEcologicalApplicationValues = chain.EcologicalApplication | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeTechnicalTeamValues = chain.TotalTechnologyTeam //技术团队 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterTechnicalTeamValues = chain.TotalTechnologyTeam | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOperateTeamValues = chain.TotalOperateTeam //运营团队 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOperateTeamValues = chain.TotalOperateTeam | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeActiveGiveawaysValues = chain.TotalActiveGiveaways //活跃赠送 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterActiveGiveawaysValues = chain.TotalActiveGiveaways | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOriginalQuantityValues = chain.OriginalQuantityNums //原始数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOriginalQuantityValues = beforeOriginalQuantity.Sub(amountValue).RoundFloor(8).String() | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeMarketplaceMerchantValues = chain.MarketplaceMerchantNums //市商数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterMarketplaceMerchantValues = chain.MarketplaceMerchantNums | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeDevelopmentCommitteeValues = chain.DevelopmentCommittee //发展委员会 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterDevelopmentCommitteeValues = chain.DevelopmentCommittee | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforePublicWelfareAndCharityValues = chain.PublicWelfareAndCharity //公益慈善 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterPublicWelfareAndCharityValues = chain.PublicWelfareAndCharity | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeStarLevelDividendsValues = chain.StarLevelDividends //星级分红 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterStarLevelDividendsValues = chain.StarLevelDividends | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeCommunityDividends = chain.CommunityDividends //社区分红 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterCommunityDividends = chain.CommunityDividends | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeDestructionQuantityValues = chain.DestructionQuantityNums //销毁数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterDestructionQuantityValues = chain.DestructionQuantityNums | |||
amountFeeValue := decimal.NewFromFloat(amountFee) //余额价值 | |||
originalFunds, _ := decimal.NewFromString(chain.OriginalFunds) //原始资金 | |||
afterOriginalFundValues := originalFunds.Add(amountFeeValue).RoundFloor(8).String() | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOriginalQuantityFundValues = chain.OriginalFunds //原始资金 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOriginalQuantityFundValues = afterOriginalFundValues | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeMarketplaceMerchantFundValues = chain.MarketplaceMerchantFunds //市商资金 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterMarketplaceMerchantFundValues = chain.MarketplaceMerchantFunds | |||
break | |||
case int(enum.GreenEnergyExchangeBalance): //兑换账户余额 | |||
var destructionSetting *md2.DestructionSettingStruct | |||
err := json.Unmarshal([]byte(chain.DestructionSetting), &destructionSetting) | |||
if err != nil { | |||
return err | |||
} | |||
decimalRate := decimal.NewFromInt(100) //百分比 | |||
amountFeeValue := decimal.NewFromFloat(amountFee) //手续费 | |||
marketplaceMerchantNums, _ := decimal.NewFromString(chain.MarketplaceMerchantNums) | |||
marketplaceMerchant, _ := decimal.NewFromString(destructionSetting.MarketplaceMerchant) //市商数量百分比 | |||
afterMarketplaceMerchantValues := marketplaceMerchantNums.Add(amountFeeValue.Mul(marketplaceMerchant.Div(decimalRate))).RoundFloor(8).String() | |||
developmentCommitteeNums, _ := decimal.NewFromString(chain.DevelopmentCommittee) | |||
developmentCommittee, _ := decimal.NewFromString(destructionSetting.DevelopmentCommittee) //发展委员会百分比 | |||
afterDevelopmentCommitteeValues := developmentCommitteeNums.Add(amountFeeValue.Mul(developmentCommittee.Div(decimalRate))).RoundFloor(8).String() | |||
publicWelfareAndCharityNums, _ := decimal.NewFromString(chain.PublicWelfareAndCharity) | |||
publicWelfareAndCharity, _ := decimal.NewFromString(destructionSetting.PublicWelfareAndCharity) //公益慈善百分比 | |||
afterPublicWelfareAndCharityValues := publicWelfareAndCharityNums.Add(amountFeeValue.Mul(publicWelfareAndCharity.Div(decimalRate))).RoundFloor(8).String() | |||
starLevelDividendsNums, _ := decimal.NewFromString(chain.StarLevelDividends) | |||
starLevelDividends, _ := decimal.NewFromString(destructionSetting.StarLevelDividends) //星级分红百分比 | |||
afterStarLevelDividendsValues := starLevelDividendsNums.Add(amountFeeValue.Mul(starLevelDividends.Div(decimalRate))).RoundFloor(8).String() | |||
var afterCommunityDividendsValues = chain.CommunityDividends | |||
if chain.CommunityDividends != "" { | |||
communityDividendsNums, _ := decimal.NewFromString(chain.CommunityDividends) | |||
communityDividends, _ := decimal.NewFromString(destructionSetting.CommunityDividends) //社区分红百分比 | |||
afterCommunityDividendsValues = communityDividendsNums.Add(amountFeeValue.Mul(communityDividends.Div(decimalRate))).RoundFloor(8).String() | |||
} | |||
destructionQuantityNums, _ := decimal.NewFromString(chain.DestructionQuantityNums) | |||
destructionQuantity, _ := decimal.NewFromString(destructionSetting.DestructionQuantity) //销毁百分比 | |||
afterDestructionQuantityValues := destructionQuantityNums.Add(amountFeeValue.Mul(destructionQuantity.Div(decimalRate))).RoundFloor(8).String() | |||
originalQuantityNums, _ := decimal.NewFromString(chain.OriginalQuantityNums) //原始数量 | |||
afterOriginalQuantityValues := originalQuantityNums.Add(amountValue.Sub(amountFeeValue)).RoundFloor(8).String() | |||
originalFunds, _ := decimal.NewFromString(chain.OriginalFunds) //原始资金 | |||
afterOriginalFundValues := originalFunds.Sub(nowPrice.Mul(amountValue.Sub(amountFeeValue))).RoundFloor(8).String() | |||
oneCirclesAvailableGreenEnergyPointsFlow.Direction = 1 | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeEcologicalApplicationValues = chain.EcologicalApplication //生态应用 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterEcologicalApplicationValues = chain.EcologicalApplication | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeTechnicalTeamValues = chain.TotalTechnologyTeam //技术团队 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterTechnicalTeamValues = chain.TotalTechnologyTeam | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOperateTeamValues = chain.TotalOperateTeam //运营团队 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOperateTeamValues = chain.TotalOperateTeam | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeActiveGiveawaysValues = chain.TotalActiveGiveaways //活跃赠送 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterActiveGiveawaysValues = chain.TotalActiveGiveaways | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOriginalQuantityValues = chain.OriginalQuantityNums //原始数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOriginalQuantityValues = afterOriginalQuantityValues | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeMarketplaceMerchantValues = chain.MarketplaceMerchantNums //市商数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterMarketplaceMerchantValues = afterMarketplaceMerchantValues | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterMarketplaceMerchantValues = afterMarketplaceMerchantValues | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeDevelopmentCommitteeValues = chain.DevelopmentCommittee //发展委员会 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterDevelopmentCommitteeValues = afterDevelopmentCommitteeValues | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforePublicWelfareAndCharityValues = chain.PublicWelfareAndCharity //公益慈善 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterPublicWelfareAndCharityValues = afterPublicWelfareAndCharityValues | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeStarLevelDividendsValues = chain.StarLevelDividends //星级分红 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterStarLevelDividendsValues = afterStarLevelDividendsValues | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeCommunityDividends = chain.CommunityDividends //社区分红百分比 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterCommunityDividends = afterCommunityDividendsValues | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeDestructionQuantityValues = chain.DestructionQuantityNums //销毁数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterDestructionQuantityValues = afterDestructionQuantityValues | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeMarketplaceMerchantFundValues = chain.MarketplaceMerchantFunds //市商资金 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterMarketplaceMerchantFundValues = chain.MarketplaceMerchantFunds | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOriginalQuantityFundValues = chain.OriginalFunds //原始资金 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOriginalQuantityFundValues = afterOriginalFundValues | |||
//TODO::新增 / 更新 one_circles_star_level_dividends_records 记录 | |||
oneCirclesStarLevelDividendsRecords, err := db.OneCirclesStarLevelDividendsRecordsGetOneByParamsBySession(session, map[string]interface{}{ | |||
"key": "date", | |||
"value": now.Format("2006-01-02"), | |||
}) | |||
if err != nil { | |||
return err | |||
} | |||
if oneCirclesStarLevelDividendsRecords == nil { | |||
oneCirclesStarLevelDividendsRecords = &model.OneCirclesStarLevelDividendsRecords{ | |||
Amount: amountFeeValue.Mul(starLevelDividends.Div(decimalRate)).String(), | |||
AlreadyDividendsAmount: "", | |||
NotDividendsAmount: "", | |||
Date: now.Format("2006-01-02"), | |||
} | |||
_, err = db.OneCirclesStarLevelDividendsRecordsInsertBySession(session, oneCirclesStarLevelDividendsRecords) | |||
if err != nil { | |||
return err | |||
} | |||
} else { | |||
oneCirclesStarLevelDividendsRecordsAmountValue, _ := decimal.NewFromString(oneCirclesStarLevelDividendsRecords.Amount) | |||
oneCirclesStarLevelDividendsRecordsAmountValue = oneCirclesStarLevelDividendsRecordsAmountValue.Add(amountFeeValue.Mul(starLevelDividends.Div(decimalRate))) | |||
oneCirclesStarLevelDividendsRecords.Amount = oneCirclesStarLevelDividendsRecordsAmountValue.String() | |||
_, err = db.OneCirclesStarLevelDividendsRecordsUpdateBySession(session, oneCirclesStarLevelDividendsRecords.Id, oneCirclesStarLevelDividendsRecords, "amount") | |||
if err != nil { | |||
return err | |||
} | |||
} | |||
break | |||
case int(enum.SettlementStarLevelDividends): //星级分红 | |||
beforeStarLevelDividends, _ := decimal.NewFromString(chain.StarLevelDividends) | |||
oneCirclesAvailableGreenEnergyPointsFlow.Direction = 1 | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeEcologicalApplicationValues = chain.EcologicalApplication //生态应用 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterEcologicalApplicationValues = chain.EcologicalApplication | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeTechnicalTeamValues = chain.TotalTechnologyTeam //技术团队 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterTechnicalTeamValues = chain.TotalTechnologyTeam | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOperateTeamValues = chain.TotalOperateTeam //运营团队 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOperateTeamValues = chain.TotalOperateTeam | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeActiveGiveawaysValues = chain.TotalActiveGiveaways //活跃赠送 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterActiveGiveawaysValues = chain.TotalActiveGiveaways | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOriginalQuantityValues = chain.OriginalQuantityNums //原始数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOriginalQuantityValues = chain.OriginalQuantityNums | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeMarketplaceMerchantValues = chain.MarketplaceMerchantNums //市商数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterMarketplaceMerchantValues = chain.MarketplaceMerchantNums | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeDevelopmentCommitteeValues = chain.DevelopmentCommittee //发展委员会 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterDevelopmentCommitteeValues = chain.DevelopmentCommittee | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforePublicWelfareAndCharityValues = chain.PublicWelfareAndCharity //公益慈善 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterPublicWelfareAndCharityValues = chain.PublicWelfareAndCharity | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeStarLevelDividendsValues = chain.StarLevelDividends //星级分红 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterStarLevelDividendsValues = beforeStarLevelDividends.Sub(amountValue).RoundFloor(8).String() | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeCommunityDividends = chain.CommunityDividends //社区分红 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterCommunityDividends = chain.CommunityDividends | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeDestructionQuantityValues = chain.DestructionQuantityNums //销毁数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterDestructionQuantityValues = chain.DestructionQuantityNums | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOriginalQuantityFundValues = chain.OriginalFunds //原始资金 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOriginalQuantityFundValues = chain.OriginalFunds | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeMarketplaceMerchantFundValues = chain.MarketplaceMerchantFunds //市商资金 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterMarketplaceMerchantFundValues = chain.MarketplaceMerchantFunds | |||
break | |||
case int(enum.MarketplaceMerchantNumsAutoExchangeMarketplaceMerchantFunds): //市商数量自动兑换市商资金 | |||
beforeOriginalQuantityNums, _ := decimal.NewFromString(chain.OriginalQuantityNums) | |||
beforeMarketplaceMerchantNums, _ := decimal.NewFromString(chain.MarketplaceMerchantNums) | |||
beforeOriginalFunds, _ := decimal.NewFromString(chain.OriginalFunds) | |||
beforeMarketplaceMerchantFunds, _ := decimal.NewFromString(chain.MarketplaceMerchantFunds) | |||
oneCirclesAvailableGreenEnergyPointsFlow.Direction = 1 | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeEcologicalApplicationValues = chain.EcologicalApplication //生态应用 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterEcologicalApplicationValues = chain.EcologicalApplication | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeTechnicalTeamValues = chain.TotalTechnologyTeam //技术团队 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterTechnicalTeamValues = chain.TotalTechnologyTeam | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOperateTeamValues = chain.TotalOperateTeam //运营团队 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOperateTeamValues = chain.TotalOperateTeam | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeActiveGiveawaysValues = chain.TotalActiveGiveaways //活跃赠送 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterActiveGiveawaysValues = chain.TotalActiveGiveaways | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOriginalQuantityValues = chain.OriginalQuantityNums //原始数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOriginalQuantityValues = beforeOriginalQuantityNums.Add(amountValue).String() | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeMarketplaceMerchantValues = chain.MarketplaceMerchantNums //市商数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterMarketplaceMerchantValues = beforeMarketplaceMerchantNums.Sub(amountValue).String() | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeDevelopmentCommitteeValues = chain.DevelopmentCommittee //发展委员会 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterDevelopmentCommitteeValues = chain.DevelopmentCommittee | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforePublicWelfareAndCharityValues = chain.PublicWelfareAndCharity //公益慈善 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterPublicWelfareAndCharityValues = chain.PublicWelfareAndCharity | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeStarLevelDividendsValues = chain.StarLevelDividends //星级分红 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterStarLevelDividendsValues = chain.StarLevelDividends //星级分红 | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeCommunityDividends = chain.CommunityDividends //社区分红 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterCommunityDividends = chain.CommunityDividends | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeDestructionQuantityValues = chain.DestructionQuantityNums //销毁数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterDestructionQuantityValues = chain.DestructionQuantityNums | |||
amountFeeValue := decimal.NewFromFloat(amountFee) //金额 | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOriginalQuantityFundValues = chain.OriginalFunds //原始资金 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOriginalQuantityFundValues = beforeOriginalFunds.Sub(amountFeeValue).String() | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeMarketplaceMerchantFundValues = chain.MarketplaceMerchantFunds //市商资金 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterMarketplaceMerchantFundValues = beforeMarketplaceMerchantFunds.Add(amountFeeValue).String() | |||
break | |||
case int(enum.MarketplaceMerchantFundsAutoExchangeMarketplaceMerchantNums): //市商资金自动兑换市商数量 | |||
beforeOriginalQuantityNums, _ := decimal.NewFromString(chain.OriginalQuantityNums) | |||
beforeMarketplaceMerchantNums, _ := decimal.NewFromString(chain.MarketplaceMerchantNums) | |||
beforeOriginalFunds, _ := decimal.NewFromString(chain.OriginalFunds) | |||
beforeMarketplaceMerchantFunds, _ := decimal.NewFromString(chain.MarketplaceMerchantFunds) | |||
oneCirclesAvailableGreenEnergyPointsFlow.Direction = 1 | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeEcologicalApplicationValues = chain.EcologicalApplication //生态应用 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterEcologicalApplicationValues = chain.EcologicalApplication | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeTechnicalTeamValues = chain.TotalTechnologyTeam //技术团队 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterTechnicalTeamValues = chain.TotalTechnologyTeam | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOperateTeamValues = chain.TotalOperateTeam //运营团队 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOperateTeamValues = chain.TotalOperateTeam | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeActiveGiveawaysValues = chain.TotalActiveGiveaways //活跃赠送 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterActiveGiveawaysValues = chain.TotalActiveGiveaways | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOriginalQuantityValues = chain.OriginalQuantityNums //原始数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOriginalQuantityValues = beforeOriginalQuantityNums.Sub(amountValue).String() | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeMarketplaceMerchantValues = chain.MarketplaceMerchantNums //市商数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterMarketplaceMerchantValues = beforeMarketplaceMerchantNums.Add(amountValue).String() | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeDevelopmentCommitteeValues = chain.DevelopmentCommittee //发展委员会 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterDevelopmentCommitteeValues = chain.DevelopmentCommittee | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforePublicWelfareAndCharityValues = chain.PublicWelfareAndCharity //公益慈善 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterPublicWelfareAndCharityValues = chain.PublicWelfareAndCharity | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeStarLevelDividendsValues = chain.StarLevelDividends //星级分红 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterStarLevelDividendsValues = chain.StarLevelDividends //星级分红 | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeCommunityDividends = chain.CommunityDividends //社区分红 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterCommunityDividends = chain.CommunityDividends | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeDestructionQuantityValues = chain.DestructionQuantityNums //销毁数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterDestructionQuantityValues = chain.DestructionQuantityNums | |||
amountFeeValue := decimal.NewFromFloat(amountFee) //金额 | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOriginalQuantityFundValues = chain.OriginalFunds //原始资金 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOriginalQuantityFundValues = beforeOriginalFunds.Add(amountFeeValue).String() | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeMarketplaceMerchantFundValues = chain.MarketplaceMerchantFunds //市商资金 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterMarketplaceMerchantFundValues = beforeMarketplaceMerchantFunds.Sub(amountFeeValue).String() | |||
break | |||
case int(enum.CommunityDividends): //社区分红 | |||
beforeCommunityDividends, _ := decimal.NewFromString(chain.CommunityDividends) | |||
oneCirclesAvailableGreenEnergyPointsFlow.Direction = 2 | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeEcologicalApplicationValues = chain.EcologicalApplication //生态应用 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterEcologicalApplicationValues = chain.EcologicalApplication | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeTechnicalTeamValues = chain.TotalTechnologyTeam //技术团队 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterTechnicalTeamValues = chain.TotalTechnologyTeam | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOperateTeamValues = chain.TotalOperateTeam //运营团队 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOperateTeamValues = chain.TotalOperateTeam | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeActiveGiveawaysValues = chain.TotalActiveGiveaways //活跃赠送 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterActiveGiveawaysValues = chain.TotalActiveGiveaways | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOriginalQuantityValues = chain.OriginalQuantityNums //原始数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOriginalQuantityValues = chain.OriginalQuantityNums | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeMarketplaceMerchantValues = chain.MarketplaceMerchantNums //市商数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterMarketplaceMerchantValues = chain.MarketplaceMerchantNums | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeDevelopmentCommitteeValues = chain.DevelopmentCommittee //发展委员会 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterDevelopmentCommitteeValues = chain.DevelopmentCommittee | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforePublicWelfareAndCharityValues = chain.PublicWelfareAndCharity //公益慈善 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterPublicWelfareAndCharityValues = chain.PublicWelfareAndCharity | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeStarLevelDividendsValues = chain.StarLevelDividends //星级分红 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterStarLevelDividendsValues = chain.StarLevelDividends //星级分红 | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeDestructionQuantityValues = chain.DestructionQuantityNums //销毁数量 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterDestructionQuantityValues = chain.DestructionQuantityNums | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeOriginalQuantityFundValues = chain.OriginalFunds //原始资金 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterOriginalQuantityFundValues = chain.OriginalFunds | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeMarketplaceMerchantFundValues = chain.MarketplaceMerchantFunds //市商资金 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterMarketplaceMerchantFundValues = chain.MarketplaceMerchantFunds | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforeCommunityDividends = chain.CommunityDividends //社区分红 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterCommunityDividends = beforeCommunityDividends.Sub(amountValue).RoundFloor(8).String() | |||
break | |||
} | |||
chain.EcologicalApplication = oneCirclesAvailableGreenEnergyPointsFlow.AfterEcologicalApplicationValues //生态应用 | |||
chain.TotalTechnologyTeam = oneCirclesAvailableGreenEnergyPointsFlow.AfterTechnicalTeamValues //技术团队 | |||
chain.TotalOperateTeam = oneCirclesAvailableGreenEnergyPointsFlow.AfterOperateTeamValues //运营团队 | |||
chain.TotalActiveGiveaways = oneCirclesAvailableGreenEnergyPointsFlow.AfterActiveGiveawaysValues //活跃赠送 | |||
chain.OriginalQuantityNums = oneCirclesAvailableGreenEnergyPointsFlow.AfterOriginalQuantityValues //原始数量 | |||
chain.MarketplaceMerchantNums = oneCirclesAvailableGreenEnergyPointsFlow.AfterMarketplaceMerchantValues //市商数量 | |||
chain.DevelopmentCommittee = oneCirclesAvailableGreenEnergyPointsFlow.AfterDevelopmentCommitteeValues //发展委员会 | |||
chain.PublicWelfareAndCharity = oneCirclesAvailableGreenEnergyPointsFlow.AfterPublicWelfareAndCharityValues //公益慈善 | |||
chain.StarLevelDividends = oneCirclesAvailableGreenEnergyPointsFlow.AfterStarLevelDividendsValues //星级分红 | |||
chain.CommunityDividends = oneCirclesAvailableGreenEnergyPointsFlow.AfterCommunityDividends //社区分红 | |||
chain.DestructionQuantityNums = oneCirclesAvailableGreenEnergyPointsFlow.AfterDestructionQuantityValues //销毁数量 | |||
chain.OriginalFunds = oneCirclesAvailableGreenEnergyPointsFlow.AfterOriginalQuantityFundValues //原始资金 | |||
chain.MarketplaceMerchantFunds = oneCirclesAvailableGreenEnergyPointsFlow.AfterMarketplaceMerchantFundValues //市商资金 | |||
oneCirclesAvailableGreenEnergyPointsFlow.BeforePrice = chain.NowPrice //价格 | |||
oneCirclesAvailableGreenEnergyPointsFlow.AfterPrice = nowPriceValue | |||
//更新 `one_circles_green_energy_basic_setting` 表 | |||
if chain.NowPrice != nowPriceValue { | |||
chain.NowPrice = nowPriceValue | |||
} | |||
_, err := db.OneCirclesGreenEnergyBasicSettingUpdate(session, chain.Id, chain, | |||
"ecological_application", | |||
"total_technology_team", | |||
"total_operate_team", | |||
"total_active_giveaways", | |||
"original_quantity_nums", | |||
"now_price", | |||
"original_funds", | |||
"marketplace_merchant_nums", | |||
"marketplace_merchant_funds", | |||
"development_committee", | |||
"public_welfare_and_charity", | |||
"star_level_dividends", | |||
"community_dividends", | |||
"destruction_quantity_nums", | |||
) | |||
if err != nil { | |||
return err | |||
} | |||
//插入 `one_circles_available_green_energy_points_flow` 记录 | |||
_, err = db.OneCirclesAvailableGreenEnergyPointsFlowInsert(session, &oneCirclesAvailableGreenEnergyPointsFlow) | |||
if err != nil { | |||
return err | |||
} | |||
return nil | |||
} |
@@ -0,0 +1,41 @@ | |||
package enum | |||
// 可用绿色能量流水-种类 | |||
type EggEnergyAvailableEnergyFlowKind int | |||
const ( | |||
PersonalActivePointRedemption EggEnergyAvailableEnergyFlowKind = iota + 1 | |||
TeamActivePointRedemption | |||
AccountBalanceExchangeEggEnergy | |||
EggEnergyExchangeAccountBalance | |||
SettlementStarLevelDividends | |||
CommunityDividends | |||
PlatformProfitability | |||
MarketplaceMerchantNumsAutoExchangeMarketplaceMerchantFunds | |||
MarketplaceMerchantFundsAutoExchangeMarketplaceMerchantNums | |||
) | |||
func (kind EggEnergyAvailableEnergyFlowKind) String() string { | |||
switch kind { | |||
case PersonalActivePointRedemption: | |||
return "个人蛋蛋积分兑换" | |||
case TeamActivePointRedemption: | |||
return "团队蛋蛋积分兑换" | |||
case AccountBalanceExchangeEggEnergy: | |||
return "余额兑换蛋蛋能量" | |||
case EggEnergyExchangeAccountBalance: | |||
return "蛋蛋能量兑换余额" | |||
case SettlementStarLevelDividends: | |||
return "星级分红" | |||
case CommunityDividends: | |||
return "社区分红" | |||
case PlatformProfitability: | |||
return "平台盈利" | |||
case MarketplaceMerchantNumsAutoExchangeMarketplaceMerchantFunds: | |||
return "市商数量自动兑换市商资金" | |||
case MarketplaceMerchantFundsAutoExchangeMarketplaceMerchantNums: | |||
return "市商资金自动兑换市商数量" | |||
default: | |||
return "未知状态" | |||
} | |||
} |
@@ -0,0 +1,244 @@ | |||
package egg_energy | |||
import ( | |||
"code.fnuoos.com/EggPlanet/egg_models.git/src/implement" | |||
"code.fnuoos.com/EggPlanet/egg_models.git/src/model" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/enum" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/md" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/rule" | |||
md2 "code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/md" | |||
egg_system_rules "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/cache" | |||
zhios_order_relate_logx "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/logx" | |||
"code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git/rabbit" | |||
"encoding/json" | |||
"errors" | |||
"fmt" | |||
"strings" | |||
"time" | |||
"xorm.io/xorm" | |||
) | |||
// SettlementGiveActivityCoin 结算观看激励广告得到蛋蛋积分 | |||
func SettlementGiveActivityCoin(engine *xorm.Engine, uid int64, ch *rabbit.Channel) (err error) { | |||
//1、查找 `egg_energy_basic_setting` 基础设置 | |||
eggEnergyBasicSettingDb := implement.NewEggEnergyBasicSettingDb(engine) | |||
eggEnergyBasicSetting, err := eggEnergyBasicSettingDb.EggEnergyBasicSettingGetOneByParams(map[string]interface{}{ | |||
"key": "is_open", | |||
"value": 1, | |||
}) | |||
if err != nil { | |||
return | |||
} | |||
if eggEnergyBasicSetting == nil { | |||
err = errors.New("蛋蛋能量设置未开启!") | |||
return | |||
} | |||
if eggEnergyBasicSetting.VideoRewardIsOpen == 1 { | |||
var videoRewardSystem *md2.VideoRewardSystemStruct | |||
err = json.Unmarshal([]byte(eggEnergyBasicSetting.VideoRewardSystem), &videoRewardSystem) | |||
if err != nil { | |||
return | |||
} | |||
if videoRewardSystem.RewardValue == "" || videoRewardSystem.RewardTotalNum == "" || videoRewardSystem.IntervalMinutes == "" || videoRewardSystem.EachRoundHour == "" { | |||
err = errors.New("视屏奖励机制设置未完全!") | |||
return | |||
} | |||
var rewardSystem []*md2.RewardSystemStruct | |||
err = json.Unmarshal([]byte(eggEnergyBasicSetting.RewardSystem), &rewardSystem) | |||
if err != nil { | |||
return | |||
} | |||
if len(rewardSystem) == 0 { | |||
err = errors.New("未设置奖励机制!") | |||
return | |||
} | |||
rewardValue := egg_system_rules.StrToFloat64(videoRewardSystem.RewardValue) //奖励多少个活跃积分 | |||
var rewardSystemMap = map[int]*md2.RewardSystemStruct{} | |||
for _, v := range rewardSystem { | |||
rewardSystemMap[v.Level] = v | |||
} | |||
publicPlatoonUserRelationDb := implement.NewPublicPlatoonUserRelationDb(engine) | |||
publicPlatoonUserRelation, err1 := publicPlatoonUserRelationDb.PublicPlatoonUserRelationGetOneByParams(map[string]interface{}{ | |||
"key": "uid", | |||
"value": uid, | |||
}) | |||
if err1 != nil { | |||
return err1 | |||
} | |||
var rewardFather []struct { | |||
Uid int64 `json:"uid"` //用户id | |||
RewardValue float64 `json:"reward_value"` //奖励值 | |||
} | |||
var fatherUids []string | |||
if publicPlatoonUserRelation != nil { | |||
fatherUids = strings.Split(publicPlatoonUserRelation.FatherUid, "-") | |||
} | |||
for k, id := range fatherUids { | |||
tmpOneCirclesPublicPlatoonUserRelation, err11 := publicPlatoonUserRelationDb.PublicPlatoonUserRelationGetOneByParams(map[string]interface{}{ | |||
"key": "id", | |||
"value": id, | |||
}) | |||
if err11 != nil { | |||
return err11 | |||
} | |||
if tmpOneCirclesPublicPlatoonUserRelation == nil { | |||
continue | |||
} | |||
if tmpOneCirclesPublicPlatoonUserRelation.Uid <= 0 { | |||
//待填充位 | |||
continue | |||
} | |||
fatherUid := egg_system_rules.Int64ToStr(tmpOneCirclesPublicPlatoonUserRelation.Uid) | |||
fatherReward := rewardSystemMap[k+1] | |||
//TODO::判断是否活跃 | |||
var m model.EggSignIn | |||
has, err33 := engine.Where("uid =?", fatherUid).And("end_time >=?", time.Now().Format("2006-01-02 15:04:05")).Get(&m) | |||
if err33 != nil { | |||
return err33 | |||
} | |||
if !has { | |||
//不活跃不需要奖励 | |||
continue | |||
} | |||
//判断是否满足奖励条件 | |||
userRelateDb := implement.NewUserRelateDb(engine) | |||
userCount, _, err2 := userRelateDb.SumUserRelateByParentUid(fatherUid) | |||
if err2 != nil { | |||
return err2 | |||
} | |||
if fatherReward != nil && userCount >= egg_system_rules.StrToInt64(fatherReward.RewardCondition) { | |||
fatherRewardValue := rewardValue * (egg_system_rules.StrToFloat64(fatherReward.RewardValue) / 100) | |||
rewardFather = append(rewardFather, struct { | |||
Uid int64 `json:"uid"` //用户id | |||
RewardValue float64 `json:"reward_value"` //奖励值 | |||
}{ | |||
Uid: egg_system_rules.StrToInt64(fatherUid), | |||
RewardValue: fatherRewardValue, | |||
}) | |||
} | |||
} | |||
//增加 egg_user_watch_records 记录 | |||
eggEnergyUserWatchRecordsDb := implement.NewEggEnergyUserWatchRecordsDb(engine) | |||
eggEnergyUserWatchRecords, err1 := eggEnergyUserWatchRecordsDb.EggEnergyUserWatchRecordsGetOneByParams(map[string]interface{}{ | |||
"key": "uid", | |||
"value": uid, | |||
}) | |||
if err1 != nil { | |||
return err1 | |||
} | |||
now := time.Now() | |||
if eggEnergyUserWatchRecords == nil { | |||
residueWatchAdNum := egg_system_rules.StrToInt(videoRewardSystem.RewardTotalNum) - 1 | |||
if residueWatchAdNum < 0 { | |||
residueWatchAdNum = egg_system_rules.StrToInt(videoRewardSystem.RewardTotalNum) | |||
} | |||
_, err2 := eggEnergyUserWatchRecordsDb.EggEnergyUserWatchRecordsInsert(&model.EggEnergyUserWatchRecords{ | |||
Uid: uid, | |||
NextWatchAdDate: now.Add(time.Hour * time.Duration(egg_system_rules.StrToInt(videoRewardSystem.EachRoundHour))), | |||
ResidueWatchAdNum: egg_system_rules.StrToInt(videoRewardSystem.RewardTotalNum) - 1, | |||
CreateAt: now, | |||
UpdateAt: now, | |||
}) | |||
if err2 != nil { | |||
return err2 | |||
} | |||
} else { | |||
residueWatchAdNum := eggEnergyUserWatchRecords.ResidueWatchAdNum - 1 | |||
nextWatchAdDate := eggEnergyUserWatchRecords.NextWatchAdDate | |||
if residueWatchAdNum == 0 { //最后一条广告 | |||
residueWatchAdNum = egg_system_rules.StrToInt(videoRewardSystem.RewardTotalNum) | |||
} | |||
if residueWatchAdNum == egg_system_rules.StrToInt(videoRewardSystem.RewardTotalNum)-1 { //第一条广告 | |||
nextWatchAdDate = now.Add(time.Hour * time.Duration(egg_system_rules.StrToInt(videoRewardSystem.EachRoundHour))) | |||
} | |||
eggEnergyUserWatchRecords.ResidueWatchAdNum = residueWatchAdNum | |||
eggEnergyUserWatchRecords.NextWatchAdDate = nextWatchAdDate | |||
_, err2 := eggEnergyUserWatchRecordsDb.EggEnergyUserWatchRecordsUpdate(eggEnergyUserWatchRecords.Id, eggEnergyUserWatchRecords, "residue_watch_ad_num", "next_watch_ad_date") | |||
if err2 != nil { | |||
return err2 | |||
} | |||
} | |||
session := engine.NewSession() | |||
defer func() { | |||
session.Close() | |||
if err := recover(); err != nil { | |||
_ = zhios_order_relate_logx.Error(err) | |||
} | |||
}() | |||
session.Begin() | |||
//给相应的用户加上"个人"活跃积分 | |||
err = rule.DealUserVirtualCoin(session, md.DealUserVirtualCoinReq{ | |||
Kind: "add", | |||
Title: enum.UserVirtualAmountFlowTransferType.String(enum.EggEnergyWatchAdRewardPersonalActiveCoin), | |||
TransferType: int(enum.EggEnergyWatchAdRewardPersonalActiveCoin), | |||
CoinId: eggEnergyBasicSetting.PersonEggPointsCoinId, | |||
Uid: uid, | |||
Amount: rewardValue, | |||
}) | |||
if err != nil { | |||
_ = session.Rollback() | |||
fmt.Println("err:::::2222", err) | |||
return err | |||
} | |||
//给相应的用户加上"团队"活跃积分 | |||
for _, vv := range rewardFather { | |||
//TODO::推入rabbitmq 异步处理 | |||
ch.Publish(md2.EggEnergyExchange, md.DealUserVirtualCoinReq{ | |||
Kind: "add", | |||
Title: enum.UserVirtualAmountFlowTransferType.String(enum.EggEnergyWatchAdRewardTeamActiveCoin), | |||
TransferType: int(enum.EggEnergyWatchAdRewardTeamActiveCoin), | |||
CoinId: eggEnergyBasicSetting.TeamEggPointsCoinId, | |||
Uid: vv.Uid, | |||
Amount: vv.RewardValue, | |||
}, md2.EggEnergyRoutKeyForSettlementPublicGiveActivityCoin) | |||
} | |||
err = session.Commit() | |||
if err != nil { | |||
_ = session.Rollback() | |||
return errors.New("事务提交失败") | |||
} | |||
redisKey := fmt.Sprintf(md2.UserNextWatchAdDate, uid) | |||
var watchAdDate string | |||
if eggEnergyUserWatchRecords.ResidueWatchAdNum == egg_system_rules.StrToInt(videoRewardSystem.RewardTotalNum) { | |||
if eggEnergyUserWatchRecords.NextWatchAdDate.Before(time.Now()) { | |||
watchAdDate = "" | |||
} else { | |||
watchAdDate = eggEnergyUserWatchRecords.NextWatchAdDate.Format("2006-01-02 15:04:05") | |||
} | |||
} else { | |||
watchAdDate = time.Now().Add(time.Duration(egg_system_rules.StrToInt64(videoRewardSystem.IntervalMinutes)) * time.Second).Format("2006-01-02 15:04:05") | |||
} | |||
cache.SetEx(redisKey, watchAdDate, 60*60*24) //TODO::默认缓存1小时 | |||
} | |||
return | |||
} | |||
// CalcUserContinuousDailyActivityDays 计算用户连续活跃天数 | |||
func CalcUserContinuousDailyActivityDays(engine *xorm.Engine, uid int, startDate string, endDate string) (err error, days int, isContinuousDailyActivity bool) { | |||
startAt, err := time.ParseInLocation("2006-01-02", startDate, time.Local) //起始时间 | |||
endAt, err := time.ParseInLocation("2006-01-02", endDate, time.Local) //起始时间 | |||
var list []model.EggEnergyUserActivity | |||
err = engine.Where("date >= ?", startAt.Format("2006-01-02")). | |||
And("date < ?", endAt.Format("2006-01-02")). | |||
And("uid =?", uid).Find(&list) | |||
if err != nil { | |||
fmt.Println("err:::::1111", err) | |||
return | |||
} | |||
days = len(list) | |||
diffDays := egg_system_rules.GetDiffDays(endAt, startAt) //相差天数 | |||
if days == diffDays { | |||
isContinuousDailyActivity = true | |||
} | |||
return | |||
} |
@@ -0,0 +1,276 @@ | |||
package egg_energy | |||
import ( | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/db" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/db/model" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/md" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/one_circles/enum" | |||
md2 "code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/one_circles/md" | |||
egg_system_rules "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/cache" | |||
"code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git/rabbit" | |||
"encoding/json" | |||
"errors" | |||
"fmt" | |||
"github.com/shopspring/decimal" | |||
"math/rand" | |||
"time" | |||
"xorm.io/xorm" | |||
) | |||
// SettlementSignInGreenEnergy 计算签到得到绿色能量 | |||
func SettlementSignInGreenEnergy(engine *xorm.Engine, masterId string, ch *rabbit.Channel) (err error) { | |||
//1、查找 `one_circles_green_energy_basic_setting` 基础设置 | |||
oneCirclesGreenEnergyBasicSetting, err := db.OneCirclesGreenEnergyBasicSettingGetOneByParams(engine, map[string]interface{}{ | |||
"key": "is_open", | |||
"value": 1, | |||
}) | |||
if err != nil { | |||
return | |||
} | |||
if oneCirclesGreenEnergyBasicSetting == nil { | |||
return errors.New("开关未开!!") | |||
} | |||
//3、统计签到结束的用户数据 | |||
now := time.Now() | |||
var page = 1 | |||
var pageSize = 100 | |||
for { | |||
var list []model.OneCirclesGreenEnergySignIn | |||
err = engine.Where("end_time <= ?", now.Format("2006-01-02 15:04:05")).And("is_completed =?", 0).Limit(pageSize, (page-1)*pageSize).Asc("id").Find(&list) | |||
if err != nil { | |||
fmt.Println("err:::::1111", err) | |||
return | |||
} | |||
if len(list) <= 0 { | |||
break | |||
} | |||
var ids []int64 | |||
for _, v := range list { | |||
//TODO::推入rabbitmq 异步处理 | |||
ch.Publish(md.OneCirclesExchange, md.OneCirclesStructForSignIn{ | |||
MasterId: masterId, | |||
Uid: v.Uid, | |||
Id: v.Id, | |||
EndTime: v.EndTime, | |||
}, md.OneCirclesRoutKeyForSignIn) | |||
ids = append(ids, v.Id) | |||
} | |||
//6、更新 `one_circles_green_energy_sign_in` 中的 is_completed 状态 | |||
//if len(ids) > 0 { | |||
// _, err = engine.In("id", ids).Update(&model.OneCirclesGreenEnergySignIn{ | |||
// IsCompleted: 1, | |||
// }) | |||
//} | |||
page++ | |||
time.Sleep(time.Millisecond * time.Duration(rand.Intn(1000))) | |||
} | |||
return | |||
} | |||
func HandleSettlementSignInGreenEnergy(ch *rabbit.Channel, engine *xorm.Engine, masterId string, id int64, uid int, endTime string) (err error) { | |||
//1、查找 `one_circles_green_energy_basic_setting` 基础设置 | |||
//oneCirclesGreenEnergyBasicSetting, cb, err := svc.GetPrice(engine, masterId) | |||
//if err != nil { | |||
// return | |||
//} | |||
//if cb != nil { | |||
// defer cb() // 释放锁 | |||
//} | |||
oneCirclesGreenEnergyBasicSetting, err := db.OneCirclesGreenEnergyBasicSettingGetOneByParams(engine, map[string]interface{}{ | |||
"key": "is_open", | |||
"value": 1, | |||
}) | |||
var teamRewardSetting *md2.TeamRewardSettingStruct | |||
err = json.Unmarshal([]byte(oneCirclesGreenEnergyBasicSetting.TeamReward), &teamRewardSetting) | |||
if err != nil { | |||
return | |||
} | |||
if teamRewardSetting.RewardDecrementValue == "" || teamRewardSetting.RewardEndValue == "" || teamRewardSetting.MemberSelfIsOpenGetTeamReward == "" || teamRewardSetting.OneRoundDuration == "" { | |||
err = errors.New("团队奖励设置未完全!") | |||
return | |||
} | |||
var oneRoundDuration = egg_system_rules.StrToInt(teamRewardSetting.OneRoundDuration) | |||
var rewardDecrement = egg_system_rules.StrToFloat64(teamRewardSetting.RewardDecrementValue) / 100 //递减百分比 | |||
var rewardEndValue = egg_system_rules.StrToFloat64(teamRewardSetting.RewardEndValue) //奖励结束值 | |||
fmt.Println("rewardDecrement>>>>>>>>>>>>", rewardDecrement) | |||
fmt.Println("rewardEndValue>>>>>>>>>>>>", rewardEndValue) | |||
//2、获取当前签到收益 | |||
err, reward := CalcNowSignInGreenEnergy(engine, oneCirclesGreenEnergyBasicSetting) | |||
if err != nil { | |||
return err | |||
} | |||
rewardValue := egg_system_rules.Float64ToStrPrec8(egg_system_rules.StrToFloat64(reward) * float64(oneRoundDuration) * 60 * 60) | |||
//3、统计签到结束的用户数据 | |||
var reduceTotalGreenEnergy float64 | |||
//4.2给相应的用户加上个人的绿色积分(可用数量) | |||
var oneCirclesDealUserCoinData = md.DealUserCoinReq{ | |||
Kind: "add", | |||
Mid: masterId, | |||
Title: md.OneCirclesGreenEnergySignInSettlementPersonalReward, | |||
TransferType: md.OneCirclesGreenEnergySignInSettlementPersonalRewardForUserVirtualCoinFlow, | |||
OrdId: "", | |||
CoinId: oneCirclesGreenEnergyBasicSetting.PersonGreenEnergyCoinId, | |||
Uid: uid, | |||
Amount: egg_system_rules.StrToFloat64(rewardValue), | |||
} | |||
reduceTotalGreenEnergy += egg_system_rules.StrToFloat64(rewardValue) | |||
//4.2给相应的上级用户加上团队奖励的绿色积分(结算数量) | |||
relates, err1 := db.DbsUserRelate(engine, uid, 0) | |||
if err1 != nil { | |||
fmt.Println("err:::::3333", err1) | |||
return err1 | |||
} | |||
var oneCirclesDealUserCoinDataForParents []md.DealUserCoinReq | |||
var parentRewardValue = egg_system_rules.StrToFloat64(rewardValue) | |||
if relates != nil { | |||
for _, relate := range *relates { | |||
parentRewardValue = parentRewardValue * rewardDecrement | |||
if parentRewardValue <= rewardEndValue { | |||
break | |||
} | |||
//TODO::判断是否活跃 | |||
var m model.OneCirclesGreenEnergySignIn | |||
if endTime != "" { | |||
has, err3333333 := engine.Where("uid =?", relate.ParentUid).And("end_time >=?", endTime).Get(&m) | |||
if err3333333 != nil { | |||
fmt.Println("err:::::3333333", err3333333) | |||
return err3333333 | |||
} | |||
if !has { | |||
//不活跃不需要奖励 | |||
continue | |||
} | |||
} else { | |||
has, err3333333 := engine.Where("uid =?", relate.ParentUid).And("end_time >=?", time.Now().Format("2006-01-02 15:04:05")).Get(&m) | |||
if err3333333 != nil { | |||
fmt.Println("err:::::3333333", err3333333) | |||
return err3333333 | |||
} | |||
if !has { | |||
//不活跃不需要奖励 | |||
continue | |||
} | |||
} | |||
oneCirclesDealUserCoinDataForParents = append(oneCirclesDealUserCoinDataForParents, md.DealUserCoinReq{ | |||
Kind: "add", | |||
Mid: masterId, | |||
Title: md.OneCirclesGreenEnergySignInSettlementTeamReward, | |||
TransferType: md.OneCirclesGreenEnergySignInSettlementTeamRewardForUserVirtualCoinFlow, | |||
OrdId: "", | |||
CoinId: oneCirclesGreenEnergyBasicSetting.TeamGreenEnergyCoinId, | |||
Uid: relate.ParentUid, | |||
Amount: parentRewardValue, | |||
}) | |||
reduceTotalGreenEnergy += parentRewardValue | |||
} | |||
} | |||
//5、减少“活跃赠送” 中的绿色能量 | |||
if reduceTotalGreenEnergy > 0 { | |||
err = DealAvailableGreenEnergyCoin(engine.NewSession(), int(enum.SignInReward), reduceTotalGreenEnergy, 0, enum.SignInReward.String(), oneCirclesGreenEnergyBasicSetting, oneCirclesGreenEnergyBasicSetting.NowPrice, masterId) | |||
if err != nil { | |||
fmt.Println("err:::::55555", err) | |||
return err | |||
} | |||
} | |||
//6、更新 `one_circles_green_energy_sign_in` 中的 is_completed 状态 | |||
_, err = engine.Where("id = ?", id).Update(&model.OneCirclesGreenEnergySignIn{ | |||
IsCompleted: 1, | |||
}) | |||
if err != nil { | |||
fmt.Println("err:::::66666", err) | |||
return err | |||
} | |||
////TODO::推入rabbitmq 异步处理 | |||
ch.Publish(md.OneCirclesExchange, oneCirclesDealUserCoinData, md.OneCirclesRoutKeyForRewardUserCoin) //个人的奖励 | |||
for _, oneCirclesDealUserCoinDataForParent := range oneCirclesDealUserCoinDataForParents { | |||
ch.Publish(md.OneCirclesExchange, oneCirclesDealUserCoinDataForParent, md.OneCirclesRoutKeyForRewardUserCoin) //上级的奖励 | |||
} | |||
return | |||
} | |||
// CalcNowSignInGreenEnergy 计算当前签到拿多少绿色能量/秒 | |||
func CalcNowSignInGreenEnergy(engine *xorm.Engine, oneCirclesGreenEnergyBasicSetting *model.OneCirclesGreenEnergyBasicSetting) (err error, rewardValue string) { | |||
rewardValue, _ = cache.GetString("one_circle_reward_value") | |||
if rewardValue == "" { | |||
if oneCirclesGreenEnergyBasicSetting == nil { | |||
//1、查找 `one_circles_green_energy_basic_setting` 基础设置 | |||
oneCirclesGreenEnergyBasicSetting, err = db.OneCirclesGreenEnergyBasicSettingGetOneByParams(engine, map[string]interface{}{ | |||
"key": "is_open", | |||
"value": 1, | |||
}) | |||
if err != nil { | |||
return | |||
} | |||
} | |||
var signInRewards []*md2.SignInRewardStruct | |||
err = json.Unmarshal([]byte(oneCirclesGreenEnergyBasicSetting.SignInReward), &signInRewards) | |||
if err != nil { | |||
return | |||
} | |||
if len(signInRewards) == 0 { | |||
err = errors.New("未设置签到奖励!") | |||
return | |||
} | |||
//2、统计全网用户数 | |||
sqlStr := "SELECT COUNT(*) AS total FROM user " | |||
nativeString, _ := db.QueryNativeString(engine, sqlStr) | |||
userCount := egg_system_rules.StrToInt64(nativeString[0]["total"]) | |||
for _, v := range signInRewards { | |||
if egg_system_rules.StrToInt64(v.VipMemberEndNums) >= userCount && userCount >= egg_system_rules.StrToInt64(v.VipMemberStartNums) { | |||
//rewardValue = egg_system_rules.Float64ToStrPrec8(egg_system_rules.StrToFloat64(v.RewardValue) * float64(oneRoundDuration) * 60 * 60) | |||
rewardValue = v.RewardValue | |||
} | |||
} | |||
cache.SetEx("one_circle_reward_value", rewardValue, 3600*8) //8小时 | |||
} | |||
return | |||
} | |||
// CalcTodayGreenEnergyPriceRises 计算绿色能量今日价格涨幅 | |||
func CalcTodayGreenEnergyPriceRises(engine *xorm.Engine, oneCirclesGreenEnergyBasicSetting *model.OneCirclesGreenEnergyBasicSetting) (err error, rises float64, isRises bool) { | |||
now := time.Now() | |||
if oneCirclesGreenEnergyBasicSetting == nil { | |||
//1、查找 `one_circles_green_energy_basic_setting` 基础设置 | |||
oneCirclesGreenEnergyBasicSetting, err = db.OneCirclesGreenEnergyBasicSettingGetOneByParams(engine, map[string]interface{}{ | |||
"key": "is_open", | |||
"value": 1, | |||
}) | |||
if err != nil { | |||
return | |||
} | |||
} | |||
//2、查找昨日价格 | |||
var m model.OneCirclesGreenEnergyPrice | |||
if has, err1 := engine.Where("date =?", now.AddDate(0, 0, -1).Format("2006-01-02")).And("hour = 23").Get(&m); err1 != nil || has == false { | |||
err = err1 | |||
return | |||
} | |||
yesterdayPrice, _ := decimal.NewFromString(m.Price) | |||
todayPrice, _ := decimal.NewFromString(oneCirclesGreenEnergyBasicSetting.NowPrice) | |||
if todayPrice.GreaterThanOrEqual(yesterdayPrice) { | |||
isRises = true | |||
rises, _ = todayPrice.Sub(yesterdayPrice).Div(yesterdayPrice).Float64() | |||
} else { | |||
rises, _ = yesterdayPrice.Sub(todayPrice).Div(todayPrice).Float64() | |||
} | |||
return | |||
} |
@@ -0,0 +1,99 @@ | |||
package md | |||
type VipEquitySettingStruct struct { | |||
VipLevelId string `json:"vip_level_id"` //会员等级id | |||
ExchangeAccountBalanceFee string `json:"exchange_account_balance_fee"` //兑换余额手续费 | |||
DividendRatio string `json:"dividend_ratio"` //分红比例 | |||
} | |||
type TeamRewardSettingStruct struct { | |||
RewardDecrementValue string `json:"reward_decrement_value"` //递减百分比 | |||
RewardEndValue string `json:"reward_end_value"` //奖励结束值 | |||
MemberSelfIsOpenGetTeamReward string `json:"member_self_is_open_get_team_reward"` //会员是否活跃得到团队奖励 | |||
OneRoundDuration string `json:"one_round_duration"` //一轮持续时间 | |||
} | |||
type SignInRewardStruct struct { | |||
VipMemberStartNums string `json:"vip_member_start_nums"` //会员起始数量 | |||
VipMemberEndNums string `json:"vip_member_end_nums"` //会员结束数量 | |||
RewardValue string `json:"reward_value"` //奖励值 | |||
} | |||
type PriceSettingStruct struct { | |||
PriceHigherThanValue string `json:"price_higher_than_value"` //高于x元 | |||
MarketplaceMerchantsNumsExchangeMarketplaceMerchantsFundValue string `json:"marketplace_merchants_nums_exchange_marketplace_merchants_fund_value"` //市商数量单笔x数量自动兑换 | |||
PriceBelowValue string `json:"price_below_value"` //低于x元 | |||
MarketplaceMerchantsFundExchangeMarketplaceMerchantsNumsValue string `json:"marketplace_merchants_fund_exchange_marketplace_merchants_nums_value"` //市商资金单笔x元自动兑换 | |||
} | |||
type DestructionSettingStruct struct { | |||
DestructionQuantity string `json:"destruction_quantity"` //销毁百分比 | |||
PublicWelfareAndCharity string `json:"public_welfare_and_charity"` //公益慈善百分比 | |||
DevelopmentCommittee string `json:"development_committee"` //发展委员会百分比 | |||
StarLevelDividends string `json:"star_level_dividends"` //星级分红百分比 | |||
MarketplaceMerchant string `json:"marketplace_merchant"` //市商数量百分比 | |||
CommunityDividends string `json:"community_dividends"` //社区分红百分比 | |||
} | |||
type WelfareOrdersLimit struct { | |||
ContinuousDailyActivityNums string `json:"continuous_daily_activity_nums"` //连续日活 | |||
DirectPushLimit struct { | |||
DirectPushUserNums string `json:"direct_push_user_nums"` //直推用户数 | |||
ContinuousDailyActivityNums string `json:"continuous_daily_activity_nums"` //连续日活 | |||
} `json:"direct_push_limit"` //直推机制 | |||
WelfareOrdersProfitExchange string `json:"welfare_orders_profit_exchange"` //福利订单利润兑换率 | |||
SingleUserLimitBuyNums string `json:"single_user_limit_buy_nums"` //单个用户限购 | |||
PlatformMembers []struct { | |||
From string `json:"from"` | |||
To string `json:"to"` | |||
} `json:"platform_members"` //平台会员 | |||
} | |||
const DealUserCoinRequestIdPrefix = "egg_deal_user_coin:%d:uid:%d" | |||
type AddPublicPlatoonUserRelationCommissionReq struct { | |||
Uid string `json:"uid"` | |||
RecommendUid string `json:"recommend_uid"` //推荐人uid | |||
} | |||
type VideoRewardSystemStruct struct { | |||
RewardValue string `json:"reward_value"` //奖励X个活跃积分 | |||
RewardTotalNum string `json:"reward_total_num"` //一共X个奖励视屏 | |||
IntervalMinutes string `json:"interval_minutes"` //间隔X秒 | |||
EachRoundHour string `json:"each_round_hour"` //每一轮X个小时 | |||
} | |||
type RewardSystemStruct struct { | |||
Level int `json:"level"` //圈层 | |||
RewardCondition string `json:"reward_condition"` //奖励条件 | |||
RewardValue string `json:"reward_value"` //奖励值 | |||
} | |||
type ExchangeRulesStruct struct { | |||
AutoExchangeNumsByPerson string `json:"auto_exchange_nums_by_person"` //个人数量X个,自动兑换可用蛋蛋能量 | |||
AutoExchangeRateByPerson string `json:"auto_exchange_rate_by_person"` //个人数量百分比,自动兑换可用蛋蛋能量 | |||
AutoExchangeNumsByTeam string `json:"auto_exchange_nums_by_team"` //团队数量X个,自动兑换团队蛋蛋能量 | |||
AutoExchangeRateByTeam string `json:"auto_exchange_rate_by_team"` //团队数量百分比,自动兑换团队蛋蛋能量 | |||
} | |||
const UserNextWatchAdDate = "user_next_watch_date:%d" | |||
type CalcPriceIncreaseFormulaResp struct { | |||
GetEggEnergyNums string `json:"get_egg_energy_nums"` //得到蛋蛋能量的数量 | |||
BeforePrice string `json:"before_price"` //变更前-价格 | |||
AfterPrice string `json:"after_price"` //变更后-价格 | |||
BeforePlanetTotalValue string `json:"before_planet_total_value"` //变更前-星球总价值 | |||
AfterPlanetTotalValue string `json:"after_planet_total_value"` //变更后-星球总价值 | |||
BeforeEnergyTotalNums string `json:"before_energy_total_nums"` //变更前-现行总量 | |||
AfterEnergyTotalNums string `json:"after_energy_total_nums"` //变更后-现行总量 | |||
} | |||
type CalcPriceReductionFormulaResp struct { | |||
GetEggEnergyAmount string `json:"get_egg_energy_amount"` //得到蛋蛋能量的钱 | |||
BeforePrice string `json:"before_price"` //变更前-价格 | |||
AfterPrice string `json:"after_price"` //变更后-价格 | |||
BeforePlanetTotalValue string `json:"before_planet_total_value"` //变更前-星球总价值 | |||
AfterPlanetTotalValue string `json:"after_planet_total_value"` //变更后-星球总价值 | |||
BeforeEnergyTotalNums string `json:"before_energy_total_nums"` //变更前-现行总量 | |||
AfterEnergyTotalNums string `json:"after_energy_total_nums"` //变更后-现行总量 | |||
} |
@@ -0,0 +1,53 @@ | |||
package md | |||
const EggEnergyExchange = "egg.energy" | |||
const ( | |||
EggEnergyRoutKeyForStarLevelDividend = "star_level_dividend" // 星级分红 | |||
EggEnergyRoutKeyForSettlementPublicGiveActivityCoin = "settlement_public_give_activity_coin" // 计算观看激励视屏得到活跃积分 | |||
EggEnergyRoutKeyForReadyExchangeGreenEnergyToPerson = "ready_exchange_egg_energy_to_person" // 准备兑换个人蛋蛋能量 | |||
EggEnergyRoutKeyForStartExchangeGreenEnergyToPerson = "start_exchange_egg_energy_to_person" // 开始兑换个人蛋蛋能量 | |||
EggEnergyRoutKeyForAutoExchangeGreenEnergyToPerson = "auto_exchange_egg_energy_to_person" // 自动兑换个人蛋蛋能量 | |||
EggEnergyRoutKeyForReadyExchangeGreenEnergyToTeam = "ready_exchange_egg_energy_to_team" // 自动兑换团队蛋蛋能量 | |||
EggEnergyRoutKeyForStartExchangeGreenEnergyToTeam = "start_exchange_egg_energy_to_team" // 开始兑换团队蛋蛋能量 | |||
EggEnergyRoutKeyForAutoExchangeGreenEnergyToTeam = "auto_exchange_egg_energy_to_team" // 自动兑换团队蛋蛋能量 | |||
EggEnergyRoutKeyForSignIn = "sign_in" // 签到 | |||
EggEnergyRoutKeyForSignInUpdateRecords = "sign_in_update_records" // 签到更新记录 | |||
EggEnergyRoutKeyForRewardUserCoin = "reward_user_coin" // 奖励用户虚拟币 | |||
) | |||
type EggEnergyStructForSignIn struct { | |||
MasterId string `json:"master_id"` | |||
Uid int `json:"uid"` | |||
Id int64 `json:"id"` | |||
EndTime string `json:"end_time"` | |||
} | |||
type UpdateEggEnergyStructForSignInRecords struct { | |||
Id int64 `json:"id"` | |||
Uid int `json:"uid"` | |||
} | |||
type EggEnergyStructForStarLevelDividends struct { | |||
Uid int64 `json:"uid"` | |||
SignDividend float64 `json:"sign_dividend"` | |||
} | |||
type EggEnergyStructForStartExchangeGreenEnergy struct { | |||
Uid int64 `json:"uid"` | |||
Amount string `json:"amount"` | |||
PointCoinId int `json:"point_coin_id"` | |||
EnergyCoinId int `json:"energy_coin_id"` | |||
AutoExchangeNumsAmount string `json:"auto_exchange_nums_amount"` | |||
StartExchangeTime string `json:"start_exchange_time"` //发起兑换时间 | |||
EndExchangeTime string `json:"end_exchange_time"` //截止兑换时间 | |||
} | |||
type EggEnergyStructForAutoExchangeGreenEnergy struct { | |||
Uid int64 `json:"uid"` | |||
EnergyCoinId int `json:"energy_coin_id"` | |||
AutoExchangeNumsAmount string `json:"auto_exchange_nums_amount"` | |||
StartExchangeTime string `json:"start_exchange_time"` //发起兑换时间 | |||
EndExchangeTime string `json:"end_exchange_time"` //截止兑换时间 | |||
} |
@@ -0,0 +1,304 @@ | |||
package egg_energy | |||
import ( | |||
"code.fnuoos.com/EggPlanet/egg_models.git/src/implement" | |||
"code.fnuoos.com/EggPlanet/egg_models.git/src/model" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/enum" | |||
md2 "code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/md" | |||
egg_system_rules "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/cache" | |||
zhios_order_relate_logx "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/logx" | |||
"code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git/rabbit" | |||
"encoding/json" | |||
"errors" | |||
"fmt" | |||
"github.com/shopspring/decimal" | |||
"time" | |||
"xorm.io/xorm" | |||
) | |||
const SettlementStarLevelDividendsLockKey = "settlement_star_level_dividends_lock_key" | |||
// SettlementStarLevelDividends 蛋蛋能量星级分红 | |||
func SettlementStarLevelDividends(engine *xorm.Engine, masterId string, ch *rabbit.Channel) (err error) { | |||
now := time.Now() | |||
fmt.Println(now.Hour()) | |||
if !(now.Hour() > 2 && now.Hour() < 8) { | |||
//TODO::只在凌晨一点 ~ 凌晨 8 点运行 | |||
return errors.New("非运行时间") | |||
} | |||
//TODO::增加“悲观锁”防止串行 | |||
getString, _ := cache.GetString(SettlementStarLevelDividendsLockKey) | |||
if getString != "" { | |||
fmt.Println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", "上一次结算未执行完") | |||
return errors.New("上一次结算未执行完") | |||
} | |||
cache.SetEx(SettlementStarLevelDividendsLockKey, "running", 3600*8) //8小时 | |||
//1、查找 `egg_energy_basic_setting` 基础设置 | |||
eggEnergyBasicSettingDb := implement.NewEggEnergyBasicSettingDb(engine) | |||
eggEnergyBasicSetting, err := eggEnergyBasicSettingDb.EggEnergyBasicSettingGetOneByParams(map[string]interface{}{ | |||
"key": "is_open", | |||
"value": 1, | |||
}) | |||
if err != nil { | |||
return | |||
} | |||
isLimitDividend := eggEnergyBasicSetting.IsLimitDividend | |||
if isLimitDividend != 1 { | |||
return errors.New("必须开启限制分红!") | |||
} | |||
startDate := now.AddDate(0, 0, -1).Format("2006-01-02") + " 00:00:00" | |||
endDate := now.Format("2006-01-02") + " 00:00:00" | |||
var list []model.EggSignIn | |||
err = engine.Where("start_time >= ?", startDate).And("start_time <=?", endDate).Find(&list) | |||
if err != nil { | |||
fmt.Println("err:::::1111", err) | |||
return | |||
} | |||
if len(list) <= 0 { | |||
return errors.New("无须参与星级分红用户!") | |||
} | |||
var vipEquitySetting []*md2.VipEquitySettingStruct | |||
err = json.Unmarshal([]byte(eggEnergyBasicSetting.VipEquitySetting), &vipEquitySetting) | |||
if err != nil { | |||
fmt.Println("err:::::22222", err) | |||
return | |||
} | |||
userLevelDb := implement.NewUserLevelDb(engine) | |||
allUserLevel, err := userLevelDb.UserLevelAllByAsc() | |||
if err != nil { | |||
return err | |||
} | |||
var allUserLevelMap = map[int]model.UserLevel{} | |||
for _, v := range allUserLevel { | |||
allUserLevelMap[v.Id] = *v | |||
} | |||
session := engine.NewSession() | |||
defer func() { | |||
session.Close() | |||
if err := recover(); err != nil { | |||
_ = zhios_order_relate_logx.Error(err) | |||
} | |||
}() | |||
session.Begin() | |||
//2、查找 `egg_star_level_dividends_records` 基础设置 | |||
eggStarLevelDividendsRecordsDb := implement.NewEggStarLevelDividendsRecordsDb(engine) | |||
eggStarLevelDividendsRecords, err := eggStarLevelDividendsRecordsDb.EggStarLevelDividendsRecordsGetOneByParamsBySession(session, map[string]interface{}{ | |||
"key": "date", | |||
"value": now.AddDate(0, 0, -1).Format("2006-01-02"), | |||
}) | |||
if err != nil { | |||
fmt.Println("err:::::33333", err) | |||
return | |||
} | |||
if eggStarLevelDividendsRecords == nil { | |||
return errors.New("今日无分红积分!") | |||
} | |||
//3、统计各等级人数 | |||
dividendAmountValue, _ := decimal.NewFromString(eggStarLevelDividendsRecords.Amount) | |||
decimalRate := decimal.NewFromInt(100) //百分比 | |||
var vipLevelUserTotalMap = map[string]map[string]int64{} | |||
var vipEquitySettingMap = map[string]string{} | |||
for _, v := range vipEquitySetting { | |||
dividendRatioValue, _ := decimal.NewFromString(v.DividendRatio) | |||
dividendRatioValue = dividendRatioValue.Div(decimalRate) //分红比例 | |||
vipEquitySettingMap[v.VipLevelId] = dividendAmountValue.Mul(dividendRatioValue).String() //TODO::计算各会员等级能得到多少分红 | |||
userLevel, err1 := userLevelDb.UserLevelByID(v.VipLevelId) | |||
if err1 != nil { | |||
fmt.Println("err:::::444444", err1) | |||
return err1 | |||
} | |||
var ms []*model.UserLevel | |||
err1 = session.Where("is_use=1").Where("level_weight > ?", userLevel.LevelWeight).Find(&ms) | |||
if err1 != nil { | |||
fmt.Println("err:::::55555", err1) | |||
return err1 | |||
} | |||
var tmpVipLevelId = []string{v.VipLevelId} | |||
for _, m := range ms { | |||
tmpVipLevelId = append(tmpVipLevelId, egg_system_rules.IntToStr(m.Id)) | |||
} | |||
var users model.User | |||
count, err1 := session.In("level", tmpVipLevelId).Count(&users) | |||
if err1 != nil { | |||
fmt.Println("err:::::66666", err1) | |||
return err1 | |||
} | |||
vipLevelUserTotalMap[v.VipLevelId] = map[string]int64{} | |||
vipLevelUserTotalMap[v.VipLevelId]["count"] = count | |||
vipLevelUserTotalMap[v.VipLevelId]["weight"] = int64(userLevel.LevelWeight) | |||
} | |||
//4、处理分红 | |||
var userSignInArr []int64 | |||
var totalDividendValue = decimal.Decimal{} | |||
userRelateDb := implement.NewUserRelateDb(engine) | |||
for _, l := range list { | |||
userSignInArr = append(userSignInArr, l.Uid) | |||
if len(userSignInArr) >= 10000 { | |||
var users []*model.User | |||
err = session.In("uid", userSignInArr).Find(&users) | |||
if err != nil { | |||
fmt.Println("err:::::7777777", err) | |||
return err | |||
} | |||
for _, item := range users { | |||
var siginDividendValue = decimal.Decimal{} | |||
for k, v := range vipLevelUserTotalMap { | |||
if int(v["weight"]) > allUserLevelMap[item.Level].LevelWeight { | |||
continue | |||
} | |||
if vipEquitySettingMap[k] != "" && vipLevelUserTotalMap[k]["count"] > 0 { | |||
dividendValue, _ := decimal.NewFromString(vipEquitySettingMap[k]) | |||
userTotal := decimal.NewFromInt(vipLevelUserTotalMap[k]["count"]) | |||
siginDividendValue = siginDividendValue.Add(dividendValue.Div(userTotal)) | |||
} | |||
} | |||
if siginDividendValue.GreaterThan(decimal.NewFromInt(0)) { | |||
//TODO::统计当前有多少直推用户昨天签到了 | |||
userRelates, err1 := userRelateDb.FindUserRelateByParentUid(item.Id, 1) | |||
if err1 != nil { | |||
fmt.Println("err:::::88888888", err1) | |||
return err | |||
} | |||
var userRelatesUids []int64 | |||
if userRelates != nil { | |||
for _, userRelate := range *userRelates { | |||
userRelatesUids = append(userRelatesUids, userRelate.Uid) | |||
} | |||
} | |||
if len(userRelatesUids) > 0 { | |||
var eggEnergySignIns []*model.EggSignIn | |||
err = engine.Where("start_time >= ?", startDate).And("start_time <=?", endDate).In("uid", userRelatesUids).And("is_completed =?", 0).Find(&eggEnergySignIns) | |||
if err != nil { | |||
fmt.Println("err:::::999999999", err) | |||
return | |||
} | |||
if len(eggEnergySignIns) > 0 { | |||
userRelatesUidsValue := decimal.NewFromInt(int64(len(userRelatesUids))) | |||
eggEnergySignInsValue := decimal.NewFromInt(int64(len(eggEnergySignIns))) | |||
siginDividendValue = siginDividendValue.Mul(eggEnergySignInsValue.Div(userRelatesUidsValue)) | |||
} else { | |||
siginDividendValue = decimal.NewFromFloat(0) | |||
} | |||
} else { | |||
siginDividendValue = decimal.NewFromFloat(0) | |||
} | |||
siginDividend, _ := siginDividendValue.Float64() | |||
if siginDividend > 0 { | |||
//TODO::推入rabbitmq 异步处理 | |||
ch.Publish(md2.EggEnergyExchange, md2.EggEnergyStructForStarLevelDividends{ | |||
Uid: item.Id, | |||
SignDividend: siginDividend, | |||
}, md2.EggEnergyRoutKeyForStarLevelDividend) | |||
totalDividendValue = totalDividendValue.Add(siginDividendValue) | |||
} | |||
} | |||
} | |||
userSignInArr = []int64{} | |||
} | |||
} | |||
if len(userSignInArr) > 0 { | |||
var users []*model.User | |||
err = session.In("uid", userSignInArr).Find(&users) | |||
if err != nil { | |||
fmt.Println("err:::::7777777", err) | |||
return err | |||
} | |||
for _, item := range users { | |||
var siginDividendValue = decimal.Decimal{} | |||
for k, v := range vipLevelUserTotalMap { | |||
if int(v["weight"]) > allUserLevelMap[item.Level].LevelWeight { | |||
continue | |||
} | |||
if vipEquitySettingMap[k] != "" && vipLevelUserTotalMap[k]["count"] > 0 { | |||
dividendValue, _ := decimal.NewFromString(vipEquitySettingMap[k]) | |||
userTotal := decimal.NewFromInt(vipLevelUserTotalMap[k]["count"]) | |||
siginDividendValue = siginDividendValue.Add(dividendValue.Div(userTotal)) | |||
} | |||
} | |||
if siginDividendValue.GreaterThan(decimal.NewFromInt(0)) { | |||
//TODO::统计当前有多少直推用户昨天签到了 | |||
userRelates, err1 := userRelateDb.FindUserRelateByParentUid(item.Id, 1) | |||
if err1 != nil { | |||
fmt.Println("err:::::88888888", err1) | |||
return err | |||
} | |||
var userRelatesUids []int64 | |||
if userRelates != nil { | |||
for _, userRelate := range *userRelates { | |||
userRelatesUids = append(userRelatesUids, userRelate.Uid) | |||
} | |||
} | |||
if len(userRelatesUids) > 0 { | |||
var eggEnergySignIns []*model.EggSignIn | |||
err = engine.Where("start_time >= ?", startDate).And("start_time <=?", endDate).In("uid", userRelatesUids).And("is_completed =?", 0).Find(&eggEnergySignIns) | |||
if err != nil { | |||
fmt.Println("err:::::999999999", err) | |||
return | |||
} | |||
if len(eggEnergySignIns) > 0 { | |||
userRelatesUidsValue := decimal.NewFromInt(int64(len(userRelatesUids))) | |||
eggEnergySignInsValue := decimal.NewFromInt(int64(len(eggEnergySignIns))) | |||
siginDividendValue = siginDividendValue.Mul(eggEnergySignInsValue.Div(userRelatesUidsValue)) | |||
} else { | |||
siginDividendValue = decimal.NewFromFloat(0) | |||
} | |||
} else { | |||
siginDividendValue = decimal.NewFromFloat(0) | |||
} | |||
siginDividend, _ := siginDividendValue.Float64() | |||
if siginDividend > 0 { | |||
//TODO::推入rabbitmq 异步处理 | |||
ch.Publish(md2.EggEnergyExchange, md2.EggEnergyStructForStarLevelDividends{ | |||
Uid: item.Id, | |||
SignDividend: siginDividend, | |||
}, md2.EggEnergyRoutKeyForStarLevelDividend) | |||
totalDividendValue = totalDividendValue.Add(siginDividendValue) | |||
} | |||
} | |||
} | |||
} | |||
//5、更新 egg_star_level_dividends_records 记录 | |||
eggStarLevelDividendsRecords.AlreadyDividendsAmount = totalDividendValue.String() | |||
eggStarLevelDividendsRecords.NotDividendsAmount = dividendAmountValue.Sub(totalDividendValue).String() | |||
_, err = eggStarLevelDividendsRecordsDb.EggStarLevelDividendsRecordsUpdateBySession(session, eggStarLevelDividendsRecords.Id, eggStarLevelDividendsRecords, "already_dividends_amount", "not_dividends_amount") | |||
if err != nil { | |||
_ = session.Rollback() | |||
fmt.Println("err:::::8888888", err) | |||
return err | |||
} | |||
//6、 减少“星级分红”中的绿色能量 | |||
totalDividend, _ := totalDividendValue.Float64() | |||
err = DealAvailableGreenEnergyCoin(session, int(enum.SettlementStarLevelDividends), totalDividend, 0, enum.SettlementStarLevelDividends.String(), nil, "", masterId) | |||
if err != nil { | |||
_ = session.Rollback() | |||
fmt.Println("err:::::9999999", err) | |||
return err | |||
} | |||
err = session.Commit() | |||
if err != nil { | |||
_ = session.Rollback() | |||
return errors.New("事务提交失败") | |||
} | |||
return | |||
} |
@@ -0,0 +1,101 @@ | |||
package svc | |||
import ( | |||
"code.fnuoos.com/EggPlanet/egg_models.git/src/implement" | |||
"code.fnuoos.com/EggPlanet/egg_models.git/src/model" | |||
zhios_order_relate_utils "code.fnuoos.com/EggPlanet/egg_models.git/utils" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/md" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/cache" | |||
"errors" | |||
"fmt" | |||
"math/rand" | |||
"reflect" | |||
"time" | |||
"xorm.io/xorm" | |||
) | |||
const redisMutexLockExpTime = 15 | |||
// TryGetDistributedLock 分布式锁获取 | |||
// requestId 用于标识请求客户端,可以是随机字符串,需确保唯一 | |||
func TryGetDistributedLock(lockKey, requestId string, isNegative bool) bool { | |||
if isNegative { // 多次尝试获取 | |||
retry := 1 | |||
for { | |||
ok, err := cache.Do("SET", lockKey, requestId, "EX", redisMutexLockExpTime, "NX") | |||
// 获取锁成功 | |||
if err == nil && ok == "OK" { | |||
return true | |||
} | |||
// 尝试多次没获取成功 | |||
if retry > 99 { | |||
return false | |||
} | |||
time.Sleep(time.Millisecond * time.Duration(rand.Intn(100))) | |||
retry += 1 | |||
} | |||
} else { // 只尝试一次 | |||
ok, err := cache.Do("SET", lockKey, requestId, "EX", redisMutexLockExpTime, "NX") | |||
// 获取锁成功 | |||
if err == nil && ok == "OK" { | |||
return true | |||
} | |||
return false | |||
} | |||
} | |||
// ReleaseDistributedLock 释放锁,通过比较requestId,用于确保客户端只释放自己的锁,使用lua脚本保证操作的原子型 | |||
func ReleaseDistributedLock(lockKey, requestId string) (bool, error) { | |||
luaScript := ` | |||
if redis.call("get",KEYS[1]) == ARGV[1] | |||
then | |||
return redis.call("del",KEYS[1]) | |||
else | |||
return 0 | |||
end` | |||
do, err := cache.Do("eval", luaScript, 1, lockKey, requestId) | |||
fmt.Println(reflect.TypeOf(do)) | |||
fmt.Println(do) | |||
if zhios_order_relate_utils.AnyToInt64(do) == 1 { | |||
return true, err | |||
} else { | |||
return false, err | |||
} | |||
} | |||
func GetDistributedLockRequestId(prefix string) string { | |||
return prefix + zhios_order_relate_utils.IntToStr(rand.Intn(100000000)) | |||
} | |||
// HandleDistributedLock 处理余额更新时获取锁和释放锁 如果加锁成功,使用语句 ` defer cb() ` 释放锁 | |||
func handleDistributedLock(requestIdPrefix string) (cb func(), err error) { | |||
// 获取余额更新锁 | |||
balanceLockKey := fmt.Sprintf(md.EggEnergyNowPriceUpdateLock) | |||
requestId := GetDistributedLockRequestId(requestIdPrefix) | |||
balanceLockOk := TryGetDistributedLock(balanceLockKey, requestId, true) | |||
if !balanceLockOk { | |||
return nil, errors.New("获取价格系统繁忙,请稍后再试") | |||
} | |||
cb = func() { | |||
_, _ = ReleaseDistributedLock(balanceLockKey, requestId) | |||
} | |||
return cb, nil | |||
} | |||
func GetEggEnergyCoreData(engine *xorm.Engine) (coreData *model.EggEnergyCoreData, cb func(), err error) { | |||
requestIdPrefix := fmt.Sprintf(md.DealEggEnergyNowPriceRequestIdPrefix, time.Now().UnixMicro()) | |||
cb, err = handleDistributedLock(requestIdPrefix) | |||
if err != nil { | |||
return | |||
} | |||
eggEnergyCoreDataDb := implement.NewEggEnergyCoreDataDb(engine) | |||
coreData, err = eggEnergyCoreDataDb.EggEnergyCoreDataGet() | |||
if err != nil { | |||
return | |||
} | |||
return | |||
} |
@@ -0,0 +1,909 @@ | |||
package rule | |||
import ( | |||
"code.fnuoos.com/EggPlanet/egg_models.git/src/implement" | |||
"code.fnuoos.com/EggPlanet/egg_models.git/src/model" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/md" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/utils" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/cache" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/logx" | |||
"errors" | |||
"fmt" | |||
"math" | |||
"strconv" | |||
"strings" | |||
"time" | |||
"xorm.io/xorm" | |||
) | |||
// AddPublicPlatoonUserRelationCommission 新增公排用户关系记录 | |||
func AddPublicPlatoonUserRelationCommission(engine *xorm.Engine, AddPublicPlatoonUserRelationCommissionReqList []*md.AddPublicPlatoonUserRelationCommissionReq) (map[string]*model.PublicPlatoonUserRelation, error) { | |||
var resp = map[string]*model.PublicPlatoonUserRelation{} | |||
//查找 `public_platoon_basic_setting` 基础设置 | |||
publicPlatoonBasicSettingDb := implement.NewPublicPlatoonBasicSettingDb(engine) | |||
publicPlatoonBasicSetting, err := publicPlatoonBasicSettingDb.PublicPlatoonBasicSettingGetOneByParams(map[string]interface{}{ | |||
"key": "is_open", | |||
"value": 1, | |||
}) | |||
if err != nil { | |||
return nil, err | |||
} | |||
if publicPlatoonBasicSetting == nil { | |||
return nil, errors.New("公排制度未开启") | |||
} | |||
publicPlatoonUserRelationDb := implement.NewPublicPlatoonUserRelationDb(engine) | |||
for _, param := range AddPublicPlatoonUserRelationCommissionReqList { | |||
isHasPublicPlatoonUserRelation, err11 := publicPlatoonUserRelationDb.PublicPlatoonUserRelationGetOneByParams(map[string]interface{}{ | |||
"key": "uid", | |||
"value": param.Uid, | |||
}) | |||
if err11 != nil { | |||
return nil, err11 | |||
} | |||
if isHasPublicPlatoonUserRelation != nil { | |||
return nil, errors.New("当前用户已加入公排") | |||
} | |||
//1、判断是否有推荐人 | |||
if param.RecommendUid != "" { | |||
//2、有推荐人 | |||
//判断是否有uid为-1 (代表等待新用户填充) 的记录 | |||
PublicPlatoonUserRelation, err1 := publicPlatoonUserRelationDb.PublicPlatoonUserRelationGetOneByPid(param.RecommendUid, map[string]interface{}{ | |||
"key": "uid", | |||
"value": -1, | |||
}) | |||
if err1 != nil { | |||
return nil, err1 | |||
} | |||
if PublicPlatoonUserRelation != nil { | |||
now := time.Now() | |||
oldUid := PublicPlatoonUserRelation.Uid | |||
PublicPlatoonUserRelation.Uid = egg_system_rules.StrToInt64(param.Uid) | |||
PublicPlatoonUserRelation.RecommendUid = egg_system_rules.StrToInt64(param.RecommendUid) | |||
PublicPlatoonUserRelation.CreateAt = now.Format("2006-01-02 15:04:05") | |||
PublicPlatoonUserRelation.UpdateAt = now.Format("2006-01-02 15:04:05") | |||
PublicPlatoonUserRelation.JoinAt = now.Format("2006-01-02 15:04:05") | |||
updateAffected, err2 := publicPlatoonUserRelationDb.PublicPlatoonUserRelationUpdate(engine.NewSession(), PublicPlatoonUserRelation.Id, PublicPlatoonUserRelation) | |||
if err2 != nil { | |||
return nil, err2 | |||
} | |||
if updateAffected == 0 { | |||
err = errors.New("更新 public_platoon_user_relation 记录失败") | |||
return nil, err | |||
} else { | |||
for n := 1; n <= 9; n++ { | |||
str := "father_uid" + strconv.Itoa(n) | |||
sql := fmt.Sprintf("UPDATE `public_platoon_user_relation` SET %s=%s where %s=%s", str, param.Uid, str, egg_system_rules.Int64ToStr(oldUid)) | |||
fmt.Println(">>>>>>>sql>>>>>>>", sql) | |||
_, err = engine.Exec(sql) | |||
if err != nil { | |||
return nil, err | |||
} | |||
} | |||
resp[param.Uid] = PublicPlatoonUserRelation | |||
} | |||
continue | |||
} | |||
res, err := PublicPlatoon(engine, egg_system_rules.StrToInt64(param.Uid), egg_system_rules.StrToInt64(param.RecommendUid), *publicPlatoonBasicSetting) | |||
if err != nil { | |||
return nil, err | |||
} | |||
resp[param.Uid] = &res | |||
} | |||
} | |||
return resp, nil | |||
} | |||
/* | |||
公排方法 | |||
TODO 相关公式: | |||
1: 每个等级的起始值(1+5^0+5^1+5^2+...+5^x-2), 每个等级的结束值(`5^0+5^1+5^2+...+5^x-1) | |||
2: 根据position查找父级position { (position-1)/5 } | |||
3: 根据position查找等级level {position-5^0-5^1-5^2-...-5^x 是否 <0 ? => x+1 } | |||
4: 根据最新自增`id` 逆向推导 position {levelFirstPosition + (position-1)%5} | |||
*/ | |||
func PublicPlatoon(engine *xorm.Engine, uid, recommendUid int64, PublicPlatoonBasicSetting model.PublicPlatoonBasicSetting) (model.PublicPlatoonUserRelation, error) { | |||
var standardPublicPlatoonRelation md.StandardPublicPlatoonRelation | |||
var PublicPlatoonUserRelation model.PublicPlatoonUserRelation | |||
var fatherUid int64 | |||
//1、 查找当前 public_platoon_user_relation 中 recommendUid 的记录 | |||
publicPlatoonUserRelationDb := implement.NewPublicPlatoonUserRelationDb(engine) | |||
m, err := publicPlatoonUserRelationDb.PublicPlatoonUserRelationGetOneByParams(map[string]interface{}{ | |||
"key": "uid", | |||
"value": recommendUid, | |||
}) | |||
if err != nil { | |||
return model.PublicPlatoonUserRelation{}, err | |||
} | |||
//2、 查找当前 public_platoon_user_relation 中 recommendUid 所有的子记录 | |||
PublicPlatoonUserRelations, err := publicPlatoonUserRelationDb.PublicPlatoonUserRelationFindByPid(m.Uid, "father_uid1", "position1") | |||
if err != nil { | |||
return model.PublicPlatoonUserRelation{}, err | |||
} | |||
if len(PublicPlatoonUserRelations) == 0 { | |||
fatherUid = m.Uid | |||
//证明是第一个 | |||
standardPublicPlatoonRelation.FatherUid1 = m.Uid | |||
standardPublicPlatoonRelation.FatherUid2 = m.FatherUid1 | |||
standardPublicPlatoonRelation.FatherUid3 = m.FatherUid2 | |||
standardPublicPlatoonRelation.FatherUid4 = m.FatherUid3 | |||
standardPublicPlatoonRelation.FatherUid5 = m.FatherUid4 | |||
standardPublicPlatoonRelation.FatherUid6 = m.FatherUid5 | |||
standardPublicPlatoonRelation.FatherUid7 = m.FatherUid6 | |||
standardPublicPlatoonRelation.FatherUid8 = m.FatherUid7 | |||
standardPublicPlatoonRelation.FatherUid9 = m.FatherUid8 | |||
standardPublicPlatoonRelation.Pid1 = m.Position | |||
standardPublicPlatoonRelation.Pid2 = m.Position1 | |||
standardPublicPlatoonRelation.Pid3 = m.Position2 | |||
standardPublicPlatoonRelation.Pid4 = m.Position3 | |||
standardPublicPlatoonRelation.Pid5 = m.Position4 | |||
standardPublicPlatoonRelation.Pid6 = m.Position5 | |||
standardPublicPlatoonRelation.Pid7 = m.Position6 | |||
standardPublicPlatoonRelation.Pid8 = m.Position7 | |||
standardPublicPlatoonRelation.Pid9 = m.Position8 | |||
standardPublicPlatoonRelation.Position1 = SearchPositionFirstSonPosition(m.Position, int64(PublicPlatoonBasicSetting.SeveralTimes)) | |||
standardPublicPlatoonRelation.Position2 = ReverseDeductionPositionByFather(m.Position1, int64(m.Level1), int64(PublicPlatoonBasicSetting.SeveralTimes), 0) | |||
standardPublicPlatoonRelation.Position3 = ReverseDeductionPositionByFather(m.Position2, int64(m.Level2), int64(PublicPlatoonBasicSetting.SeveralTimes), 0) | |||
standardPublicPlatoonRelation.Position4 = ReverseDeductionPositionByFather(m.Position3, int64(m.Level3), int64(PublicPlatoonBasicSetting.SeveralTimes), 0) | |||
standardPublicPlatoonRelation.Position5 = ReverseDeductionPositionByFather(m.Position4, int64(m.Level4), int64(PublicPlatoonBasicSetting.SeveralTimes), 0) | |||
standardPublicPlatoonRelation.Position6 = ReverseDeductionPositionByFather(m.Position5, int64(m.Level5), int64(PublicPlatoonBasicSetting.SeveralTimes), 0) | |||
standardPublicPlatoonRelation.Position7 = ReverseDeductionPositionByFather(m.Position6, int64(m.Level6), int64(PublicPlatoonBasicSetting.SeveralTimes), 0) | |||
standardPublicPlatoonRelation.Position8 = ReverseDeductionPositionByFather(m.Position7, int64(m.Level7), int64(PublicPlatoonBasicSetting.SeveralTimes), 0) | |||
standardPublicPlatoonRelation.Position9 = ReverseDeductionPositionByFather(m.Position8, int64(m.Level8), int64(PublicPlatoonBasicSetting.SeveralTimes), 0) | |||
if m.Level1 == 0 { | |||
m.Level1-- | |||
} | |||
if m.Level2 == 0 { | |||
m.Level2-- | |||
} | |||
if m.Level3 == 0 { | |||
m.Level3-- | |||
} | |||
if m.Level4 == 0 { | |||
m.Level4-- | |||
} | |||
if m.Level5 == 0 { | |||
m.Level5-- | |||
} | |||
if m.Level6 == 0 { | |||
m.Level6-- | |||
} | |||
if m.Level7 == 0 { | |||
m.Level7-- | |||
} | |||
if m.Level8 == 0 { | |||
m.Level8-- | |||
} | |||
if m.Level9 == 0 { | |||
m.Level9-- | |||
} | |||
standardPublicPlatoonRelation.Level1 = m.Level + 1 | |||
standardPublicPlatoonRelation.Level2 = m.Level1 + 1 | |||
standardPublicPlatoonRelation.Level3 = m.Level2 + 1 | |||
standardPublicPlatoonRelation.Level4 = m.Level3 + 1 | |||
standardPublicPlatoonRelation.Level5 = m.Level4 + 1 | |||
standardPublicPlatoonRelation.Level6 = m.Level5 + 1 | |||
standardPublicPlatoonRelation.Level7 = m.Level6 + 1 | |||
standardPublicPlatoonRelation.Level8 = m.Level7 + 1 | |||
standardPublicPlatoonRelation.Level9 = m.Level8 + 1 | |||
standardPublicPlatoonRelation.LevelTotal = m.LevelTotal + 1 | |||
} else { | |||
//TODO::判断直属下级是否排满 | |||
if len(PublicPlatoonUserRelations) >= PublicPlatoonBasicSetting.SeveralTimes { | |||
var fatherLevel float64 | |||
makeSearchLevel(&m.Position, float64(PublicPlatoonBasicSetting.SeveralTimes), &fatherLevel) | |||
var times = 0 | |||
data, father, err := FindSuitablePosition(engine, &m.Position, float64(PublicPlatoonBasicSetting.SeveralTimes), m.Uid, int64(fatherLevel), ×) | |||
if err != nil { | |||
return model.PublicPlatoonUserRelation{}, err | |||
} | |||
fatherUid = father | |||
standardPublicPlatoonRelation = data | |||
} else { | |||
fatherUid = m.Uid | |||
standardPublicPlatoonRelation.FatherUid1 = PublicPlatoonUserRelations[0].FatherUid1 | |||
standardPublicPlatoonRelation.FatherUid2 = PublicPlatoonUserRelations[0].FatherUid2 | |||
standardPublicPlatoonRelation.FatherUid3 = PublicPlatoonUserRelations[0].FatherUid3 | |||
standardPublicPlatoonRelation.FatherUid4 = PublicPlatoonUserRelations[0].FatherUid4 | |||
standardPublicPlatoonRelation.FatherUid5 = PublicPlatoonUserRelations[0].FatherUid5 | |||
standardPublicPlatoonRelation.FatherUid6 = PublicPlatoonUserRelations[0].FatherUid6 | |||
standardPublicPlatoonRelation.FatherUid7 = PublicPlatoonUserRelations[0].FatherUid7 | |||
standardPublicPlatoonRelation.FatherUid8 = PublicPlatoonUserRelations[0].FatherUid8 | |||
standardPublicPlatoonRelation.FatherUid9 = PublicPlatoonUserRelations[0].FatherUid9 | |||
standardPublicPlatoonRelation.Pid1 = PublicPlatoonUserRelations[0].Pid1 | |||
standardPublicPlatoonRelation.Pid2 = PublicPlatoonUserRelations[0].Pid2 | |||
standardPublicPlatoonRelation.Pid3 = PublicPlatoonUserRelations[0].Pid3 | |||
standardPublicPlatoonRelation.Pid4 = PublicPlatoonUserRelations[0].Pid4 | |||
standardPublicPlatoonRelation.Pid5 = PublicPlatoonUserRelations[0].Pid5 | |||
standardPublicPlatoonRelation.Pid6 = PublicPlatoonUserRelations[0].Pid6 | |||
standardPublicPlatoonRelation.Pid7 = PublicPlatoonUserRelations[0].Pid7 | |||
standardPublicPlatoonRelation.Pid8 = PublicPlatoonUserRelations[0].Pid8 | |||
standardPublicPlatoonRelation.Pid9 = PublicPlatoonUserRelations[0].Pid9 | |||
standardPublicPlatoonRelation.Position1 = PublicPlatoonUserRelations[0].Position1 + 1 | |||
if PublicPlatoonUserRelations[0].Position2 != 0 { | |||
standardPublicPlatoonRelation.Position2 = PublicPlatoonUserRelations[0].Position2 + 1 | |||
} | |||
if PublicPlatoonUserRelations[0].Position3 != 0 { | |||
standardPublicPlatoonRelation.Position3 = PublicPlatoonUserRelations[0].Position3 + 1 | |||
} | |||
if PublicPlatoonUserRelations[0].Position4 != 0 { | |||
standardPublicPlatoonRelation.Position4 = PublicPlatoonUserRelations[0].Position4 + 1 | |||
} | |||
if PublicPlatoonUserRelations[0].Position5 != 0 { | |||
standardPublicPlatoonRelation.Position5 = PublicPlatoonUserRelations[0].Position5 + 1 | |||
} | |||
if PublicPlatoonUserRelations[0].Position6 != 0 { | |||
standardPublicPlatoonRelation.Position6 = PublicPlatoonUserRelations[0].Position6 + 1 | |||
} | |||
if PublicPlatoonUserRelations[0].Position7 != 0 { | |||
standardPublicPlatoonRelation.Position7 = PublicPlatoonUserRelations[0].Position7 + 1 | |||
} | |||
if PublicPlatoonUserRelations[0].Position8 != 0 { | |||
standardPublicPlatoonRelation.Position8 = PublicPlatoonUserRelations[0].Position8 + 1 | |||
} | |||
if PublicPlatoonUserRelations[0].Position9 != 0 { | |||
standardPublicPlatoonRelation.Position9 = PublicPlatoonUserRelations[0].Position9 + 1 | |||
} | |||
standardPublicPlatoonRelation.Level1 = PublicPlatoonUserRelations[0].Level1 | |||
standardPublicPlatoonRelation.Level2 = PublicPlatoonUserRelations[0].Level2 | |||
standardPublicPlatoonRelation.Level3 = PublicPlatoonUserRelations[0].Level3 | |||
standardPublicPlatoonRelation.Level4 = PublicPlatoonUserRelations[0].Level4 | |||
standardPublicPlatoonRelation.Level5 = PublicPlatoonUserRelations[0].Level5 | |||
standardPublicPlatoonRelation.Level6 = PublicPlatoonUserRelations[0].Level6 | |||
standardPublicPlatoonRelation.Level7 = PublicPlatoonUserRelations[0].Level7 | |||
standardPublicPlatoonRelation.Level8 = PublicPlatoonUserRelations[0].Level8 | |||
standardPublicPlatoonRelation.Level9 = PublicPlatoonUserRelations[0].Level9 | |||
standardPublicPlatoonRelation.LevelTotal = PublicPlatoonUserRelations[0].LevelTotal | |||
} | |||
} | |||
//2、查找对应pid的 public_platoon_user_relation 记录 | |||
var m1 model.PublicPlatoonUserRelation | |||
if has, err := engine.Where("uid=?", fatherUid).Get(&m1); err != nil || has == false { | |||
return PublicPlatoonUserRelation, err | |||
} | |||
var fatherUidStr string | |||
if m1.FatherUid == "" { | |||
//TODO::顶级 | |||
fatherUidStr = egg_system_rules.IntToStr(m1.Id) | |||
} else { | |||
fatherUids := strings.Split(m1.FatherUid, "-") | |||
if len(fatherUids) >= PublicPlatoonBasicSetting.SeveralRows { | |||
fatherUidStr = egg_system_rules.IntToStr(m1.Id) + "-" + strings.Join(fatherUids[0:PublicPlatoonBasicSetting.SeveralRows:len(fatherUids)], "-") | |||
} else { | |||
fatherUidStr = egg_system_rules.IntToStr(m1.Id) + "-" + m1.FatherUid | |||
} | |||
} | |||
// 3、插入 public_platoon_user_relation 记录 | |||
now := time.Now() | |||
PublicPlatoonUserRelation.Uid = uid | |||
PublicPlatoonUserRelation.FatherUid = fatherUidStr | |||
PublicPlatoonUserRelation.FatherUid1 = standardPublicPlatoonRelation.FatherUid1 | |||
PublicPlatoonUserRelation.FatherUid2 = standardPublicPlatoonRelation.FatherUid2 | |||
PublicPlatoonUserRelation.FatherUid3 = standardPublicPlatoonRelation.FatherUid3 | |||
PublicPlatoonUserRelation.FatherUid4 = standardPublicPlatoonRelation.FatherUid4 | |||
PublicPlatoonUserRelation.FatherUid5 = standardPublicPlatoonRelation.FatherUid5 | |||
PublicPlatoonUserRelation.FatherUid6 = standardPublicPlatoonRelation.FatherUid6 | |||
PublicPlatoonUserRelation.FatherUid7 = standardPublicPlatoonRelation.FatherUid7 | |||
PublicPlatoonUserRelation.FatherUid8 = standardPublicPlatoonRelation.FatherUid8 | |||
PublicPlatoonUserRelation.FatherUid9 = standardPublicPlatoonRelation.FatherUid9 | |||
PublicPlatoonUserRelation.Pid1 = standardPublicPlatoonRelation.Pid1 | |||
PublicPlatoonUserRelation.Pid2 = standardPublicPlatoonRelation.Pid2 | |||
PublicPlatoonUserRelation.Pid3 = standardPublicPlatoonRelation.Pid3 | |||
PublicPlatoonUserRelation.Pid4 = standardPublicPlatoonRelation.Pid4 | |||
PublicPlatoonUserRelation.Pid5 = standardPublicPlatoonRelation.Pid5 | |||
PublicPlatoonUserRelation.Pid6 = standardPublicPlatoonRelation.Pid6 | |||
PublicPlatoonUserRelation.Pid7 = standardPublicPlatoonRelation.Pid7 | |||
PublicPlatoonUserRelation.Pid8 = standardPublicPlatoonRelation.Pid8 | |||
PublicPlatoonUserRelation.Pid9 = standardPublicPlatoonRelation.Pid9 | |||
PublicPlatoonUserRelation.Position = 1 | |||
PublicPlatoonUserRelation.Position1 = standardPublicPlatoonRelation.Position1 | |||
PublicPlatoonUserRelation.Position2 = standardPublicPlatoonRelation.Position2 | |||
PublicPlatoonUserRelation.Position3 = standardPublicPlatoonRelation.Position3 | |||
PublicPlatoonUserRelation.Position4 = standardPublicPlatoonRelation.Position4 | |||
PublicPlatoonUserRelation.Position5 = standardPublicPlatoonRelation.Position5 | |||
PublicPlatoonUserRelation.Position6 = standardPublicPlatoonRelation.Position6 | |||
PublicPlatoonUserRelation.Position7 = standardPublicPlatoonRelation.Position7 | |||
PublicPlatoonUserRelation.Position8 = standardPublicPlatoonRelation.Position8 | |||
PublicPlatoonUserRelation.Position9 = standardPublicPlatoonRelation.Position9 | |||
PublicPlatoonUserRelation.Level = 1 | |||
PublicPlatoonUserRelation.Level1 = standardPublicPlatoonRelation.Level1 | |||
PublicPlatoonUserRelation.Level2 = standardPublicPlatoonRelation.Level2 | |||
PublicPlatoonUserRelation.Level3 = standardPublicPlatoonRelation.Level3 | |||
PublicPlatoonUserRelation.Level4 = standardPublicPlatoonRelation.Level4 | |||
PublicPlatoonUserRelation.Level5 = standardPublicPlatoonRelation.Level5 | |||
PublicPlatoonUserRelation.Level6 = standardPublicPlatoonRelation.Level6 | |||
PublicPlatoonUserRelation.Level7 = standardPublicPlatoonRelation.Level7 | |||
PublicPlatoonUserRelation.Level8 = standardPublicPlatoonRelation.Level8 | |||
PublicPlatoonUserRelation.Level9 = standardPublicPlatoonRelation.Level9 | |||
PublicPlatoonUserRelation.LevelTotal = standardPublicPlatoonRelation.LevelTotal | |||
PublicPlatoonUserRelation.RecommendUid = recommendUid | |||
PublicPlatoonUserRelation.JoinAt = now.Format("2006-01-02 15:04:05") | |||
PublicPlatoonUserRelation.CreateAt = now.Format("2006-01-02 15:04:05") | |||
PublicPlatoonUserRelation.UpdateAt = now.Format("2006-01-02 15:04:05") | |||
PublicPlatoonUserRelation.HasSonNum = 0 | |||
_, err = publicPlatoonUserRelationDb.PublicPlatoonUserRelationInsert(&PublicPlatoonUserRelation) | |||
if err != nil { | |||
return model.PublicPlatoonUserRelation{}, err | |||
} | |||
// 4、改变直属父级的 has_son_num 数量 | |||
update, err := engine.Where("uid = ?", fatherUid).SetExpr("has_son_num", "has_son_num + 1").Update(new(model.PublicPlatoonUserRelation)) | |||
if err != nil { | |||
return PublicPlatoonUserRelation, err | |||
} | |||
if update == 0 { | |||
return PublicPlatoonUserRelation, errors.New("更新has_son_num数据出错") | |||
} | |||
return PublicPlatoonUserRelation, nil | |||
} | |||
// ReverseDeductionPosition 逆向推导 position | |||
func ReverseDeductionPosition(calcPosition, levelFirstPosition, severalTimes int) (position int) { | |||
remainder := (calcPosition - 1) % severalTimes | |||
position = levelFirstPosition + remainder | |||
return | |||
} | |||
func ReverseDeductionPositionByFather(fatherPosition, level, severalTimes, remainder int64) (position int64) { | |||
if fatherPosition == 0 { | |||
position = 0 | |||
return | |||
} | |||
firstPosition := GetLevelForFirstPosition(level, severalTimes) | |||
endPosition := firstPosition + int64(math.Pow(float64(severalTimes), float64(level-1))) - 1 | |||
position = fatherPosition + (fatherPosition-firstPosition)*severalTimes + (endPosition - fatherPosition) + 1 | |||
return | |||
} | |||
func FindSuitablePosition(engine *xorm.Engine, position *int64, severalTimes float64, fuid, fatherLevel int64, times *int) (standardPublicPlatoonRelation md.StandardPublicPlatoonRelation, fatherUid int64, err error) { | |||
*times++ | |||
positionName := "position" + egg_system_rules.IntToStr(*times) | |||
fatherName := "father_uid" + egg_system_rules.IntToStr(*times) | |||
firstSonPosition := SearchPositionFirstSonPosition(*position, int64(severalTimes)) | |||
var tempLevel float64 | |||
makeSearchLevel(&firstSonPosition, severalTimes, &tempLevel) | |||
firstSonLevel := int64(tempLevel) | |||
endSonPosition := firstSonPosition + int64(math.Pow(severalTimes, float64(firstSonLevel-fatherLevel))) - 1 | |||
publicPlatoonUserRelationDb := implement.NewPublicPlatoonUserRelationDb(engine) | |||
list, _, err := publicPlatoonUserRelationDb.PublicPlatoonUserRelationFindCountByPosition(fuid, fatherName, positionName, int64(firstSonPosition), int64(endSonPosition)) | |||
if err != nil { | |||
return standardPublicPlatoonRelation, fatherUid, err | |||
} | |||
if list[0].HasSonNum == int(severalTimes) { | |||
//TODO::则证明该层直属下级无空位 | |||
position = &firstSonPosition | |||
return FindSuitablePosition(engine, position, severalTimes, fuid, fatherLevel, times) | |||
} else if list[0].HasSonNum == 0 { | |||
fatherUid = list[0].Uid | |||
//TODO::新的一层 | |||
standardPublicPlatoonRelation.FatherUid1 = list[0].Uid | |||
standardPublicPlatoonRelation.FatherUid2 = list[0].FatherUid1 | |||
standardPublicPlatoonRelation.FatherUid3 = list[0].FatherUid2 | |||
standardPublicPlatoonRelation.FatherUid4 = list[0].FatherUid3 | |||
standardPublicPlatoonRelation.FatherUid5 = list[0].FatherUid4 | |||
standardPublicPlatoonRelation.FatherUid6 = list[0].FatherUid5 | |||
standardPublicPlatoonRelation.FatherUid7 = list[0].FatherUid6 | |||
standardPublicPlatoonRelation.FatherUid8 = list[0].FatherUid7 | |||
standardPublicPlatoonRelation.FatherUid9 = list[0].FatherUid8 | |||
standardPublicPlatoonRelation.Pid1 = list[0].Position | |||
standardPublicPlatoonRelation.Pid2 = list[0].Position1 | |||
standardPublicPlatoonRelation.Pid3 = list[0].Position2 | |||
standardPublicPlatoonRelation.Pid4 = list[0].Position3 | |||
standardPublicPlatoonRelation.Pid5 = list[0].Position4 | |||
standardPublicPlatoonRelation.Pid6 = list[0].Position5 | |||
standardPublicPlatoonRelation.Pid7 = list[0].Position6 | |||
standardPublicPlatoonRelation.Pid8 = list[0].Position7 | |||
standardPublicPlatoonRelation.Pid9 = list[0].Position8 | |||
standardPublicPlatoonRelation.Position1 = SearchPositionFirstSonPosition(list[0].Position, int64(severalTimes)) | |||
standardPublicPlatoonRelation.Position2 = ReverseDeductionPositionByFather(list[0].Position1, int64(list[0].Level1), int64(severalTimes), 0) | |||
standardPublicPlatoonRelation.Position3 = ReverseDeductionPositionByFather(list[0].Position2, int64(list[0].Level2), int64(severalTimes), 0) | |||
standardPublicPlatoonRelation.Position4 = ReverseDeductionPositionByFather(list[0].Position3, int64(list[0].Level3), int64(severalTimes), 0) | |||
standardPublicPlatoonRelation.Position5 = ReverseDeductionPositionByFather(list[0].Position4, int64(list[0].Level4), int64(severalTimes), 0) | |||
standardPublicPlatoonRelation.Position6 = ReverseDeductionPositionByFather(list[0].Position5, int64(list[0].Level5), int64(severalTimes), 0) | |||
standardPublicPlatoonRelation.Position7 = ReverseDeductionPositionByFather(list[0].Position6, int64(list[0].Level6), int64(severalTimes), 0) | |||
standardPublicPlatoonRelation.Position8 = ReverseDeductionPositionByFather(list[0].Position7, int64(list[0].Level7), int64(severalTimes), 0) | |||
standardPublicPlatoonRelation.Position9 = ReverseDeductionPositionByFather(list[0].Position8, int64(list[0].Level8), int64(severalTimes), 0) | |||
if list[0].Level1 == 0 { | |||
list[0].Level1-- | |||
} | |||
if list[0].Level2 == 0 { | |||
list[0].Level2-- | |||
} | |||
if list[0].Level3 == 0 { | |||
list[0].Level3-- | |||
} | |||
if list[0].Level4 == 0 { | |||
list[0].Level4-- | |||
} | |||
if list[0].Level5 == 0 { | |||
list[0].Level5-- | |||
} | |||
if list[0].Level6 == 0 { | |||
list[0].Level6-- | |||
} | |||
if list[0].Level7 == 0 { | |||
list[0].Level7-- | |||
} | |||
if list[0].Level8 == 0 { | |||
list[0].Level8-- | |||
} | |||
if list[0].Level9 == 0 { | |||
list[0].Level9-- | |||
} | |||
standardPublicPlatoonRelation.Level1 = list[0].Level + 1 | |||
standardPublicPlatoonRelation.Level2 = list[0].Level1 + 1 | |||
standardPublicPlatoonRelation.Level3 = list[0].Level2 + 1 | |||
standardPublicPlatoonRelation.Level4 = list[0].Level3 + 1 | |||
standardPublicPlatoonRelation.Level5 = list[0].Level4 + 1 | |||
standardPublicPlatoonRelation.Level6 = list[0].Level5 + 1 | |||
standardPublicPlatoonRelation.Level7 = list[0].Level6 + 1 | |||
standardPublicPlatoonRelation.Level8 = list[0].Level7 + 1 | |||
standardPublicPlatoonRelation.Level9 = list[0].Level8 + 1 | |||
standardPublicPlatoonRelation.LevelTotal = list[0].LevelTotal + 1 | |||
} else { | |||
fatherUid = list[0].Uid | |||
_, _, _, _, getPositionName, _, _, _ := GetPosition(list[0], *times+1) | |||
//PublicPlatoonUserRelations, err := db.PublicPlatoonUserRelationFindByPid(engine, m.Position, m.Uid, "pid1", "father_uid1", "position1") | |||
PublicPlatoonUserRelations, err := publicPlatoonUserRelationDb.PublicPlatoonUserRelationFindByPid(list[0].Uid, "father_uid1", getPositionName) | |||
if err != nil { | |||
return standardPublicPlatoonRelation, fatherUid, err | |||
} | |||
if PublicPlatoonUserRelations[0].Position2 == 0 { | |||
PublicPlatoonUserRelations[0].Position2 = -1 | |||
} | |||
if PublicPlatoonUserRelations[0].Position3 == 0 { | |||
standardPublicPlatoonRelation.Position3 = -1 | |||
} | |||
if PublicPlatoonUserRelations[0].Position4 == 0 { | |||
standardPublicPlatoonRelation.Position4 = -1 | |||
} | |||
if PublicPlatoonUserRelations[0].Position5 == 0 { | |||
standardPublicPlatoonRelation.Position5 = -1 | |||
} | |||
if PublicPlatoonUserRelations[0].Position6 == 0 { | |||
standardPublicPlatoonRelation.Position6 = -1 | |||
} | |||
if PublicPlatoonUserRelations[0].Position7 == 0 { | |||
standardPublicPlatoonRelation.Position7 = -1 | |||
} | |||
if PublicPlatoonUserRelations[0].Position8 == 0 { | |||
standardPublicPlatoonRelation.Position8 = -1 | |||
} | |||
if PublicPlatoonUserRelations[0].Position9 == 0 { | |||
standardPublicPlatoonRelation.Position9 = -1 | |||
} | |||
standardPublicPlatoonRelation = md.StandardPublicPlatoonRelation{ | |||
FatherUid1: PublicPlatoonUserRelations[0].FatherUid1, | |||
FatherUid2: PublicPlatoonUserRelations[0].FatherUid2, | |||
FatherUid3: PublicPlatoonUserRelations[0].FatherUid3, | |||
FatherUid4: PublicPlatoonUserRelations[0].FatherUid4, | |||
FatherUid5: PublicPlatoonUserRelations[0].FatherUid5, | |||
FatherUid6: PublicPlatoonUserRelations[0].FatherUid6, | |||
FatherUid7: PublicPlatoonUserRelations[0].FatherUid7, | |||
FatherUid8: PublicPlatoonUserRelations[0].FatherUid8, | |||
FatherUid9: PublicPlatoonUserRelations[0].FatherUid9, | |||
Pid1: PublicPlatoonUserRelations[0].Pid1, | |||
Pid2: PublicPlatoonUserRelations[0].Pid2, | |||
Pid3: PublicPlatoonUserRelations[0].Pid3, | |||
Pid4: PublicPlatoonUserRelations[0].Pid4, | |||
Pid5: PublicPlatoonUserRelations[0].Pid5, | |||
Pid6: PublicPlatoonUserRelations[0].Pid6, | |||
Pid7: PublicPlatoonUserRelations[0].Pid7, | |||
Pid8: PublicPlatoonUserRelations[0].Pid8, | |||
Pid9: PublicPlatoonUserRelations[0].Pid9, | |||
Position1: PublicPlatoonUserRelations[0].Position1 + 1, | |||
Position2: PublicPlatoonUserRelations[0].Position2 + 1, | |||
Position3: PublicPlatoonUserRelations[0].Position3 + 1, | |||
Position4: PublicPlatoonUserRelations[0].Position4 + 1, | |||
Position5: PublicPlatoonUserRelations[0].Position5 + 1, | |||
Position6: PublicPlatoonUserRelations[0].Position6 + 1, | |||
Position7: PublicPlatoonUserRelations[0].Position7 + 1, | |||
Position8: PublicPlatoonUserRelations[0].Position8 + 1, | |||
Position9: PublicPlatoonUserRelations[0].Position9 + 1, | |||
Level1: PublicPlatoonUserRelations[0].Level1, | |||
Level2: PublicPlatoonUserRelations[0].Level2, | |||
Level3: PublicPlatoonUserRelations[0].Level3, | |||
Level4: PublicPlatoonUserRelations[0].Level4, | |||
Level5: PublicPlatoonUserRelations[0].Level5, | |||
Level6: PublicPlatoonUserRelations[0].Level6, | |||
Level7: PublicPlatoonUserRelations[0].Level7, | |||
Level8: PublicPlatoonUserRelations[0].Level8, | |||
Level9: PublicPlatoonUserRelations[0].Level9, | |||
LevelTotal: PublicPlatoonUserRelations[0].LevelTotal, | |||
} | |||
return standardPublicPlatoonRelation, fatherUid, nil | |||
} | |||
return | |||
} | |||
func GetPosition(m model.PublicPlatoonUserRelation, times int) (position, pid int64, level int, fatherUid int64, positionName, pidName, levelName, fatherUidName string) { | |||
if times == 1 { | |||
position = m.Position1 | |||
positionName = "position1" | |||
pid = m.Pid1 | |||
pidName = "pid1" | |||
level = m.Level1 | |||
levelName = "level1" | |||
fatherUid = m.FatherUid1 | |||
fatherUidName = "father_uid1" | |||
} | |||
if times == 2 { | |||
position = m.Position2 | |||
positionName = "position2" | |||
pid = m.Pid2 | |||
pidName = "pid2" | |||
level = m.Level2 | |||
levelName = "level2" | |||
fatherUid = m.FatherUid2 | |||
fatherUidName = "father_uid2" | |||
} | |||
if times == 3 { | |||
position = m.Position3 | |||
positionName = "position3" | |||
pid = m.Pid3 | |||
pidName = "pid3" | |||
level = m.Level3 | |||
levelName = "level3" | |||
fatherUid = m.FatherUid3 | |||
fatherUidName = "father_uid3" | |||
} | |||
if times == 4 { | |||
position = m.Position4 | |||
positionName = "position4" | |||
pid = m.Pid4 | |||
pidName = "pid4" | |||
level = m.Level4 | |||
levelName = "level4" | |||
fatherUid = m.FatherUid4 | |||
fatherUidName = "father_uid4" | |||
} | |||
if times == 5 { | |||
position = m.Position5 | |||
positionName = "position5" | |||
pid = m.Pid5 | |||
pidName = "pid5" | |||
level = m.Level5 | |||
levelName = "level5" | |||
fatherUid = m.FatherUid5 | |||
fatherUidName = "father_uid5" | |||
} | |||
if times == 6 { | |||
position = m.Position6 | |||
positionName = "position6" | |||
pid = m.Pid6 | |||
pidName = "pid6" | |||
level = m.Level6 | |||
levelName = "level6" | |||
fatherUid = m.FatherUid6 | |||
fatherUidName = "father_uid6" | |||
} | |||
if times == 7 { | |||
position = m.Position7 | |||
positionName = "position7" | |||
pid = m.Pid7 | |||
pidName = "pid7" | |||
level = m.Level7 | |||
levelName = "level7" | |||
fatherUid = m.FatherUid7 | |||
fatherUidName = "father_uid7" | |||
} | |||
if times == 8 { | |||
position = m.Position8 | |||
positionName = "position8" | |||
pid = m.Pid8 | |||
pidName = "pid8" | |||
level = m.Level8 | |||
levelName = "level8" | |||
fatherUid = m.FatherUid8 | |||
fatherUidName = "father_uid8" | |||
} | |||
if times == 9 { | |||
position = m.Position9 | |||
positionName = "position9" | |||
pid = m.Pid9 | |||
pidName = "pid9" | |||
level = m.Level9 | |||
levelName = "level9" | |||
fatherUid = m.FatherUid9 | |||
fatherUidName = "father_uid9" | |||
} | |||
return | |||
} | |||
// GetLevelForFirstPosition 返回当前等级的起始值 | |||
func GetLevelForFirstPosition(level, severalTimes int64) (position int64) { | |||
position = position + 1 | |||
for n := int64(0); n <= (level - 2); n++ { | |||
position += int64(math.Pow(float64(severalTimes), float64(n))) | |||
} | |||
return | |||
} | |||
// 查找归属父级id | |||
func MakeSearchPid(position int, row int) (pid int) { | |||
divisionValue := (position - 1) / row | |||
if divisionValue == 0 { | |||
pid = 1 | |||
return | |||
} else { | |||
if (divisionValue*row + 1) == position { | |||
pid = divisionValue | |||
return | |||
} else { | |||
pid = divisionValue + 1 | |||
return | |||
} | |||
} | |||
} | |||
// 查找当前位置下的第一个子集位置 | |||
func SearchPositionFirstSonPosition(position int64, times int64) (sonPosition int64) { | |||
sonPosition = (position * times) - (times - 2) | |||
return | |||
} | |||
// 查找当前位位置相当于父级的等级 | |||
func SearchPositionSonForLevel(fatherUid string, fatherPosition int64) (level int) { | |||
fatherUids := strings.Split(fatherUid, "-") | |||
for key, item := range fatherUids { | |||
if item == egg_system_rules.Int64ToStr(fatherPosition) { | |||
level = key + 1 | |||
break | |||
} | |||
} | |||
return | |||
} | |||
// FindWaitForDealUsers 查询待处理的用户 | |||
func FindWaitForDealUsers(engine *xorm.Engine, page, pageSize int) (err error, resp []int64) { | |||
now := time.Now().Format("2006-01-02") | |||
publicPlatoonUserRelationDb := implement.NewPublicPlatoonUserRelationDb(engine) | |||
lists, err := publicPlatoonUserRelationDb.PublicPlatoonUserRelationFindByParamsByPage(map[string]interface{}{ | |||
"key": "wait_for_settlement_date", | |||
"value": now, | |||
}, page, pageSize) | |||
if err != nil { | |||
return | |||
} | |||
for _, list := range *lists { | |||
resp = append(resp, list.Uid) | |||
} | |||
return | |||
} | |||
// 递归查找等级 | |||
func makeSearchLevel(position *int64, rows float64, times *float64) (level int) { | |||
difference := *position - int64(math.Pow(rows, *times)) | |||
*times++ | |||
if difference <= 0 { | |||
return int(*times) | |||
} else { | |||
position = &difference | |||
return makeSearchLevel(position, rows, times) | |||
} | |||
} | |||
// DealCommonWealthPunish 处理公排处罚 | |||
func DealCommonWealthPunish(engine *xorm.Engine, uid int64, reason string) (err error, resp []map[string]string) { | |||
session := engine.NewSession() | |||
defer func() { | |||
session.Close() | |||
if err := recover(); err != nil { | |||
_ = zhios_order_relate_logx.Error(err) | |||
} | |||
}() | |||
session.Begin() | |||
//1、查找 `user_public_platoon_setting` 基础设置 | |||
publicPlatoonBasicSettingDb := implement.NewPublicPlatoonBasicSettingDb(engine) | |||
PublicPlatoonBasicSetting, err := publicPlatoonBasicSettingDb.PublicPlatoonBasicSettingGetOneByParams(map[string]interface{}{ | |||
"key": "is_open", | |||
"value": 1, | |||
}) | |||
if err != nil { | |||
_ = session.Rollback() | |||
return | |||
} | |||
//2、查询出 `public_platoon_user_relation` 中相关记录 && 将该记录的uid置为 -1 | |||
publicPlatoonUserRelationDb := implement.NewPublicPlatoonUserRelationDb(engine) | |||
params, err := publicPlatoonUserRelationDb.PublicPlatoonUserRelationGetOneByParams(map[string]interface{}{ | |||
"key": "uid", | |||
"value": uid, | |||
}) | |||
if err != nil { | |||
_ = session.Rollback() | |||
return | |||
} | |||
if params == nil { | |||
fmt.Println("未查询到公排关系记录!!!!!!!", uid) | |||
return | |||
} | |||
//TODO::判断是否为推荐用户 | |||
if params.RecommendUid == 0 { | |||
params.Uid = params.Uid - int64(time.Now().Unix()) | |||
} else { | |||
params.Uid = params.Uid - int64(time.Now().Unix()) | |||
} | |||
for n := 1; n <= 9; n++ { | |||
str := "father_uid" + strconv.Itoa(n) | |||
sql := fmt.Sprintf("UPDATE `public_platoon_user_relation` SET %s=%s where %s=%s", str, egg_system_rules.Int64ToStr(params.Uid), str, egg_system_rules.Int64ToStr(uid)) | |||
fmt.Println(">>>>>>>sql>>>>>>>", sql) | |||
_, err = session.Exec(sql) | |||
if err != nil { | |||
_ = session.Rollback() | |||
return | |||
} | |||
} | |||
updateAffected, err := publicPlatoonUserRelationDb.PublicPlatoonUserRelationUpdate(session, params.Id, params) | |||
if err != nil { | |||
_ = session.Rollback() | |||
return | |||
} | |||
if updateAffected == 0 { | |||
err = errors.New("更新 public_platoon_user_relation 记录失败") | |||
_ = session.Rollback() | |||
return | |||
} | |||
//3、新增一条 `public_platoon_user_relation` 记录 | |||
params.Uid = uid | |||
res, err := PublicPlatoon(engine, params.Uid, params.RecommendUid, *PublicPlatoonBasicSetting) | |||
if err != nil { | |||
_ = session.Rollback() | |||
return | |||
} | |||
//4、新增一条 `public_platoon_user_system_punish_records` 记录 | |||
now := time.Now() | |||
publicPlatoonUserSystemPunishRecordsDb := implement.NewPublicPlatoonUserSystemPunishRecordsDb(engine) | |||
insertAffected, err := publicPlatoonUserSystemPunishRecordsDb.PublicPlatoonUserSystemPunishRecordsInsert(session, &model.PublicPlatoonUserSystemPunishRecords{ | |||
Uid: params.Uid, | |||
OldPosition: params.Position, | |||
NewPosition: res.Position, | |||
Date: now.AddDate(0, 0, 30).Format("2006-01-02"), | |||
Title: "系统处罚记录", | |||
Reason: reason, | |||
Type: 2, | |||
CreateAt: now.Format("2006-01-02 15:04:05"), | |||
UpdateAt: now.Format("2006-01-02 15:04:05"), | |||
}) | |||
if err != nil { | |||
_ = session.Rollback() | |||
return | |||
} | |||
if insertAffected == 0 { | |||
err = errors.New("新增 public_platoon_user_system_punish_records 记录失败") | |||
_ = session.Rollback() | |||
return | |||
} | |||
err = session.Commit() | |||
return | |||
} | |||
const DealUserPublicPlatoonPunishLockKey = "deal_user_public_platoon_lock_key" | |||
// DealUserPublicPlatoonPunish 处理公排处罚 | |||
func DealUserPublicPlatoonPunish(engine *xorm.Engine) (err error) { | |||
now := time.Now() | |||
fmt.Println(now.Hour()) | |||
if !(now.Hour() > 22 && now.Hour() < 24) { | |||
//TODO::只在凌晨一点 ~ 凌晨 8 点运行 | |||
return errors.New("非运行时间") | |||
} | |||
//TODO::增加“悲观锁”防止串行 | |||
getString, _ := cache.GetString(DealUserPublicPlatoonPunishLockKey) | |||
if getString != "" { | |||
fmt.Println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", "上一次结算未执行完") | |||
return errors.New("上一次结算未执行完") | |||
} | |||
cache.SetEx(DealUserPublicPlatoonPunishLockKey, "running", 3600*8) //8小时 | |||
//查找 `public_platoon_basic_setting` 基础设置 | |||
publicPlatoonBasicSettingDb := implement.NewPublicPlatoonBasicSettingDb(engine) | |||
PublicPlatoonBasicSetting, err := publicPlatoonBasicSettingDb.PublicPlatoonBasicSettingGetOneByParams(map[string]interface{}{ | |||
"key": "is_open", | |||
"value": 1, | |||
}) | |||
if err != nil { | |||
return err | |||
} | |||
if PublicPlatoonBasicSetting == nil { | |||
return errors.New("公排制度未开启") | |||
} | |||
publicPlatoonFreePunishWithUserDb := implement.NewPublicPlatoonFreePunishWithUserDb(engine) | |||
mapPublicPlatoonFreePunishWithUser, err := publicPlatoonFreePunishWithUserDb.FindAllPublicPlatoonFreePunishWithUser() | |||
if err != nil { | |||
return err | |||
} | |||
if PublicPlatoonBasicSetting.SystemPunishReplace == 1 { | |||
systemPunishReplaceValue := PublicPlatoonBasicSetting.SystemPunishReplaceValue | |||
startDate := now.AddDate(0, 0, -systemPunishReplaceValue).Format("2006-01-02") + " 00:00:00" | |||
var page = 1 | |||
var pageSize = 100 | |||
for { | |||
var users []model.User | |||
err = engine.Limit(pageSize, (page-1)*pageSize).Desc("uid").Find(&users) | |||
if err != nil { | |||
return err | |||
} | |||
if len(users) <= 0 { | |||
break | |||
} | |||
for _, user := range users { | |||
var list []model.EggSignIn | |||
err = engine.Where("start_time >= ?", startDate).And("uid = ?", user.Id).Find(&list) | |||
if len(list) <= 0 && mapPublicPlatoonFreePunishWithUser[user.Id] == nil { | |||
var PublicPlatoonRecordsPunishWithUser model.PublicPlatoonRecordsPunishWithUser | |||
has, err1 := engine.Where("uid = ?", user.Id).Get(&PublicPlatoonRecordsPunishWithUser) | |||
if err1 != nil { | |||
return err1 | |||
} | |||
PublicPlatoonRecordsPunishWithUserDate, _ := time.ParseInLocation("2006-01-02", PublicPlatoonRecordsPunishWithUser.Date, time.Local) | |||
if has && now.AddDate(0, 0, -7).After(PublicPlatoonRecordsPunishWithUserDate) { | |||
//TODO::不进行重复处罚 | |||
continue | |||
} | |||
//进行处罚 | |||
err, _ = DealCommonWealthPunish(engine, user.Id, "公排处罚") | |||
if err != nil { | |||
return err | |||
} | |||
//添加 public_platoon_records_punish_with_user 记录 | |||
publicPlatoonRecordsPunishWithUserDb := implement.NewPublicPlatoonRecordsPunishWithUserDb(engine) | |||
if has { | |||
PublicPlatoonRecordsPunishWithUser.Date = now.Format("2006-01-02") | |||
_, err2 := publicPlatoonRecordsPunishWithUserDb.PublicPlatoonRecordsPunishWithUserUpdate(PublicPlatoonRecordsPunishWithUser.Id, &PublicPlatoonRecordsPunishWithUser, "date") | |||
if err2 != nil { | |||
return err2 | |||
} | |||
} else { | |||
_, err2 := publicPlatoonRecordsPunishWithUserDb.PublicPlatoonRecordsPunishWithUserInsert(&model.PublicPlatoonRecordsPunishWithUser{ | |||
Uid: user.Id, | |||
Date: now.Format("2006-01-02"), | |||
}) | |||
if err2 != nil { | |||
return err2 | |||
} | |||
} | |||
} | |||
} | |||
page++ | |||
} | |||
} | |||
return | |||
} |
@@ -0,0 +1,138 @@ | |||
package rule | |||
import ( | |||
"code.fnuoos.com/EggPlanet/egg_models.git/src/implement" | |||
"code.fnuoos.com/EggPlanet/egg_models.git/src/model" | |||
zhios_order_relate_utils "code.fnuoos.com/EggPlanet/egg_models.git/utils" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/md" | |||
md2 "code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/md" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/svc" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/cache" | |||
"errors" | |||
"fmt" | |||
"github.com/shopspring/decimal" | |||
"strconv" | |||
"time" | |||
"xorm.io/xorm" | |||
) | |||
// DealUserVirtualCoin 处理给用户虚拟币积分 | |||
func DealUserVirtualCoin(session *xorm.Session, req md.DealUserVirtualCoinReq) (err error) { | |||
if req.Amount < 0 { | |||
req.Amount = 0 | |||
} | |||
//1、分布式锁阻拦 | |||
requestIdPrefix := fmt.Sprintf(md2.DealUserCoinRequestIdPrefix, req.CoinId, req.Uid) | |||
cb, err := svc.HandleDistributedLock(zhios_order_relate_utils.Int64ToStr(req.Uid), requestIdPrefix, strconv.Itoa(req.CoinId)) | |||
if err != nil { | |||
return err | |||
} | |||
if cb != nil { | |||
defer cb() // 释放锁 | |||
} | |||
//2、计算&&组装数据 | |||
now := time.Now() | |||
coinAmount, err := GetUserCoinAmount(session, req.CoinId, req.Uid) | |||
if err != nil { | |||
return err | |||
} | |||
coinAmountValue := decimal.NewFromFloat(zhios_order_relate_utils.StrToFloat64(coinAmount)) | |||
amountValue := decimal.NewFromFloat(req.Amount).RoundFloor(4) | |||
var userVirtualCoinFlow model.UserVirtualCoinFlow | |||
userVirtualCoinFlow.CoinId = req.CoinId | |||
userVirtualCoinFlow.Title = req.Title | |||
userVirtualCoinFlow.TransferType = req.TransferType | |||
userVirtualCoinFlow.Uid = req.Uid | |||
userVirtualCoinFlow.BeforeAmount = coinAmount | |||
userVirtualCoinFlow.Amount = amountValue.String() | |||
userVirtualCoinFlow.CreateAt = now.Format("2006-01-02 15:04:05") | |||
if req.Kind == "add" { | |||
userVirtualCoinFlow.Direction = 1 | |||
userVirtualCoinFlow.AfterAmount = coinAmountValue.Add(amountValue).RoundFloor(8).String() | |||
} else if req.Kind == "sub" { | |||
userVirtualCoinFlow.Direction = 2 | |||
userVirtualCoinFlow.AfterAmount = coinAmountValue.Sub(amountValue).RoundFloor(8).String() | |||
if zhios_order_relate_utils.StrToFloat64(userVirtualCoinFlow.AfterAmount) < 0 { | |||
var coin model.VirtualCoin | |||
_, err = session.Where("id = ?", req.CoinId).Get(&coin) | |||
if err != nil { | |||
return err | |||
} | |||
zhios_order_relate_utils.FilePutContents("virtual_coin_not", zhios_order_relate_utils.SerializeStr(map[string]interface{}{ | |||
"uid": userVirtualCoinFlow.Uid, | |||
"amount": userVirtualCoinFlow.Amount, | |||
"before_amount": userVirtualCoinFlow.BeforeAmount, | |||
"after_amount": userVirtualCoinFlow.AfterAmount, | |||
"coin_id": userVirtualCoinFlow.CoinId, | |||
})) | |||
return errors.New("用户" + zhios_order_relate_utils.Int64ToStr(userVirtualCoinFlow.Uid) + "的" + coin.Name + "不足") | |||
} | |||
} else { | |||
err = errors.New("错误的kind类型") | |||
return err | |||
} | |||
//3、插入 `user_virtual_coin_flow` 记录 | |||
userVirtualCoinFlowDb := implement.NewUserVirtualCoinFlowDb(session.Engine()) | |||
_, err = userVirtualCoinFlowDb.UserVirtualCoinFlowInsertBySession(session, &userVirtualCoinFlow) | |||
if err != nil { | |||
return err | |||
} | |||
//4、修改 `user_virtual_amount`的amount值 && 及缓存 | |||
err = SetCacheUserVirtualAmount(session, userVirtualCoinFlow.AfterAmount, req.CoinId, req.Uid, true) | |||
if err != nil { | |||
return err | |||
} | |||
return nil | |||
} | |||
// GetUserCoinAmount 获取用户虚拟积分余额 | |||
func GetUserCoinAmount(session *xorm.Session, coinId int, uid int64) (amount string, err error) { | |||
redisKey := fmt.Sprintf(md.UserVirtualAmountRedisKey, coinId, uid) | |||
amount, err = cache.GetString(redisKey) | |||
if err != nil { | |||
if err.Error() == "redigo: nil returned" { | |||
userVirtualAmountDb := implement.NewUserVirtualAmountDb(session.Engine()) | |||
userVirtualAmount, err := userVirtualAmountDb.GetUserVirtualWalletBySession(uid, coinId) | |||
if err != nil { | |||
return amount, err | |||
} | |||
if userVirtualAmount == nil { | |||
amount = "0" | |||
} else { | |||
amount = userVirtualAmount.Amount | |||
} | |||
//将获取到的余额值缓存至redis | |||
_ = SetCacheUserVirtualAmount(session, amount, coinId, uid, false) | |||
return amount, nil | |||
} | |||
return amount, err | |||
} | |||
return amount, nil | |||
} | |||
// SetCacheUserVirtualAmount 设置缓存的用户虚拟币积分余额 | |||
func SetCacheUserVirtualAmount(session *xorm.Session, amount string, coinId int, uid int64, isUpdateDb bool) error { | |||
redisKey := fmt.Sprintf(md.UserVirtualAmountRedisKey, coinId, uid) | |||
if isUpdateDb { | |||
_, err := session.Where("uid=?", uid).And("coin_id=?", coinId).Update(model.UserVirtualAmount{ | |||
Uid: uid, | |||
CoinId: coinId, | |||
Amount: amount, | |||
}) | |||
if err != nil { | |||
return err | |||
} | |||
} | |||
//TODO::默认缓存1小时 (先调整为 20 min) | |||
_, err := cache.SetEx(redisKey, zhios_order_relate_utils.StrToFloat64(amount), 60*20) | |||
if err != nil { | |||
return err | |||
} | |||
return nil | |||
} |
@@ -0,0 +1,84 @@ | |||
package svc | |||
import ( | |||
zhios_order_relate_utils "code.fnuoos.com/EggPlanet/egg_models.git/utils" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/md" | |||
"code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/cache" | |||
"errors" | |||
"fmt" | |||
"math/rand" | |||
"reflect" | |||
"time" | |||
) | |||
const redisMutexLockExpTime = 15 | |||
// TryGetDistributedLock 分布式锁获取 | |||
// requestId 用于标识请求客户端,可以是随机字符串,需确保唯一 | |||
func TryGetDistributedLock(lockKey, requestId string, isNegative bool) bool { | |||
if isNegative { // 多次尝试获取 | |||
retry := 1 | |||
for { | |||
ok, err := cache.Do("SET", lockKey, requestId, "EX", redisMutexLockExpTime, "NX") | |||
// 获取锁成功 | |||
if err == nil && ok == "OK" { | |||
return true | |||
} | |||
// 尝试多次没获取成功 | |||
if retry > 50 { | |||
return false | |||
} | |||
time.Sleep(time.Millisecond * time.Duration(rand.Intn(100))) | |||
retry += 1 | |||
} | |||
} else { // 只尝试一次 | |||
ok, err := cache.Do("SET", lockKey, requestId, "EX", redisMutexLockExpTime, "NX") | |||
// 获取锁成功 | |||
if err == nil && ok == "OK" { | |||
return true | |||
} | |||
return false | |||
} | |||
} | |||
// ReleaseDistributedLock 释放锁,通过比较requestId,用于确保客户端只释放自己的锁,使用lua脚本保证操作的原子型 | |||
func ReleaseDistributedLock(lockKey, requestId string) (bool, error) { | |||
luaScript := ` | |||
if redis.call("get",KEYS[1]) == ARGV[1] | |||
then | |||
return redis.call("del",KEYS[1]) | |||
else | |||
return 0 | |||
end` | |||
do, err := cache.Do("eval", luaScript, 1, lockKey, requestId) | |||
fmt.Println(reflect.TypeOf(do)) | |||
fmt.Println(do) | |||
if zhios_order_relate_utils.AnyToInt64(do) == 1 { | |||
return true, err | |||
} else { | |||
return false, err | |||
} | |||
} | |||
func GetDistributedLockRequestId(prefix string) string { | |||
return prefix + zhios_order_relate_utils.IntToStr(rand.Intn(100000000)) | |||
} | |||
// HandleDistributedLock 处理余额更新时获取锁和释放锁 如果加锁成功,使用语句 ` defer cb() ` 释放锁 | |||
func HandleDistributedLock(uid, coinId, requestIdPrefix string) (cb func(), err error) { | |||
// 获取余额更新锁 | |||
balanceLockKey := fmt.Sprintf(md.UserVirtualAmountUpdateLock, uid, coinId) | |||
requestId := GetDistributedLockRequestId(requestIdPrefix) | |||
balanceLockOk := TryGetDistributedLock(balanceLockKey, requestId, true) | |||
if !balanceLockOk { | |||
return nil, errors.New("系统繁忙,请稍后再试") | |||
} | |||
cb = func() { | |||
_, _ = ReleaseDistributedLock(balanceLockKey, requestId) | |||
} | |||
return cb, nil | |||
} |
@@ -0,0 +1,421 @@ | |||
package cache | |||
import ( | |||
"errors" | |||
"fmt" | |||
"strconv" | |||
"time" | |||
) | |||
const ( | |||
redisDialTTL = 10 * time.Second | |||
redisReadTTL = 3 * time.Second | |||
redisWriteTTL = 3 * time.Second | |||
redisIdleTTL = 10 * time.Second | |||
redisPoolTTL = 10 * time.Second | |||
redisPoolSize int = 512 | |||
redisMaxIdleConn int = 64 | |||
redisMaxActive int = 512 | |||
) | |||
var ( | |||
ErrNil = errors.New("nil return") | |||
ErrWrongArgsNum = errors.New("args num error") | |||
ErrNegativeInt = errors.New("redis cluster: unexpected value for Uint64") | |||
) | |||
// 以下为提供类型转换 | |||
func Int(reply interface{}, err error) (int, error) { | |||
if err != nil { | |||
return 0, err | |||
} | |||
switch reply := reply.(type) { | |||
case int: | |||
return reply, nil | |||
case int8: | |||
return int(reply), nil | |||
case int16: | |||
return int(reply), nil | |||
case int32: | |||
return int(reply), nil | |||
case int64: | |||
x := int(reply) | |||
if int64(x) != reply { | |||
return 0, strconv.ErrRange | |||
} | |||
return x, nil | |||
case uint: | |||
n := int(reply) | |||
if n < 0 { | |||
return 0, strconv.ErrRange | |||
} | |||
return n, nil | |||
case uint8: | |||
return int(reply), nil | |||
case uint16: | |||
return int(reply), nil | |||
case uint32: | |||
n := int(reply) | |||
if n < 0 { | |||
return 0, strconv.ErrRange | |||
} | |||
return n, nil | |||
case uint64: | |||
n := int(reply) | |||
if n < 0 { | |||
return 0, strconv.ErrRange | |||
} | |||
return n, nil | |||
case []byte: | |||
data := string(reply) | |||
if len(data) == 0 { | |||
return 0, ErrNil | |||
} | |||
n, err := strconv.ParseInt(data, 10, 0) | |||
return int(n), err | |||
case string: | |||
if len(reply) == 0 { | |||
return 0, ErrNil | |||
} | |||
n, err := strconv.ParseInt(reply, 10, 0) | |||
return int(n), err | |||
case nil: | |||
return 0, ErrNil | |||
case error: | |||
return 0, reply | |||
} | |||
return 0, fmt.Errorf("redis cluster: unexpected type for Int, got type %T", reply) | |||
} | |||
func Int64(reply interface{}, err error) (int64, error) { | |||
if err != nil { | |||
return 0, err | |||
} | |||
switch reply := reply.(type) { | |||
case int: | |||
return int64(reply), nil | |||
case int8: | |||
return int64(reply), nil | |||
case int16: | |||
return int64(reply), nil | |||
case int32: | |||
return int64(reply), nil | |||
case int64: | |||
return reply, nil | |||
case uint: | |||
n := int64(reply) | |||
if n < 0 { | |||
return 0, strconv.ErrRange | |||
} | |||
return n, nil | |||
case uint8: | |||
return int64(reply), nil | |||
case uint16: | |||
return int64(reply), nil | |||
case uint32: | |||
return int64(reply), nil | |||
case uint64: | |||
n := int64(reply) | |||
if n < 0 { | |||
return 0, strconv.ErrRange | |||
} | |||
return n, nil | |||
case []byte: | |||
data := string(reply) | |||
if len(data) == 0 { | |||
return 0, ErrNil | |||
} | |||
n, err := strconv.ParseInt(data, 10, 64) | |||
return n, err | |||
case string: | |||
if len(reply) == 0 { | |||
return 0, ErrNil | |||
} | |||
n, err := strconv.ParseInt(reply, 10, 64) | |||
return n, err | |||
case nil: | |||
return 0, ErrNil | |||
case error: | |||
return 0, reply | |||
} | |||
return 0, fmt.Errorf("redis cluster: unexpected type for Int64, got type %T", reply) | |||
} | |||
func Uint64(reply interface{}, err error) (uint64, error) { | |||
if err != nil { | |||
return 0, err | |||
} | |||
switch reply := reply.(type) { | |||
case uint: | |||
return uint64(reply), nil | |||
case uint8: | |||
return uint64(reply), nil | |||
case uint16: | |||
return uint64(reply), nil | |||
case uint32: | |||
return uint64(reply), nil | |||
case uint64: | |||
return reply, nil | |||
case int: | |||
if reply < 0 { | |||
return 0, ErrNegativeInt | |||
} | |||
return uint64(reply), nil | |||
case int8: | |||
if reply < 0 { | |||
return 0, ErrNegativeInt | |||
} | |||
return uint64(reply), nil | |||
case int16: | |||
if reply < 0 { | |||
return 0, ErrNegativeInt | |||
} | |||
return uint64(reply), nil | |||
case int32: | |||
if reply < 0 { | |||
return 0, ErrNegativeInt | |||
} | |||
return uint64(reply), nil | |||
case int64: | |||
if reply < 0 { | |||
return 0, ErrNegativeInt | |||
} | |||
return uint64(reply), nil | |||
case []byte: | |||
data := string(reply) | |||
if len(data) == 0 { | |||
return 0, ErrNil | |||
} | |||
n, err := strconv.ParseUint(data, 10, 64) | |||
return n, err | |||
case string: | |||
if len(reply) == 0 { | |||
return 0, ErrNil | |||
} | |||
n, err := strconv.ParseUint(reply, 10, 64) | |||
return n, err | |||
case nil: | |||
return 0, ErrNil | |||
case error: | |||
return 0, reply | |||
} | |||
return 0, fmt.Errorf("redis cluster: unexpected type for Uint64, got type %T", reply) | |||
} | |||
func Float64(reply interface{}, err error) (float64, error) { | |||
if err != nil { | |||
return 0, err | |||
} | |||
var value float64 | |||
err = nil | |||
switch v := reply.(type) { | |||
case float32: | |||
value = float64(v) | |||
case float64: | |||
value = v | |||
case int: | |||
value = float64(v) | |||
case int8: | |||
value = float64(v) | |||
case int16: | |||
value = float64(v) | |||
case int32: | |||
value = float64(v) | |||
case int64: | |||
value = float64(v) | |||
case uint: | |||
value = float64(v) | |||
case uint8: | |||
value = float64(v) | |||
case uint16: | |||
value = float64(v) | |||
case uint32: | |||
value = float64(v) | |||
case uint64: | |||
value = float64(v) | |||
case []byte: | |||
data := string(v) | |||
if len(data) == 0 { | |||
return 0, ErrNil | |||
} | |||
value, err = strconv.ParseFloat(string(v), 64) | |||
case string: | |||
if len(v) == 0 { | |||
return 0, ErrNil | |||
} | |||
value, err = strconv.ParseFloat(v, 64) | |||
case nil: | |||
err = ErrNil | |||
case error: | |||
err = v | |||
default: | |||
err = fmt.Errorf("redis cluster: unexpected type for Float64, got type %T", v) | |||
} | |||
return value, err | |||
} | |||
func Bool(reply interface{}, err error) (bool, error) { | |||
if err != nil { | |||
return false, err | |||
} | |||
switch reply := reply.(type) { | |||
case bool: | |||
return reply, nil | |||
case int64: | |||
return reply != 0, nil | |||
case []byte: | |||
data := string(reply) | |||
if len(data) == 0 { | |||
return false, ErrNil | |||
} | |||
return strconv.ParseBool(data) | |||
case string: | |||
if len(reply) == 0 { | |||
return false, ErrNil | |||
} | |||
return strconv.ParseBool(reply) | |||
case nil: | |||
return false, ErrNil | |||
case error: | |||
return false, reply | |||
} | |||
return false, fmt.Errorf("redis cluster: unexpected type for Bool, got type %T", reply) | |||
} | |||
func Bytes(reply interface{}, err error) ([]byte, error) { | |||
if err != nil { | |||
return nil, err | |||
} | |||
switch reply := reply.(type) { | |||
case []byte: | |||
if len(reply) == 0 { | |||
return nil, ErrNil | |||
} | |||
return reply, nil | |||
case string: | |||
data := []byte(reply) | |||
if len(data) == 0 { | |||
return nil, ErrNil | |||
} | |||
return data, nil | |||
case nil: | |||
return nil, ErrNil | |||
case error: | |||
return nil, reply | |||
} | |||
return nil, fmt.Errorf("redis cluster: unexpected type for Bytes, got type %T", reply) | |||
} | |||
func String(reply interface{}, err error) (string, error) { | |||
if err != nil { | |||
return "", err | |||
} | |||
value := "" | |||
err = nil | |||
switch v := reply.(type) { | |||
case string: | |||
if len(v) == 0 { | |||
return "", ErrNil | |||
} | |||
value = v | |||
case []byte: | |||
if len(v) == 0 { | |||
return "", ErrNil | |||
} | |||
value = string(v) | |||
case int: | |||
value = strconv.FormatInt(int64(v), 10) | |||
case int8: | |||
value = strconv.FormatInt(int64(v), 10) | |||
case int16: | |||
value = strconv.FormatInt(int64(v), 10) | |||
case int32: | |||
value = strconv.FormatInt(int64(v), 10) | |||
case int64: | |||
value = strconv.FormatInt(v, 10) | |||
case uint: | |||
value = strconv.FormatUint(uint64(v), 10) | |||
case uint8: | |||
value = strconv.FormatUint(uint64(v), 10) | |||
case uint16: | |||
value = strconv.FormatUint(uint64(v), 10) | |||
case uint32: | |||
value = strconv.FormatUint(uint64(v), 10) | |||
case uint64: | |||
value = strconv.FormatUint(v, 10) | |||
case float32: | |||
value = strconv.FormatFloat(float64(v), 'f', -1, 32) | |||
case float64: | |||
value = strconv.FormatFloat(v, 'f', -1, 64) | |||
case bool: | |||
value = strconv.FormatBool(v) | |||
case nil: | |||
err = ErrNil | |||
case error: | |||
err = v | |||
default: | |||
err = fmt.Errorf("redis cluster: unexpected type for String, got type %T", v) | |||
} | |||
return value, err | |||
} | |||
func Strings(reply interface{}, err error) ([]string, error) { | |||
if err != nil { | |||
return nil, err | |||
} | |||
switch reply := reply.(type) { | |||
case []interface{}: | |||
result := make([]string, len(reply)) | |||
for i := range reply { | |||
if reply[i] == nil { | |||
continue | |||
} | |||
switch subReply := reply[i].(type) { | |||
case string: | |||
result[i] = subReply | |||
case []byte: | |||
result[i] = string(subReply) | |||
default: | |||
return nil, fmt.Errorf("redis cluster: unexpected element type for String, got type %T", reply[i]) | |||
} | |||
} | |||
return result, nil | |||
case []string: | |||
return reply, nil | |||
case nil: | |||
return nil, ErrNil | |||
case error: | |||
return nil, reply | |||
} | |||
return nil, fmt.Errorf("redis cluster: unexpected type for Strings, got type %T", reply) | |||
} | |||
func Values(reply interface{}, err error) ([]interface{}, error) { | |||
if err != nil { | |||
return nil, err | |||
} | |||
switch reply := reply.(type) { | |||
case []interface{}: | |||
return reply, nil | |||
case nil: | |||
return nil, ErrNil | |||
case error: | |||
return nil, reply | |||
} | |||
return nil, fmt.Errorf("redis cluster: unexpected type for Values, got type %T", reply) | |||
} |
@@ -0,0 +1,413 @@ | |||
package cache | |||
import ( | |||
"encoding/json" | |||
"errors" | |||
"log" | |||
"strings" | |||
"time" | |||
redigo "github.com/gomodule/redigo/redis" | |||
) | |||
// configuration | |||
type Config struct { | |||
Server string | |||
Password string | |||
MaxIdle int // Maximum number of idle connections in the pool. | |||
// Maximum number of connections allocated by the pool at a given time. | |||
// When zero, there is no limit on the number of connections in the pool. | |||
MaxActive int | |||
// Close connections after remaining idle for this duration. If the value | |||
// is zero, then idle connections are not closed. Applications should set | |||
// the timeout to a value less than the server's timeout. | |||
IdleTimeout time.Duration | |||
// If Wait is true and the pool is at the MaxActive limit, then Get() waits | |||
// for a connection to be returned to the pool before returning. | |||
Wait bool | |||
KeyPrefix string // prefix to all keys; example is "dev environment name" | |||
KeyDelimiter string // delimiter to be used while appending keys; example is ":" | |||
KeyPlaceholder string // placeholder to be parsed using given arguments to obtain a final key; example is "?" | |||
} | |||
var pool *redigo.Pool | |||
var conf *Config | |||
func NewRedis(addr string) { | |||
if addr == "" { | |||
panic("\nredis connect string cannot be empty\n") | |||
} | |||
pool = &redigo.Pool{ | |||
MaxIdle: redisMaxIdleConn, | |||
IdleTimeout: redisIdleTTL, | |||
MaxActive: redisMaxActive, | |||
// MaxConnLifetime: redisDialTTL, | |||
Wait: true, | |||
Dial: func() (redigo.Conn, error) { | |||
c, err := redigo.Dial("tcp", addr, | |||
redigo.DialConnectTimeout(redisDialTTL), | |||
redigo.DialReadTimeout(redisReadTTL), | |||
redigo.DialWriteTimeout(redisWriteTTL), | |||
//redigo.DialDatabase(RedisDataBase), | |||
) | |||
if err != nil { | |||
log.Println("Redis Dial failed: ", err) | |||
return nil, err | |||
} | |||
return c, err | |||
}, | |||
TestOnBorrow: func(c redigo.Conn, t time.Time) error { | |||
_, err := c.Do("PING") | |||
if err != nil { | |||
log.Println("Unable to ping to redis server:", err) | |||
} | |||
return err | |||
}, | |||
} | |||
conn := pool.Get() | |||
defer conn.Close() | |||
if conn.Err() != nil { | |||
println("\nredis connect " + addr + " error: " + conn.Err().Error()) | |||
} else { | |||
println("\nredis connect " + addr + " success!\n") | |||
} | |||
} | |||
func Do(cmd string, args ...interface{}) (reply interface{}, err error) { | |||
conn := pool.Get() | |||
defer conn.Close() | |||
return conn.Do(cmd, args...) | |||
} | |||
func SelectDb(db int) (interface{}, error) { | |||
return Do("SELECT", db) | |||
} | |||
func GetPool() *redigo.Pool { | |||
return pool | |||
} | |||
func ParseKey(key string, vars []string) (string, error) { | |||
arr := strings.Split(key, conf.KeyPlaceholder) | |||
actualKey := "" | |||
if len(arr) != len(vars)+1 { | |||
return "", errors.New("redis/connection.go: Insufficient arguments to parse key") | |||
} else { | |||
for index, val := range arr { | |||
if index == 0 { | |||
actualKey = arr[index] | |||
} else { | |||
actualKey += vars[index-1] + val | |||
} | |||
} | |||
} | |||
return getPrefixedKey(actualKey), nil | |||
} | |||
func getPrefixedKey(key string) string { | |||
return conf.KeyPrefix + conf.KeyDelimiter + key | |||
} | |||
func StripEnvKey(key string) string { | |||
return strings.TrimLeft(key, conf.KeyPrefix+conf.KeyDelimiter) | |||
} | |||
func SplitKey(key string) []string { | |||
return strings.Split(key, conf.KeyDelimiter) | |||
} | |||
func Expire(key string, ttl int) (interface{}, error) { | |||
return Do("EXPIRE", key, ttl) | |||
} | |||
func Persist(key string) (interface{}, error) { | |||
return Do("PERSIST", key) | |||
} | |||
func Del(key string) (interface{}, error) { | |||
return Do("DEL", key) | |||
} | |||
func Set(key string, data interface{}) (interface{}, error) { | |||
// set | |||
return Do("SET", key, data) | |||
} | |||
func SetNX(key string, data interface{}) (interface{}, error) { | |||
return Do("SETNX", key, data) | |||
} | |||
func SetEx(key string, data interface{}, ttl int) (interface{}, error) { | |||
return Do("SETEX", key, ttl, data) | |||
} | |||
func SetJson(key string, data interface{}, ttl int) bool { | |||
c, err := json.Marshal(data) | |||
if err != nil { | |||
return false | |||
} | |||
if ttl < 1 { | |||
_, err = Set(key, c) | |||
} else { | |||
_, err = SetEx(key, c, ttl) | |||
} | |||
if err != nil { | |||
return false | |||
} | |||
return true | |||
} | |||
func GetJson(key string, dst interface{}) error { | |||
b, err := GetBytes(key) | |||
if err != nil { | |||
return err | |||
} | |||
if err = json.Unmarshal(b, dst); err != nil { | |||
return err | |||
} | |||
return nil | |||
} | |||
func Get(key string) (interface{}, error) { | |||
// get | |||
return Do("GET", key) | |||
} | |||
func GetTTL(key string) (time.Duration, error) { | |||
ttl, err := redigo.Int64(Do("TTL", key)) | |||
return time.Duration(ttl) * time.Second, err | |||
} | |||
func GetBytes(key string) ([]byte, error) { | |||
return redigo.Bytes(Do("GET", key)) | |||
} | |||
func GetString(key string) (string, error) { | |||
return redigo.String(Do("GET", key)) | |||
} | |||
func GetStringMap(key string) (map[string]string, error) { | |||
return redigo.StringMap(Do("GET", key)) | |||
} | |||
func GetInt(key string) (int, error) { | |||
return redigo.Int(Do("GET", key)) | |||
} | |||
func GetInt64(key string) (int64, error) { | |||
return redigo.Int64(Do("GET", key)) | |||
} | |||
func GetStringLength(key string) (int, error) { | |||
return redigo.Int(Do("STRLEN", key)) | |||
} | |||
func ZAdd(key string, score float64, data interface{}) (interface{}, error) { | |||
return Do("ZADD", key, score, data) | |||
} | |||
func ZAddNX(key string, score float64, data interface{}) (interface{}, error) { | |||
return Do("ZADD", key, "NX", score, data) | |||
} | |||
func ZRem(key string, data interface{}) (interface{}, error) { | |||
return Do("ZREM", key, data) | |||
} | |||
func ZRange(key string, start int, end int, withScores bool) ([]interface{}, error) { | |||
if withScores { | |||
return redigo.Values(Do("ZRANGE", key, start, end, "WITHSCORES")) | |||
} | |||
return redigo.Values(Do("ZRANGE", key, start, end)) | |||
} | |||
func ZRemRangeByScore(key string, start int64, end int64) ([]interface{}, error) { | |||
return redigo.Values(Do("ZREMRANGEBYSCORE", key, start, end)) | |||
} | |||
func ZCard(setName string) (int64, error) { | |||
return redigo.Int64(Do("ZCARD", setName)) | |||
} | |||
func ZScan(setName string) (int64, error) { | |||
return redigo.Int64(Do("ZCARD", setName)) | |||
} | |||
func SAdd(setName string, data interface{}) (interface{}, error) { | |||
return Do("SADD", setName, data) | |||
} | |||
func SCard(setName string) (int64, error) { | |||
return redigo.Int64(Do("SCARD", setName)) | |||
} | |||
func SIsMember(setName string, data interface{}) (bool, error) { | |||
return redigo.Bool(Do("SISMEMBER", setName, data)) | |||
} | |||
func SMembers(setName string) ([]string, error) { | |||
return redigo.Strings(Do("SMEMBERS", setName)) | |||
} | |||
func SRem(setName string, data interface{}) (interface{}, error) { | |||
return Do("SREM", setName, data) | |||
} | |||
func HSet(key string, HKey string, data interface{}) (interface{}, error) { | |||
return Do("HSET", key, HKey, data) | |||
} | |||
func HGet(key string, HKey string) (interface{}, error) { | |||
return Do("HGET", key, HKey) | |||
} | |||
func HMGet(key string, hashKeys ...string) ([]interface{}, error) { | |||
ret, err := Do("HMGET", key, hashKeys) | |||
if err != nil { | |||
return nil, err | |||
} | |||
reta, ok := ret.([]interface{}) | |||
if !ok { | |||
return nil, errors.New("result not an array") | |||
} | |||
return reta, nil | |||
} | |||
func HMSet(key string, hashKeys []string, vals []interface{}) (interface{}, error) { | |||
if len(hashKeys) == 0 || len(hashKeys) != len(vals) { | |||
var ret interface{} | |||
return ret, errors.New("bad length") | |||
} | |||
input := []interface{}{key} | |||
for i, v := range hashKeys { | |||
input = append(input, v, vals[i]) | |||
} | |||
return Do("HMSET", input...) | |||
} | |||
func HGetString(key string, HKey string) (string, error) { | |||
return redigo.String(Do("HGET", key, HKey)) | |||
} | |||
func HGetFloat(key string, HKey string) (float64, error) { | |||
f, err := redigo.Float64(Do("HGET", key, HKey)) | |||
return f, err | |||
} | |||
func HGetInt(key string, HKey string) (int, error) { | |||
return redigo.Int(Do("HGET", key, HKey)) | |||
} | |||
func HGetInt64(key string, HKey string) (int64, error) { | |||
return redigo.Int64(Do("HGET", key, HKey)) | |||
} | |||
func HGetBool(key string, HKey string) (bool, error) { | |||
return redigo.Bool(Do("HGET", key, HKey)) | |||
} | |||
func HDel(key string, HKey string) (interface{}, error) { | |||
return Do("HDEL", key, HKey) | |||
} | |||
func HGetAll(key string) (map[string]interface{}, error) { | |||
vals, err := redigo.Values(Do("HGETALL", key)) | |||
if err != nil { | |||
return nil, err | |||
} | |||
num := len(vals) / 2 | |||
result := make(map[string]interface{}, num) | |||
for i := 0; i < num; i++ { | |||
key, _ := redigo.String(vals[2*i], nil) | |||
result[key] = vals[2*i+1] | |||
} | |||
return result, nil | |||
} | |||
func FlushAll() bool { | |||
res, _ := redigo.String(Do("FLUSHALL")) | |||
if res == "" { | |||
return false | |||
} | |||
return true | |||
} | |||
// NOTE: Use this in production environment with extreme care. | |||
// Read more here:https://redigo.io/commands/keys | |||
func Keys(pattern string) ([]string, error) { | |||
return redigo.Strings(Do("KEYS", pattern)) | |||
} | |||
func HKeys(key string) ([]string, error) { | |||
return redigo.Strings(Do("HKEYS", key)) | |||
} | |||
func Exists(key string) bool { | |||
count, err := redigo.Int(Do("EXISTS", key)) | |||
if count == 0 || err != nil { | |||
return false | |||
} | |||
return true | |||
} | |||
func Incr(key string) (int64, error) { | |||
return redigo.Int64(Do("INCR", key)) | |||
} | |||
func Decr(key string) (int64, error) { | |||
return redigo.Int64(Do("DECR", key)) | |||
} | |||
func IncrBy(key string, incBy int64) (int64, error) { | |||
return redigo.Int64(Do("INCRBY", key, incBy)) | |||
} | |||
func DecrBy(key string, decrBy int64) (int64, error) { | |||
return redigo.Int64(Do("DECRBY", key, decrBy)) | |||
} | |||
func IncrByFloat(key string, incBy float64) (float64, error) { | |||
return redigo.Float64(Do("INCRBYFLOAT", key, incBy)) | |||
} | |||
func DecrByFloat(key string, decrBy float64) (float64, error) { | |||
return redigo.Float64(Do("DECRBYFLOAT", key, decrBy)) | |||
} | |||
// use for message queue | |||
func LPush(key string, data interface{}) (interface{}, error) { | |||
// set | |||
return Do("LPUSH", key, data) | |||
} | |||
func LPop(key string) (interface{}, error) { | |||
return Do("LPOP", key) | |||
} | |||
func LPopString(key string) (string, error) { | |||
return redigo.String(Do("LPOP", key)) | |||
} | |||
func LPopFloat(key string) (float64, error) { | |||
f, err := redigo.Float64(Do("LPOP", key)) | |||
return f, err | |||
} | |||
func LPopInt(key string) (int, error) { | |||
return redigo.Int(Do("LPOP", key)) | |||
} | |||
func LPopInt64(key string) (int64, error) { | |||
return redigo.Int64(Do("LPOP", key)) | |||
} | |||
func RPush(key string, data interface{}) (interface{}, error) { | |||
// set | |||
return Do("RPUSH", key, data) | |||
} | |||
func RPop(key string) (interface{}, error) { | |||
return Do("RPOP", key) | |||
} | |||
func RPopString(key string) (string, error) { | |||
return redigo.String(Do("RPOP", key)) | |||
} | |||
func RPopFloat(key string) (float64, error) { | |||
f, err := redigo.Float64(Do("RPOP", key)) | |||
return f, err | |||
} | |||
func RPopInt(key string) (int, error) { | |||
return redigo.Int(Do("RPOP", key)) | |||
} | |||
func RPopInt64(key string) (int64, error) { | |||
return redigo.Int64(Do("RPOP", key)) | |||
} | |||
func Scan(cursor int64, pattern string, count int64) (int64, []string, error) { | |||
var items []string | |||
var newCursor int64 | |||
values, err := redigo.Values(Do("SCAN", cursor, "MATCH", pattern, "COUNT", count)) | |||
if err != nil { | |||
return 0, nil, err | |||
} | |||
values, err = redigo.Scan(values, &newCursor, &items) | |||
if err != nil { | |||
return 0, nil, err | |||
} | |||
return newCursor, items, nil | |||
} | |||
func LPushMax(key string, data ...interface{}) (interface{}, error) { | |||
// set | |||
return Do("LPUSH", key, data) | |||
} |
@@ -0,0 +1,622 @@ | |||
package cache | |||
import ( | |||
"strconv" | |||
"time" | |||
"github.com/go-redis/redis" | |||
) | |||
var pools *redis.ClusterClient | |||
func NewRedisCluster(addrs []string) error { | |||
opt := &redis.ClusterOptions{ | |||
Addrs: addrs, | |||
PoolSize: redisPoolSize, | |||
PoolTimeout: redisPoolTTL, | |||
IdleTimeout: redisIdleTTL, | |||
DialTimeout: redisDialTTL, | |||
ReadTimeout: redisReadTTL, | |||
WriteTimeout: redisWriteTTL, | |||
} | |||
pools = redis.NewClusterClient(opt) | |||
if err := pools.Ping().Err(); err != nil { | |||
return err | |||
} | |||
return nil | |||
} | |||
func RCGet(key string) (interface{}, error) { | |||
res, err := pools.Get(key).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return []byte(res), nil | |||
} | |||
func RCSet(key string, value interface{}) error { | |||
err := pools.Set(key, value, 0).Err() | |||
return convertError(err) | |||
} | |||
func RCGetSet(key string, value interface{}) (interface{}, error) { | |||
res, err := pools.GetSet(key, value).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return []byte(res), nil | |||
} | |||
func RCSetNx(key string, value interface{}) (int64, error) { | |||
res, err := pools.SetNX(key, value, 0).Result() | |||
if err != nil { | |||
return 0, convertError(err) | |||
} | |||
if res { | |||
return 1, nil | |||
} | |||
return 0, nil | |||
} | |||
func RCSetEx(key string, value interface{}, timeout int64) error { | |||
_, err := pools.Set(key, value, time.Duration(timeout)*time.Second).Result() | |||
if err != nil { | |||
return convertError(err) | |||
} | |||
return nil | |||
} | |||
// nil表示成功,ErrNil表示数据库内已经存在这个key,其他表示数据库发生错误 | |||
func RCSetNxEx(key string, value interface{}, timeout int64) error { | |||
res, err := pools.SetNX(key, value, time.Duration(timeout)*time.Second).Result() | |||
if err != nil { | |||
return convertError(err) | |||
} | |||
if res { | |||
return nil | |||
} | |||
return ErrNil | |||
} | |||
func RCMGet(keys ...string) ([]interface{}, error) { | |||
res, err := pools.MGet(keys...).Result() | |||
return res, convertError(err) | |||
} | |||
// 为确保多个key映射到同一个slot,每个key最好加上hash tag,如:{test} | |||
func RCMSet(kvs map[string]interface{}) error { | |||
pairs := make([]string, 0, len(kvs)*2) | |||
for k, v := range kvs { | |||
val, err := String(v, nil) | |||
if err != nil { | |||
return err | |||
} | |||
pairs = append(pairs, k, val) | |||
} | |||
return convertError(pools.MSet(pairs).Err()) | |||
} | |||
// 为确保多个key映射到同一个slot,每个key最好加上hash tag,如:{test} | |||
func RCMSetNX(kvs map[string]interface{}) (bool, error) { | |||
pairs := make([]string, 0, len(kvs)*2) | |||
for k, v := range kvs { | |||
val, err := String(v, nil) | |||
if err != nil { | |||
return false, err | |||
} | |||
pairs = append(pairs, k, val) | |||
} | |||
res, err := pools.MSetNX(pairs).Result() | |||
return res, convertError(err) | |||
} | |||
func RCExpireAt(key string, timestamp int64) (int64, error) { | |||
res, err := pools.ExpireAt(key, time.Unix(timestamp, 0)).Result() | |||
if err != nil { | |||
return 0, convertError(err) | |||
} | |||
if res { | |||
return 1, nil | |||
} | |||
return 0, nil | |||
} | |||
func RCDel(keys ...string) (int64, error) { | |||
args := make([]interface{}, 0, len(keys)) | |||
for _, key := range keys { | |||
args = append(args, key) | |||
} | |||
res, err := pools.Del(keys...).Result() | |||
if err != nil { | |||
return res, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func RCIncr(key string) (int64, error) { | |||
res, err := pools.Incr(key).Result() | |||
if err != nil { | |||
return res, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func RCIncrBy(key string, delta int64) (int64, error) { | |||
res, err := pools.IncrBy(key, delta).Result() | |||
if err != nil { | |||
return res, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func RCExpire(key string, duration int64) (int64, error) { | |||
res, err := pools.Expire(key, time.Duration(duration)*time.Second).Result() | |||
if err != nil { | |||
return 0, convertError(err) | |||
} | |||
if res { | |||
return 1, nil | |||
} | |||
return 0, nil | |||
} | |||
func RCExists(key string) (bool, error) { | |||
res, err := pools.Exists(key).Result() | |||
if err != nil { | |||
return false, convertError(err) | |||
} | |||
if res > 0 { | |||
return true, nil | |||
} | |||
return false, nil | |||
} | |||
func RCHGet(key string, field string) (interface{}, error) { | |||
res, err := pools.HGet(key, field).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return []byte(res), nil | |||
} | |||
func RCHLen(key string) (int64, error) { | |||
res, err := pools.HLen(key).Result() | |||
if err != nil { | |||
return res, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func RCHSet(key string, field string, val interface{}) error { | |||
value, err := String(val, nil) | |||
if err != nil && err != ErrNil { | |||
return err | |||
} | |||
_, err = pools.HSet(key, field, value).Result() | |||
if err != nil { | |||
return convertError(err) | |||
} | |||
return nil | |||
} | |||
func RCHDel(key string, fields ...string) (int64, error) { | |||
args := make([]interface{}, 0, len(fields)+1) | |||
args = append(args, key) | |||
for _, field := range fields { | |||
args = append(args, field) | |||
} | |||
res, err := pools.HDel(key, fields...).Result() | |||
if err != nil { | |||
return 0, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func RCHMGet(key string, fields ...string) (interface{}, error) { | |||
args := make([]interface{}, 0, len(fields)+1) | |||
args = append(args, key) | |||
for _, field := range fields { | |||
args = append(args, field) | |||
} | |||
if len(fields) == 0 { | |||
return nil, ErrNil | |||
} | |||
res, err := pools.HMGet(key, fields...).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func RCHMSet(key string, kvs ...interface{}) error { | |||
if len(kvs) == 0 { | |||
return nil | |||
} | |||
if len(kvs)%2 != 0 { | |||
return ErrWrongArgsNum | |||
} | |||
var err error | |||
v := map[string]interface{}{} // todo change | |||
v["field"], err = String(kvs[0], nil) | |||
if err != nil && err != ErrNil { | |||
return err | |||
} | |||
v["value"], err = String(kvs[1], nil) | |||
if err != nil && err != ErrNil { | |||
return err | |||
} | |||
pairs := make([]string, 0, len(kvs)-2) | |||
if len(kvs) > 2 { | |||
for _, kv := range kvs[2:] { | |||
kvString, err := String(kv, nil) | |||
if err != nil && err != ErrNil { | |||
return err | |||
} | |||
pairs = append(pairs, kvString) | |||
} | |||
} | |||
v["paris"] = pairs | |||
_, err = pools.HMSet(key, v).Result() | |||
if err != nil { | |||
return convertError(err) | |||
} | |||
return nil | |||
} | |||
func RCHKeys(key string) ([]string, error) { | |||
res, err := pools.HKeys(key).Result() | |||
if err != nil { | |||
return res, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func RCHVals(key string) ([]interface{}, error) { | |||
res, err := pools.HVals(key).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
rs := make([]interface{}, 0, len(res)) | |||
for _, res := range res { | |||
rs = append(rs, res) | |||
} | |||
return rs, nil | |||
} | |||
func RCHGetAll(key string) (map[string]string, error) { | |||
vals, err := pools.HGetAll(key).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return vals, nil | |||
} | |||
func RCHIncrBy(key, field string, delta int64) (int64, error) { | |||
res, err := pools.HIncrBy(key, field, delta).Result() | |||
if err != nil { | |||
return res, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func RCZAdd(key string, kvs ...interface{}) (int64, error) { | |||
args := make([]interface{}, 0, len(kvs)+1) | |||
args = append(args, key) | |||
args = append(args, kvs...) | |||
if len(kvs) == 0 { | |||
return 0, nil | |||
} | |||
if len(kvs)%2 != 0 { | |||
return 0, ErrWrongArgsNum | |||
} | |||
zs := make([]redis.Z, len(kvs)/2) | |||
for i := 0; i < len(kvs); i += 2 { | |||
idx := i / 2 | |||
score, err := Float64(kvs[i], nil) | |||
if err != nil && err != ErrNil { | |||
return 0, err | |||
} | |||
zs[idx].Score = score | |||
zs[idx].Member = kvs[i+1] | |||
} | |||
res, err := pools.ZAdd(key, zs...).Result() | |||
if err != nil { | |||
return res, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func RCZRem(key string, members ...string) (int64, error) { | |||
args := make([]interface{}, 0, len(members)) | |||
args = append(args, key) | |||
for _, member := range members { | |||
args = append(args, member) | |||
} | |||
res, err := pools.ZRem(key, members).Result() | |||
if err != nil { | |||
return res, convertError(err) | |||
} | |||
return res, err | |||
} | |||
func RCZRange(key string, min, max int64, withScores bool) (interface{}, error) { | |||
res := make([]interface{}, 0) | |||
if withScores { | |||
zs, err := pools.ZRangeWithScores(key, min, max).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
for _, z := range zs { | |||
res = append(res, z.Member, strconv.FormatFloat(z.Score, 'f', -1, 64)) | |||
} | |||
} else { | |||
ms, err := pools.ZRange(key, min, max).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
for _, m := range ms { | |||
res = append(res, m) | |||
} | |||
} | |||
return res, nil | |||
} | |||
func RCZRangeByScoreWithScore(key string, min, max int64) (map[string]int64, error) { | |||
opt := new(redis.ZRangeBy) | |||
opt.Min = strconv.FormatInt(int64(min), 10) | |||
opt.Max = strconv.FormatInt(int64(max), 10) | |||
opt.Count = -1 | |||
opt.Offset = 0 | |||
vals, err := pools.ZRangeByScoreWithScores(key, *opt).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
res := make(map[string]int64, len(vals)) | |||
for _, val := range vals { | |||
key, err := String(val.Member, nil) | |||
if err != nil && err != ErrNil { | |||
return nil, err | |||
} | |||
res[key] = int64(val.Score) | |||
} | |||
return res, nil | |||
} | |||
func RCLRange(key string, start, stop int64) (interface{}, error) { | |||
res, err := pools.LRange(key, start, stop).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func RCLSet(key string, index int, value interface{}) error { | |||
err := pools.LSet(key, int64(index), value).Err() | |||
return convertError(err) | |||
} | |||
func RCLLen(key string) (int64, error) { | |||
res, err := pools.LLen(key).Result() | |||
if err != nil { | |||
return res, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func RCLRem(key string, count int, value interface{}) (int, error) { | |||
val, _ := value.(string) | |||
res, err := pools.LRem(key, int64(count), val).Result() | |||
if err != nil { | |||
return int(res), convertError(err) | |||
} | |||
return int(res), nil | |||
} | |||
func RCTTl(key string) (int64, error) { | |||
duration, err := pools.TTL(key).Result() | |||
if err != nil { | |||
return int64(duration.Seconds()), convertError(err) | |||
} | |||
return int64(duration.Seconds()), nil | |||
} | |||
func RCLPop(key string) (interface{}, error) { | |||
res, err := pools.LPop(key).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func RCRPop(key string) (interface{}, error) { | |||
res, err := pools.RPop(key).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func RCBLPop(key string, timeout int) (interface{}, error) { | |||
res, err := pools.BLPop(time.Duration(timeout)*time.Second, key).Result() | |||
if err != nil { | |||
// 兼容redis 2.x | |||
if err == redis.Nil { | |||
return nil, ErrNil | |||
} | |||
return nil, err | |||
} | |||
return res[1], nil | |||
} | |||
func RCBRPop(key string, timeout int) (interface{}, error) { | |||
res, err := pools.BRPop(time.Duration(timeout)*time.Second, key).Result() | |||
if err != nil { | |||
// 兼容redis 2.x | |||
if err == redis.Nil { | |||
return nil, ErrNil | |||
} | |||
return nil, convertError(err) | |||
} | |||
return res[1], nil | |||
} | |||
func RCLPush(key string, value ...interface{}) error { | |||
args := make([]interface{}, 0, len(value)+1) | |||
args = append(args, key) | |||
args = append(args, value...) | |||
vals := make([]string, 0, len(value)) | |||
for _, v := range value { | |||
val, err := String(v, nil) | |||
if err != nil && err != ErrNil { | |||
return err | |||
} | |||
vals = append(vals, val) | |||
} | |||
_, err := pools.LPush(key, vals).Result() // todo ... | |||
if err != nil { | |||
return convertError(err) | |||
} | |||
return nil | |||
} | |||
func RCRPush(key string, value ...interface{}) error { | |||
args := make([]interface{}, 0, len(value)+1) | |||
args = append(args, key) | |||
args = append(args, value...) | |||
vals := make([]string, 0, len(value)) | |||
for _, v := range value { | |||
val, err := String(v, nil) | |||
if err != nil && err != ErrNil { | |||
if err == ErrNil { | |||
continue | |||
} | |||
return err | |||
} | |||
if val == "" { | |||
continue | |||
} | |||
vals = append(vals, val) | |||
} | |||
_, err := pools.RPush(key, vals).Result() // todo ... | |||
if err != nil { | |||
return convertError(err) | |||
} | |||
return nil | |||
} | |||
// 为确保srcKey跟destKey映射到同一个slot,srcKey和destKey需要加上hash tag,如:{test} | |||
func RCBRPopLPush(srcKey string, destKey string, timeout int) (interface{}, error) { | |||
res, err := pools.BRPopLPush(srcKey, destKey, time.Duration(timeout)*time.Second).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
// 为确保srcKey跟destKey映射到同一个slot,srcKey和destKey需要加上hash tag,如:{test} | |||
func RCRPopLPush(srcKey string, destKey string) (interface{}, error) { | |||
res, err := pools.RPopLPush(srcKey, destKey).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func RCSAdd(key string, members ...interface{}) (int64, error) { | |||
args := make([]interface{}, 0, len(members)+1) | |||
args = append(args, key) | |||
args = append(args, members...) | |||
ms := make([]string, 0, len(members)) | |||
for _, member := range members { | |||
m, err := String(member, nil) | |||
if err != nil && err != ErrNil { | |||
return 0, err | |||
} | |||
ms = append(ms, m) | |||
} | |||
res, err := pools.SAdd(key, ms).Result() // todo ... | |||
if err != nil { | |||
return res, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func RCSPop(key string) ([]byte, error) { | |||
res, err := pools.SPop(key).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return []byte(res), nil | |||
} | |||
func RCSIsMember(key string, member interface{}) (bool, error) { | |||
m, _ := member.(string) | |||
res, err := pools.SIsMember(key, m).Result() | |||
if err != nil { | |||
return res, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func RCSRem(key string, members ...interface{}) (int64, error) { | |||
args := make([]interface{}, 0, len(members)+1) | |||
args = append(args, key) | |||
args = append(args, members...) | |||
ms := make([]string, 0, len(members)) | |||
for _, member := range members { | |||
m, err := String(member, nil) | |||
if err != nil && err != ErrNil { | |||
return 0, err | |||
} | |||
ms = append(ms, m) | |||
} | |||
res, err := pools.SRem(key, ms).Result() // todo ... | |||
if err != nil { | |||
return res, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func RCSMembers(key string) ([]string, error) { | |||
res, err := pools.SMembers(key).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func RCScriptLoad(luaScript string) (interface{}, error) { | |||
res, err := pools.ScriptLoad(luaScript).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func RCEvalSha(sha1 string, numberKeys int, keysArgs ...interface{}) (interface{}, error) { | |||
vals := make([]interface{}, 0, len(keysArgs)+2) | |||
vals = append(vals, sha1, numberKeys) | |||
vals = append(vals, keysArgs...) | |||
keys := make([]string, 0, numberKeys) | |||
args := make([]string, 0, len(keysArgs)-numberKeys) | |||
for i, value := range keysArgs { | |||
val, err := String(value, nil) | |||
if err != nil && err != ErrNil { | |||
return nil, err | |||
} | |||
if i < numberKeys { | |||
keys = append(keys, val) | |||
} else { | |||
args = append(args, val) | |||
} | |||
} | |||
res, err := pools.EvalSha(sha1, keys, args).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func RCEval(luaScript string, numberKeys int, keysArgs ...interface{}) (interface{}, error) { | |||
vals := make([]interface{}, 0, len(keysArgs)+2) | |||
vals = append(vals, luaScript, numberKeys) | |||
vals = append(vals, keysArgs...) | |||
keys := make([]string, 0, numberKeys) | |||
args := make([]string, 0, len(keysArgs)-numberKeys) | |||
for i, value := range keysArgs { | |||
val, err := String(value, nil) | |||
if err != nil && err != ErrNil { | |||
return nil, err | |||
} | |||
if i < numberKeys { | |||
keys = append(keys, val) | |||
} else { | |||
args = append(args, val) | |||
} | |||
} | |||
res, err := pools.Eval(luaScript, keys, args).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func RCGetBit(key string, offset int64) (int64, error) { | |||
res, err := pools.GetBit(key, offset).Result() | |||
if err != nil { | |||
return res, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func RCSetBit(key string, offset uint32, value int) (int, error) { | |||
res, err := pools.SetBit(key, int64(offset), value).Result() | |||
return int(res), convertError(err) | |||
} | |||
func RCGetClient() *redis.ClusterClient { | |||
return pools | |||
} | |||
func convertError(err error) error { | |||
if err == redis.Nil { | |||
// 为了兼容redis 2.x,这里不返回 ErrNil,ErrNil在调用redis_cluster_reply函数时才返回 | |||
return nil | |||
} | |||
return err | |||
} |
@@ -0,0 +1,324 @@ | |||
package cache | |||
import ( | |||
"errors" | |||
"log" | |||
"strings" | |||
"time" | |||
redigo "github.com/gomodule/redigo/redis" | |||
) | |||
type RedisPool struct { | |||
*redigo.Pool | |||
} | |||
func NewRedisPool(cfg *Config) *RedisPool { | |||
return &RedisPool{&redigo.Pool{ | |||
MaxIdle: cfg.MaxIdle, | |||
IdleTimeout: cfg.IdleTimeout, | |||
MaxActive: cfg.MaxActive, | |||
Wait: cfg.Wait, | |||
Dial: func() (redigo.Conn, error) { | |||
c, err := redigo.Dial("tcp", cfg.Server) | |||
if err != nil { | |||
log.Println("Redis Dial failed: ", err) | |||
return nil, err | |||
} | |||
if cfg.Password != "" { | |||
if _, err := c.Do("AUTH", cfg.Password); err != nil { | |||
c.Close() | |||
log.Println("Redis AUTH failed: ", err) | |||
return nil, err | |||
} | |||
} | |||
return c, err | |||
}, | |||
TestOnBorrow: func(c redigo.Conn, t time.Time) error { | |||
_, err := c.Do("PING") | |||
if err != nil { | |||
log.Println("Unable to ping to redis server:", err) | |||
} | |||
return err | |||
}, | |||
}} | |||
} | |||
func (p *RedisPool) Do(cmd string, args ...interface{}) (reply interface{}, err error) { | |||
conn := pool.Get() | |||
defer conn.Close() | |||
return conn.Do(cmd, args...) | |||
} | |||
func (p *RedisPool) GetPool() *redigo.Pool { | |||
return pool | |||
} | |||
func (p *RedisPool) ParseKey(key string, vars []string) (string, error) { | |||
arr := strings.Split(key, conf.KeyPlaceholder) | |||
actualKey := "" | |||
if len(arr) != len(vars)+1 { | |||
return "", errors.New("redis/connection.go: Insufficient arguments to parse key") | |||
} else { | |||
for index, val := range arr { | |||
if index == 0 { | |||
actualKey = arr[index] | |||
} else { | |||
actualKey += vars[index-1] + val | |||
} | |||
} | |||
} | |||
return getPrefixedKey(actualKey), nil | |||
} | |||
func (p *RedisPool) getPrefixedKey(key string) string { | |||
return conf.KeyPrefix + conf.KeyDelimiter + key | |||
} | |||
func (p *RedisPool) StripEnvKey(key string) string { | |||
return strings.TrimLeft(key, conf.KeyPrefix+conf.KeyDelimiter) | |||
} | |||
func (p *RedisPool) SplitKey(key string) []string { | |||
return strings.Split(key, conf.KeyDelimiter) | |||
} | |||
func (p *RedisPool) Expire(key string, ttl int) (interface{}, error) { | |||
return Do("EXPIRE", key, ttl) | |||
} | |||
func (p *RedisPool) Persist(key string) (interface{}, error) { | |||
return Do("PERSIST", key) | |||
} | |||
func (p *RedisPool) Del(key string) (interface{}, error) { | |||
return Do("DEL", key) | |||
} | |||
func (p *RedisPool) Set(key string, data interface{}) (interface{}, error) { | |||
// set | |||
return Do("SET", key, data) | |||
} | |||
func (p *RedisPool) SetNX(key string, data interface{}) (interface{}, error) { | |||
return Do("SETNX", key, data) | |||
} | |||
func (p *RedisPool) SetEx(key string, data interface{}, ttl int) (interface{}, error) { | |||
return Do("SETEX", key, ttl, data) | |||
} | |||
func (p *RedisPool) Get(key string) (interface{}, error) { | |||
// get | |||
return Do("GET", key) | |||
} | |||
func (p *RedisPool) GetStringMap(key string) (map[string]string, error) { | |||
// get | |||
return redigo.StringMap(Do("GET", key)) | |||
} | |||
func (p *RedisPool) GetTTL(key string) (time.Duration, error) { | |||
ttl, err := redigo.Int64(Do("TTL", key)) | |||
return time.Duration(ttl) * time.Second, err | |||
} | |||
func (p *RedisPool) GetBytes(key string) ([]byte, error) { | |||
return redigo.Bytes(Do("GET", key)) | |||
} | |||
func (p *RedisPool) GetString(key string) (string, error) { | |||
return redigo.String(Do("GET", key)) | |||
} | |||
func (p *RedisPool) GetInt(key string) (int, error) { | |||
return redigo.Int(Do("GET", key)) | |||
} | |||
func (p *RedisPool) GetStringLength(key string) (int, error) { | |||
return redigo.Int(Do("STRLEN", key)) | |||
} | |||
func (p *RedisPool) ZAdd(key string, score float64, data interface{}) (interface{}, error) { | |||
return Do("ZADD", key, score, data) | |||
} | |||
func (p *RedisPool) ZRem(key string, data interface{}) (interface{}, error) { | |||
return Do("ZREM", key, data) | |||
} | |||
func (p *RedisPool) ZRange(key string, start int, end int, withScores bool) ([]interface{}, error) { | |||
if withScores { | |||
return redigo.Values(Do("ZRANGE", key, start, end, "WITHSCORES")) | |||
} | |||
return redigo.Values(Do("ZRANGE", key, start, end)) | |||
} | |||
func (p *RedisPool) SAdd(setName string, data interface{}) (interface{}, error) { | |||
return Do("SADD", setName, data) | |||
} | |||
func (p *RedisPool) SCard(setName string) (int64, error) { | |||
return redigo.Int64(Do("SCARD", setName)) | |||
} | |||
func (p *RedisPool) SIsMember(setName string, data interface{}) (bool, error) { | |||
return redigo.Bool(Do("SISMEMBER", setName, data)) | |||
} | |||
func (p *RedisPool) SMembers(setName string) ([]string, error) { | |||
return redigo.Strings(Do("SMEMBERS", setName)) | |||
} | |||
func (p *RedisPool) SRem(setName string, data interface{}) (interface{}, error) { | |||
return Do("SREM", setName, data) | |||
} | |||
func (p *RedisPool) HSet(key string, HKey string, data interface{}) (interface{}, error) { | |||
return Do("HSET", key, HKey, data) | |||
} | |||
func (p *RedisPool) HGet(key string, HKey string) (interface{}, error) { | |||
return Do("HGET", key, HKey) | |||
} | |||
func (p *RedisPool) HMGet(key string, hashKeys ...string) ([]interface{}, error) { | |||
ret, err := Do("HMGET", key, hashKeys) | |||
if err != nil { | |||
return nil, err | |||
} | |||
reta, ok := ret.([]interface{}) | |||
if !ok { | |||
return nil, errors.New("result not an array") | |||
} | |||
return reta, nil | |||
} | |||
func (p *RedisPool) HMSet(key string, hashKeys []string, vals []interface{}) (interface{}, error) { | |||
if len(hashKeys) == 0 || len(hashKeys) != len(vals) { | |||
var ret interface{} | |||
return ret, errors.New("bad length") | |||
} | |||
input := []interface{}{key} | |||
for i, v := range hashKeys { | |||
input = append(input, v, vals[i]) | |||
} | |||
return Do("HMSET", input...) | |||
} | |||
func (p *RedisPool) HGetString(key string, HKey string) (string, error) { | |||
return redigo.String(Do("HGET", key, HKey)) | |||
} | |||
func (p *RedisPool) HGetFloat(key string, HKey string) (float64, error) { | |||
f, err := redigo.Float64(Do("HGET", key, HKey)) | |||
return float64(f), err | |||
} | |||
func (p *RedisPool) HGetInt(key string, HKey string) (int, error) { | |||
return redigo.Int(Do("HGET", key, HKey)) | |||
} | |||
func (p *RedisPool) HGetInt64(key string, HKey string) (int64, error) { | |||
return redigo.Int64(Do("HGET", key, HKey)) | |||
} | |||
func (p *RedisPool) HGetBool(key string, HKey string) (bool, error) { | |||
return redigo.Bool(Do("HGET", key, HKey)) | |||
} | |||
func (p *RedisPool) HDel(key string, HKey string) (interface{}, error) { | |||
return Do("HDEL", key, HKey) | |||
} | |||
func (p *RedisPool) HGetAll(key string) (map[string]interface{}, error) { | |||
vals, err := redigo.Values(Do("HGETALL", key)) | |||
if err != nil { | |||
return nil, err | |||
} | |||
num := len(vals) / 2 | |||
result := make(map[string]interface{}, num) | |||
for i := 0; i < num; i++ { | |||
key, _ := redigo.String(vals[2*i], nil) | |||
result[key] = vals[2*i+1] | |||
} | |||
return result, nil | |||
} | |||
// NOTE: Use this in production environment with extreme care. | |||
// Read more here:https://redigo.io/commands/keys | |||
func (p *RedisPool) Keys(pattern string) ([]string, error) { | |||
return redigo.Strings(Do("KEYS", pattern)) | |||
} | |||
func (p *RedisPool) HKeys(key string) ([]string, error) { | |||
return redigo.Strings(Do("HKEYS", key)) | |||
} | |||
func (p *RedisPool) Exists(key string) (bool, error) { | |||
count, err := redigo.Int(Do("EXISTS", key)) | |||
if count == 0 { | |||
return false, err | |||
} else { | |||
return true, err | |||
} | |||
} | |||
func (p *RedisPool) Incr(key string) (int64, error) { | |||
return redigo.Int64(Do("INCR", key)) | |||
} | |||
func (p *RedisPool) Decr(key string) (int64, error) { | |||
return redigo.Int64(Do("DECR", key)) | |||
} | |||
func (p *RedisPool) IncrBy(key string, incBy int64) (int64, error) { | |||
return redigo.Int64(Do("INCRBY", key, incBy)) | |||
} | |||
func (p *RedisPool) DecrBy(key string, decrBy int64) (int64, error) { | |||
return redigo.Int64(Do("DECRBY", key)) | |||
} | |||
func (p *RedisPool) IncrByFloat(key string, incBy float64) (float64, error) { | |||
return redigo.Float64(Do("INCRBYFLOAT", key, incBy)) | |||
} | |||
func (p *RedisPool) DecrByFloat(key string, decrBy float64) (float64, error) { | |||
return redigo.Float64(Do("DECRBYFLOAT", key, decrBy)) | |||
} | |||
// use for message queue | |||
func (p *RedisPool) LPush(key string, data interface{}) (interface{}, error) { | |||
// set | |||
return Do("LPUSH", key, data) | |||
} | |||
func (p *RedisPool) LPop(key string) (interface{}, error) { | |||
return Do("LPOP", key) | |||
} | |||
func (p *RedisPool) LPopString(key string) (string, error) { | |||
return redigo.String(Do("LPOP", key)) | |||
} | |||
func (p *RedisPool) LPopFloat(key string) (float64, error) { | |||
f, err := redigo.Float64(Do("LPOP", key)) | |||
return float64(f), err | |||
} | |||
func (p *RedisPool) LPopInt(key string) (int, error) { | |||
return redigo.Int(Do("LPOP", key)) | |||
} | |||
func (p *RedisPool) LPopInt64(key string) (int64, error) { | |||
return redigo.Int64(Do("LPOP", key)) | |||
} | |||
func (p *RedisPool) RPush(key string, data interface{}) (interface{}, error) { | |||
// set | |||
return Do("RPUSH", key, data) | |||
} | |||
func (p *RedisPool) RPop(key string) (interface{}, error) { | |||
return Do("RPOP", key) | |||
} | |||
func (p *RedisPool) RPopString(key string) (string, error) { | |||
return redigo.String(Do("RPOP", key)) | |||
} | |||
func (p *RedisPool) RPopFloat(key string) (float64, error) { | |||
f, err := redigo.Float64(Do("RPOP", key)) | |||
return float64(f), err | |||
} | |||
func (p *RedisPool) RPopInt(key string) (int, error) { | |||
return redigo.Int(Do("RPOP", key)) | |||
} | |||
func (p *RedisPool) RPopInt64(key string) (int64, error) { | |||
return redigo.Int64(Do("RPOP", key)) | |||
} | |||
func (p *RedisPool) Scan(cursor int64, pattern string, count int64) (int64, []string, error) { | |||
var items []string | |||
var newCursor int64 | |||
values, err := redigo.Values(Do("SCAN", cursor, "MATCH", pattern, "COUNT", count)) | |||
if err != nil { | |||
return 0, nil, err | |||
} | |||
values, err = redigo.Scan(values, &newCursor, &items) | |||
if err != nil { | |||
return 0, nil, err | |||
} | |||
return newCursor, items, nil | |||
} |
@@ -0,0 +1,617 @@ | |||
package cache | |||
import ( | |||
"strconv" | |||
"time" | |||
"github.com/go-redis/redis" | |||
) | |||
type RedisClusterPool struct { | |||
client *redis.ClusterClient | |||
} | |||
func NewRedisClusterPool(addrs []string) (*RedisClusterPool, error) { | |||
opt := &redis.ClusterOptions{ | |||
Addrs: addrs, | |||
PoolSize: 512, | |||
PoolTimeout: 10 * time.Second, | |||
IdleTimeout: 10 * time.Second, | |||
DialTimeout: 10 * time.Second, | |||
ReadTimeout: 3 * time.Second, | |||
WriteTimeout: 3 * time.Second, | |||
} | |||
c := redis.NewClusterClient(opt) | |||
if err := c.Ping().Err(); err != nil { | |||
return nil, err | |||
} | |||
return &RedisClusterPool{client: c}, nil | |||
} | |||
func (p *RedisClusterPool) Get(key string) (interface{}, error) { | |||
res, err := p.client.Get(key).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return []byte(res), nil | |||
} | |||
func (p *RedisClusterPool) Set(key string, value interface{}) error { | |||
err := p.client.Set(key, value, 0).Err() | |||
return convertError(err) | |||
} | |||
func (p *RedisClusterPool) GetSet(key string, value interface{}) (interface{}, error) { | |||
res, err := p.client.GetSet(key, value).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return []byte(res), nil | |||
} | |||
func (p *RedisClusterPool) SetNx(key string, value interface{}) (int64, error) { | |||
res, err := p.client.SetNX(key, value, 0).Result() | |||
if err != nil { | |||
return 0, convertError(err) | |||
} | |||
if res { | |||
return 1, nil | |||
} | |||
return 0, nil | |||
} | |||
func (p *RedisClusterPool) SetEx(key string, value interface{}, timeout int64) error { | |||
_, err := p.client.Set(key, value, time.Duration(timeout)*time.Second).Result() | |||
if err != nil { | |||
return convertError(err) | |||
} | |||
return nil | |||
} | |||
// nil表示成功,ErrNil表示数据库内已经存在这个key,其他表示数据库发生错误 | |||
func (p *RedisClusterPool) SetNxEx(key string, value interface{}, timeout int64) error { | |||
res, err := p.client.SetNX(key, value, time.Duration(timeout)*time.Second).Result() | |||
if err != nil { | |||
return convertError(err) | |||
} | |||
if res { | |||
return nil | |||
} | |||
return ErrNil | |||
} | |||
func (p *RedisClusterPool) MGet(keys ...string) ([]interface{}, error) { | |||
res, err := p.client.MGet(keys...).Result() | |||
return res, convertError(err) | |||
} | |||
// 为确保多个key映射到同一个slot,每个key最好加上hash tag,如:{test} | |||
func (p *RedisClusterPool) MSet(kvs map[string]interface{}) error { | |||
pairs := make([]string, 0, len(kvs)*2) | |||
for k, v := range kvs { | |||
val, err := String(v, nil) | |||
if err != nil { | |||
return err | |||
} | |||
pairs = append(pairs, k, val) | |||
} | |||
return convertError(p.client.MSet(pairs).Err()) | |||
} | |||
// 为确保多个key映射到同一个slot,每个key最好加上hash tag,如:{test} | |||
func (p *RedisClusterPool) MSetNX(kvs map[string]interface{}) (bool, error) { | |||
pairs := make([]string, 0, len(kvs)*2) | |||
for k, v := range kvs { | |||
val, err := String(v, nil) | |||
if err != nil { | |||
return false, err | |||
} | |||
pairs = append(pairs, k, val) | |||
} | |||
res, err := p.client.MSetNX(pairs).Result() | |||
return res, convertError(err) | |||
} | |||
func (p *RedisClusterPool) ExpireAt(key string, timestamp int64) (int64, error) { | |||
res, err := p.client.ExpireAt(key, time.Unix(timestamp, 0)).Result() | |||
if err != nil { | |||
return 0, convertError(err) | |||
} | |||
if res { | |||
return 1, nil | |||
} | |||
return 0, nil | |||
} | |||
func (p *RedisClusterPool) Del(keys ...string) (int64, error) { | |||
args := make([]interface{}, 0, len(keys)) | |||
for _, key := range keys { | |||
args = append(args, key) | |||
} | |||
res, err := p.client.Del(keys...).Result() | |||
if err != nil { | |||
return res, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func (p *RedisClusterPool) Incr(key string) (int64, error) { | |||
res, err := p.client.Incr(key).Result() | |||
if err != nil { | |||
return res, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func (p *RedisClusterPool) IncrBy(key string, delta int64) (int64, error) { | |||
res, err := p.client.IncrBy(key, delta).Result() | |||
if err != nil { | |||
return res, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func (p *RedisClusterPool) Expire(key string, duration int64) (int64, error) { | |||
res, err := p.client.Expire(key, time.Duration(duration)*time.Second).Result() | |||
if err != nil { | |||
return 0, convertError(err) | |||
} | |||
if res { | |||
return 1, nil | |||
} | |||
return 0, nil | |||
} | |||
func (p *RedisClusterPool) Exists(key string) (bool, error) { // todo (bool, error) | |||
res, err := p.client.Exists(key).Result() | |||
if err != nil { | |||
return false, convertError(err) | |||
} | |||
if res > 0 { | |||
return true, nil | |||
} | |||
return false, nil | |||
} | |||
func (p *RedisClusterPool) HGet(key string, field string) (interface{}, error) { | |||
res, err := p.client.HGet(key, field).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return []byte(res), nil | |||
} | |||
func (p *RedisClusterPool) HLen(key string) (int64, error) { | |||
res, err := p.client.HLen(key).Result() | |||
if err != nil { | |||
return res, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func (p *RedisClusterPool) HSet(key string, field string, val interface{}) error { | |||
value, err := String(val, nil) | |||
if err != nil && err != ErrNil { | |||
return err | |||
} | |||
_, err = p.client.HSet(key, field, value).Result() | |||
if err != nil { | |||
return convertError(err) | |||
} | |||
return nil | |||
} | |||
func (p *RedisClusterPool) HDel(key string, fields ...string) (int64, error) { | |||
args := make([]interface{}, 0, len(fields)+1) | |||
args = append(args, key) | |||
for _, field := range fields { | |||
args = append(args, field) | |||
} | |||
res, err := p.client.HDel(key, fields...).Result() | |||
if err != nil { | |||
return 0, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func (p *RedisClusterPool) HMGet(key string, fields ...string) (interface{}, error) { | |||
args := make([]interface{}, 0, len(fields)+1) | |||
args = append(args, key) | |||
for _, field := range fields { | |||
args = append(args, field) | |||
} | |||
if len(fields) == 0 { | |||
return nil, ErrNil | |||
} | |||
res, err := p.client.HMGet(key, fields...).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func (p *RedisClusterPool) HMSet(key string, kvs ...interface{}) error { | |||
if len(kvs) == 0 { | |||
return nil | |||
} | |||
if len(kvs)%2 != 0 { | |||
return ErrWrongArgsNum | |||
} | |||
var err error | |||
v := map[string]interface{}{} // todo change | |||
v["field"], err = String(kvs[0], nil) | |||
if err != nil && err != ErrNil { | |||
return err | |||
} | |||
v["value"], err = String(kvs[1], nil) | |||
if err != nil && err != ErrNil { | |||
return err | |||
} | |||
pairs := make([]string, 0, len(kvs)-2) | |||
if len(kvs) > 2 { | |||
for _, kv := range kvs[2:] { | |||
kvString, err := String(kv, nil) | |||
if err != nil && err != ErrNil { | |||
return err | |||
} | |||
pairs = append(pairs, kvString) | |||
} | |||
} | |||
v["paris"] = pairs | |||
_, err = p.client.HMSet(key, v).Result() | |||
if err != nil { | |||
return convertError(err) | |||
} | |||
return nil | |||
} | |||
func (p *RedisClusterPool) HKeys(key string) ([]string, error) { | |||
res, err := p.client.HKeys(key).Result() | |||
if err != nil { | |||
return res, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func (p *RedisClusterPool) HVals(key string) ([]interface{}, error) { | |||
res, err := p.client.HVals(key).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
rs := make([]interface{}, 0, len(res)) | |||
for _, res := range res { | |||
rs = append(rs, res) | |||
} | |||
return rs, nil | |||
} | |||
func (p *RedisClusterPool) HGetAll(key string) (map[string]string, error) { | |||
vals, err := p.client.HGetAll(key).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return vals, nil | |||
} | |||
func (p *RedisClusterPool) HIncrBy(key, field string, delta int64) (int64, error) { | |||
res, err := p.client.HIncrBy(key, field, delta).Result() | |||
if err != nil { | |||
return res, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func (p *RedisClusterPool) ZAdd(key string, kvs ...interface{}) (int64, error) { | |||
args := make([]interface{}, 0, len(kvs)+1) | |||
args = append(args, key) | |||
args = append(args, kvs...) | |||
if len(kvs) == 0 { | |||
return 0, nil | |||
} | |||
if len(kvs)%2 != 0 { | |||
return 0, ErrWrongArgsNum | |||
} | |||
zs := make([]redis.Z, len(kvs)/2) | |||
for i := 0; i < len(kvs); i += 2 { | |||
idx := i / 2 | |||
score, err := Float64(kvs[i], nil) | |||
if err != nil && err != ErrNil { | |||
return 0, err | |||
} | |||
zs[idx].Score = score | |||
zs[idx].Member = kvs[i+1] | |||
} | |||
res, err := p.client.ZAdd(key, zs...).Result() | |||
if err != nil { | |||
return res, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func (p *RedisClusterPool) ZRem(key string, members ...string) (int64, error) { | |||
args := make([]interface{}, 0, len(members)) | |||
args = append(args, key) | |||
for _, member := range members { | |||
args = append(args, member) | |||
} | |||
res, err := p.client.ZRem(key, members).Result() | |||
if err != nil { | |||
return res, convertError(err) | |||
} | |||
return res, err | |||
} | |||
func (p *RedisClusterPool) ZRange(key string, min, max int64, withScores bool) (interface{}, error) { | |||
res := make([]interface{}, 0) | |||
if withScores { | |||
zs, err := p.client.ZRangeWithScores(key, min, max).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
for _, z := range zs { | |||
res = append(res, z.Member, strconv.FormatFloat(z.Score, 'f', -1, 64)) | |||
} | |||
} else { | |||
ms, err := p.client.ZRange(key, min, max).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
for _, m := range ms { | |||
res = append(res, m) | |||
} | |||
} | |||
return res, nil | |||
} | |||
func (p *RedisClusterPool) ZRangeByScoreWithScore(key string, min, max int64) (map[string]int64, error) { | |||
opt := new(redis.ZRangeBy) | |||
opt.Min = strconv.FormatInt(int64(min), 10) | |||
opt.Max = strconv.FormatInt(int64(max), 10) | |||
opt.Count = -1 | |||
opt.Offset = 0 | |||
vals, err := p.client.ZRangeByScoreWithScores(key, *opt).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
res := make(map[string]int64, len(vals)) | |||
for _, val := range vals { | |||
key, err := String(val.Member, nil) | |||
if err != nil && err != ErrNil { | |||
return nil, err | |||
} | |||
res[key] = int64(val.Score) | |||
} | |||
return res, nil | |||
} | |||
func (p *RedisClusterPool) LRange(key string, start, stop int64) (interface{}, error) { | |||
res, err := p.client.LRange(key, start, stop).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func (p *RedisClusterPool) LSet(key string, index int, value interface{}) error { | |||
err := p.client.LSet(key, int64(index), value).Err() | |||
return convertError(err) | |||
} | |||
func (p *RedisClusterPool) LLen(key string) (int64, error) { | |||
res, err := p.client.LLen(key).Result() | |||
if err != nil { | |||
return res, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func (p *RedisClusterPool) LRem(key string, count int, value interface{}) (int, error) { | |||
val, _ := value.(string) | |||
res, err := p.client.LRem(key, int64(count), val).Result() | |||
if err != nil { | |||
return int(res), convertError(err) | |||
} | |||
return int(res), nil | |||
} | |||
func (p *RedisClusterPool) TTl(key string) (int64, error) { | |||
duration, err := p.client.TTL(key).Result() | |||
if err != nil { | |||
return int64(duration.Seconds()), convertError(err) | |||
} | |||
return int64(duration.Seconds()), nil | |||
} | |||
func (p *RedisClusterPool) LPop(key string) (interface{}, error) { | |||
res, err := p.client.LPop(key).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func (p *RedisClusterPool) RPop(key string) (interface{}, error) { | |||
res, err := p.client.RPop(key).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func (p *RedisClusterPool) BLPop(key string, timeout int) (interface{}, error) { | |||
res, err := p.client.BLPop(time.Duration(timeout)*time.Second, key).Result() | |||
if err != nil { | |||
// 兼容redis 2.x | |||
if err == redis.Nil { | |||
return nil, ErrNil | |||
} | |||
return nil, err | |||
} | |||
return res[1], nil | |||
} | |||
func (p *RedisClusterPool) BRPop(key string, timeout int) (interface{}, error) { | |||
res, err := p.client.BRPop(time.Duration(timeout)*time.Second, key).Result() | |||
if err != nil { | |||
// 兼容redis 2.x | |||
if err == redis.Nil { | |||
return nil, ErrNil | |||
} | |||
return nil, convertError(err) | |||
} | |||
return res[1], nil | |||
} | |||
func (p *RedisClusterPool) LPush(key string, value ...interface{}) error { | |||
args := make([]interface{}, 0, len(value)+1) | |||
args = append(args, key) | |||
args = append(args, value...) | |||
vals := make([]string, 0, len(value)) | |||
for _, v := range value { | |||
val, err := String(v, nil) | |||
if err != nil && err != ErrNil { | |||
return err | |||
} | |||
vals = append(vals, val) | |||
} | |||
_, err := p.client.LPush(key, vals).Result() // todo ... | |||
if err != nil { | |||
return convertError(err) | |||
} | |||
return nil | |||
} | |||
func (p *RedisClusterPool) RPush(key string, value ...interface{}) error { | |||
args := make([]interface{}, 0, len(value)+1) | |||
args = append(args, key) | |||
args = append(args, value...) | |||
vals := make([]string, 0, len(value)) | |||
for _, v := range value { | |||
val, err := String(v, nil) | |||
if err != nil && err != ErrNil { | |||
if err == ErrNil { | |||
continue | |||
} | |||
return err | |||
} | |||
if val == "" { | |||
continue | |||
} | |||
vals = append(vals, val) | |||
} | |||
_, err := p.client.RPush(key, vals).Result() // todo ... | |||
if err != nil { | |||
return convertError(err) | |||
} | |||
return nil | |||
} | |||
// 为确保srcKey跟destKey映射到同一个slot,srcKey和destKey需要加上hash tag,如:{test} | |||
func (p *RedisClusterPool) BRPopLPush(srcKey string, destKey string, timeout int) (interface{}, error) { | |||
res, err := p.client.BRPopLPush(srcKey, destKey, time.Duration(timeout)*time.Second).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
// 为确保srcKey跟destKey映射到同一个slot,srcKey和destKey需要加上hash tag,如:{test} | |||
func (p *RedisClusterPool) RPopLPush(srcKey string, destKey string) (interface{}, error) { | |||
res, err := p.client.RPopLPush(srcKey, destKey).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func (p *RedisClusterPool) SAdd(key string, members ...interface{}) (int64, error) { | |||
args := make([]interface{}, 0, len(members)+1) | |||
args = append(args, key) | |||
args = append(args, members...) | |||
ms := make([]string, 0, len(members)) | |||
for _, member := range members { | |||
m, err := String(member, nil) | |||
if err != nil && err != ErrNil { | |||
return 0, err | |||
} | |||
ms = append(ms, m) | |||
} | |||
res, err := p.client.SAdd(key, ms).Result() // todo ... | |||
if err != nil { | |||
return res, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func (p *RedisClusterPool) SPop(key string) ([]byte, error) { | |||
res, err := p.client.SPop(key).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return []byte(res), nil | |||
} | |||
func (p *RedisClusterPool) SIsMember(key string, member interface{}) (bool, error) { | |||
m, _ := member.(string) | |||
res, err := p.client.SIsMember(key, m).Result() | |||
if err != nil { | |||
return res, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func (p *RedisClusterPool) SRem(key string, members ...interface{}) (int64, error) { | |||
args := make([]interface{}, 0, len(members)+1) | |||
args = append(args, key) | |||
args = append(args, members...) | |||
ms := make([]string, 0, len(members)) | |||
for _, member := range members { | |||
m, err := String(member, nil) | |||
if err != nil && err != ErrNil { | |||
return 0, err | |||
} | |||
ms = append(ms, m) | |||
} | |||
res, err := p.client.SRem(key, ms).Result() // todo ... | |||
if err != nil { | |||
return res, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func (p *RedisClusterPool) SMembers(key string) ([]string, error) { | |||
res, err := p.client.SMembers(key).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func (p *RedisClusterPool) ScriptLoad(luaScript string) (interface{}, error) { | |||
res, err := p.client.ScriptLoad(luaScript).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func (p *RedisClusterPool) EvalSha(sha1 string, numberKeys int, keysArgs ...interface{}) (interface{}, error) { | |||
vals := make([]interface{}, 0, len(keysArgs)+2) | |||
vals = append(vals, sha1, numberKeys) | |||
vals = append(vals, keysArgs...) | |||
keys := make([]string, 0, numberKeys) | |||
args := make([]string, 0, len(keysArgs)-numberKeys) | |||
for i, value := range keysArgs { | |||
val, err := String(value, nil) | |||
if err != nil && err != ErrNil { | |||
return nil, err | |||
} | |||
if i < numberKeys { | |||
keys = append(keys, val) | |||
} else { | |||
args = append(args, val) | |||
} | |||
} | |||
res, err := p.client.EvalSha(sha1, keys, args).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func (p *RedisClusterPool) Eval(luaScript string, numberKeys int, keysArgs ...interface{}) (interface{}, error) { | |||
vals := make([]interface{}, 0, len(keysArgs)+2) | |||
vals = append(vals, luaScript, numberKeys) | |||
vals = append(vals, keysArgs...) | |||
keys := make([]string, 0, numberKeys) | |||
args := make([]string, 0, len(keysArgs)-numberKeys) | |||
for i, value := range keysArgs { | |||
val, err := String(value, nil) | |||
if err != nil && err != ErrNil { | |||
return nil, err | |||
} | |||
if i < numberKeys { | |||
keys = append(keys, val) | |||
} else { | |||
args = append(args, val) | |||
} | |||
} | |||
res, err := p.client.Eval(luaScript, keys, args).Result() | |||
if err != nil { | |||
return nil, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func (p *RedisClusterPool) GetBit(key string, offset int64) (int64, error) { | |||
res, err := p.client.GetBit(key, offset).Result() | |||
if err != nil { | |||
return res, convertError(err) | |||
} | |||
return res, nil | |||
} | |||
func (p *RedisClusterPool) SetBit(key string, offset uint32, value int) (int, error) { | |||
res, err := p.client.SetBit(key, int64(offset), value).Result() | |||
return int(res), convertError(err) | |||
} | |||
func (p *RedisClusterPool) GetClient() *redis.ClusterClient { | |||
return pools | |||
} |
@@ -0,0 +1,388 @@ | |||
package egg_system_rules | |||
import ( | |||
"encoding/binary" | |||
"encoding/json" | |||
"fmt" | |||
"math" | |||
"reflect" | |||
"strconv" | |||
"strings" | |||
) | |||
func ToString(raw interface{}, e error) (res string) { | |||
if e != nil { | |||
return "" | |||
} | |||
return AnyToString(raw) | |||
} | |||
func ToInt64(raw interface{}, e error) int64 { | |||
if e != nil { | |||
return 0 | |||
} | |||
return AnyToInt64(raw) | |||
} | |||
func IsNil(i interface{}) bool { | |||
vi := reflect.ValueOf(i) | |||
if vi.Kind() == reflect.Ptr { | |||
return vi.IsNil() | |||
} | |||
return false | |||
} | |||
func AnyToBool(raw interface{}) bool { | |||
switch i := raw.(type) { | |||
case float32, float64, int, int64, uint, uint8, uint16, uint32, uint64, int8, int16, int32: | |||
return i != 0 | |||
case []byte: | |||
return i != nil | |||
case string: | |||
if i == "false" { | |||
return false | |||
} | |||
return i != "" | |||
case error: | |||
return false | |||
case nil: | |||
return true | |||
} | |||
val := fmt.Sprint(raw) | |||
val = strings.TrimLeft(val, "&") | |||
if strings.TrimLeft(val, "{}") == "" { | |||
return false | |||
} | |||
if strings.TrimLeft(val, "[]") == "" { | |||
return false | |||
} | |||
// ptr type | |||
b, err := json.Marshal(raw) | |||
if err != nil { | |||
return false | |||
} | |||
if strings.TrimLeft(string(b), "\"\"") == "" { | |||
return false | |||
} | |||
if strings.TrimLeft(string(b), "{}") == "" { | |||
return false | |||
} | |||
return true | |||
} | |||
func AnyToInt64(raw interface{}) int64 { | |||
switch i := raw.(type) { | |||
case string: | |||
res, _ := strconv.ParseInt(i, 10, 64) | |||
return res | |||
case []byte: | |||
return BytesToInt64(i) | |||
case int: | |||
return int64(i) | |||
case int64: | |||
return i | |||
case uint: | |||
return int64(i) | |||
case uint8: | |||
return int64(i) | |||
case uint16: | |||
return int64(i) | |||
case uint32: | |||
return int64(i) | |||
case uint64: | |||
return int64(i) | |||
case int8: | |||
return int64(i) | |||
case int16: | |||
return int64(i) | |||
case int32: | |||
return int64(i) | |||
case float32: | |||
return int64(i) | |||
case float64: | |||
return int64(i) | |||
case error: | |||
return 0 | |||
case bool: | |||
if i { | |||
return 1 | |||
} | |||
return 0 | |||
} | |||
return 0 | |||
} | |||
func AnyToString(raw interface{}) string { | |||
switch i := raw.(type) { | |||
case []byte: | |||
return string(i) | |||
case int: | |||
return strconv.FormatInt(int64(i), 10) | |||
case int64: | |||
return strconv.FormatInt(i, 10) | |||
case float32: | |||
return Float64ToStr(float64(i)) | |||
case float64: | |||
return Float64ToStr(i) | |||
case uint: | |||
return strconv.FormatInt(int64(i), 10) | |||
case uint8: | |||
return strconv.FormatInt(int64(i), 10) | |||
case uint16: | |||
return strconv.FormatInt(int64(i), 10) | |||
case uint32: | |||
return strconv.FormatInt(int64(i), 10) | |||
case uint64: | |||
return strconv.FormatInt(int64(i), 10) | |||
case int8: | |||
return strconv.FormatInt(int64(i), 10) | |||
case int16: | |||
return strconv.FormatInt(int64(i), 10) | |||
case int32: | |||
return strconv.FormatInt(int64(i), 10) | |||
case string: | |||
return i | |||
case error: | |||
return i.Error() | |||
case bool: | |||
return strconv.FormatBool(i) | |||
} | |||
return fmt.Sprintf("%#v", raw) | |||
} | |||
func AnyToFloat64(raw interface{}) float64 { | |||
switch i := raw.(type) { | |||
case []byte: | |||
f, _ := strconv.ParseFloat(string(i), 64) | |||
return f | |||
case int: | |||
return float64(i) | |||
case int64: | |||
return float64(i) | |||
case float32: | |||
return float64(i) | |||
case float64: | |||
return i | |||
case uint: | |||
return float64(i) | |||
case uint8: | |||
return float64(i) | |||
case uint16: | |||
return float64(i) | |||
case uint32: | |||
return float64(i) | |||
case uint64: | |||
return float64(i) | |||
case int8: | |||
return float64(i) | |||
case int16: | |||
return float64(i) | |||
case int32: | |||
return float64(i) | |||
case string: | |||
f, _ := strconv.ParseFloat(i, 64) | |||
return f | |||
case bool: | |||
if i { | |||
return 1 | |||
} | |||
} | |||
return 0 | |||
} | |||
func ToByte(raw interface{}, e error) []byte { | |||
if e != nil { | |||
return []byte{} | |||
} | |||
switch i := raw.(type) { | |||
case string: | |||
return []byte(i) | |||
case int: | |||
return Int64ToBytes(int64(i)) | |||
case int64: | |||
return Int64ToBytes(i) | |||
case float32: | |||
return Float32ToByte(i) | |||
case float64: | |||
return Float64ToByte(i) | |||
case uint: | |||
return Int64ToBytes(int64(i)) | |||
case uint8: | |||
return Int64ToBytes(int64(i)) | |||
case uint16: | |||
return Int64ToBytes(int64(i)) | |||
case uint32: | |||
return Int64ToBytes(int64(i)) | |||
case uint64: | |||
return Int64ToBytes(int64(i)) | |||
case int8: | |||
return Int64ToBytes(int64(i)) | |||
case int16: | |||
return Int64ToBytes(int64(i)) | |||
case int32: | |||
return Int64ToBytes(int64(i)) | |||
case []byte: | |||
return i | |||
case error: | |||
return []byte(i.Error()) | |||
case bool: | |||
if i { | |||
return []byte("true") | |||
} | |||
return []byte("false") | |||
} | |||
return []byte(fmt.Sprintf("%#v", raw)) | |||
} | |||
func Int64ToBytes(i int64) []byte { | |||
var buf = make([]byte, 8) | |||
binary.BigEndian.PutUint64(buf, uint64(i)) | |||
return buf | |||
} | |||
func BytesToInt64(buf []byte) int64 { | |||
return int64(binary.BigEndian.Uint64(buf)) | |||
} | |||
func StrToInt(s string) int { | |||
res, _ := strconv.Atoi(s) | |||
return res | |||
} | |||
func StrToInt64(s string) int64 { | |||
res, _ := strconv.ParseInt(s, 10, 64) | |||
return res | |||
} | |||
func Float32ToByte(float float32) []byte { | |||
bits := math.Float32bits(float) | |||
bytes := make([]byte, 4) | |||
binary.LittleEndian.PutUint32(bytes, bits) | |||
return bytes | |||
} | |||
func ByteToFloat32(bytes []byte) float32 { | |||
bits := binary.LittleEndian.Uint32(bytes) | |||
return math.Float32frombits(bits) | |||
} | |||
func Float64ToByte(float float64) []byte { | |||
bits := math.Float64bits(float) | |||
bytes := make([]byte, 8) | |||
binary.LittleEndian.PutUint64(bytes, bits) | |||
return bytes | |||
} | |||
func ByteToFloat64(bytes []byte) float64 { | |||
bits := binary.LittleEndian.Uint64(bytes) | |||
return math.Float64frombits(bits) | |||
} | |||
func Float64ToStr(f float64) string { | |||
return strconv.FormatFloat(f, 'f', 2, 64) | |||
} | |||
func Float64ToStrPrec1(f float64) string { | |||
return strconv.FormatFloat(f, 'f', 1, 64) | |||
} | |||
func Float64ToStrPrec4(f float64) string { | |||
return strconv.FormatFloat(f, 'f', 4, 64) | |||
} | |||
func Float64ToStrPrec10(f float64) string { | |||
return strconv.FormatFloat(f, 'f', 10, 64) | |||
} | |||
func Float64ToStrPrec8(f float64) string { | |||
return strconv.FormatFloat(f, 'f', 8, 64) | |||
} | |||
func Float64ToStrPrec6(f float64) string { | |||
return strconv.FormatFloat(f, 'f', 6, 64) | |||
} | |||
func Float64ToStrByPrec(f float64, prec int) string { | |||
return strconv.FormatFloat(f, 'f', prec, 64) | |||
} | |||
func Float32ToStr(f float32) string { | |||
return Float64ToStr(float64(f)) | |||
} | |||
func StrToFloat64(s string) float64 { | |||
res, err := strconv.ParseFloat(s, 64) | |||
if err != nil { | |||
return 0 | |||
} | |||
return res | |||
} | |||
func StrToFormat(s string, prec int) string { | |||
ex := strings.Split(s, ".") | |||
if len(ex) == 2 { | |||
if StrToFloat64(ex[1]) == 0 { //小数点后面为空就是不要小数点了 | |||
return ex[0] | |||
} | |||
//看取多少位 | |||
str := ex[1] | |||
str1 := str | |||
if prec < len(str) { | |||
str1 = str[0:prec] | |||
} else { | |||
for i := 0; i < prec-len(str); i++ { | |||
str1 += "0" | |||
} | |||
} | |||
if prec > 0 { | |||
return ex[0] + "." + str1 | |||
} else { | |||
return ex[0] | |||
} | |||
} | |||
return s | |||
} | |||
func StrToFloat32(s string) float32 { | |||
res, err := strconv.ParseFloat(s, 32) | |||
if err != nil { | |||
return 0 | |||
} | |||
return float32(res) | |||
} | |||
func StrToBool(s string) bool { | |||
b, _ := strconv.ParseBool(s) | |||
return b | |||
} | |||
func BoolToStr(b bool) string { | |||
if b { | |||
return "true" | |||
} | |||
return "false" | |||
} | |||
func FloatToInt64(f float64) int64 { | |||
return int64(f) | |||
} | |||
func IntToStr(i int) string { | |||
return strconv.Itoa(i) | |||
} | |||
func Int64ToStr(i int64) string { | |||
return strconv.FormatInt(i, 10) | |||
} | |||
func IntToFloat64(i int) float64 { | |||
s := strconv.Itoa(i) | |||
res, err := strconv.ParseFloat(s, 64) | |||
if err != nil { | |||
return 0 | |||
} | |||
return res | |||
} | |||
func Int64ToFloat64(i int64) float64 { | |||
s := strconv.FormatInt(i, 10) | |||
res, err := strconv.ParseFloat(s, 64) | |||
if err != nil { | |||
return 0 | |||
} | |||
return res | |||
} |
@@ -0,0 +1,209 @@ | |||
package egg_system_rules | |||
import ( | |||
"bytes" | |||
"crypto/tls" | |||
"fmt" | |||
"io" | |||
"io/ioutil" | |||
"net/http" | |||
"net/url" | |||
"sort" | |||
"strings" | |||
"time" | |||
) | |||
var CurlDebug bool | |||
func CurlGet(router string, header map[string]string) ([]byte, error) { | |||
return curl(http.MethodGet, router, nil, header) | |||
} | |||
func CurlGetJson(router string, body interface{}, header map[string]string) ([]byte, error) { | |||
return curl_new(http.MethodGet, router, body, header) | |||
} | |||
// 只支持form 与json 提交, 请留意body的类型, 支持string, []byte, map[string]string | |||
func CurlPost(router string, body interface{}, header map[string]string) ([]byte, error) { | |||
return curl(http.MethodPost, router, body, header) | |||
} | |||
func CurlPut(router string, body interface{}, header map[string]string) ([]byte, error) { | |||
return curl(http.MethodPut, router, body, header) | |||
} | |||
// 只支持form 与json 提交, 请留意body的类型, 支持string, []byte, map[string]string | |||
func CurlPatch(router string, body interface{}, header map[string]string) ([]byte, error) { | |||
return curl(http.MethodPatch, router, body, header) | |||
} | |||
// CurlDelete is curl delete | |||
func CurlDelete(router string, body interface{}, header map[string]string) ([]byte, error) { | |||
return curl(http.MethodDelete, router, body, header) | |||
} | |||
func curl(method, router string, body interface{}, header map[string]string) ([]byte, error) { | |||
var reqBody io.Reader | |||
contentType := "application/json" | |||
switch v := body.(type) { | |||
case string: | |||
reqBody = strings.NewReader(v) | |||
case []byte: | |||
reqBody = bytes.NewReader(v) | |||
case map[string]string: | |||
val := url.Values{} | |||
for k, v := range v { | |||
val.Set(k, v) | |||
} | |||
reqBody = strings.NewReader(val.Encode()) | |||
contentType = "application/x-www-form-urlencoded" | |||
case map[string]interface{}: | |||
val := url.Values{} | |||
for k, v := range v { | |||
val.Set(k, v.(string)) | |||
} | |||
reqBody = strings.NewReader(val.Encode()) | |||
contentType = "application/x-www-form-urlencoded" | |||
} | |||
if header == nil { | |||
header = map[string]string{"Content-Type": contentType} | |||
} | |||
if _, ok := header["Content-Type"]; !ok { | |||
header["Content-Type"] = contentType | |||
} | |||
resp, er := CurlReq(method, router, reqBody, header) | |||
if er != nil { | |||
return nil, er | |||
} | |||
res, err := ioutil.ReadAll(resp.Body) | |||
if CurlDebug { | |||
blob := SerializeStr(body) | |||
if contentType != "application/json" { | |||
blob = HttpBuild(body) | |||
} | |||
fmt.Printf("\n\n=====================\n[url]: %s\n[time]: %s\n[method]: %s\n[content-type]: %v\n[req_header]: %s\n[req_body]: %#v\n[resp_err]: %v\n[resp_header]: %v\n[resp_body]: %v\n=====================\n\n", | |||
router, | |||
time.Now().Format("2006-01-02 15:04:05.000"), | |||
method, | |||
contentType, | |||
HttpBuildQuery(header), | |||
blob, | |||
err, | |||
SerializeStr(resp.Header), | |||
string(res), | |||
) | |||
} | |||
resp.Body.Close() | |||
return res, err | |||
} | |||
func curl_new(method, router string, body interface{}, header map[string]string) ([]byte, error) { | |||
var reqBody io.Reader | |||
contentType := "application/json" | |||
if header == nil { | |||
header = map[string]string{"Content-Type": contentType} | |||
} | |||
if _, ok := header["Content-Type"]; !ok { | |||
header["Content-Type"] = contentType | |||
} | |||
resp, er := CurlReq(method, router, reqBody, header) | |||
if er != nil { | |||
return nil, er | |||
} | |||
res, err := ioutil.ReadAll(resp.Body) | |||
if CurlDebug { | |||
blob := SerializeStr(body) | |||
if contentType != "application/json" { | |||
blob = HttpBuild(body) | |||
} | |||
fmt.Printf("\n\n=====================\n[url]: %s\n[time]: %s\n[method]: %s\n[content-type]: %v\n[req_header]: %s\n[req_body]: %#v\n[resp_err]: %v\n[resp_header]: %v\n[resp_body]: %v\n=====================\n\n", | |||
router, | |||
time.Now().Format("2006-01-02 15:04:05.000"), | |||
method, | |||
contentType, | |||
HttpBuildQuery(header), | |||
blob, | |||
err, | |||
SerializeStr(resp.Header), | |||
string(res), | |||
) | |||
} | |||
resp.Body.Close() | |||
return res, err | |||
} | |||
func CurlReq(method, router string, reqBody io.Reader, header map[string]string) (*http.Response, error) { | |||
req, _ := http.NewRequest(method, router, reqBody) | |||
if header != nil { | |||
for k, v := range header { | |||
req.Header.Set(k, v) | |||
} | |||
} | |||
// 绕过github等可能因为特征码返回503问题 | |||
// https://www.imwzk.com/posts/2021-03-14-why-i-always-get-503-with-golang/ | |||
defaultCipherSuites := []uint16{0xc02f, 0xc030, 0xc02b, 0xc02c, 0xcca8, 0xcca9, 0xc013, 0xc009, | |||
0xc014, 0xc00a, 0x009c, 0x009d, 0x002f, 0x0035, 0xc012, 0x000a} | |||
client := &http.Client{ | |||
Transport: &http.Transport{ | |||
TLSClientConfig: &tls.Config{ | |||
InsecureSkipVerify: true, | |||
CipherSuites: append(defaultCipherSuites[8:], defaultCipherSuites[:8]...), | |||
}, | |||
}, | |||
// 获取301重定向 | |||
CheckRedirect: func(req *http.Request, via []*http.Request) error { | |||
return http.ErrUseLastResponse | |||
}, | |||
} | |||
return client.Do(req) | |||
} | |||
// 组建get请求参数,sortAsc true为小到大,false为大到小,nil不排序 a=123&b=321 | |||
func HttpBuildQuery(args map[string]string, sortAsc ...bool) string { | |||
str := "" | |||
if len(args) == 0 { | |||
return str | |||
} | |||
if len(sortAsc) > 0 { | |||
keys := make([]string, 0, len(args)) | |||
for k := range args { | |||
keys = append(keys, k) | |||
} | |||
if sortAsc[0] { | |||
sort.Strings(keys) | |||
} else { | |||
sort.Sort(sort.Reverse(sort.StringSlice(keys))) | |||
} | |||
for _, k := range keys { | |||
str += "&" + k + "=" + args[k] | |||
} | |||
} else { | |||
for k, v := range args { | |||
str += "&" + k + "=" + v | |||
} | |||
} | |||
return str[1:] | |||
} | |||
func HttpBuild(body interface{}, sortAsc ...bool) string { | |||
params := map[string]string{} | |||
if args, ok := body.(map[string]interface{}); ok { | |||
for k, v := range args { | |||
params[k] = AnyToString(v) | |||
} | |||
return HttpBuildQuery(params, sortAsc...) | |||
} | |||
if args, ok := body.(map[string]string); ok { | |||
for k, v := range args { | |||
params[k] = AnyToString(v) | |||
} | |||
return HttpBuildQuery(params, sortAsc...) | |||
} | |||
if args, ok := body.(map[string]int); ok { | |||
for k, v := range args { | |||
params[k] = AnyToString(v) | |||
} | |||
return HttpBuildQuery(params, sortAsc...) | |||
} | |||
return AnyToString(body) | |||
} |
@@ -0,0 +1,22 @@ | |||
package egg_system_rules | |||
import ( | |||
"os" | |||
"path" | |||
"strings" | |||
"time" | |||
) | |||
// 获取文件后缀 | |||
func FileExt(fname string) string { | |||
return strings.ToLower(strings.TrimLeft(path.Ext(fname), ".")) | |||
} | |||
func FilePutContents(fileName string, content string) { | |||
fd, _ := os.OpenFile("./tmp/"+fileName+".logs", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644) | |||
fd_time := time.Now().Format("2006-01-02 15:04:05") | |||
fd_content := strings.Join([]string{"[", fd_time, "] ", content, "\n"}, "") | |||
buf := []byte(fd_content) | |||
fd.Write(buf) | |||
fd.Close() | |||
} |
@@ -0,0 +1,59 @@ | |||
package egg_system_rules | |||
import ( | |||
"math" | |||
) | |||
func CouponFormat(data string) string { | |||
switch data { | |||
case "0.00", "0", "": | |||
return "" | |||
default: | |||
return Int64ToStr(FloatToInt64(StrToFloat64(data))) | |||
} | |||
} | |||
func CommissionFormat(data string) string { | |||
if data != "" && data != "0" { | |||
return data | |||
} | |||
return "" | |||
} | |||
func HideString(src string, hLen int) string { | |||
str := []rune(src) | |||
if hLen == 0 { | |||
hLen = 4 | |||
} | |||
hideStr := "" | |||
for i := 0; i < hLen; i++ { | |||
hideStr += "*" | |||
} | |||
hideLen := len(str) / 2 | |||
showLen := len(str) - hideLen | |||
if hideLen == 0 || showLen == 0 { | |||
return hideStr | |||
} | |||
subLen := showLen / 2 | |||
if subLen == 0 { | |||
return string(str[:showLen]) + hideStr | |||
} | |||
s := string(str[:subLen]) | |||
s += hideStr | |||
s += string(str[len(str)-subLen:]) | |||
return s | |||
} | |||
// SaleCountFormat is 格式化销量 | |||
func SaleCountFormat(s string) string { | |||
return s + "已售" | |||
} | |||
// 小数格式化 | |||
func FloatFormat(f float64, i int) float64 { | |||
if i > 14 { | |||
return f | |||
} | |||
p := math.Pow10(i) | |||
return float64(int64((f+0.000000000000009)*p)) / p | |||
} |
@@ -0,0 +1,245 @@ | |||
package zhios_order_relate_logx | |||
import ( | |||
"os" | |||
"strings" | |||
"time" | |||
"go.uber.org/zap" | |||
"go.uber.org/zap/zapcore" | |||
) | |||
type LogConfig struct { | |||
AppName string `yaml:"app_name" json:"app_name" toml:"app_name"` | |||
Level string `yaml:"level" json:"level" toml:"level"` | |||
StacktraceLevel string `yaml:"stacktrace_level" json:"stacktrace_level" toml:"stacktrace_level"` | |||
IsStdOut bool `yaml:"is_stdout" json:"is_stdout" toml:"is_stdout"` | |||
TimeFormat string `yaml:"time_format" json:"time_format" toml:"time_format"` // second, milli, nano, standard, iso, | |||
Encoding string `yaml:"encoding" json:"encoding" toml:"encoding"` // console, json | |||
Skip int `yaml:"skip" json:"skip" toml:"skip"` | |||
IsFileOut bool `yaml:"is_file_out" json:"is_file_out" toml:"is_file_out"` | |||
FileDir string `yaml:"file_dir" json:"file_dir" toml:"file_dir"` | |||
FileName string `yaml:"file_name" json:"file_name" toml:"file_name"` | |||
FileMaxSize int `yaml:"file_max_size" json:"file_max_size" toml:"file_max_size"` | |||
FileMaxAge int `yaml:"file_max_age" json:"file_max_age" toml:"file_max_age"` | |||
} | |||
var ( | |||
l *LogX = defaultLogger() | |||
conf *LogConfig | |||
) | |||
// default logger setting | |||
func defaultLogger() *LogX { | |||
conf = &LogConfig{ | |||
Level: "debug", | |||
StacktraceLevel: "error", | |||
IsStdOut: true, | |||
TimeFormat: "standard", | |||
Encoding: "console", | |||
Skip: 2, | |||
} | |||
writers := []zapcore.WriteSyncer{os.Stdout} | |||
lg, lv := newZapLogger(setLogLevel(conf.Level), setLogLevel(conf.StacktraceLevel), conf.Encoding, conf.TimeFormat, conf.Skip, zapcore.NewMultiWriteSyncer(writers...)) | |||
zap.RedirectStdLog(lg) | |||
return &LogX{logger: lg, atomLevel: lv} | |||
} | |||
// initial standard log, if you don't init, it will use default logger setting | |||
func InitDefaultLogger(cfg *LogConfig) { | |||
var writers []zapcore.WriteSyncer | |||
if cfg.IsStdOut || (!cfg.IsStdOut && !cfg.IsFileOut) { | |||
writers = append(writers, os.Stdout) | |||
} | |||
if cfg.IsFileOut { | |||
writers = append(writers, NewRollingFile(cfg.FileDir, cfg.FileName, cfg.FileMaxSize, cfg.FileMaxAge)) | |||
} | |||
lg, lv := newZapLogger(setLogLevel(cfg.Level), setLogLevel(cfg.StacktraceLevel), cfg.Encoding, cfg.TimeFormat, cfg.Skip, zapcore.NewMultiWriteSyncer(writers...)) | |||
zap.RedirectStdLog(lg) | |||
if cfg.AppName != "" { | |||
lg = lg.With(zap.String("app", cfg.AppName)) // 加上应用名称 | |||
} | |||
l = &LogX{logger: lg, atomLevel: lv} | |||
} | |||
// create a new logger | |||
func NewLogger(cfg *LogConfig) *LogX { | |||
var writers []zapcore.WriteSyncer | |||
if cfg.IsStdOut || (!cfg.IsStdOut && !cfg.IsFileOut) { | |||
writers = append(writers, os.Stdout) | |||
} | |||
if cfg.IsFileOut { | |||
writers = append(writers, NewRollingFile(cfg.FileDir, cfg.FileName, cfg.FileMaxSize, cfg.FileMaxAge)) | |||
} | |||
lg, lv := newZapLogger(setLogLevel(cfg.Level), setLogLevel(cfg.StacktraceLevel), cfg.Encoding, cfg.TimeFormat, cfg.Skip, zapcore.NewMultiWriteSyncer(writers...)) | |||
zap.RedirectStdLog(lg) | |||
if cfg.AppName != "" { | |||
lg = lg.With(zap.String("app", cfg.AppName)) // 加上应用名称 | |||
} | |||
return &LogX{logger: lg, atomLevel: lv} | |||
} | |||
// create a new zaplog logger | |||
func newZapLogger(level, stacktrace zapcore.Level, encoding, timeType string, skip int, output zapcore.WriteSyncer) (*zap.Logger, *zap.AtomicLevel) { | |||
encCfg := zapcore.EncoderConfig{ | |||
TimeKey: "T", | |||
LevelKey: "L", | |||
NameKey: "N", | |||
CallerKey: "C", | |||
MessageKey: "M", | |||
StacktraceKey: "S", | |||
LineEnding: zapcore.DefaultLineEnding, | |||
EncodeCaller: zapcore.ShortCallerEncoder, | |||
EncodeDuration: zapcore.NanosDurationEncoder, | |||
EncodeLevel: zapcore.LowercaseLevelEncoder, | |||
} | |||
setTimeFormat(timeType, &encCfg) // set time type | |||
atmLvl := zap.NewAtomicLevel() // set level | |||
atmLvl.SetLevel(level) | |||
encoder := zapcore.NewJSONEncoder(encCfg) // 确定encoder格式 | |||
if encoding == "console" { | |||
encoder = zapcore.NewConsoleEncoder(encCfg) | |||
} | |||
return zap.New(zapcore.NewCore(encoder, output, atmLvl), zap.AddCaller(), zap.AddStacktrace(stacktrace), zap.AddCallerSkip(skip)), &atmLvl | |||
} | |||
// set log level | |||
func setLogLevel(lvl string) zapcore.Level { | |||
switch strings.ToLower(lvl) { | |||
case "panic": | |||
return zapcore.PanicLevel | |||
case "fatal": | |||
return zapcore.FatalLevel | |||
case "error": | |||
return zapcore.ErrorLevel | |||
case "warn", "warning": | |||
return zapcore.WarnLevel | |||
case "info": | |||
return zapcore.InfoLevel | |||
default: | |||
return zapcore.DebugLevel | |||
} | |||
} | |||
// set time format | |||
func setTimeFormat(timeType string, z *zapcore.EncoderConfig) { | |||
switch strings.ToLower(timeType) { | |||
case "iso": // iso8601 standard | |||
z.EncodeTime = zapcore.ISO8601TimeEncoder | |||
case "sec": // only for unix second, without millisecond | |||
z.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) { | |||
enc.AppendInt64(t.Unix()) | |||
} | |||
case "second": // unix second, with millisecond | |||
z.EncodeTime = zapcore.EpochTimeEncoder | |||
case "milli", "millisecond": // millisecond | |||
z.EncodeTime = zapcore.EpochMillisTimeEncoder | |||
case "nano", "nanosecond": // nanosecond | |||
z.EncodeTime = zapcore.EpochNanosTimeEncoder | |||
default: // standard format | |||
z.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) { | |||
enc.AppendString(t.Format("2006-01-02 15:04:05.000")) | |||
} | |||
} | |||
} | |||
func GetLevel() string { | |||
switch l.atomLevel.Level() { | |||
case zapcore.PanicLevel: | |||
return "panic" | |||
case zapcore.FatalLevel: | |||
return "fatal" | |||
case zapcore.ErrorLevel: | |||
return "error" | |||
case zapcore.WarnLevel: | |||
return "warn" | |||
case zapcore.InfoLevel: | |||
return "info" | |||
default: | |||
return "debug" | |||
} | |||
} | |||
func SetLevel(lvl string) { | |||
l.atomLevel.SetLevel(setLogLevel(lvl)) | |||
} | |||
// temporary add call skip | |||
func AddCallerSkip(skip int) *LogX { | |||
l.logger.WithOptions(zap.AddCallerSkip(skip)) | |||
return l | |||
} | |||
// permanent add call skip | |||
func AddDepth(skip int) *LogX { | |||
l.logger = l.logger.WithOptions(zap.AddCallerSkip(skip)) | |||
return l | |||
} | |||
// permanent add options | |||
func AddOptions(opts ...zap.Option) *LogX { | |||
l.logger = l.logger.WithOptions(opts...) | |||
return l | |||
} | |||
func AddField(k string, v interface{}) { | |||
l.logger.With(zap.Any(k, v)) | |||
} | |||
func AddFields(fields map[string]interface{}) *LogX { | |||
for k, v := range fields { | |||
l.logger.With(zap.Any(k, v)) | |||
} | |||
return l | |||
} | |||
// Normal log | |||
func Debug(e interface{}, args ...interface{}) error { | |||
return l.Debug(e, args...) | |||
} | |||
func Info(e interface{}, args ...interface{}) error { | |||
return l.Info(e, args...) | |||
} | |||
func Warn(e interface{}, args ...interface{}) error { | |||
return l.Warn(e, args...) | |||
} | |||
func Error(e interface{}, args ...interface{}) error { | |||
return l.Error(e, args...) | |||
} | |||
func Panic(e interface{}, args ...interface{}) error { | |||
return l.Panic(e, args...) | |||
} | |||
func Fatal(e interface{}, args ...interface{}) error { | |||
return l.Fatal(e, args...) | |||
} | |||
// Format logs | |||
func Debugf(format string, args ...interface{}) error { | |||
return l.Debugf(format, args...) | |||
} | |||
func Infof(format string, args ...interface{}) error { | |||
return l.Infof(format, args...) | |||
} | |||
func Warnf(format string, args ...interface{}) error { | |||
return l.Warnf(format, args...) | |||
} | |||
func Errorf(format string, args ...interface{}) error { | |||
return l.Errorf(format, args...) | |||
} | |||
func Panicf(format string, args ...interface{}) error { | |||
return l.Panicf(format, args...) | |||
} | |||
func Fatalf(format string, args ...interface{}) error { | |||
return l.Fatalf(format, args...) | |||
} | |||
func formatFieldMap(m FieldMap) []Field { | |||
var res []Field | |||
for k, v := range m { | |||
res = append(res, zap.Any(k, v)) | |||
} | |||
return res | |||
} |
@@ -0,0 +1,105 @@ | |||
package zhios_order_relate_logx | |||
import ( | |||
"bytes" | |||
"io" | |||
"os" | |||
"path/filepath" | |||
"time" | |||
"gopkg.in/natefinch/lumberjack.v2" | |||
) | |||
// output interface | |||
type WriteSyncer interface { | |||
io.Writer | |||
Sync() error | |||
} | |||
// split writer | |||
func NewRollingFile(dir, filename string, maxSize, MaxAge int) WriteSyncer { | |||
s, err := os.Stat(dir) | |||
if err != nil || !s.IsDir() { | |||
os.RemoveAll(dir) | |||
if err := os.MkdirAll(dir, 0766); err != nil { | |||
panic(err) | |||
} | |||
} | |||
return newLumberjackWriteSyncer(&lumberjack.Logger{ | |||
Filename: filepath.Join(dir, filename), | |||
MaxSize: maxSize, // megabytes, MB | |||
MaxAge: MaxAge, // days | |||
LocalTime: true, | |||
Compress: false, | |||
}) | |||
} | |||
type lumberjackWriteSyncer struct { | |||
*lumberjack.Logger | |||
buf *bytes.Buffer | |||
logChan chan []byte | |||
closeChan chan interface{} | |||
maxSize int | |||
} | |||
func newLumberjackWriteSyncer(l *lumberjack.Logger) *lumberjackWriteSyncer { | |||
ws := &lumberjackWriteSyncer{ | |||
Logger: l, | |||
buf: bytes.NewBuffer([]byte{}), | |||
logChan: make(chan []byte, 5000), | |||
closeChan: make(chan interface{}), | |||
maxSize: 1024, | |||
} | |||
go ws.run() | |||
return ws | |||
} | |||
func (l *lumberjackWriteSyncer) run() { | |||
ticker := time.NewTicker(1 * time.Second) | |||
for { | |||
select { | |||
case <-ticker.C: | |||
if l.buf.Len() > 0 { | |||
l.sync() | |||
} | |||
case bs := <-l.logChan: | |||
_, err := l.buf.Write(bs) | |||
if err != nil { | |||
continue | |||
} | |||
if l.buf.Len() > l.maxSize { | |||
l.sync() | |||
} | |||
case <-l.closeChan: | |||
l.sync() | |||
return | |||
} | |||
} | |||
} | |||
func (l *lumberjackWriteSyncer) Stop() { | |||
close(l.closeChan) | |||
} | |||
func (l *lumberjackWriteSyncer) Write(bs []byte) (int, error) { | |||
b := make([]byte, len(bs)) | |||
for i, c := range bs { | |||
b[i] = c | |||
} | |||
l.logChan <- b | |||
return 0, nil | |||
} | |||
func (l *lumberjackWriteSyncer) Sync() error { | |||
return nil | |||
} | |||
func (l *lumberjackWriteSyncer) sync() error { | |||
defer l.buf.Reset() | |||
_, err := l.Logger.Write(l.buf.Bytes()) | |||
if err != nil { | |||
return err | |||
} | |||
return nil | |||
} |
@@ -0,0 +1,192 @@ | |||
package zhios_order_relate_logx | |||
import ( | |||
"errors" | |||
"fmt" | |||
"strconv" | |||
"go.uber.org/zap" | |||
) | |||
type LogX struct { | |||
logger *zap.Logger | |||
atomLevel *zap.AtomicLevel | |||
} | |||
type Field = zap.Field | |||
type FieldMap map[string]interface{} | |||
// 判断其他类型--start | |||
func getFields(msg string, format bool, args ...interface{}) (string, []Field) { | |||
var str []interface{} | |||
var fields []zap.Field | |||
if len(args) > 0 { | |||
for _, v := range args { | |||
if f, ok := v.(Field); ok { | |||
fields = append(fields, f) | |||
} else if f, ok := v.(FieldMap); ok { | |||
fields = append(fields, formatFieldMap(f)...) | |||
} else { | |||
str = append(str, AnyToString(v)) | |||
} | |||
} | |||
if format { | |||
return fmt.Sprintf(msg, str...), fields | |||
} | |||
str = append([]interface{}{msg}, str...) | |||
return fmt.Sprintln(str...), fields | |||
} | |||
return msg, []Field{} | |||
} | |||
func (l *LogX) Debug(s interface{}, args ...interface{}) error { | |||
es, e := checkErr(s) | |||
if es != "" { | |||
msg, field := getFields(es, false, args...) | |||
l.logger.Debug(msg, field...) | |||
} | |||
return e | |||
} | |||
func (l *LogX) Info(s interface{}, args ...interface{}) error { | |||
es, e := checkErr(s) | |||
if es != "" { | |||
msg, field := getFields(es, false, args...) | |||
l.logger.Info(msg, field...) | |||
} | |||
return e | |||
} | |||
func (l *LogX) Warn(s interface{}, args ...interface{}) error { | |||
es, e := checkErr(s) | |||
if es != "" { | |||
msg, field := getFields(es, false, args...) | |||
l.logger.Warn(msg, field...) | |||
} | |||
return e | |||
} | |||
func (l *LogX) Error(s interface{}, args ...interface{}) error { | |||
es, e := checkErr(s) | |||
if es != "" { | |||
msg, field := getFields(es, false, args...) | |||
l.logger.Error(msg, field...) | |||
} | |||
return e | |||
} | |||
func (l *LogX) DPanic(s interface{}, args ...interface{}) error { | |||
es, e := checkErr(s) | |||
if es != "" { | |||
msg, field := getFields(es, false, args...) | |||
l.logger.DPanic(msg, field...) | |||
} | |||
return e | |||
} | |||
func (l *LogX) Panic(s interface{}, args ...interface{}) error { | |||
es, e := checkErr(s) | |||
if es != "" { | |||
msg, field := getFields(es, false, args...) | |||
l.logger.Panic(msg, field...) | |||
} | |||
return e | |||
} | |||
func (l *LogX) Fatal(s interface{}, args ...interface{}) error { | |||
es, e := checkErr(s) | |||
if es != "" { | |||
msg, field := getFields(es, false, args...) | |||
l.logger.Fatal(msg, field...) | |||
} | |||
return e | |||
} | |||
func checkErr(s interface{}) (string, error) { | |||
switch e := s.(type) { | |||
case error: | |||
return e.Error(), e | |||
case string: | |||
return e, errors.New(e) | |||
case []byte: | |||
return string(e), nil | |||
default: | |||
return "", nil | |||
} | |||
} | |||
func (l *LogX) LogError(err error) error { | |||
return l.Error(err.Error()) | |||
} | |||
func (l *LogX) Debugf(msg string, args ...interface{}) error { | |||
s, f := getFields(msg, true, args...) | |||
l.logger.Debug(s, f...) | |||
return errors.New(s) | |||
} | |||
func (l *LogX) Infof(msg string, args ...interface{}) error { | |||
s, f := getFields(msg, true, args...) | |||
l.logger.Info(s, f...) | |||
return errors.New(s) | |||
} | |||
func (l *LogX) Warnf(msg string, args ...interface{}) error { | |||
s, f := getFields(msg, true, args...) | |||
l.logger.Warn(s, f...) | |||
return errors.New(s) | |||
} | |||
func (l *LogX) Errorf(msg string, args ...interface{}) error { | |||
s, f := getFields(msg, true, args...) | |||
l.logger.Error(s, f...) | |||
return errors.New(s) | |||
} | |||
func (l *LogX) DPanicf(msg string, args ...interface{}) error { | |||
s, f := getFields(msg, true, args...) | |||
l.logger.DPanic(s, f...) | |||
return errors.New(s) | |||
} | |||
func (l *LogX) Panicf(msg string, args ...interface{}) error { | |||
s, f := getFields(msg, true, args...) | |||
l.logger.Panic(s, f...) | |||
return errors.New(s) | |||
} | |||
func (l *LogX) Fatalf(msg string, args ...interface{}) error { | |||
s, f := getFields(msg, true, args...) | |||
l.logger.Fatal(s, f...) | |||
return errors.New(s) | |||
} | |||
func AnyToString(raw interface{}) string { | |||
switch i := raw.(type) { | |||
case []byte: | |||
return string(i) | |||
case int: | |||
return strconv.FormatInt(int64(i), 10) | |||
case int64: | |||
return strconv.FormatInt(i, 10) | |||
case float32: | |||
return strconv.FormatFloat(float64(i), 'f', 2, 64) | |||
case float64: | |||
return strconv.FormatFloat(i, 'f', 2, 64) | |||
case uint: | |||
return strconv.FormatInt(int64(i), 10) | |||
case uint8: | |||
return strconv.FormatInt(int64(i), 10) | |||
case uint16: | |||
return strconv.FormatInt(int64(i), 10) | |||
case uint32: | |||
return strconv.FormatInt(int64(i), 10) | |||
case uint64: | |||
return strconv.FormatInt(int64(i), 10) | |||
case int8: | |||
return strconv.FormatInt(int64(i), 10) | |||
case int16: | |||
return strconv.FormatInt(int64(i), 10) | |||
case int32: | |||
return strconv.FormatInt(int64(i), 10) | |||
case string: | |||
return i | |||
case error: | |||
return i.Error() | |||
} | |||
return fmt.Sprintf("%#v", raw) | |||
} |
@@ -0,0 +1,23 @@ | |||
package egg_system_rules | |||
import ( | |||
"encoding/json" | |||
) | |||
func Serialize(data interface{}) []byte { | |||
res, err := json.Marshal(data) | |||
if err != nil { | |||
return []byte{} | |||
} | |||
return res | |||
} | |||
func Unserialize(b []byte, dst interface{}) { | |||
if err := json.Unmarshal(b, dst); err != nil { | |||
dst = nil | |||
} | |||
} | |||
func SerializeStr(data interface{}, arg ...interface{}) string { | |||
return string(Serialize(data)) | |||
} |
@@ -0,0 +1,203 @@ | |||
package egg_system_rules | |||
import ( | |||
"fmt" | |||
"github.com/syyongx/php2go" | |||
"math/rand" | |||
"reflect" | |||
"sort" | |||
"strings" | |||
"time" | |||
) | |||
func Implode(glue string, args ...interface{}) string { | |||
data := make([]string, len(args)) | |||
for i, s := range args { | |||
data[i] = fmt.Sprint(s) | |||
} | |||
return strings.Join(data, glue) | |||
} | |||
// 字符串是否在数组里 | |||
func InArr(target string, str_array []string) bool { | |||
for _, element := range str_array { | |||
if target == element { | |||
return true | |||
} | |||
} | |||
return false | |||
} | |||
func InArrToInt(target int, str_array []int) bool { | |||
for _, element := range str_array { | |||
if target == element { | |||
return true | |||
} | |||
} | |||
return false | |||
} | |||
// 把数组的值放到key里 | |||
func ArrayColumn(array interface{}, key string) (result map[string]interface{}, err error) { | |||
result = make(map[string]interface{}) | |||
t := reflect.TypeOf(array) | |||
v := reflect.ValueOf(array) | |||
if t.Kind() != reflect.Slice { | |||
return nil, nil | |||
} | |||
if v.Len() == 0 { | |||
return nil, nil | |||
} | |||
for i := 0; i < v.Len(); i++ { | |||
indexv := v.Index(i) | |||
if indexv.Type().Kind() != reflect.Struct { | |||
return nil, nil | |||
} | |||
mapKeyInterface := indexv.FieldByName(key) | |||
if mapKeyInterface.Kind() == reflect.Invalid { | |||
return nil, nil | |||
} | |||
mapKeyString, err := InterfaceToString(mapKeyInterface.Interface()) | |||
if err != nil { | |||
return nil, err | |||
} | |||
result[mapKeyString] = indexv.Interface() | |||
} | |||
return result, err | |||
} | |||
// 转string | |||
func InterfaceToString(v interface{}) (result string, err error) { | |||
switch reflect.TypeOf(v).Kind() { | |||
case reflect.Int64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32: | |||
result = fmt.Sprintf("%v", v) | |||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | |||
result = fmt.Sprintf("%v", v) | |||
case reflect.String: | |||
result = v.(string) | |||
default: | |||
err = nil | |||
} | |||
return result, err | |||
} | |||
func HideTrueName(name string) string { | |||
res := "**" | |||
if name != "" { | |||
runs := []rune(name) | |||
leng := len(runs) | |||
if leng <= 3 { | |||
res = string(runs[0:1]) + res | |||
} else if leng < 5 { | |||
res = string(runs[0:2]) + res | |||
} else if leng < 10 { | |||
res = string(runs[0:2]) + "***" + string(runs[leng-2:leng]) | |||
} else if leng < 16 { | |||
res = string(runs[0:3]) + "****" + string(runs[leng-3:leng]) | |||
} else { | |||
res = string(runs[0:4]) + "*****" + string(runs[leng-4:leng]) | |||
} | |||
} | |||
return res | |||
} | |||
func GetQueryParam(uri string) map[string]string { | |||
//根据问号分割路由还是query参数 | |||
uriList := strings.Split(uri, "?") | |||
var query = make(map[string]string, 0) | |||
//有参数才处理 | |||
if len(uriList) == 2 { | |||
//分割query参数 | |||
var queryList = strings.Split(uriList[1], "&") | |||
if len(queryList) > 0 { | |||
//key value 分别赋值 | |||
for _, v := range queryList { | |||
var valueList = strings.Split(v, "=") | |||
if len(valueList) == 2 { | |||
value, _ := php2go.URLDecode(valueList[1]) | |||
if value == "" { | |||
value = valueList[1] | |||
} | |||
query[valueList[0]] = value | |||
} | |||
} | |||
} | |||
} | |||
return query | |||
} | |||
// JoinStringsInASCII 按照规则,参数名ASCII码从小到大排序后拼接 | |||
// data 待拼接的数据 | |||
// sep 连接符 | |||
// onlyValues 是否只包含参数值,true则不包含参数名,否则参数名和参数值均有 | |||
// includeEmpty 是否包含空值,true则包含空值,否则不包含,注意此参数不影响参数名的存在 | |||
// exceptKeys 被排除的参数名,不参与排序及拼接 | |||
func JoinStringsInASCII(data map[string]string, sep string, onlyValues, includeEmpty bool, exceptKeys ...string) string { | |||
var list []string | |||
var keyList []string | |||
m := make(map[string]int) | |||
if len(exceptKeys) > 0 { | |||
for _, except := range exceptKeys { | |||
m[except] = 1 | |||
} | |||
} | |||
for k := range data { | |||
if _, ok := m[k]; ok { | |||
continue | |||
} | |||
value := data[k] | |||
if !includeEmpty && value == "" { | |||
continue | |||
} | |||
if onlyValues { | |||
keyList = append(keyList, k) | |||
} else { | |||
list = append(list, fmt.Sprintf("%s=%s", k, value)) | |||
} | |||
} | |||
if onlyValues { | |||
sort.Strings(keyList) | |||
for _, v := range keyList { | |||
list = append(list, AnyToString(data[v])) | |||
} | |||
} else { | |||
sort.Strings(list) | |||
} | |||
return strings.Join(list, sep) | |||
} | |||
// x的y次方 | |||
func RandPow(l int) string { | |||
var i = "1" | |||
for j := 0; j < l; j++ { | |||
i += "0" | |||
} | |||
k := StrToInt64(i) | |||
n := rand.New(rand.NewSource(time.Now().UnixNano())).Int63n(k) | |||
ls := "%0" + IntToStr(l) + "v" | |||
str := fmt.Sprintf(ls, n) | |||
//min := int(math.Pow10(l - 1)) | |||
//max := int(math.Pow10(l) - 1) | |||
return str | |||
} | |||
// 根据显示长度截取字符串 | |||
func ShowSubstr(s string, l int) string { | |||
if len(s) <= l { | |||
return s | |||
} | |||
ss, sl, rl, rs := "", 0, 0, []rune(s) | |||
for _, r := range rs { | |||
rint := int(r) | |||
if rint < 128 { | |||
rl = 1 | |||
} else { | |||
rl = 2 | |||
} | |||
if sl+rl > l { | |||
break | |||
} | |||
sl += rl | |||
ss += string(r) | |||
} | |||
return ss | |||
} |
@@ -0,0 +1,295 @@ | |||
package egg_system_rules | |||
import ( | |||
"errors" | |||
"fmt" | |||
"strconv" | |||
"strings" | |||
"time" | |||
) | |||
func StrToTime(s string) (int64, error) { | |||
// delete all not int characters | |||
if s == "" { | |||
return time.Now().Unix(), nil | |||
} | |||
r := make([]rune, 14) | |||
l := 0 | |||
// 过滤除数字以外的字符 | |||
for _, v := range s { | |||
if '0' <= v && v <= '9' { | |||
r[l] = v | |||
l++ | |||
if l == 14 { | |||
break | |||
} | |||
} | |||
} | |||
for l < 14 { | |||
r[l] = '0' // 补0 | |||
l++ | |||
} | |||
t, err := time.Parse("20060102150405", string(r)) | |||
if err != nil { | |||
return 0, err | |||
} | |||
return t.Unix(), nil | |||
} | |||
func String2TimeV2(timeStr string) time.Time { | |||
toTime, err := time.ParseInLocation("2006-01-02", timeStr, time.Local) | |||
if err != nil { | |||
return time.Now() | |||
} | |||
return toTime | |||
} | |||
func StringToTime(timeStr string) (time.Time, error) { | |||
toTime, err := time.ParseInLocation("2006-01-02 15:04:05", timeStr, time.Local) | |||
return toTime, err | |||
} | |||
func TimeToStr(unixSecTime interface{}, layout ...string) string { | |||
i := AnyToInt64(unixSecTime) | |||
if i == 0 { | |||
return "" | |||
} | |||
f := "2006-01-02 15:04:05" | |||
if len(layout) > 0 { | |||
f = layout[0] | |||
} | |||
return time.Unix(i, 0).Format(f) | |||
} | |||
func FormatNanoUnix() string { | |||
return strings.Replace(time.Now().Format("20060102150405.0000000"), ".", "", 1) | |||
} | |||
func TimeParse(format, src string) (time.Time, error) { | |||
return time.ParseInLocation(format, src, time.Local) | |||
} | |||
func TimeParseStd(src string) time.Time { | |||
t, _ := TimeParse("2006-01-02 15:04:05", src) | |||
return t | |||
} | |||
func TimeStdParseUnix(src string) int64 { | |||
t, err := TimeParse("2006-01-02 15:04:05", src) | |||
if err != nil { | |||
return 0 | |||
} | |||
return t.Unix() | |||
} | |||
func TimeStdParseUnixDate(src string) int64 { | |||
t, err := TimeParse("2006-01-02", src) | |||
if err != nil { | |||
return 0 | |||
} | |||
return t.Unix() | |||
} | |||
// 获取一个当前时间 时间间隔 时间戳 | |||
func GetTimeInterval(unit string, amount int) (startTime, endTime int64) { | |||
t := time.Now() | |||
nowTime := t.Unix() | |||
tmpTime := int64(0) | |||
switch unit { | |||
case "years": | |||
tmpTime = time.Date(t.Year()+amount, t.Month(), t.Day(), t.Hour(), 0, 0, 0, t.Location()).Unix() | |||
case "months": | |||
tmpTime = time.Date(t.Year(), t.Month()+time.Month(amount), t.Day(), t.Hour(), 0, 0, 0, t.Location()).Unix() | |||
case "days": | |||
tmpTime = time.Date(t.Year(), t.Month(), t.Day()+amount, t.Hour(), 0, 0, 0, t.Location()).Unix() | |||
case "hours": | |||
tmpTime = time.Date(t.Year(), t.Month(), t.Day(), t.Hour()+amount, 0, 0, 0, t.Location()).Unix() | |||
} | |||
if amount > 0 { | |||
startTime = nowTime | |||
endTime = tmpTime | |||
} else { | |||
startTime = tmpTime | |||
endTime = nowTime | |||
} | |||
return | |||
} | |||
// 几天前 | |||
func TimeInterval(newTime int) string { | |||
now := time.Now().Unix() | |||
newTime64 := AnyToInt64(newTime) | |||
if newTime64 >= now { | |||
return "刚刚" | |||
} | |||
interval := now - newTime64 | |||
switch { | |||
case interval < 60: | |||
return AnyToString(interval) + "秒前" | |||
case interval < 60*60: | |||
return AnyToString(interval/60) + "分前" | |||
case interval < 60*60*24: | |||
return AnyToString(interval/60/60) + "小时前" | |||
case interval < 60*60*24*30: | |||
return AnyToString(interval/60/60/24) + "天前" | |||
case interval < 60*60*24*30*12: | |||
return AnyToString(interval/60/60/24/30) + "月前" | |||
default: | |||
return AnyToString(interval/60/60/24/30/12) + "年前" | |||
} | |||
} | |||
// 时分秒字符串转时间戳,传入示例:8:40 or 8:40:10 | |||
func HmsToUnix(str string) (int64, error) { | |||
t := time.Now() | |||
arr := strings.Split(str, ":") | |||
if len(arr) < 3 { | |||
return 0, errors.New("Time format error") | |||
} | |||
h, _ := strconv.Atoi(arr[0]) | |||
m, _ := strconv.Atoi(arr[1]) | |||
s := 0 | |||
if len(arr) == 3 { | |||
s, _ = strconv.Atoi(arr[2]) | |||
} | |||
formatted1 := fmt.Sprintf("%d%02d%02d%02d%02d%02d", t.Year(), t.Month(), t.Day(), h, m, s) | |||
res, err := time.ParseInLocation("20060102150405", formatted1, time.Local) | |||
if err != nil { | |||
return 0, err | |||
} else { | |||
return res.Unix(), nil | |||
} | |||
} | |||
// 获取特定时间范围 | |||
func GetTimeRange(s string) map[string]int64 { | |||
t := time.Now() | |||
var stime, etime time.Time | |||
switch s { | |||
case "today": | |||
stime = time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location()) | |||
etime = time.Date(t.Year(), t.Month(), t.Day()+1, 0, 0, 0, 0, t.Location()) | |||
case "yesterday": | |||
stime = time.Date(t.Year(), t.Month(), t.Day()-1, 0, 0, 0, 0, t.Location()) | |||
etime = time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location()) | |||
case "within_seven_days": | |||
// 前6天0点 | |||
stime = time.Date(t.Year(), t.Month(), t.Day()-6, 0, 0, 0, 0, t.Location()) | |||
// 明天 0点 | |||
etime = time.Date(t.Year(), t.Month(), t.Day()+1, 0, 0, 0, 0, t.Location()) | |||
case "current_month": | |||
stime = time.Date(t.Year(), t.Month(), 0, 0, 0, 0, 0, t.Location()) | |||
etime = time.Date(t.Year(), t.Month()+1, 0, 0, 0, 0, 0, t.Location()) | |||
case "last_month": | |||
stime = time.Date(t.Year(), t.Month()-1, 0, 0, 0, 0, 0, t.Location()) | |||
etime = time.Date(t.Year(), t.Month(), 0, 0, 0, 0, 0, t.Location()) | |||
} | |||
return map[string]int64{ | |||
"start": stime.Unix(), | |||
"end": etime.Unix(), | |||
} | |||
} | |||
// 获取特定时间范围 | |||
func GetTimes(s string) map[string]string { | |||
t := time.Now() | |||
var stime, etime time.Time | |||
switch s { | |||
case "today": | |||
stime = time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location()) | |||
etime = time.Date(t.Year(), t.Month(), t.Day()+1, 0, 0, 0, 0, t.Location()) | |||
case "yesterday": | |||
stime = time.Date(t.Year(), t.Month(), t.Day()-1, 0, 0, 0, 0, t.Location()) | |||
etime = time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location()) | |||
case "within_seven_days": | |||
// 前6天0点 | |||
stime = time.Date(t.Year(), t.Month(), t.Day()-6, 0, 0, 0, 0, t.Location()) | |||
// 明天 0点 | |||
etime = time.Date(t.Year(), t.Month(), t.Day()+1, 0, 0, 0, 0, t.Location()) | |||
case "current_month": | |||
stime = time.Date(t.Year(), t.Month(), 0, 0, 0, 0, 0, t.Location()) | |||
etime = time.Date(t.Year(), t.Month()+1, 0, 0, 0, 0, 0, t.Location()) | |||
case "last_month": | |||
stime = time.Date(t.Year(), t.Month()-1, 0, 0, 0, 0, 0, t.Location()) | |||
etime = time.Date(t.Year(), t.Month(), 0, 0, 0, 0, 0, t.Location()) | |||
} | |||
return map[string]string{ | |||
"start": stime.Format("2006-01-02 15:04:05"), | |||
"end": etime.Format("2006-01-02 15:04:05"), | |||
} | |||
} | |||
// 获取传入的时间所在月份的第一天,即某月第一天的0点。如传入time.Now(), 返回当前月份的第一天0点时间。 | |||
func GetFirstDateOfMonth(d time.Time) time.Time { | |||
d = d.AddDate(0, 0, -d.Day()+1) | |||
return GetZeroTime(d) | |||
} | |||
// 获取传入的时间所在月份的最后一天,即某月最后一天的0点。如传入time.Now(), 返回当前月份的最后一天0点时间。 | |||
func GetLastDateOfMonth(d time.Time) time.Time { | |||
return GetFirstDateOfMonth(d).AddDate(0, 1, -1) | |||
} | |||
func GetAnyFirstDateOfMonth(d time.Time, monthDiff int) time.Time { | |||
year, month, _ := d.Date() | |||
thisMonth := time.Date(year, month, 1, 0, 0, 0, 0, time.Local) | |||
monthOneDay := thisMonth.AddDate(0, monthDiff, 0) | |||
return monthOneDay | |||
} | |||
// 当天时间戳 | |||
func GetDateTime(date string) (int64, int64) { | |||
//获取当前时区 | |||
loc, _ := time.LoadLocation("Local") | |||
//日期当天0点时间戳(拼接字符串) | |||
startDate := date + "_00:00:00" | |||
startTime, _ := time.ParseInLocation("2006-01-02_15:04:05", startDate, loc) | |||
//日期当天23时59分时间戳 | |||
endDate := date + "_23:59:59" | |||
end, _ := time.ParseInLocation("2006-01-02_15:04:05", endDate, loc) | |||
//返回当天0点和23点59分的时间戳 | |||
return startTime.Unix(), end.Unix() | |||
} | |||
// 获取某一天的0点时间 | |||
func GetZeroTime(d time.Time) time.Time { | |||
return time.Date(d.Year(), d.Month(), d.Day(), 0, 0, 0, 0, d.Location()) | |||
} | |||
// getYearMonthToDay 查询指定年份指定月份有多少天 | |||
// @params year int 指定年份 | |||
// @params month int 指定月份 | |||
func GetYearMonthToDay(year int, month int) int { | |||
// 有31天的月份 | |||
day31 := map[int]bool{ | |||
1: true, | |||
3: true, | |||
5: true, | |||
7: true, | |||
8: true, | |||
10: true, | |||
12: true, | |||
} | |||
if day31[month] == true { | |||
return 31 | |||
} | |||
// 有30天的月份 | |||
day30 := map[int]bool{ | |||
4: true, | |||
6: true, | |||
9: true, | |||
11: true, | |||
} | |||
if day30[month] == true { | |||
return 30 | |||
} | |||
// 计算是平年还是闰年 | |||
if (year%4 == 0 && year%100 != 0) || year%400 == 0 { | |||
// 得出2月的天数 | |||
return 29 | |||
} | |||
// 得出2月的天数 | |||
return 28 | |||
} |
@@ -0,0 +1,29 @@ | |||
package egg_system_rules | |||
import "time" | |||
func Time2String(date time.Time, format string) string { | |||
if format == "" { | |||
format = "2006-01-02 15:04:05" | |||
} | |||
timeS := date.Format(format) | |||
if timeS == "0001-01-01 00:00:00" { | |||
return "" | |||
} | |||
return timeS | |||
} | |||
func String2Time(timeStr string) time.Time { | |||
toTime, err := time.ParseInLocation("2006-01-02 15:04:05", timeStr, time.Local) | |||
if err != nil { | |||
return time.Now() | |||
} | |||
return toTime | |||
} | |||
// GetDiffDays 获取两个时间相差的天数,0表同一天,正数表t1>t2,负数表t1<t2 | |||
func GetDiffDays(t1, t2 time.Time) int { | |||
t1 = time.Date(t1.Year(), t1.Month(), t1.Day(), 0, 0, 0, 0, time.Local) | |||
t2 = time.Date(t2.Year(), t2.Month(), t2.Day(), 0, 0, 0, 0, time.Local) | |||
return int(t1.Sub(t2).Hours() / 24) | |||
} |
@@ -0,0 +1,38 @@ | |||
package egg_system_rules | |||
import ( | |||
"math/rand" | |||
"time" | |||
) | |||
const ( | |||
KC_RAND_KIND_NUM = 0 // 纯数字 | |||
KC_RAND_KIND_LOWER = 1 // 小写字母 | |||
KC_RAND_KIND_UPPER = 2 // 大写字母 | |||
KC_RAND_KIND_ALL = 3 // 数字、大小写字母 | |||
) | |||
// OrderUUID is only num for uuid | |||
func OrderUUID(uid int) string { | |||
ustr := IntToStr(uid) | |||
tstr := Int64ToStr(time.Now().Unix()) | |||
ulen := len(ustr) | |||
tlen := len(tstr) | |||
rlen := 18 - ulen - tlen | |||
krb := Krand(rlen, KC_RAND_KIND_NUM) | |||
return ustr + tstr + string(krb) | |||
} | |||
func Krand(size int, kind int) []byte { | |||
ikind, kinds, result := kind, [][]int{[]int{10, 48}, []int{26, 97}, []int{26, 65}}, make([]byte, size) | |||
isAll := kind > 2 || kind < 0 | |||
rand.Seed(time.Now().UnixNano()) | |||
for i := 0; i < size; i++ { | |||
if isAll { // random ikind | |||
ikind = rand.Intn(3) | |||
} | |||
scope, base := kinds[ikind][0], kinds[ikind][1] | |||
result[i] = uint8(base + rand.Intn(scope)) | |||
} | |||
return result | |||
} |