Create & Init Project...

This commit is contained in:
2019-04-22 18:49:16 +08:00
commit fc4fa37393
25440 changed files with 4054998 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/job/main/credit-timer/cmd:all-srcs",
"//app/job/main/credit-timer/conf:all-srcs",
"//app/job/main/credit-timer/dao:all-srcs",
"//app/job/main/credit-timer/http:all-srcs",
"//app/job/main/credit-timer/model:all-srcs",
"//app/job/main/credit-timer/service:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,64 @@
credit项目的timer用于定时结案等。
##### Version 1.3.14
> 1.http use bm
##### Version 1.3.13
> 1.move item to main
##### Version 1.3.12
> 1.delete statsd
##### Version 1.3.11
> 1.fix kpi and add log
##### Version 1.3.10
> 1.add goconvey test
# Version 1.3.9
> 1.kpi table blocked_kpi_data double write
# Version 1.3.8
> 1.del opinion join
# Version 1.3.7
> 1.KPI算法优化
# Version 1.3.6
> 2.支持info的status字段
# Version 1.3.5
> 1.大众仲裁无投票数限制
# Version 1.3.4
> 1.风纪委员评级调整
# Version 1.3.3
> 1.add reservedTime="600s"
# Version 1.3.2
> 1.job add prom
# Version 1.3.1
> 1.sql 加索引优化
# Version 1.3.0
> 1.迁移大仓库
# Version 1.2.0
> 1.添加手动结算kpi
> 2.修复排行百分比0
# Version 1.1.1
> 1.投票上限结案
# Version 1.1.0
> 1.风纪委众议
# Version 1.0.1
> 1.风纪委绩效考核评分和kpi
# Version 1.0.0
> 1.版本初始化
> 2.定时更新案件状态,风纪委状态,投票状态

View File

@@ -0,0 +1,14 @@
# Owner
zhaogangtao
# Author
wangyuzhe
hejianbing
liangguangsheng
lintanghui
# Reviewer
zhaogangtao
hejianbing
wangyuzhe
lintanghui

View File

@@ -0,0 +1,20 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- hejianbing
- liangguangsheng
- lintanghui
- wangyuzhe
- zhaogangtao
labels:
- job
- job/main/credit-timer
- main
options:
no_parent_owners: true
reviewers:
- hejianbing
- liangguangsheng
- lintanghui
- wangyuzhe
- zhaogangtao

View File

@@ -0,0 +1,11 @@
#### credit-timer-job
##### 项目简介
> 1.异步任务,定时更新风纪委投票结案
##### 编译环境
> 请只用golang v1.7.x以上版本编译执行。
##### 依赖包
> 1.公共包go-common

View File

