Initial commit

This commit is contained in:
Donny
2019-04-22 20:46:32 +08:00
commit 49ab8aadd1
25441 changed files with 4055000 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/interface/main/up-rating/cmd:all-srcs",
"//app/interface/main/up-rating/conf:all-srcs",
"//app/interface/main/up-rating/dao:all-srcs",
"//app/interface/main/up-rating/http:all-srcs",
"//app/interface/main/up-rating/model:all-srcs",
"//app/interface/main/up-rating/service:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,4 @@
#### up-rating-interface
##### Version 0.0.1
> 1. 初始化up-rating-interface

View File

@@ -0,0 +1,8 @@
# Owner
gaopeng
# Author
gaopeng,shaozhenyu
# Reviewer
all

View File

@@ -0,0 +1,13 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- gaopeng
- gaopeng,shaozhenyu
labels:
- interface
- interface/main/up-rating
- main
options:
no_parent_owners: true
reviewers:
- gaopeng,shaozhenyu

View File

@@ -0,0 +1,10 @@
#### up-rating-interface
##### 项目简介
> up-rating-interface up主等级体系
##### 编译环境
> 请只用golang v1.8.x以上版本编译执行
##### 依赖包
> 1.公共包go-common

View File

@@ -0,0 +1,42 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
)
go_binary(
name = "cmd",
embed = [":go_default_library"],
tags = ["automanaged"],
)
go_library(
name = "go_default_library",
srcs = ["main.go"],
data = ["up-rating-interface.toml"],
importpath = "go-common/app/interface/main/up-rating/cmd",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/up-rating/conf:go_default_library",
"//app/interface/main/up-rating/http:go_default_library",
"//library/log:go_default_library",
"//library/net/trace:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,43 @@
package main
import (
"flag"
"os"
"os/signal"
"syscall"
"go-common/app/interface/main/up-rating/conf"
"go-common/app/interface/main/up-rating/http"
"go-common/library/log"
"go-common/library/net/trace"
)
func main() {
flag.Parse()
// init conf,log,trace,stat,perf
if err := conf.Init(); err != nil {
panic(err)
}
log.Init(conf.Conf.Log)
defer log.Close()
trace.Init(conf.Conf.Tracer)
defer trace.Close()
http.Init(conf.Conf)
log.Info("up-rating-interface start")
// signal handler
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
s := <-c
log.Info("up-rating-interface get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGSTOP, syscall.SIGINT:
log.Info("up-rating-interface exit")
return
case syscall.SIGHUP:
// TODO reload
default:
return
}
}
}

View File

