Files

64 lines
1.6 KiB
Go

package ctxmgr
import (
"math"
"time"
)
// CalculateDecayedWeight 计算考虑时间半衰期与里程碑豁免后的有效权重
func CalculateDecayedWeight(rawWeight float64, createdAt time.Time, isMilestone bool, cfg TimeDecayConfig) float64 {
if rawWeight <= 0 {
rawWeight = 1.00
}
if !cfg.Enabled {
return rawWeight
}
// 里程碑事件豁免衰减,作为永久基石
if isMilestone && cfg.MilestoneExempt {
return rawWeight
}
halfLife := cfg.HalfLifeDays
if halfLife <= 0 {
halfLife = 7.0
}
daysDiff := time.Since(createdAt).Hours() / 24.0
if daysDiff <= 0 {
return rawWeight
}
lambda := math.Ln2 / halfLife
decayFactor := math.Exp(-lambda * daysDiff)
decayed := rawWeight * decayFactor
// 应用衰减下限保护,防止早期有价值信息完全被截断
floor := rawWeight * cfg.MinWeightFloor
if decayed < floor {
decayed = floor
}
return math.Round(decayed*1000) / 1000
}
// ApplyTimeDecayToActivities 对活动流批量应用时间衰减并按最终有效权重重排
func ApplyTimeDecayToActivities(items []ActivityItem, cfg TimeDecayConfig) []ActivityItem {
res := make([]ActivityItem, len(items))
for i, it := range items {
it.DecayedWeight = CalculateDecayedWeight(it.RawWeight, it.CreatedAt, it.IsMilestone, cfg)
res[i] = it
}
// 稳定排序:按 DecayedWeight 降序,相同时按时间倒序
for i := 0; i < len(res); i++ {
for j := i + 1; j < len(res); j++ {
if res[j].DecayedWeight > res[i].DecayedWeight ||
(res[j].DecayedWeight == res[i].DecayedWeight && res[j].CreatedAt.After(res[i].CreatedAt)) {
res[i], res[j] = res[j], res[i]
}
}
}
return res
}