From cc9bfd43b52f443d45295f56058b483bb18ff45c Mon Sep 17 00:00:00 2001 From: Brian Buller Date: Fri, 13 Nov 2015 11:15:03 -0600 Subject: [PATCH] More Achieve Work --- assets/css/statbot.css | 1 - assets/js/levelup_main.js | 2 +- levelup_model.go | 25 +++++ processor_levelupachieve.go | 201 ++++++++++++++++++++++++++++++------ statbot.go | 2 + 5 files changed, 199 insertions(+), 32 deletions(-) diff --git a/assets/css/statbot.css b/assets/css/statbot.css index 81b4e20..d4414c2 100644 --- a/assets/css/statbot.css +++ b/assets/css/statbot.css @@ -32,7 +32,6 @@ body { .content { margin: 0 auto; padding: 0 2em; - max-width: 800px; margin-bottom: 50px; line-height: 1.6em; } diff --git a/assets/js/levelup_main.js b/assets/js/levelup_main.js index 46f316b..5ea11fe 100644 --- a/assets/js/levelup_main.js +++ b/assets/js/levelup_main.js @@ -111,7 +111,7 @@ function buildList() { userName = levelUpStats.users[i].name, idName = userName.replace('.','_'); - B("#userXpList").append(B('
').attr('id',"levelup-user-"+idName).addClass('levelup-user pure-u-1 pure-u-md-11-24').attr('data-username',userName)); + B("#userXpList").append(B('
').attr('id',"levelup-user-"+idName).addClass('levelup-user pure-u-1 pure-u-md-10-24 pure-u-lg-6-24 pure-u-xl-5-24').attr('data-username',userName)); var userNameSpan = B("").attr('id','levelup-user-'+idName+'-name'); userNameSpan.addClass('levelup-username'); var levelDiv = B("
").attr('id','levelup-user-'+idName+'-level'); diff --git a/levelup_model.go b/levelup_model.go index e2f5ace..4d431d7 100644 --- a/levelup_model.go +++ b/levelup_model.go @@ -66,3 +66,28 @@ func getAllNonLevelUpStats(user string) map[string]int { closeDatabase() return ret } + +func getAllUserAcheivements(user string) map[string]int { + openDatabase() + ret := make(map[string]bool) + db.Update(func(tx *bolt.Tx) error { + var b, uB, uSB *bolt.Bucket + var err error + + b = tx.Bucket([]byte("users")) + if b == nil { + return fmt.Errorf("Unable to open 'users' bucket") + } + if uB = b.Bucket([]byte(user)); uB != nil { + if uSB = uB.Bucket([]byte("achievements")); uSB != nil { + return uSB.ForEach(func(k, v []byte) error { + ret[string(k)] = (string(v) == "true") + return nil + }) + } + } + return err + }) + closeDatabase() + return ret +} diff --git a/processor_levelupachieve.go b/processor_levelupachieve.go index 8adee02..36be6b6 100644 --- a/processor_levelupachieve.go +++ b/processor_levelupachieve.go @@ -2,6 +2,19 @@ package main import "net/http" +type levelUpAchievement struct { + GetName func() string + GetText func() string + GetKeyName func() string + // Processes the message, returns true if the achievement was triggered + ProcessMessage func(ustat *UserLevelUpStats) bool +} + +func (achieve *levelUpAchievement) DoesUserHave(ustat *UserLevelUpStats) bool { + val, ok := ustat.Achievements[achieve.GetKeyName()] + if ustat.Achievements +} + type levelUpAchieveStatProcessor struct { Achievements []levelUpAchievement } @@ -16,47 +29,42 @@ func (p *levelUpAchieveStatProcessor) GetStatKeys() []string { } } -func (p *levelUpAcheiveStatProcessor) Initialize() { - // TODO: Set up achievements - p.Achievements = append(p.Achievements, levelUpAchievement{ - GetName: func() string { - }, - GetText: func() string { - }, - DoesUserHave: func(uID string) bool { - }, - ProcessMessage: func(m *Message) bool { - }, - }) - -} - -type levelUpAchievement struct { - GetName func() string - GetText func() string - // Returns whether the user already has this achievement - DoesUserHave func(uID string) bool - // Processes the message, returns true if the achievement was triggered - ProcessMessage func(m *Message) bool +// UserLevelUpStats is just a struct for caching user data... +// This processor needs to crunch a lot of numbers, this should make +// it quicker/easier +type UserLevelUpStats struct { + Name string + Xp int + ChannelStats map[string]int + OtherStats map[string]int + Achievements map[string]bool + CurrentMsg *Message + CurrentCh *Channel } func (p *levelUpAchieveStatProcessor) ProcessMessage(m *Message) { - type UserLevelUpStats struct { - Name string - Xp int - ChannelStats map[string]int - OtherStats map[string]int - } var u *User var err error if u, err = getUserInfo(m.User); err != nil { return } - userStat := UserLevelUpStats{Name: u.Name} + userStat := UserLevelUpStats{Name: u.Name, CurrentMsg: m} userStat.Xp, _ = getUserStat(u.ID, "levelup-xp") userStat.ChannelStats = getAllLevelUpChannelXp(u.ID) userStat.OtherStats = getAllNonLevelUpStats(u.ID) + userStat.Achievements = getAllUserAchievements(u.ID) + chnl, err := getChannelInfo(m.Channel) + if err == nil { + userStat.CurrentCh = chnl + } + + for _, achieve := range p.Achievements { + if !achieve.DoesUserHave(userStat) { + // User doesn't already have this achieve, let it process the message + achieve.ProcessMessage(userStat) + } + } } func (p *levelUpAchieveStatProcessor) ProcessAdminMessage(m *Message) {} func (p *levelUpAchieveStatProcessor) ProcessBotMessage(m *Message) {} @@ -100,5 +108,138 @@ func (wm *levelUpAchieveWebModule) GetBottomMenuEntries() []menuItem { func (wm *levelUpAchieveWebModule) handleLevelUpAchieveGeneral(w http.ResponseWriter, req *http.Request) { initRequest(w, req) - setMenuItemActive("Achieve GET!") + //setMenuItemActive("Achieve GET!") +} + +/* + * Achieve Stat Processor Initialization + * It's down here because it's so long what with all + * of it's achievements and such. + */ +func (p *levelUpAcheiveStatProcessor) Initialize() { + // TODO: Set up achievements + p.Achievements = append(p.Achievements, + // Early Bird Achievement + levelUpAchievement{ + GetName: func() string { + return "Early Bird" + }, + GetText: func() string { + return "You seem to enjoy chatting before 7 AM" + }, + GetKeyName: func() string { + return "levelup-achieve-earlybird" + }, + ProcessMessage: func(u *userStat) bool { + // TODO: What condition makes this happen? + if m.Time.Hour() > 3 && m.Time.Hour() < 7 { + numMsgs := 0 + numMsgs = numMsgs + userStat.OtherStats["message-hour-04"] + numMsgs = numMsgs + userStat.OtherStats["message-hour-05"] + numMsgs = numMsgs + userStat.OtherStats["message-hour-06"] + /* + if chnl.Name == "random" { + addUserStat(m.User, "levelup-xp", 1) + } else if chnl.Name == "general" { + addUserStat(m.User, "levelup-xp", 2) + } else { + addUserStat(m.User, "levelup-xp", 3) + addUserStat(m.User, "levelup-xp-"+chnl.Name, 1) + } + */ + } + return false + }, + }, + ) + + p.Achievements = append(p.Achievements, + // Night Owl Achievement + levelUpAchievement{ + GetName: func() string { + return "Night Owl" + }, + GetText: func() string { + return "You seem to enjoy chatting after 12 AM" + }, + GetKeyName: func() string { + return "levelup-achieve-nightowl" + }, + ProcessMessage: func(u *userStat) bool { + // TODO: What condition makes this happen? + }, + }, + ) + + p.Achievements = append(p.Achievements, + // Around the Clock Achievement + levelUpAchievement{ + GetName: func() string { + return "Around the Clock" + }, + GetText: func() string { + return "You have sent at least one message in every hour of the day" + }, + GetKeyName: func() string { + return "levelup-achieve-aroundtheclock" + }, + ProcessMessage: func(u *userStat) bool { + // TODO: What condition makes this happen? + }, + }, + ) + + p.Achievements = append(p.Achievements, + // Beginner Achievement + levelUpAchievement{ + GetName: func() string { + return "Beginner" + }, + GetText: func() string { + return "Get on the XP Chart" + }, + GetKeyName: func() string { + return "levelup-achieve-beginner" + }, + ProcessMessage: func(u *userStat) bool { + // TODO: What condition makes this happen? + }, + }, + ) + + p.Achievements = append(p.Achievements, + // Experienced Achievement + levelUpAchievement{ + GetName: func() string { + return "Experienced" + }, + GetText: func() string { + return "Reach level 5" + }, + GetKeyName: func() string { + return "levelup-achieve-experienced" + }, + ProcessMessage: func(u *userStat) bool { + // TODO: What condition makes this happen? + }, + }, + ) + + p.Achievements = append(p.Achievements, + // Super Advanced! Achievement + levelUpAchievement{ + GetName: func() string { + return "Super Advanced!" + }, + GetText: func() string { + return "Reach level 10" + }, + GetKeyName: func() string { + return "levelup-achieve-superadvanced" + }, + ProcessMessage: func(u *userStat) bool { + // TODO: What condition makes this happen? + }, + }, + ) } diff --git a/statbot.go b/statbot.go index 7e2a749..31ec042 100644 --- a/statbot.go +++ b/statbot.go @@ -9,6 +9,7 @@ import ( const programName = "statbot" +// Message Processors are interfaces for interacting. type messageProcessor interface { GetName() string GetHelp() string @@ -25,6 +26,7 @@ type messageProcessor interface { var messageProcessors []messageProcessor +// Message Processors are interfaces for accumulating statistics. type statProcessor interface { GetName() string GetStatKeys() []string