@@ -0,0 +1,111 @@
# This is a TOML document. Boom.
version = "1.0.0"
user = "nobody"
pid = "/tmp/up-rating-interface.pid"
dir = "./"
perf = "0.0.0.0:7422"
checkFile = "/data/www/up-rating-interface.html"
family = "up-rating-interface"
address = ""
[bm]
addr = "0.0.0.0:7420"
maxListen = 1000
timeout = "1s"
[log]
dir = "/data/log/up-rating-interface/"
stdout = true
[db]
[db.main]
dsn = "rating:OruSYjDPiZRnsNH860Jl1MEXVgofb9kW@tcp(172.16.33.205:3308)/bilibili_up_rating?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 5
idle = 5
idleTimeout ="4h"
queryTimeout = "5s"
execTimeout = "5s"
tranTimeout = "10s"
[db.main.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[db.slave]
dsn = "rating_reader:tTzLBEk2WRnjKdCuIcbx8XpDr7sy0NH5@tcp(172.16.33.205:3308)/bilibili_up_rating?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 5
idle = 5
idleTimeout = "4h"
queryTimeout = "5s"
execTimeout = "5s"
tranTimeout = "10s"
[db.slave.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[multiHTTP]
[multiHTTP.inner]
addrs = ["0.0.0.0:7420"]
maxListen = 10
[multiHTTP.local]
addrs = ["0.0.0.0:7421"]
maxListen = 10
[app]
key = "345b38393c90f093"
secret = "598c2f3e826f36f6feb9c4f671e39adf"
[identify]
whiteAccessKey = "a2a1eb0ac97d6ba08b85aa0151528f34"
whiteMid = 23675773
csrf = true
[identify.app]
key = "7c7ac0db1aa05587"
secret = "9a6d62d93290c5f771ad381e9ca23f26"
[identify.memcache]
name = "go-business/identify"
proto = "unix"
addr = "/tmp/shd-platform-identify-web-mc.sock"
active = 1024
idle = 64
dialTimeout = "50ms"
readTimeout = "90ms"
writeTimeout = "80ms"
idleTimeout = "80s"
[identify.host]
auth = "http://passport.bilibili.co"
secret = "http://open.bilibili.co"
[identify.httpClient]
key = "7c7ac0db1aa05587"
secret = "9a6d62d93290c5f771ad381e9ca23f26"
dial = "50ms"
timeout = "100ms"
keepAlive = "60s"
[identify.httpClient.breaker]
window = "10s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[identify.httpClient.url]
"http://passport.bilibili.co/intranet/auth/tokenInfo" = {timeout = "100ms"}
"http://passport.bilibili.co/intranet/auth/cookieInfo" = {timeout = "100ms"}
"http://open.bilibili.co/api/getsecret" = {timeout = "500ms"}
[redis]
name = "up-rating-interface"
proto = "tcp"
addr = "10.23.103.180:6379"
idle = 10
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "1m"
upRatingExpire = "5m"

View File

@@ -0,0 +1,38 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["conf.go"],
importpath = "go-common/app/interface/main/up-rating/conf",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/cache/redis:go_default_library",
"//library/conf:go_default_library",
"//library/database/sql:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/trace:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/BurntSushi/toml:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,124 @@
package conf
import (
"errors"
"flag"
"go-common/library/cache/redis"
"go-common/library/conf"
"go-common/library/database/sql"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/trace"
"go-common/library/time"
"github.com/BurntSushi/toml"
)
var (
// ConfPath local config path
ConfPath string
// Conf config
Conf = &Config{}
client *conf.Client
)
// Config str
type Config struct {
// base
// channal len
ChanSize int64
// log
Log *log.Config
// http
BM *bm.ServerConfig
// identify
App *bm.App
// tracer
Tracer *trace.Config
// tick load pgc
Tick time.Duration
// orm
DB *DB
// http client of search
HTTPClient *HTTPClient
// host
Host *Host
// redis
Redis *Redis
}
// DB def db struct
type DB struct {
Main *sql.Config
Slave *sql.Config
}
// Redis .
type Redis struct {
*redis.Config
UpRatingExpire time.Duration
}
// HTTPClient http client
type HTTPClient struct {
Read *bm.ClientConfig
}
// Host http host
type Host struct {
AccountURI string
ArchiveURI string
UperURI string
}
func init() {
flag.StringVar(&ConfPath, "conf", "", "default config path")
}
// Init init conf
func Init() (err error) {
if ConfPath != "" {
return local()
}
return remote()
}
func local() (err error) {
_, err = toml.DecodeFile(ConfPath, &Conf)
return
}
func remote() (err error) {
if client, err = conf.New(); err != nil {
return
}
if err = load(); err != nil {
return
}
go func() {
for range client.Event() {
log.Info("config reload")
if load() != nil {
log.Error("config reload error (%v)", err)
}
}
}()
return
}
func load() (err error) {
var (
s string
ok bool
tmpConf *Config
)
if s, ok = client.Toml2(); !ok {
return errors.New("load config center error")
}
if _, err = toml.Decode(s, &tmpConf); err != nil {
return errors.New("could not decode config")
}
*Conf = *tmpConf
return
}

View File

@@ -0,0 +1,57 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"dao_test.go",
"rating_test.go",
"redis_test.go",
],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//app/interface/main/up-rating/conf:go_default_library",
"//app/interface/main/up-rating/model:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"rating.go",
"redis.go",
],
importpath = "go-common/app/interface/main/up-rating/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/up-rating/conf:go_default_library",
"//app/interface/main/up-rating/model:go_default_library",
"//library/cache/redis:go_default_library",
"//library/database/sql:go_default_library",
"//library/log:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,56 @@
package dao
import (
"context"
"time"
"go-common/app/interface/main/up-rating/conf"
"go-common/library/cache/redis"
"go-common/library/database/sql"
"go-common/library/log"
)
// Dao def dao struct
type Dao struct {
c *conf.Config
db *sql.DB
rddb *sql.DB
redis *redis.Pool
upRatingExpire int64
}
// New fn
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
db: sql.NewMySQL(c.DB.Main),
rddb: sql.NewMySQL(c.DB.Slave),
redis: redis.NewPool(c.Redis.Config),
upRatingExpire: int64(time.Duration(c.Redis.UpRatingExpire) / time.Second),
}
return d
}
// Ping ping db
func (d *Dao) Ping(c context.Context) (err error) {
if err = d.db.Ping(c); err != nil {
log.Error("d.db.Ping error(%v)", err)
return
}
return
}
// Close close db conn
func (d *Dao) Close() {
if d.db != nil {
d.db.Close()
}
if d.redis != nil {
d.redis.Close()
}
}
// BeginTran begin transcation
func (d *Dao) BeginTran(c context.Context) (tx *sql.Tx, err error) {
return d.db.Begin(c)
}