@@ -0,0 +1,45 @@
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 = [
"convey-test.toml",
"credit-timer-job-test.toml",
],
importpath = "go-common/app/job/main/credit-timer/cmd",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/credit-timer/conf:go_default_library",
"//app/job/main/credit-timer/http:go_default_library",
"//app/job/main/credit-timer/service: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,106 @@
# This is a TOML document. Boom.
version = "1.0.0"
user = "nobody"
pid = "/tmp/credit-timer.pid"
dir = "./"
perf = "0.0.0.0:6330"
family = "credit-timer"
address = "172.16.33.54"
env = "qa"
[xlog]
dir = "/data/log/credit-timer/"
[tracer]
proto = "udp"
addr = "172.16.33.46:5140"
tag = "platform/credit-timer"
[identify]
[identify.app]
key = "3c4e41f926e51656"
secret = "26a2095b60c24154521d24ae62b885bb"
[identify.memcache]
name = "go-business/identify"
proto = "tcp"
addr = "172.16.33.54:11211"
active = 5
idle = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "80s"
[identify.host]
auth = "http://passport.bilibili.com"
secret = "http://open.bilibili.com"
[identify.authHTTPClient]
dial = "1s"
timeout = "1s"
keepAlive = "60s"
timer = 1000
[identify.authHTTPClient.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[identify.secretHTTPClient]
dial = "1s"
timeout = "1s"
keepAlive = "60s"
timer = 1000
[identify.secretHTTPClient.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[mysql]
addr = "172.16.33.205:3306"
dsn = "blocked:mUdFycLKSbvPgdE28lCveqN77SqsGOmy@tcp(172.16.33.205:3306)/blocked?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 5
idle = 2
idleTimeout ="4h"
queryTimeout = "1s"
execTimeout = "1s"
tranTimeout = "1s"
[mysql.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[memcache]
name = "credit"
proto = "tcp"
addr = "172.16.33.54:11211"
idle = 5
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "24h"
[redis]
name = "credit"
proto = "tcp"
addr = "172.16.33.54:6379"
idle = 100
active = 100
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "720h"
[judge]
votetimer="60s"
caseTimer="60s"
juryTimer="60s"
confTimer="120s"
reservedTime="600s"

View File

@@ -0,0 +1,110 @@
# This is a TOML document. Boom.
version = "1.0.0"
user = "nobody"
pid = "/tmp/credit-timer.pid"
dir = "./"
perf = "0.0.0.0:6330"
family = "credit-timer"
address = "172.16.33.54"
env = "qa"
[xlog]
dir = "/data/log/credit-timer/"
[tracer]
proto = "udp"
addr = "172.16.33.46:5140"
tag = "platform/credit-timer"
[bm]
addr = "0.0.0.0:6331"
timeout = "1s"
[identify]
[identify.app]
key = "3c4e41f926e51656"
secret = "26a2095b60c24154521d24ae62b885bb"
[identify.memcache]
name = "go-business/identify"
proto = "tcp"
addr = "172.16.33.54:11211"
active = 5
idle = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "80s"
[identify.host]
auth = "http://passport.bilibili.com"
secret = "http://open.bilibili.com"
[identify.authHTTPClient]
dial = "1s"
timeout = "1s"
keepAlive = "60s"
timer = 1000
[identify.authHTTPClient.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[identify.secretHTTPClient]
dial = "1s"
timeout = "1s"
keepAlive = "60s"
timer = 1000
[identify.secretHTTPClient.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[mysql]
addr = "172.16.33.205:3306"
dsn = "blocked:mUdFycLKSbvPgdE28lCveqN77SqsGOmy@tcp(172.16.33.205:3306)/blocked?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 5
idle = 2
idleTimeout ="4h"
queryTimeout = "1s"
execTimeout = "1s"
tranTimeout = "1s"
[mysql.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[memcache]
name = "credit"
proto = "tcp"
addr = "172.16.33.54:11211"
idle = 5
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "24h"
[redis]
name = "credit"
proto = "tcp"
addr = "172.16.33.54:6379"
idle = 100
active = 100
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "720h"
[judge]
votetimer="60s"
caseTimer="60s"
juryTimer="60s"
confTimer="120s"
reservedTime="600s"

View File

@@ -0,0 +1,52 @@
package main
import (
"flag"
"os"
"os/signal"
"syscall"
"go-common/app/job/main/credit-timer/conf"
"go-common/app/job/main/credit-timer/http"
"go-common/app/job/main/credit-timer/service"
"go-common/library/log"
)
var (
srv *service.Service
)
func main() {
flag.Parse()
if err := conf.Init(); err != nil {
log.Error("conf.Init() error(%v)", err)
panic(err)
}
log.Init(conf.Conf.Xlog)
defer log.Close()
log.Info("credit-timer start")
http.Init(conf.Conf)
signalHandler()
}
func signalHandler() {
var (
err error
ch = make(chan os.Signal, 1)
)
signal.Notify(ch, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
si := <-ch
switch si {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
log.Info("get a signal %s, stop the consume process", si.String())
if err = srv.Close(); err != nil {
log.Error("srv close consumer error(%v)", err)
}
return
case syscall.SIGHUP:
default:
return
}
}
}

View File

@@ -0,0 +1,36 @@
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/job/main/credit-timer/conf",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/conf:go_default_library",
"//library/database/sql:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster: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,100 @@
package conf
import (
"errors"
"flag"
"go-common/library/conf"
"go-common/library/database/sql"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/time"
"github.com/BurntSushi/toml"
)
// Conf global variable.
var (
Conf = &Config{}
client *conf.Client
confPath string
)
// Config struct of conf.
type Config struct {
// base
// app
App *bm.App
// Env
Env string
// goroutine sleep
Tick time.Duration
// log
Xlog *log.Config
// httpClinet
Mysql *sql.Config
Judge *Judge
// bm service
BM *bm.ServerConfig
}
// Judge is judge config.
type Judge struct {
ReservedTime time.Duration // 结案前N分钟停止获取case
VoteTimer time.Duration
CaseTimer time.Duration
JuryTimer time.Duration
ConfTimer time.Duration
CaseEndVoteTotal int64
}
func init() {
flag.StringVar(&confPath, "conf", "", "default config path")
}
// Init create config instance.
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,56 @@
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",
"mysql_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/credit-timer/conf:go_default_library",
"//app/job/main/credit-timer/model:go_default_library",
"//vendor/github.com/go-sql-driver/mysql:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
"//vendor/gopkg.in/h2non/gock.v1:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"mysql.go",
],
importpath = "go-common/app/job/main/credit-timer/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/credit-timer/conf:go_default_library",
"//app/job/main/credit-timer/model:go_default_library",
"//library/database/sql: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,35 @@
package dao
import (
"context"
"go-common/app/job/main/credit-timer/conf"
"go-common/library/database/sql"
)
// Dao struct info of Dao.
type Dao struct {
db *sql.DB
c *conf.Config
}
// New new a Dao and return.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
db: sql.NewMySQL(c.Mysql),
}
return
}
// Close close connections of mc, redis, db.
func (d *Dao) Close() {
if d.db != nil {
d.db.Close()
}
}
// Ping ping health of db.
func (d *Dao) Ping(c context.Context) (err error) {
return d.db.Ping(c)
}

View File

@@ -0,0 +1,32 @@
package dao
import (
"context"
"flag"
"path/filepath"
"strings"
"go-common/app/job/main/credit-timer/conf"
_ "github.com/go-sql-driver/mysql"
"gopkg.in/h2non/gock.v1"
)
var d *Dao
func init() {
dir, _ := filepath.Abs("../cmd/convey-test.toml")
flag.Set("conf", dir)
conf.Init()
d = New(conf.Conf)
}
func httpMock(method, url string) *gock.Request {
r := gock.New(url)
r.Method = strings.ToUpper(method)
return r
}
func ctx() context.Context {
return context.Background()
}

View File

@@ -0,0 +1,309 @@
package dao
import (
"context"
"strconv"
"time"
"go-common/app/job/main/credit-timer/model"
"go-common/library/database/sql"
"go-common/library/log"
)
const (
_updateKPISQL = "INSERT INTO blocked_kpi(mid,day,rate,rank,rank_per,rank_total) VALUES (?,?,?,?,?,?) ON DUPLICATE KEY UPDATE rate=?,rank=?,rank_per=?,rank_total=?"
_updateKPIDataSQL = "INSERT INTO blocked_kpi_data(mid,day,point,active_days,vote_total,vote_radio,blocked_total,opinion_num,opinion_likes,opinion_hates,vote_real_total) VALUES (?,?,?,?,?,?,?,?,?,?,?) ON DUPLICATE KEY UPDATE point=?,active_days=?,vote_total=?,vote_radio=?,blocked_total=?,opinion_num=?,opinion_likes=?,opinion_hates=?,vote_real_total=?"
_updateKPIPointSQL = "INSERT INTO blocked_kpi_point(mid,day,point,active_days,vote_total,vote_radio,blocked_total,opinion_num,opinion_likes,opinion_hates) VALUES (?,?,?,?,?,?,?,?,?,?) ON DUPLICATE KEY UPDATE point=?,active_days=?,vote_total=?,vote_radio=?,blocked_total=?,opinion_num=?,opinion_likes=?,opinion_hates=?"
_updateCaseEndTimeSQL = "UPDATE blocked_case SET status=3 WHERE status = 1 AND end_time < ?"
_updateCaseEndVoteSQL = "UPDATE blocked_case SET end_time=? WHERE status = 1 AND end_time > ? AND (vote_rule+vote_break+vote_delete) >= ?"
_updateJurySQL = "UPDATE blocked_jury SET status=2,invalid_reason=? WHERE status=1 AND expired < ?"
_updateJuryExpiredSQL = "UPDATE blocked_jury SET status=1, expired=? WHERE mid = ?"
_updateVoteSQL = "UPDATE blocked_case_vote SET vote=3 WHERE vote=0 AND expired > ? AND expired < ? "
_selConfSQL = "SELECT config_key,content FROM blocked_config"
_selJurySQL = "SELECT mid FROM blocked_jury WHERE status=1"
_selJuryKPISQL = "SELECT mid FROM blocked_jury WHERE expired BETWEEN ? AND ?"
_countVoteTotalSQL = "SELECT COUNT(*) FROM blocked_case_vote v INNER JOIN blocked_case c ON c.id=v.cid AND c.status=4 WHERE v.mid = ? AND v.vote IN (1,2,4) AND v.ctime BETWEEN ? AND ?"
_countRightViolateSQL = "SELECT COUNT(*) FROM blocked_case_vote v INNER JOIN blocked_case c ON c.id=v.cid AND v.vote IN(1,4) AND c.judge_type = 1 AND c.status=4 WHERE v.mid = ? AND v.ctime BETWEEN ? AND ?"
_countRightLegalSQL = "SELECT COUNT(*) FROM blocked_case_vote v INNER JOIN blocked_case c ON c.id=v.cid AND v.vote = 2 AND c.judge_type = 2 AND c.status=4 WHERE v.mid = ? AND v.ctime BETWEEN ? AND ?"
_CountBlockedSQL = "SELECT COUNT(*) FROM blocked_info WHERE uid = ? AND status=0 AND ctime BETWEEN ? AND ?"
_selKPIPointDaySQL = "SELECT k.mid,k.day,k.point,k.active_days,k.vote_total,k.vote_radio,k.blocked_total,k.opinion_num,k.opinion_likes,k.opinion_hates,j.expired FROM blocked_kpi_point k INNER JOIN blocked_jury j ON k.mid = j.mid WHERE day = ? ORDER BY k.point desc"
_selKPIPointSQL = "SELECT mid,day,point,active_days,vote_total,vote_radio,blocked_total FROM blocked_kpi_point WHERE mid = ? AND day = ? ORDER BY point desc"
_selKPISQL = "SELECT mid,day,rate,rank,rank_per,rank_total FROM blocked_kpi WHERE mid = ?"
_countActiveSQL = "SELECT COUNT(*) FROM (SELECT DATE_FORMAT(ctime,'%Y-%m-%d') FROM blocked_case_vote WHERE vote IN(1,2,4) AND mid=? AND ctime BETWEEN ? AND ? GROUP BY DATE_FORMAT(ctime,'%Y-%m-%d')) t"
_countOpinionSQL = "SELECT COUNT(*) FROM blocked_opinion WHERE mid = ? AND state = 0 AND ctime BETWEEN ? AND ?"
_opinionQualitySQL = "SELECT COALESCE(SUM(likes),0),COALESCE(SUM(hates),0) FROM blocked_opinion WHERE mid = ? AND state = 0 AND ctime BETWEEN ? AND ?"
_countVoteByTimeSQL = "SELECT count(*) from blocked_case_vote where vote in(1,2,4) and mid=? and ctime between ? and ?"
)
// UpdateKPI update KPI info.
func (d *Dao) UpdateKPI(c context.Context, r *model.Kpi) (err error) {
if _, err = d.db.Exec(c, _updateKPISQL, r.Mid, r.Day, r.Rate, r.Rank, r.RankPer, r.RankTotal, r.Rate, r.Rank, r.RankPer, r.RankTotal); err != nil {
log.Error("d.UpdateKPI err(%v)", err)
}
return
}
// UpdateKPIData update kpi_data info.
func (d *Dao) UpdateKPIData(c context.Context, r *model.KpiData) (err error) {
if _, err = d.db.Exec(c, _updateKPIDataSQL, r.Mid, r.Day, r.Point, r.ActiveDays, r.VoteTotal, r.VoteRadio, r.BlockedTotal, r.OpinionNum, r.OpinionLikes, r.OpinionHates, r.VoteRealTotal, r.Point, r.ActiveDays, r.VoteTotal, r.VoteRadio, r.BlockedTotal, r.OpinionNum, r.OpinionLikes, r.OpinionHates, r.VoteRealTotal); err != nil {
log.Error("d.UpdateKPIPoint err(%v)", err)
}
return
}
// UpdateKPIPoint update kpi point info.
func (d *Dao) UpdateKPIPoint(c context.Context, r *model.KpiPoint) (err error) {
if _, err = d.db.Exec(c, _updateKPIPointSQL, r.Mid, r.Day, r.Point, r.ActiveDays, r.VoteTotal, r.VoteRadio, r.BlockedTotal, r.OpinionNum, r.OpinionLikes, r.OpinionHates, r.Point, r.ActiveDays, r.VoteTotal, r.VoteRadio, r.BlockedTotal, r.OpinionNum, r.OpinionLikes, r.OpinionHates); err != nil {
log.Error("d.UpdateKPIPoint err(%v)", err)
}
return
}
// UpdateCaseEndTime update case status to CaseStatusDealing which expired time less than now.
func (d *Dao) UpdateCaseEndTime(c context.Context, now time.Time) (affect int64, err error) {
rows, err := d.db.Exec(c, _updateCaseEndTimeSQL, now)
if err != nil {
log.Error("d.UpdateCaseEndTime err(%v)", err)
return
}
return rows.RowsAffected()
}
// UpdateCaseEndVote update case status to CaseStatusDealing which vote total more than conf case vote total.
func (d *Dao) UpdateCaseEndVote(c context.Context, vt int64, ts time.Time) (affect int64, err error) {
rows, err := d.db.Exec(c, _updateCaseEndVoteSQL, ts, ts, vt)
if err != nil {
log.Error("d.UpdateCaseEndVote err(%v)", err)
return
}
return rows.RowsAffected()
}
// UpdateJury update jury status to expired which expired time less than ts.
func (d *Dao) UpdateJury(c context.Context, now time.Time) (affect int64, err error) {
rows, err := d.db.Exec(c, _updateJurySQL, model.JuryExpire, now)
if err != nil {
log.Error("d.UpdateJury err(%v)", err)
return
}
return rows.RowsAffected()
}
// UpdateJuryExpired update jury expired.
func (d *Dao) UpdateJuryExpired(c context.Context, mid int64, expired time.Time) (err error) {
if _, err = d.db.Exec(c, _updateJuryExpiredSQL, expired, mid); err != nil {
log.Error("d.UpdateJuryExpired err(%v)", err)
}
return
}
// UpdateVote update vote status to give up which do not vote and expired less than ts.
func (d *Dao) UpdateVote(c context.Context, now time.Time) (affect int64, err error) {
rows, err := d.db.Exec(c, _updateVoteSQL, now.Add(-4*time.Hour), now)
if err != nil {
log.Error("d.updateVote err(%v)", err)
return
}
return rows.RowsAffected()
}
// LoadConf load conf.
func (d *Dao) LoadConf(c context.Context) (vTotal int64, err error) {
var (
key string
value string
)
rows, err := d.db.Query(c, _selConfSQL)
if err != nil {
log.Error("d.loadConf err(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
if err = rows.Scan(&key, &value); err != nil {
log.Error("rows.Scan err(%v)", err)
return
}
switch key {
case "case_vote_max":
if vTotal, err = strconv.ParseInt(value, 10, 64); err != nil {
return
}
}
}
err = rows.Err()
return
}
// JuryList get jury list.
func (d *Dao) JuryList(c context.Context) (res []int64, err error) {
var rows *sql.Rows
if rows, err = d.db.Prepared(_selJurySQL).Query(c); err != nil {
log.Error("dao.JuryList error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
var r int64
if err = rows.Scan(&r); err != nil {
log.Error("row.Scan() error(%v)", err)
res = nil
return
}
res = append(res, r)
}
err = rows.Err()
return
}
// JuryKPI get jury list.
func (d *Dao) JuryKPI(c context.Context, begin, end string) (res []int64, err error) {
var rows *sql.Rows
if rows, err = d.db.Prepared(_selJuryKPISQL).Query(c, begin, end); err != nil {
log.Error("dao.JuryKPI error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
var r int64
if err = rows.Scan(&r); err != nil {
log.Error("row.Scan() error(%v)", err)
res = nil
return
}
res = append(res, r)
}
err = rows.Err()
return
}
// CountVoteTotal get vote total.
func (d *Dao) CountVoteTotal(c context.Context, mid int64, begin, end string) (count int64, err error) {
row := d.db.QueryRow(c, _countVoteTotalSQL, mid, begin, end)
if err = row.Scan(&count); err != nil {
log.Error("d.CountVoteTotal err(%v)", err)
}
return
}
// CountVoteRightViolate get vote right violate count.
func (d *Dao) CountVoteRightViolate(c context.Context, mid int64, begin, end string) (count int64, err error) {
row := d.db.QueryRow(c, _countRightViolateSQL, mid, begin, end)
if err = row.Scan(&count); err != nil {
log.Error("d.CountVoteRightViolate err(%v)", err)
}
return
}
// CountVoteRightLegal get vote right legal count.
func (d *Dao) CountVoteRightLegal(c context.Context, mid int64, begin, end string) (count int64, err error) {
row := d.db.QueryRow(c, _countRightLegalSQL, mid, begin, end)
if err = row.Scan(&count); err != nil {
log.Error("d.CountVoteRightLegal err(%v)", err)
}
return
}
// CountBlocked get user block count ofter ts.
func (d *Dao) CountBlocked(c context.Context, mid int64, begin, end string) (count int64, err error) {
row := d.db.QueryRow(c, _CountBlockedSQL, mid, begin, end)
if err = row.Scan(&count); err != nil {
log.Error("d.CountBlocked err(%v)", err)
}
return
}
// KPIPointDay get KPI point day list.
func (d *Dao) KPIPointDay(c context.Context, day string) (res []model.KpiPoint, err error) {
var rows *sql.Rows
if rows, err = d.db.Query(c, _selKPIPointDaySQL, day); err != nil {
log.Error("dao.JuryKpi error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
r := model.KpiPoint{}
if err = rows.Scan(&r.Mid, &r.Day, &r.Point, &r.ActiveDays, &r.VoteTotal, &r.VoteRadio, &r.BlockedTotal, &r.OpinionNum, &r.OpinionLikes, &r.OpinionHates, &r.Expired); err != nil {
log.Error("row.Scan() error(%v)", err)
res = nil
return
}
res = append(res, r)
}
err = rows.Err()
return
}
// KPIPoint get kpi point.
func (d *Dao) KPIPoint(c context.Context, mid int64, day string) (r model.KpiPoint, err error) {
row := d.db.QueryRow(c, _selKPIPointSQL, mid, day)
if err = row.Scan(&r.Mid, &r.Day, &r.Point, &r.ActiveDays, &r.VoteTotal, &r.VoteRadio, &r.BlockedTotal); err != nil {
log.Error("d.KPIPoint err(%v)", err)
}
return
}
// KPIList get kpi list.
func (d *Dao) KPIList(c context.Context, mid int64) (res []model.Kpi, err error) {
var rows *sql.Rows
if rows, err = d.db.Query(c, _selKPISQL, mid); err != nil {
log.Error("dao.KPIList error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
r := model.Kpi{}
if err = rows.Scan(&r.Mid, &r.Day, &r.Rate, &r.Rank, &r.RankPer, &r.RankTotal); err != nil {
log.Error("row.Scan() error(%v)", err)
res = nil
return
}
res = append(res, r)
}
err = rows.Err()
return
}
// CountVoteActive get vote active days count.
func (d *Dao) CountVoteActive(c context.Context, mid int64, begin, end string) (count int64, err error) {
row := d.db.QueryRow(c, _countActiveSQL, mid, begin, end)
if err = row.Scan(&count); err != nil {
log.Error("d.CountVoteActive err(%v)", err)
}
return
}
// CountOpinion count user opinion in 30 days.
func (d *Dao) CountOpinion(c context.Context, mid int64, begin, end string) (count int64, err error) {
row := d.db.QueryRow(c, _countOpinionSQL, mid, begin, end)
if err = row.Scan(&count); err != nil {
log.Error("d.CountOpinion(mid:%d begin:%s end:%s) err(%v)", mid, begin, end, err)
}
return
}
// OpinionQuality count user opinion quality(fields likes - hates) in 30days.
func (d *Dao) OpinionQuality(c context.Context, mid int64, begin, end string) (likes, hates int64, err error) {
row := d.db.QueryRow(c, _opinionQualitySQL, mid, begin, end)
if err = row.Scan(&likes, &hates); err != nil {
if err != sql.ErrNoRows {
log.Error("d.OpinionQuality(mid:%d begin:%s end:%s) err(%v)", mid, begin, end, err)
return
}
err = nil
}
return
}
// CountVoteByTime count vote by time.
func (d *Dao) CountVoteByTime(c context.Context, mid int64, begin, end time.Time) (count int64, err error) {
var row *sql.Row
if row = d.db.QueryRow(c, _countVoteByTimeSQL, mid, begin, end); err != nil {
log.Error("d.CountVoteByTime.Query(%d) error(%v)", mid, err)
return
}
if err = row.Scan(&count); err != nil {
log.Error("row.Scan() error(%v)", err)
}
return
}

View File

@@ -0,0 +1,226 @@
package dao
import (
"context"
"testing"
"time"
"go-common/app/job/main/credit-timer/model"
. "github.com/smartystreets/goconvey/convey"
)
func Test_UpdateKPI(t *testing.T) {
r := &model.Kpi{}
r.Day = time.Now()
r.Mid = 111
r.Rate = 1
r.Rank = 10
r.RankPer = 10
r.RankTotal = 100
Convey("should return err be nil", t, func() {
err := d.UpdateKPI(context.TODO(), r)
So(err, ShouldBeNil)
})
}
func Test_UpdateKPIData(t *testing.T) {
r := &model.KpiData{}
r.Day = time.Now()
r.Mid = 111
Convey("should return err be nil", t, func() {
err := d.UpdateKPIData(context.TODO(), r)
So(err, ShouldBeNil)
})
}
func Test_UpdateKPIPoint(t *testing.T) {
r := &model.KpiPoint{}
r.Day = time.Now()
r.Mid = 1
r.Point = 100
r.ActiveDays = 10
r.BlockedTotal = 11
r.VoteRadio = 60
r.VoteTotal = 1000
Convey("should return err be nil", t, func() {
err := d.UpdateKPIPoint(context.TODO(), r)
So(err, ShouldBeNil)
})
}
func Test_UpdateCaseEndTime(t *testing.T) {
Convey("should return err be nil", t, func() {
num, err := d.UpdateCaseEndTime(context.TODO(), time.Now())
So(err, ShouldBeNil)
So(num, ShouldBeGreaterThanOrEqualTo, 0)
})
}
func Test_UpdateCaseEndVote(t *testing.T) {
Convey("should return err be nil", t, func() {
num, err := d.UpdateCaseEndVote(context.TODO(), 600, time.Now().Add(time.Minute*10))
So(err, ShouldBeNil)
So(num, ShouldBeGreaterThanOrEqualTo, 0)
})
}
func Test_UpdateJury(t *testing.T) {
Convey("should return err be nil", t, func() {
num, err := d.UpdateJury(context.TODO(), time.Now())
So(err, ShouldBeNil)
So(num, ShouldBeGreaterThanOrEqualTo, 0)
})
}
func Test_UpdateJuryExpired(t *testing.T) {
Convey("should return err be nil", t, func() {
err := d.UpdateJuryExpired(context.TODO(), 88889017, time.Now())
So(err, ShouldBeNil)
})
}
func Test_UpdateVote(t *testing.T) {
Convey("should return err be nil", t, func() {
num, err := d.UpdateVote(context.TODO(), time.Now())
So(err, ShouldBeNil)
So(num, ShouldBeGreaterThanOrEqualTo, 0)
})
}
func Test_LoadConf(t *testing.T) {
Convey("should return err be nil", t, func() {
vTotal, err := d.LoadConf(context.TODO())
So(err, ShouldBeNil)
So(vTotal, ShouldBeGreaterThanOrEqualTo, 0)
})
}
func Test_JuryList(t *testing.T) {
Convey("should return err be nil", t, func() {
mids, err := d.JuryList(context.TODO())
So(err, ShouldBeNil)
So(mids, ShouldNotResemble, []int64{})
})
}
func Test_JuryKPI(t *testing.T) {
begin := time.Now().Format("2006-01-02")
end := time.Now().AddDate(0, 0, 1).Format("2006-01-02")
Convey("should return err be nil", t, func() {
res, err := d.JuryKPI(context.TODO(), begin, end)
So(err, ShouldBeNil)
So(res, ShouldNotResemble, []int64{})
})
}
func Test_CountVoteTotal(t *testing.T) {
begin := time.Now().Format("2006-01-02")
end := time.Now().AddDate(0, 0, 1).Format("2006-01-02")
Convey("should return err be nil", t, func() {
count, err := d.CountVoteTotal(context.TODO(), 88889017, begin, end)
So(err, ShouldBeNil)
So(count, ShouldBeGreaterThanOrEqualTo, 0)
})
}
func Test_CountVoteRightViolate(t *testing.T) {
begin := time.Now().AddDate(0, 0, -30).Format("2006-01-02")
end := time.Now().AddDate(0, 0, 1).Format("2006-01-02")
Convey("should return err be nil", t, func() {
count, err := d.CountVoteRightViolate(context.TODO(), 88889017, begin, end)
So(err, ShouldBeNil)
So(count, ShouldBeGreaterThanOrEqualTo, 0)
})
}
func Test_CountVoteRightLegal(t *testing.T) {
begin := time.Now().AddDate(0, 0, -30).Format("2006-01-02")
end := time.Now().AddDate(0, 0, 1).Format("2006-01-02")
Convey("should return err be nil", t, func() {
count, err := d.CountVoteRightLegal(context.TODO(), 88889017, begin, end)
So(err, ShouldBeNil)
So(count, ShouldBeGreaterThanOrEqualTo, 0)
})
}
func Test_CountBlocked(t *testing.T) {
begin := time.Now().AddDate(0, 0, -30).Format("2006-01-02")
end := time.Now().AddDate(0, 0, 1).Format("2006-01-02")
Convey("should return err be nil", t, func() {
count, err := d.CountBlocked(context.TODO(), 88889017, begin, end)
So(err, ShouldBeNil)
So(count, ShouldBeGreaterThanOrEqualTo, 0)
})
}
func Test_KpiPointDay(t *testing.T) {
day := time.Now().Format("2006-01-02")
Convey("should return err be nil", t, func() {
_, err := d.KPIPointDay(context.TODO(), day)
So(err, ShouldBeNil)
// So(kp, ShouldNotBeNil)
// So(kp, ShouldResemble,[]model.KpiPoint{})
})
}
func TestDao_KPIPoint(t *testing.T) {
day := time.Now().Format("2006-01-02")
Convey("should return err be nil", t, func() {
kp, _ := d.KPIPoint(context.TODO(), 88889017, day)
// So(err, ShouldBeNil)
So(kp, ShouldNotBeNil)
So(kp, ShouldResemble, model.KpiPoint{})
})
}
func Test_KPIList(t *testing.T) {
Convey("should return err be nil", t, func() {
kpis, err := d.KPIList(context.TODO(), 88889017)
So(err, ShouldBeNil)
So(kpis, ShouldNotBeNil)
// So(kpis, ShouldResemble,[]model.Kpi{})
})
}
func Test_CountVoteActive(t *testing.T) {
begin := time.Now().AddDate(0, 0, -30).Format("2006-01-02")
end := time.Now().AddDate(0, 0, 1).Format("2006-01-02")
Convey("should return err be nil", t, func() {
count, err := d.CountVoteActive(context.TODO(), 88889017, begin, end)
So(err, ShouldBeNil)
So(count, ShouldBeGreaterThanOrEqualTo, 0)
})
}
func TestDao_CountOpinion(t *testing.T) {
begin := time.Now().AddDate(0, 0, -30).Format("2006-01-02")
end := time.Now().AddDate(0, 0, 1).Format("2006-01-02")
Convey("should return err be nil", t, func() {
count, err := d.CountOpinion(context.TODO(), 88889017, begin, end)
So(err, ShouldBeNil)
So(count, ShouldBeGreaterThanOrEqualTo, 0)
})
}
func Test_OpinionQuality(t *testing.T) {
begin := time.Now().AddDate(0, 0, -30).Format("2006-01-02")
end := time.Now().AddDate(0, 0, 1).Format("2006-01-02")
Convey("should return err be nil", t, func() {
likes, hates, err := d.OpinionQuality(context.TODO(), 88889017, begin, end)
So(err, ShouldBeNil)
So(likes, ShouldBeGreaterThanOrEqualTo, 0)
So(hates, ShouldBeGreaterThanOrEqualTo, 0)
})
}
func Test_CountVoteByTime(t *testing.T) {
begin := time.Now().AddDate(0, 0, -30)
end := time.Now().AddDate(0, 0, 1)
Convey("should return err be nil", t, func() {
count, err := d.CountVoteByTime(context.TODO(), 88889017, begin, end)
So(err, ShouldBeNil)
So(count, ShouldBeGreaterThanOrEqualTo, 0)
})
}

View File

@@ -0,0 +1,34 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["http.go"],
importpath = "go-common/app/job/main/credit-timer/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/credit-timer/conf:go_default_library",
"//app/job/main/credit-timer/service:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster: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,58 @@
package http
import (
"net/http"
"strconv"
"go-common/app/job/main/credit-timer/conf"
"go-common/app/job/main/credit-timer/service"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
)
var svc *service.Service
// Init init
func Init(c *conf.Config) {
initService(c)
// init inner router
engineInner := bm.DefaultServer(c.BM)
innerRouter(engineInner)
if err := engineInner.Start(); err != nil {
log.Error("bm.DefaultServer error(%v)", err)
panic(err)
}
}
// initService init services.
func initService(c *conf.Config) {
svc = service.New(c)
}
// innerRouter init local router api path.
func innerRouter(e *bm.Engine) {
//init api
e.GET("/monitor/ping", ping)
e.POST("/fixkpi", fixkpi)
}
func ping(c *bm.Context) {
if err := svc.Ping(c); err != nil {
log.Error("answer interface ping error")
c.AbortWithStatus(http.StatusServiceUnavailable)
}
}
func fixkpi(c *bm.Context) {
params := c.Request.Form
yStr := params.Get("year")
mStr := params.Get("month")
dStr := params.Get("day")
midStr := params.Get("mid")
y, _ := strconv.ParseInt(yStr, 10, 64)
m, _ := strconv.ParseInt(mStr, 10, 64)
d, _ := strconv.ParseInt(dStr, 10, 64)
mid, _ := strconv.ParseInt(midStr, 10, 64)
res, _ := svc.FixKPI(c, int(y), int(m), int(d), mid)
c.JSON(res, nil)
}

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 = ["jury.go"],
importpath = "go-common/app/job/main/credit-timer/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,78 @@
package model
import "time"
// case status
const (
CaseStatusGranting = 1 // 发放中
CaseStatusGrantStop = 2 // 停止发放
CaseStatusDealing = 3 // 结案中
CaseStatusDealed = 4 // 已裁决
CaseStatusRestart = 5 // 待重启
CaseStatusUndealed = 6 // 未裁决
JudgeTypeUndeal = 0 // 未裁决
JudgeTypeViolate = 1 // 违规
JudgeTypeLegal = 2 // 未违规
VoteTypeUndo = 0 // 未投票
VoteTypeViolate = 1 // 违规-封禁
VoteTypeDelete = 4 // 违规-删除
VoteTypeLegal = 2 // 不违规
VoteTypeGiveUp = 3 // 放弃投票
// JuryInvalid
JuryBlocked = 1
JuryExpire = 2
JuryAdmin = 3
)
// Case is jury case info.
type Case struct {
ID int64 `json:"id"`
Mid int64 `json:"mid"`
Agree int64 `json:"agree"`
Against int64 `json:"against"`
AdminAgree int64 `json:"ad_agree"`
AdminAgainst int64 `json:"ad_against"`
PunishStatus int8 `json:"pubish_status"`
PunishResult int8 `json:"pubish_result"`
BlockDays int64 `json:"block_days"`
}
// Kpi is jury kpi info.
type Kpi struct {
ID int64 `json:"id"`
Mid int64 `json:"mid"`
Point int64 `json:"point"`
Day time.Time `json:"day"`
Rate int64 `json:"rate"`
Rank int64 `json:"rank"`
RankPer int64 `json:"rank_per"`
RankTotal int64 `json:"rankTotal"`
Expired time.Time `json:"expired"`
PreCount int64 `json:"-"`
}
// KpiPoint is jury kpi point info.
type KpiPoint struct {
ID int64 `json:"id"`
Mid int64 `json:"mid"`
Day time.Time `json:"day"`
Point int64 `json:"point"`
ActiveDays int64 `json:"activeDays"`
VoteTotal int64 `json:"voteTotal"`
VoteRadio int64 `json:"voteRadio"`
BlockedTotal int64 `json:"blockedTotal"`
Expired time.Time `json:"expired"`
OpinionNum int64 `json:"opinion_num"`
OpinionLikes int64 `json:"opinion_likes"`
OpinionHates int64 `json:"opinion_hates"`
}
// KpiData is jury kpi data info.
type KpiData struct {
KpiPoint
VoteRealTotal int64 `json:"vote_real_total"`
}

View File

@@ -0,0 +1,52 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["service_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/credit-timer/conf:go_default_library",
"//library/log:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"jury.go",
"kpi_func.go",
"service.go",
],
importpath = "go-common/app/job/main/credit-timer/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/credit-timer/conf:go_default_library",
"//app/job/main/credit-timer/dao:go_default_library",
"//app/job/main/credit-timer/model: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,285 @@
package service
import (
"context"
"time"
"go-common/app/job/main/credit-timer/model"
"go-common/library/log"
)
func (s *Service) caseProc(ctx context.Context) {
affect, err := s.dao.UpdateCaseEndTime(ctx, time.Now())
log.Info("UpdateCaseEndTime affect %d err %v", affect, err)
if s.c.Judge.CaseEndVoteTotal > 0 {
affect, err = s.dao.UpdateCaseEndVote(ctx, s.c.Judge.CaseEndVoteTotal, time.Now().Add(time.Duration(s.c.Judge.ReservedTime)))
log.Info("UpdateCaseEndVote affect %d err %v", affect, err)
}
}
func (s *Service) loadConf(ctx context.Context) {
vTotal, err := s.dao.LoadConf(ctx)
if err != nil {
log.Error("loadConf error(%v)", err)
return
}
s.c.Judge.CaseEndVoteTotal = vTotal
}
func (s *Service) juryProc(c context.Context) {
affect, err := s.dao.UpdateJury(c, time.Now())
log.Info("update jury affect %d err %v", affect, err)
}
func (s *Service) voteProc(c context.Context) {
affect, err := s.dao.UpdateVote(c, time.Now())
log.Info("update vote affect %d err %v", affect, err)
}
// ComputePoint compute KPI point.
func (s *Service) ComputePoint(c context.Context, mid int64) (r model.KpiPoint, err error) {
var (
voteTotal, voteRight, blockedTotal, activeDays, opinionNums, opinionQuality int64
voteRightViolate, voteRightLegal, likes, hates int64
//vr:投准率 vf:投准率系数 af:活跃系数 bf:违规系数 of:观点数量系数 oqf:观点质量系数
vr, vf, af, bf, of, oqf float64
point float64
begin, end string
)
begin = time.Now().AddDate(0, 0, -30).Format("2006-01-02")
end = time.Now().Format("2006-01-02")
if blockedTotal, err = s.dao.CountBlocked(c, mid, begin, end); err != nil {
return
}
if blockedTotal == 0 {
bf = float64(1)
}
if voteTotal, err = s.dao.CountVoteTotal(c, mid, begin, end); err != nil {
return
}
if voteRightViolate, err = s.dao.CountVoteRightViolate(c, mid, begin, end); err != nil {
return
}
if voteRightLegal, err = s.dao.CountVoteRightLegal(c, mid, begin, end); err != nil {
return
}
voteRight = voteRightViolate + voteRightLegal
if voteTotal > 0 {
vr = float64(voteRight) / float64(voteTotal)
vf = s.voteRightRatio(vr)
}
if activeDays, err = s.dao.CountVoteActive(c, mid, begin, end); err != nil {
return
}
af = s.activeDaysRatio(activeDays)
if opinionNums, err = s.dao.CountOpinion(c, mid, begin, end); err != nil {
return
}
of = s.opinionNumsRatio(opinionNums)
if likes, hates, err = s.dao.OpinionQuality(c, mid, begin, end); err != nil {
return
}
opinionQuality = likes - hates
oqf = s.opinionQualityRatio(opinionQuality)
log.Info("mid:%d voteTotal:%v vr:%v vf:%v af:%v bf:%v of:%v oqf:%v", mid, voteTotal, vr, vf, af, bf, of, oqf)
point = float64(voteTotal) * vr * vf * af * bf * of * oqf * 100
r.Point = int64(point)
r.ActiveDays = activeDays
r.Day = time.Now()
r.Mid = mid
r.VoteTotal = voteTotal
r.VoteRadio = int64(vr * 100)
r.BlockedTotal = blockedTotal
r.OpinionNum = opinionNums
r.OpinionLikes = likes
r.OpinionHates = hates
return
}
func (s *Service) kpiPointProc(c context.Context) (err error) {
var (
mids []int64
mid int64
r model.KpiPoint
)
if mids, err = s.dao.JuryList(c); err != nil {
log.Error("kpiPoint err(%v)", err)
return
}
for _, mid = range mids {
if r, err = s.ComputePoint(c, mid); err != nil {
log.Error("computePoint err(%v)", err)
continue
}
s.dao.UpdateKPIPoint(c, &r)
}
return
}
// KPIProc KPI process.
func (s *Service) KPIProc(c context.Context) (err error) {
var (
ps []model.Kpi
res []model.KpiPoint
k model.KpiPoint
kd model.KpiData
at int64
day string
m int64
)
day = time.Now().Format("2006-01-02")
if res, err = s.dao.KPIPointDay(c, day); err != nil {
log.Error("kpiPoint(%s) err(%v)", day, err)
}
for _, k = range res {
a := model.Kpi{}
a.Point = k.Point
if len(ps) == 0 {
a.PreCount = 0
m = 1
ps = append(ps, a)
continue
}
if ps[len(ps)-1].Point == k.Point {
m = m + 1
continue
}
a.PreCount = m
ps = append(ps, a)
m = m + 1
}
at = int64(len(res))
d := time.Now()
for _, k = range res {
if k.Expired.Format("2006-01-02") != day {
log.Info("Expired(%s)!=day(%s)", k.Expired.Format("2006-01-02"), day)
continue
}
for i, r := range ps {
log.Info("RankPer r(%+v) k(%+v)", r, k)
if r.Point == k.Point {
b := model.Kpi{}
b.Point = k.Point
b.Rank = int64(i + 1)
b.RankPer = (r.PreCount + 1) * 100 / at
b.RankTotal = at
p := b.RankPer
if p == 0 {
b.Rate = 1
b.RankPer = 1
} else if p > 0 && p <= 10 {
b.Rate = 1
} else if p > 10 && p <= 25 {
b.Rate = 2
} else if p > 25 && p <= 40 {
b.Rate = 3
} else if p > 40 && p <= 60 {
b.Rate = 4
} else if p > 60 && p <= 100 {
b.Rate = 5
}
if r.Point == 0 {
b.Rate = 5
}
b.Day = d
b.Mid = k.Mid
if err = s.dao.UpdateKPI(c, &b); err != nil {
log.Error("dao.UpdateKPI(%+v) err(%v)", b, err)
}
kd.KpiPoint = k
end := k.Day
begin := k.Day.AddDate(0, 0, -30)
count, _ := s.dao.CountVoteByTime(c, k.Mid, begin, end)
kd.VoteRealTotal = count
if err = s.dao.UpdateKPIData(c, &kd); err != nil {
log.Error("dao.UpdateKPIData(%+v) err(%v)", kd, err)
}
break
}
}
}
return
}
// FixKPI fix kpi.
func (s *Service) FixKPI(c context.Context, year, month, dd int, mid int64) (res []model.KpiPoint, err error) {
var (
ps []model.Kpi
k model.KpiPoint
kd model.KpiData
at int64
day string
m int64
)
t := time.Date(year, time.Month(month), dd, 0, 0, 0, 0, time.UTC)
day = t.Format("2006-01-02")
if res, err = s.dao.KPIPointDay(c, day); err != nil {
log.Error("kpiPoint(%s) err(%v)", day, err)
}
for _, k = range res {
a := model.Kpi{}
a.Point = k.Point
if len(ps) == 0 {
a.PreCount = 0
m = 1
ps = append(ps, a)
continue
}
if ps[len(ps)-1].Point == k.Point {
m = m + 1
continue
}
a.PreCount = m
ps = append(ps, a)
m = m + 1
}
at = int64(len(res))
for _, k = range res {
for i, r := range ps {
if r.Point == k.Point {
b := model.Kpi{}
b.Point = k.Point
b.Rank = int64(i + 1)
b.RankPer = (r.PreCount + 1) * 100 / at
b.RankTotal = at
p := b.RankPer
if p == 0 {
b.Rate = 1
b.RankPer = 1
} else if p > 0 && p <= 10 {
b.Rate = 1
} else if p > 10 && p <= 25 {
b.Rate = 2
} else if p > 25 && p <= 40 {
b.Rate = 3
} else if p > 40 && p <= 60 {
b.Rate = 4
} else if p > 60 && p <= 100 {
b.Rate = 5
}
if r.Point == 0 {
b.Rate = 5
}
b.Day = t
b.Mid = k.Mid
if b.Mid == mid {
log.Info("fix kpi mid %d kpi %v", mid, b)
if err = s.dao.UpdateKPI(c, &b); err != nil {
log.Error("dao.UpdateKPI(%+v) err(%v)", b, err)
}
kd.KpiPoint = k
end := k.Day
begin := k.Day.AddDate(0, 0, -30)
count, _ := s.dao.CountVoteByTime(c, k.Mid, begin, end)
kd.VoteRealTotal = count
if err = s.dao.UpdateKPIData(c, &kd); err != nil {
log.Error("dao.UpdateKPIData(%+v) err(%v)", kd, err)
}
}
break
}
}
}
return
}

View File

@@ -0,0 +1,81 @@
package service
// 根据投准率计算投准系数
func (s *Service) voteRightRatio(vr float64) (vf float64) {
switch {
case vr >= 0.9:
vf = float64(1.2)
case vr >= 0.8 && vr < 0.9:
vf = float64(1.1)
case vr >= 0.7 && vr < 0.8:
vf = float64(0.9)
case vr >= 0.6 && vr < 0.7:
vf = float64(0.6)
case vr >= 0.5 && vr < 0.6:
vf = float64(0.3)
case vr >= 0.4 && vr < 0.5:
vf = float64(0.1)
default:
vf = float64(0)
}
return
}
// 根据活跃天数计算活跃系数
func (s *Service) activeDaysRatio(activeDays int64) (af float64) {
switch {
case activeDays >= 26:
af = float64(1.3)
case activeDays >= 21 && activeDays <= 25:
af = float64(1.2)
case activeDays >= 16 && activeDays <= 20:
af = float64(1.1)
case activeDays >= 11 && activeDays <= 15:
af = float64(1.0)
case activeDays >= 6 && activeDays <= 10:
af = float64(0.9)
case activeDays >= 1 && activeDays <= 5:
af = float64(0.7)
default:
af = float64(0)
}
return
}
// 根据观点数量计算观点数量系数
func (s *Service) opinionNumsRatio(opinionNums int64) (of float64) {
switch {
case opinionNums >= 31:
of = 1.3
case opinionNums >= 16 && opinionNums <= 30:
of = 1.2
case opinionNums >= 6 && opinionNums <= 15:
of = 1.1
case opinionNums >= 1 && opinionNums <= 5:
of = 1
default:
of = 0.8
}
return
}
// 根据观点(赞-踩)数计算观点质量系数
func (s *Service) opinionQualityRatio(opinionQuality int64) (oqf float64) {
switch {
case opinionQuality >= 16:
oqf = 1.3
case opinionQuality >= 6 && opinionQuality <= 15:
oqf = 1.2
case opinionQuality >= 1 && opinionQuality <= 5:
oqf = 1.1
case opinionQuality == 0:
oqf = 1
case opinionQuality >= -10 && opinionQuality <= -1:
oqf = 0.8
case opinionQuality >= -20 && opinionQuality <= -11:
oqf = 0.7
case opinionQuality <= -21:
oqf = 0.5
}
return
}

View File

@@ -0,0 +1,96 @@
package service
import (
"context"
"time"
"go-common/app/job/main/credit-timer/conf"
"go-common/app/job/main/credit-timer/dao"
"go-common/library/log"
)
// Service struct of service.
type Service struct {
c *conf.Config
dao *dao.Dao
}
// New create service instance and return.
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
dao: dao.New(c),
}
go s.loadConfproc()
go s.caseproc()
go s.juryproc()
go s.voteproc()
go s.kpiproc()
return
}
func (s *Service) loadConfproc() {
for {
s.loadConf(context.TODO())
time.Sleep(time.Duration(s.c.Judge.ConfTimer))
}
}
func (s *Service) caseproc() {
for {
s.caseProc(context.TODO())
time.Sleep(time.Duration(s.c.Judge.CaseTimer))
}
}
func (s *Service) juryproc() {
for {
s.juryProc(context.TODO())
time.Sleep(time.Duration(s.c.Judge.JuryTimer))
}
}
func (s *Service) voteproc() {
for {
s.voteProc(context.TODO())
time.Sleep(time.Duration(s.c.Judge.VoteTimer))
}
}
func (s *Service) kpiproc() {
var err error
for {
d := time.Now().AddDate(0, 0, 1)
ts := time.Until(time.Date(d.Year(), d.Month(), d.Day(), 0, 0, 1, 0, time.Local))
time.Sleep(ts)
for {
err = s.kpiPointProc(context.TODO())
if err != nil {
log.Error("kpiPointProc err(%v)", err)
time.Sleep(time.Second * 5)
continue
}
break
}
log.Info("KPIPointproc err(%v)", err)
for {
err = s.KPIProc(context.TODO())
if err != nil {
log.Error("kpiProc err(%v)", err)
time.Sleep(time.Second * 5)
continue
}
break
}
log.Info("kpiproc err(%v)", err)
}
}
// Close kafka consumer close.
func (s *Service) Close() (err error) {
return
}
// Ping check service health.
func (s *Service) Ping(c context.Context) error {
return s.dao.Ping(c)
}

View File

@@ -0,0 +1,121 @@
package service
import (
"context"
"flag"
"fmt"
"path/filepath"
"testing"
"time"
"go-common/app/job/main/credit-timer/conf"
"go-common/library/log"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func init() {
dir, _ := filepath.Abs("../cmd/convey-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
// TestService_loadConf
func Test_loadConf(t *testing.T) {
Convey("should return err be nil", t, func() {
s.loadConf(context.TODO())
So(s.c.Judge.CaseEndVoteTotal, ShouldBeGreaterThanOrEqualTo, 0)
})
}
// TestService_ComputePoint
func Test_ComputePoint(t *testing.T) {
Convey("should return err be nil", t, func() {
r, err := s.ComputePoint(context.TODO(), 88889017)
So(err, ShouldBeNil)
So(r, ShouldNotBeNil)
// So(r, ShouldResemble,model.KpiPoint{})
})
}
func TestService_sort(t *testing.T) {
var (
res = []int64{1, 3, 4, 5, 5, 6, 7, 9, 9, 10, 11, 12}
ps []int64
)
for _, k := range res {
if len(ps) == 0 {
ps = append(ps, k)
continue
}
if ps[len(ps)-1] == k {
continue
}
ps = append(ps, k)
}
t.Logf("%v", ps)
for _, k := range res {
for i, r := range ps {
if r == k {
t.Logf("%d,%d,%d", k, i+1, (i+1)*100/len(ps))
break
}
}
}
}
func TestService_point(t *testing.T) {
var (
point float64
voteTotal int64
voteRight int64
//投准率
vr float64
//投准率系数
vf float64
)
voteTotal = 12
voteRight = 5
vr = float64(voteRight) / float64(voteTotal)
vf = float64(1.0)
point = float64(voteTotal) * vr * vf
t.Logf("%f", point)
}
func initConf(t *testing.T) {
if err := conf.Init(); err != nil {
t.Errorf("conf.Init() error(%v)", err)
t.FailNow()
}
log.Init(conf.Conf.Xlog)
defer log.Close()
}
func Test_Time(t *testing.T) {
Convey("should return err be nil", t, func() {
d := time.Now().AddDate(0, 0, 1)
ts1 := time.Until(time.Date(d.Year(), d.Month(), d.Day(), 0, 0, 1, 0, time.Local))
ts2 := time.Date(d.Year(), d.Month(), d.Day(), 0, 0, 1, 0, time.Local).Sub(time.Now())
t.Errorf("%#v %#v", ts1, ts2)
So(ts1, ShouldEqual, ts2)
})
}
func Test_FixKPI(t *testing.T) {
Convey("should return err be nil", t, func() {
res, err := s.FixKPI(context.TODO(), 2018, 2, 10, 7584862)
fmt.Printf("res:%+v \n", res)
So(err, ShouldBeNil)
})
}