aboutsummaryrefslogtreecommitdiff
path: root/user/xp.go
diff options
context:
space:
mode:
Diffstat (limited to 'user/xp.go')
-rw-r--r--user/xp.go99
1 files changed, 99 insertions, 0 deletions
diff --git a/user/xp.go b/user/xp.go
index f8bcd06..c2e4d08 100644
--- a/user/xp.go
+++ b/user/xp.go
@@ -1,11 +1,30 @@
package user
import (
+ "fmt"
+ "github.com/anhgelus/gokord"
"github.com/anhgelus/gokord/utils"
+ "github.com/anhgelus/les-copaings-bot/config"
"github.com/anhgelus/les-copaings-bot/exp"
"github.com/bwmarrin/discordgo"
+ "slices"
+ "sync"
+ "time"
)
+type cXP struct {
+ Cxp uint
+ *Copaing
+}
+
+func (c *cXP) ToCopaing() *Copaing {
+ return c.Copaing
+}
+
+func (c *cXP) GetXP() uint {
+ return c.Cxp
+}
+
func (c *Copaing) AddXP(s *discordgo.Session, m *discordgo.Member, xp uint, fn func(uint, uint)) {
old, err := c.GetXP()
pastLevel := exp.Level(old)
@@ -29,3 +48,83 @@ func (c *Copaing) AddXP(s *discordgo.Session, m *discordgo.Member, xp uint, fn f
onNewLevel(s, m, newLevel)
}
}
+
+func (c *Copaing) GetXP() (uint, error) {
+ cfg := config.GetGuildConfig(c.GuildID)
+ return c.GetXPForDays(cfg.DaysXPRemains)
+}
+
+func (c *Copaing) GetXPForDays(n uint) (uint, error) {
+ xp := uint(0)
+ y, m, d := time.Unix(time.Now().Unix()-int64(n*24*60*60), 0).Date()
+ rows, err := gokord.DB.
+ Model(&CopaingXP{}).
+ Where(fmt.Sprintf("created_at >= '%d-%d-%d' and guild_id = ? and discord_id = ?", y, m, d), c.GuildID, c.DiscordID).
+ Rows()
+ defer rows.Close()
+ if err != nil {
+ return 0, err
+ }
+ for rows.Next() {
+ var cXP CopaingXP
+ err = gokord.DB.ScanRows(rows, &cXP)
+ if err != nil {
+ utils.SendAlert("user/xp.go - Scanning rows", err.Error(), "discord_id", c.DiscordID, "guild_id", c.GuildID)
+ continue
+ }
+ xp += cXP.XP
+ }
+ return xp, nil
+}
+
+// GetBestXP returns n Copaing with the best XP within d days (d <= cfg.DaysXPRemain; d < 0 <=> d = cfg.DaysXPRemain)
+//
+// This function is slow
+func GetBestXP(guildId string, n uint, d int) ([]CopaingAccess, error) {
+ if d < 0 {
+ cfg := config.GetGuildConfig(guildId)
+ d = int(cfg.DaysXPRemains)
+ }
+ rows, err := gokord.DB.Model(&Copaing{}).Where("guild_id = ?", guildId).Rows()
+ defer rows.Close()
+ if err != nil {
+ return nil, err
+ }
+ var l []*cXP
+ wg := sync.WaitGroup{}
+ for rows.Next() {
+ var c Copaing
+ err = gokord.DB.ScanRows(rows, &c)
+ if err != nil {
+ utils.SendAlert("user/xp.go - Scanning rows", err.Error(), "discord_id", c.DiscordID, "guild_id", guildId)
+ continue
+ }
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ xp, err := c.GetXPForDays(uint(d))
+ if err != nil {
+ utils.SendAlert("user/xp.go - Fetching xp", err.Error(), "discord_id", c.DiscordID, "guild_id", guildId)
+ return
+ }
+ l = append(l, &cXP{Cxp: xp, Copaing: &c})
+ }()
+ }
+ wg.Wait()
+ slices.SortFunc(l, func(a, b *cXP) int {
+ // desc order
+ if a.Cxp < b.Cxp {
+ return 1
+ }
+ if a.Cxp > b.Cxp {
+ return -1
+ }
+ return 0
+ })
+ m := min(len(l), int(n))
+ cs := make([]CopaingAccess, m)
+ for i, c := range l[:m] {
+ cs[i] = c
+ }
+ return cs, nil
+}