View File

@@ -0,0 +1,36 @@
package dao
import (
"flag"
"os"
"testing"
"go-common/app/interface/main/up-rating/conf"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.up-rating-interface")
flag.Set("conf_appid", "main.archive.up-rating-interface")
flag.Set("conf_token", "db506d78d859ee901ac000bac393484c")
flag.Set("tree_id", "65467")
flag.Set("conf_version", "0.0.1")
flag.Set("deploy_env", "uat")
flag.Set("conf_host", "config.bilibili.co")
flag.Set("conf_path", "/tmp")
flag.Set("region", "sh")
flag.Set("zone", "sh001")
} else {
flag.Set("conf", "../cmd/up-rating-interface.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
os.Exit(m.Run())
}

View File

@@ -0,0 +1,58 @@
package dao
import (
"context"
"fmt"
"go-common/app/interface/main/up-rating/model"
"go-common/library/database/sql"
"go-common/library/log"
)
const (
_upScoreSQL = "SELECT mid, creativity_score, influence_score, credit_score, cdate FROM up_rating_%02d WHERE mid=? AND cdate=? AND is_deleted=0"
_taskStatusSQL = "SELECT status FROM task_status WHERE date=? "
_whitelistSQL = "SELECT count(*) FROM up_white_list WHERE mid=? AND is_deleted=0"
)
// White will del later
func (d *Dao) White(c context.Context, mid int64) (count int64, err error) {
err = d.rddb.QueryRow(c, _whitelistSQL, mid).Scan(&count)
if err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("UpScore row scan error(%v)", err)
}
}
return
}
// TaskStatus ...
func (d *Dao) TaskStatus(c context.Context, date string) (status int, err error) {
err = d.rddb.QueryRow(c, _taskStatusSQL, date).Scan(&status)
if err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("UpScore row scan error(%v)", err)
}
}
return
}
// UpScore gets score data of UP
func (d *Dao) UpScore(c context.Context, mon int, mid int64, date string) (score *model.Score, err error) {
score = new(model.Score)
row := d.rddb.QueryRow(c, fmt.Sprintf(_upScoreSQL, mon), mid, date)
err = row.Scan(&score.MID, &score.Creative, &score.Influence, &score.Credit, &score.CDate)
if err != nil {
if err == sql.ErrNoRows {
score, err = nil, nil
} else {
log.Error("UpScore row scan error(%v)", err)
}
}
return
}

View File

