func (u *User) PopulateStats() error {
	Fields, err := GetUserStatsFields()
	if err != nil {
		Error.Println("Could not get users stats fields :", err)
		return err
	}
	StatFields := make(map[string]int64)
	for _, field := range Fields {
		StatFields[field] = 0
	}
	rows, err := Db.Query("SELECT name, value FROM neb_users_stats WHERE userid = ?", u.Id)
	if err != nil {
		Error.Println("Could not get user stats :", err)
		return err
	}
	defer rows.Close()
	for rows.Next() {
		var name string
		var value int64
		err := rows.Scan(&name, &value)
		if err != nil {
			Error.Println("Could not get user Stats :", err)
			return err
		}
		StatFields[name] = value
	}
	err = rows.Err()
	if err != nil {
		Error.Println("Could not get user Stats :", err)
		return err
	}
	for field, value := range StatFields {
		var st UserStat
		st.Name = field
		st.Value = value
		u.Stats = append(u.Stats, st)
	}
	return nil
}
We load complex stats informations stored in neb_stats_tables
to make a list of stats the user has. Entry for users is the users' fields
and entries with AutoCount true are additional fields updated when a complex stat is added
package core
import (
	"crypto/rand"
	"crypto/sha512"
	"database/sql"
	"encoding/base64"
)
type Achievement struct {
	Id       int
	Name     string
	Progress uint
	Max      uint
	Icon     string
}
func (a *Achievement) isComplete() bool {
	return a.Progress == a.Max
}
type User struct {
	Id           int
	Username     string
	Rank         int
	Avatar       string
	Achievements []Achievement
	Stats        []UserStat
}
const (
	UserMaskBase = 1 << iota
	UserMaskOnlyId
	UserMaskAchievements
	UserMaskStats
	UserMaskAll = UserMaskStats | UserMaskAchievements
)
const (
	UserRankBanned = 1 << iota
	UserRankNormal
	UserRankDev
	UserRankAdmin
	UserRankTester
)
func GetUserBySession(SessionId string, BitMask int) (*User, error) {
	var user User
	var id int
	err := Db.QueryRow("SELECT userid FROM neb_sessions WHERE sessionid = ?", SessionId).Scan(&id)
	if err != nil && err == sql.ErrNoRows {
		return nil, &NebuleuseError{NebErrorDisconnected, "No session found"}
	} else if err != nil {
		return nil, err
	}
	user.Id = id
	user.FetchUserInfos(BitMask)
	go user.Heartbeat()
	return &user, nil
}
func (u *User) FetchUserInfos(Bitmask int) error {
	if Bitmask&UserMaskOnlyId != 0 {
		return nil
	}
	err := Db.QueryRow("SELECT username, rank, avatars FROM neb_users WHERE id = ?", u.Id).Scan(&u.Username, &u.Rank, &u.Avatar)
	if err != nil && err == sql.ErrNoRows {
		return &NebuleuseError{NebErrorDisconnected, "No user found"}
	} else if err != nil {
		return err
	}
	if u.Avatar == "" {
		u.Avatar = Cfg.GetConfig("defaultAvatar")
	}
	if Bitmask&UserMaskAchievements != 0 {
		u.PopulateAchievements()
	}
	if Bitmask&UserMaskStats != 0 {
		u.PopulateStats()
	}
	return nil
}
func RegisterUser(username string, password string, rank int) error {
	c := sha512.Size
	bhash := make([]byte, c)
	_, err := rand.Read(bhash)
	if err != nil {
		Error.Println("Error generating crytpo hash:", err)
		return err
	}
	hash := base64.URLEncoding.EncodeToString(bhash)
	hashedPassword := HashPassword(password, string(hash))
	stmt, err := Db.Prepare("INSERT INTO neb_users (username,password,rank,hash) VALUES (?,?,?,?)")
	_, err = stmt.Exec(username, hashedPassword, rank, string(hash))
	if err != nil {
		Error.Println("Could not register new user :", err)
		return err
	}
	return nil
}
func (u *User) PopulateAchievements() error {
	rows, err := Db.Query("SELECT id, name, max, icon, progress FROM neb_achievements AS ach LEFT JOIN neb_users_achievements AS usr ON ach.id = usr.achievementid AND usr.userid = ?", u.Id)
	if err != nil {
		Error.Println("Could not get user achievements :", err)
		return err
	}
	defer rows.Close()
	for rows.Next() {
		var ach Achievement
		var progress sql.NullInt64
		progress.Int64 = 0
		err := rows.Scan(&ach.Id, &ach.Name, &ach.Max, &ach.Icon, &progress)
		if err != nil {
			Error.Println("Could not get user achievements :", err)
			return err
		}
		ach.Progress = uint(progress.Int64)
		u.Achievements = append(u.Achievements, ach)
	}
	err = rows.Err()
	if err != nil {
		Error.Println("Could not get user achievements :", err)
		return err
	}
	return nil
}