go-common/app/job/main/reply-feed/model/algorithm.go
2019-04-22 18:49:16 +08:00

198 lines
3.9 KiB
Go

package model
import (
"math"
"time"
)
// Algorithm Algorithm
type Algorithm interface {
Score(stat *ReplyStat) *ReplyScore
Slots() []int
Name() string
}
/*
Origin Algorithm.
*/
// Origin origin algorithm
type Origin struct {
name string
slots []int
}
// NewOrigin NewLikeDesc Aogorithm
func NewOrigin(name string, slots []int) *Origin {
return &Origin{
name: name,
slots: slots,
}
}
// Name get name
func (o *Origin) Name() string {
return o.name
}
// Slots get slots
func (o *Origin) Slots() []int {
return o.slots
}
// Score calc score
func (o *Origin) Score(stat *ReplyStat) (rs *ReplyScore) {
rs = new(ReplyScore)
rs.RpID = stat.RpID
if stat.Like < 0 || stat.Reply < 0 || stat.Report < 0 || stat.Hate < 0 {
return
}
score := int64(100 * ((stat.Like + 2) / (stat.Hate + 4 + stat.Report)))
score = score<<32 | (int64(stat.Reply) & 0xFFFFFFFF)
rs.Score = float64(score)
return
}
/*
LikeDesc Algorithm order by like desc.
*/
// LikeDesc like desc
type LikeDesc struct {
name string
slots []int
}
// NewLikeDesc NewLikeDesc Aogorithm
func NewLikeDesc(name string, slots []int) *LikeDesc {
return &LikeDesc{
name: name,
slots: slots,
}
}
// Name get name
func (l *LikeDesc) Name() string {
return l.name
}
// Slots get slots
func (l *LikeDesc) Slots() []int {
return l.slots
}
// Score calc score
func (l *LikeDesc) Score(stat *ReplyStat) (rs *ReplyScore) {
rs = new(ReplyScore)
rs.RpID = stat.RpID
rs.Score = float64(stat.Like)
return
}
/*
WilsonLHRR wilson algorithm
like,reply
hate,report
*/
// WilsonLHRR WilsonLHRR
type WilsonLHRR struct {
name string
slots []int
weight *WilsonLHRRWeight
}
// NewWilsonLHRR NewWilsonLHRR
func NewWilsonLHRR(name string, slots []int, weight *WilsonLHRRWeight) *WilsonLHRR {
return &WilsonLHRR{
name: name,
slots: slots,
weight: weight,
}
}
// Name get name
func (w *WilsonLHRR) Name() string {
return w.name
}
// Slots get slots
func (w *WilsonLHRR) Slots() []int {
return w.slots
}
// Score calc score
func (w *WilsonLHRR) Score(stat *ReplyStat) (rs *ReplyScore) {
rs = new(ReplyScore)
rs.RpID = stat.RpID
if stat.Like < 0 || stat.Reply < 0 || stat.Report < 0 || stat.Hate < 0 {
return
}
ups := float64(stat.Like)*w.weight.Like + float64(stat.Reply)*w.weight.Reply
downs := float64(stat.Hate)*w.weight.Hate + float64(stat.Report)*w.weight.Report
n := ups + downs
if n == 0 {
return
}
z := float64(2)
p := ups / n
rs.Score = (p + math.Pow(z, 2)/(2*n) - (z/(2*n))*math.Sqrt(4*n*(1-p)*p+math.Pow(z, 2))) / (1 + math.Pow(z, 2)/n)
return
}
/*
WilsonLHRRFluid wilson algorightm dynamic score by time
like,reply
hate,report
*/
// WilsonLHRRFluid WilsonLHRRFluid
type WilsonLHRRFluid struct {
name string
slots []int
weight *WilsonLHRRFluidWeight
}
// NewWilsonLHRRFluid NewWilsonLHRRFluid
func NewWilsonLHRRFluid(name string, slots []int, weight *WilsonLHRRFluidWeight) *WilsonLHRRFluid {
return &WilsonLHRRFluid{
name: name,
slots: slots,
weight: weight,
}
}
// Name get name
func (w *WilsonLHRRFluid) Name() string {
return w.name
}
// Slots get slots
func (w *WilsonLHRRFluid) Slots() []int {
return w.slots
}
func coolDownFunc(weight *WilsonLHRRFluidWeight, duration float64) (coefficient float64) {
return 1.5 - (0.5 / (1 + math.Exp(-weight.Slope*(duration))))
}
// Score calc score
func (w *WilsonLHRRFluid) Score(stat *ReplyStat) (rs *ReplyScore) {
rs = new(ReplyScore)
rs.RpID = stat.RpID
if stat.Like < 0 || stat.Reply < 0 || stat.Report < 0 || stat.Hate < 0 {
return
}
ups := float64(stat.Like)*w.weight.Like + float64(stat.Reply)*w.weight.Reply
downs := float64(stat.Hate)*w.weight.Hate + float64(stat.Report)*w.weight.Report
n := ups + downs
if n == 0 {
return
}
z := float64(2)
p := ups / n
coefficient := coolDownFunc(w.weight, float64(time.Now().Unix()-int64(stat.ReplyTime))/86400)
rs.Score = ((p + math.Pow(z, 2)/(2*n) - (z/(2*n))*math.Sqrt(4*n*(1-p)*p+math.Pow(z, 2))) / (1 + math.Pow(z, 2)/n)) * coefficient
return
}