@@ -0,0 +1,41 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoTaskStatus(t *testing.T) {
convey.Convey("TaskStatus", t, func(ctx convey.C) {
var (
c = context.Background()
date = "2018-11-01"
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
status, err := d.TaskStatus(c, date)
ctx.Convey("Then err should be nil.status should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(status, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoUpScore(t *testing.T) {
convey.Convey("UpScore", t, func(ctx convey.C) {
var (
c = context.Background()
mon = int(11)
mid = int64(1)
date = "2018-11-01"
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.UpScore(c, mon, mid, date)
ctx.Convey("Then err should be nil.score should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,77 @@
package dao
import (
"context"
"encoding/json"
"fmt"
"go-common/app/interface/main/up-rating/model"
"go-common/library/cache/redis"
"github.com/pkg/errors"
)
// GetUpRatingCache ...
func (d *Dao) GetUpRatingCache(c context.Context, mid int64) (rating *model.Rating, err error) {
var (
key = upRatingKey(mid)
conn = d.redis.Get(c)
data []byte
)
defer conn.Close()
if data, err = redis.Bytes(conn.Do("GET", key)); err != nil {
if err == redis.ErrNil {
err = nil
}
return
}
rating = new(model.Rating)
if err = json.Unmarshal(data, &rating); err != nil {
err = errors.WithStack(err)
return nil, err
}
return
}
// ExpireUpRatingCache ...
func (d *Dao) ExpireUpRatingCache(c context.Context, mid int64) (err error) {
var (
key = upRatingKey(mid)
conn = d.redis.Get(c)
)
defer conn.Close()
if err = conn.Send("EXPIRE", key, 0); err != nil {
return
}
return
}
// SetUpRatingCache ...
func (d *Dao) SetUpRatingCache(c context.Context, mid int64, rating *model.Rating) (err error) {
var (
key = upRatingKey(mid)
conn = d.redis.Get(c)
bs []byte
)
defer conn.Close()
if bs, err = json.Marshal(rating); err != nil {
return errors.WithStack(err)
}
if err = conn.Send("SET", key, bs); err != nil {
return
}
if err = conn.Send("EXPIRE", key, d.upRatingExpire); err != nil {
return
}
if err = conn.Flush(); err != nil {
return
}
if _, err = conn.Receive(); err != nil {
return
}
return
}
func upRatingKey(mid int64) string {
return fmt.Sprintf("up_rating_detail_mid_%d", mid)
}

View File

@@ -0,0 +1,55 @@
package dao
import (
"context"
"testing"
"go-common/app/interface/main/up-rating/model"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoGetUpRatingCache(t *testing.T) {
convey.Convey("GetUpRatingCache", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.GetUpRatingCache(c, mid)
ctx.Convey("Then err should be nil.rating should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoSetUpRatingCache(t *testing.T) {
convey.Convey("SetUpRatingCache", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
rating = &model.Rating{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.SetUpRatingCache(c, mid, rating)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoupRatingKey(t *testing.T) {
convey.Convey("upRatingKey", t, func(ctx convey.C) {
var (
mid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := upRatingKey(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,40 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"cache.go",
"http.go",
"rating.go",
],
importpath = "go-common/app/interface/main/up-rating/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/up-rating/conf:go_default_library",
"//app/interface/main/up-rating/service:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/middleware/auth:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,26 @@
package http
import (
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
)
func expireUpRating(c *bm.Context) {
arg := new(struct {
MID int64 `form:"mid"`
})
if err := c.Bind(arg); err != nil {
log.Error("error bind arg")
c.JSON(nil, ecode.RequestErr)
return
}
mid := arg.MID
err := svc.ExpireUpRatingCache(c, mid)
if err != nil {
log.Error("svc.ExpireUpRatingCache mid(%v) err(%v)", mid, err)
c.JSON(nil, err)
return
}
c.JSON(true, err)
}

View File

@@ -0,0 +1,53 @@
package http
import (
"net/http"
"go-common/app/interface/main/up-rating/conf"
"go-common/app/interface/main/up-rating/service"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/auth"
)
var (
svc *service.Service
authSvr *auth.Auth
)
// Init http server
func Init(c *conf.Config) {
initService(c)
engine := bm.DefaultServer(c.BM)
externalRouter(engine)
if err := engine.Start(); err != nil {
log.Error("engine.Start error(%v)", err)
panic(err)
}
}
func initService(c *conf.Config) {
svc = service.New(c)
authSvr = auth.New(nil)
}
func externalRouter(e *bm.Engine) {
e.Ping(ping)
// define routers
group := e.Group("/studio/up-rating", authSvr.User)
{
group.GET("/info", upRating)
}
cache := group.Group("/cache")
{
cache.GET("/expire/up", expireUpRating)
}
}
func ping(c *bm.Context) {
var err error
if err = svc.Ping(c); err != nil {
log.Error("service ping error(%v)", err)
c.AbortWithStatus(http.StatusServiceUnavailable)
}
}

View File

@@ -0,0 +1,24 @@
package http
import (
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
)
func upRating(c *bm.Context) {
midI, ok := c.Get("mid")
if !ok {
log.Error("error get mid")
c.JSON(nil, ecode.NoLogin)
return
}
mid, _ := midI.(int64)
rating, err := svc.UpRating(c, mid)
if err != nil {
log.Error("svc.UpRating mid(%v) err(%v)", mid, err)
c.JSON(nil, err)
return
}
c.JSON(rating, err)
}

View File

@@ -0,0 +1,28 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["rating.go"],
importpath = "go-common/app/interface/main/up-rating/model",
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,155 @@
package model
import (
"fmt"
"time"
)
const (
// TotalScore of up rating
TotalScore = 600
// LowerBoundScore ...
LowerBoundScore = 240
)
// Rating of up
type Rating struct {
Score *Score `json:"score"`
Rank *Rank `json:"rank"`
Prize *Prize `json:"prize"`
Privileges []*Privilege `json:"privileges"`
}
// Score of rating
type Score struct {
MID int64 `json:"mid"`
Magnetic int `json:"magnetic"` // 电磁力
Creative int `json:"creative"` // 创作力
Influence int `json:"influence"` // 影响力
Credit int `json:"credit"` // 信用分
CDate time.Time `json:"c_date"` // 统计月
StatStart time.Time `json:"stat_start"` // 统计周期开始日
StatEnd time.Time `json:"stat_end"` // 统计周期结束日
}
// Rank of rating
type Rank struct {
Level RankLevel `json:"level"`
Desc string `json:"desc"`
}
// RankLevel of rank
type RankLevel int8
// RankLevel list
const (
RankLevelSuper RankLevel = 10 * (1 + iota)
RankLevelStrong
RankLevelStandout
RankLevelNormal
RankLevelNone
)
// Ranks list all levels of rank
var Ranks = []RankLevel{
RankLevelSuper,
RankLevelStrong,
RankLevelStandout,
RankLevelNormal,
RankLevelNone,
}
// rank meta info
var rankMeta = map[RankLevel]struct {
score int
desc string
}{
RankLevelSuper: {int(0.9 * TotalScore), "超能力"},
RankLevelStrong: {int(0.75 * TotalScore), "强能力"},
RankLevelStandout: {int(0.6 * TotalScore), "异能力"},
RankLevelNormal: {int(0.3 * TotalScore), "常能力"},
RankLevelNone: {0, "新能力"},
}
// Score of rankLevel
func (r RankLevel) Score() int {
if m, ok := rankMeta[r]; ok {
return m.score
}
return RankLevelNone.Score()
}
// Rank content of rankLevel
func (r RankLevel) Rank() *Rank {
if m, ok := rankMeta[r]; ok {
return &Rank{
Level: r,
Desc: m.desc,
}
}
return RankLevelNone.Rank()
}
// Prize of rating
type Prize struct {
Level PrizeLevel `json:"level"`
Desc string `json:"desc"`
Content string `json:"content"`
}
// PrizeLevel of prize
type PrizeLevel int8
// Prize Level List
const (
PrizeLevelOne PrizeLevel = 10 * (1 + iota)
PrizeLevelTwo
PrizeLevelThree
PrizeLevelFour
PrizeLevelFive
)
// Prizes list prize levels by priority
var Prizes = []PrizeLevel{
PrizeLevelOne,
PrizeLevelTwo,
PrizeLevelThree,
PrizeLevelFour,
PrizeLevelFive,
}
var prizeMeta = map[PrizeLevel]struct {
desc string
content func(arg ...interface{}) string
}{
PrizeLevelOne: {desc: "睥睨众生奖", content: func(...interface{}) string {
return "恭喜你获得超高的电磁力,那可真是会当临绝顶,一览众山小吖"
}},
PrizeLevelTwo: {desc: "稳如泰山奖", content: func(...interface{}) string {
return "稳如泰山是你的优点,也可能是你的天花板,试着努力突破一下吧"
}},
PrizeLevelThree: {desc: "飞速进步奖", content: func(arg ...interface{}) string {
return fmt.Sprintf("本月电磁力上升%d分真是付出了超级多努力呢请继续加油吧", arg[0])
}},
PrizeLevelFour: {desc: "特别有趣奖", content: func(...interface{}) string {
return "看来你是被2233娘选中的孩子希望这样的幸运能够继续支撑你努力"
}},
PrizeLevelFive: {desc: "全村希望奖", content: func(...interface{}) string {
return "作为全村的希望,未来的你一定会感谢现在持续努力的自己"
}},
}
// Prize constructor
func (p PrizeLevel) Prize(arg ...interface{}) *Prize {
if meta, ok := prizeMeta[p]; ok {
return &Prize{
Level: p,
Desc: meta.desc,
Content: meta.content(arg...),
}
}
return PrizeLevelFive.Prize(arg...)
}
// Privilege of rating
type Privilege struct{}

View File

@@ -0,0 +1,39 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"cache.go",
"rating.go",
"service.go",
],
importpath = "go-common/app/interface/main/up-rating/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/up-rating/conf:go_default_library",
"//app/interface/main/up-rating/dao:go_default_library",
"//app/interface/main/up-rating/model:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,8 @@
package service
import "context"
// ExpireUpRatingCache ...
func (s *Service) ExpireUpRatingCache(c context.Context, mid int64) error {
return s.dao.ExpireUpRatingCache(c, mid)
}

View File

@@ -0,0 +1,180 @@
package service
import (
"context"
"time"
"go-common/app/interface/main/up-rating/model"
"go-common/library/ecode"
"go-common/library/log"
)
const (
_cdateLayout = "2006-01-02"
_taskFinished = 1
)
// UpRating gets data from cache and falls back to db
func (s *Service) UpRating(c context.Context, mid int64) (rating *model.Rating, err error) {
var allow bool
if allow, err = s.allow(c, mid); err != nil {
return
}
if !allow {
err = ecode.UpRatingNoPermission
return
}
var redisErr error
if rating, redisErr = s.dao.GetUpRatingCache(c, mid); redisErr != nil {
log.Error("s.dao.GetUpRatingCache error(%v)", redisErr)
}
if rating == nil {
if rating, err = s.UpRatingDB(c, mid); err != nil {
return
}
if redisErr = s.dao.SetUpRatingCache(c, mid, rating); redisErr != nil {
log.Error("s.dao.SetUpRatingCache error(%v)", redisErr)
}
}
return
}
// UpRatingDB gets data from db
func (s *Service) UpRatingDB(c context.Context, mid int64) (rating *model.Rating, err error) {
rating = &model.Rating{}
if rating.Score, err = s.latestScore(c, mid); err != nil {
return
}
if rating.Score.Magnetic < model.LowerBoundScore {
return nil, ecode.UpRatingScoreLimit
}
if rating.Rank, err = s.rank(rating.Score); err != nil {
log.Error("s.rank error(%v)", err)
return
}
if rating.Prize, err = s.prize(c, rating.Score); err != nil {
log.Error("s.prize error(%v)", err)
return
}
// privileges left for furture development
rating.Privileges = make([]*model.Privilege, 0)
return
}
func (s *Service) rank(score *model.Score) (rank *model.Rank, err error) {
for _, r := range model.Ranks {
if score.Magnetic >= r.Score() {
rank = r.Rank()
return
}
}
rank = model.RankLevelNone.Rank()
return
}
func (s *Service) prize(c context.Context, score *model.Score) (prize *model.Prize, err error) {
pass := false
m := map[model.PrizeLevel]func(){
model.PrizeLevelOne: func() {
if pass = score.Magnetic >= model.TotalScore*0.95; pass {
prize = model.PrizeLevelOne.Prize()
}
},
model.PrizeLevelTwo: func() {
tmp := score
if tmp.Magnetic < model.TotalScore*0.75 {
return
}
for j := 2; j > 0; j-- {
if tmp, err = s.score(c, tmp.MID, prevRatingTime(tmp.CDate)); err != nil || tmp == nil {
return
}
if tmp.Magnetic < model.TotalScore*0.75 {
return
}
}
pass = true
prize = model.PrizeLevelTwo.Prize()
},
model.PrizeLevelThree: func() {
var prev *model.Score
if prev, err = s.score(c, score.MID, prevRatingTime(score.CDate)); err != nil || prev == nil {
return
}
v := score.Magnetic - prev.Magnetic
if pass = v >= model.TotalScore*0.1; pass {
prize = model.PrizeLevelThree.Prize(v)
}
},
model.PrizeLevelFour: func() {
g := func(i int) bool {
return i == 233 || i == 223
}
if pass = g(score.Credit) || g(score.Creative) || g(score.Influence); pass {
prize = model.PrizeLevelFour.Prize()
}
},
model.PrizeLevelFive: func() {
pass = true
prize = model.PrizeLevelFive.Prize()
},
}
for _, p := range model.Prizes {
m[p]()
if err != nil || pass {
break
}
}
return
}
func (s *Service) latestScore(c context.Context, mid int64) (score *model.Score, err error) {
var status int
ratingTime := prevRatingTime(time.Now())
if status, err = s.dao.TaskStatus(c, ratingTime.Format(_cdateLayout)); err != nil {
return
}
if status != _taskFinished {
ratingTime = prevRatingTime(ratingTime)
if status, err = s.dao.TaskStatus(c, ratingTime.Format(_cdateLayout)); err != nil {
return
}
if status != _taskFinished {
err = ecode.UpRatingNoData
return
}
}
return s.score(c, mid, ratingTime)
}
func (s *Service) score(c context.Context, mid int64, ratingTime time.Time) (score *model.Score, err error) {
score, err = s.dao.UpScore(c, int(ratingTime.Month()), mid, ratingTime.Format(_cdateLayout))
if err != nil {
log.Error("s.dao.UpScore err(%v)", err)
return
}
if score == nil {
log.Error("s.dao.UpScore mid(%v) ratingTime(%v) not found", mid, ratingTime.String())
return
}
score.Magnetic = score.Creative + score.Credit + score.Influence
score.StatEnd = time.Date(score.CDate.Year(), score.CDate.Month()+1, 1, 0, 0, 0, 0, score.CDate.Location()).AddDate(0, 0, -1)
score.StatStart = time.Date(score.CDate.Year()-1, score.CDate.Month()+1, 1, 0, 0, 0, 0, score.CDate.Location())
return
}
func prevRatingTime(queryTime time.Time) time.Time {
return time.Date(queryTime.Year(), queryTime.Month()-1, 1, 0, 0, 0, 0, queryTime.Location())
}
func (s *Service) allow(c context.Context, mid int64) (b bool, err error) {
count, err := s.dao.White(c, mid)
if err != nil {
return
}
b = count != 0
return
}

View File

@@ -0,0 +1,34 @@
package service
import (
"context"
"go-common/app/interface/main/up-rating/conf"
"go-common/app/interface/main/up-rating/dao"
)
// Service is up-dao service
type Service struct {
conf *conf.Config
// dao dao
dao *dao.Dao
}
// New fn
func New(c *conf.Config) (s *Service) {
s = &Service{
conf: c,
dao: dao.New(c),
}
return s
}
// Ping fn
func (s *Service) Ping(c context.Context) (err error) {
return s.dao.Ping(c)
}
// Close dao
func (s *Service) Close() {
s.dao.Close()
}