198 lines
3.9 KiB
Go
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
|
||
|
}
|