This commit is contained in:
parent
3302634f61
commit
4d5b25a761
43
dataBase.go
43
dataBase.go
@ -68,7 +68,11 @@ type Player struct {
|
|||||||
level int
|
level int
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchPlayer(r *sql.Rows, p *Player) error {
|
type scannable interface {
|
||||||
|
Scan(dest ...interface{}) error
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchPlayer(r scannable, p *Player) error {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
lastOnline string
|
lastOnline string
|
||||||
@ -119,73 +123,56 @@ func (db *dbLayer) getPlayers(ctx context.Context) ([]Player, error) {
|
|||||||
func (db *dbLayer) getPlayerByID(ctx context.Context, id string) (*Player, error) {
|
func (db *dbLayer) getPlayerByID(ctx context.Context, id string) (*Player, error) {
|
||||||
query := "SELECT id, name, last_login, online_duration, deaths, level FROM players WHERE id = $1"
|
query := "SELECT id, name, last_login, online_duration, deaths, level FROM players WHERE id = $1"
|
||||||
|
|
||||||
rows, err := db.db.QueryContext(ctx, query, id)
|
row := db.db.QueryRowContext(ctx, query, id)
|
||||||
if err != nil {
|
if err := row.Err(); err != nil {
|
||||||
return nil, errors.Wrapf(err, "Failed to run db query [%s]", query)
|
return nil, errors.Wrapf(err, "Failed to run db query [%s]", query)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
if rows.Next() {
|
|
||||||
var p Player
|
var p Player
|
||||||
|
|
||||||
err = fetchPlayer(rows, &p)
|
err := fetchPlayer(row, &p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &p, nil
|
return &p, nil
|
||||||
}
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *dbLayer) getPlayerByName(ctx context.Context, name string) (*Player, error) {
|
func (db *dbLayer) getPlayerByName(ctx context.Context, name string) (*Player, error) {
|
||||||
query := "SELECT id, name, last_login, online_duration, deaths, level FROM players WHERE name = $1 LIMIT 1"
|
query := "SELECT id, name, last_login, online_duration, deaths, level FROM players WHERE name = $1 LIMIT 1"
|
||||||
|
|
||||||
rows, err := db.db.QueryContext(ctx, query, name)
|
row := db.db.QueryRowContext(ctx, query, name)
|
||||||
if err != nil {
|
if err := row.Err(); err != nil {
|
||||||
return nil, errors.Wrapf(err, "Failed to run db query [%s]", query)
|
return nil, errors.Wrapf(err, "Failed to run db query [%s]", query)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
if rows.Next() {
|
|
||||||
var p Player
|
var p Player
|
||||||
|
|
||||||
err = fetchPlayer(rows, &p)
|
err := fetchPlayer(row, &p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &p, nil
|
return &p, nil
|
||||||
}
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *dbLayer) getKillsByOPlayerID(ctx context.Context, playerID string) (int, error) {
|
func (db *dbLayer) getKillsByPlayerID(ctx context.Context, playerID string) (int, error) {
|
||||||
query := "SELECT SUM(count) FROM killings WHERE player_id = $1 GROUP BY player_id"
|
query := "SELECT SUM(count) FROM killings WHERE player_id = $1 GROUP BY player_id"
|
||||||
|
|
||||||
rows, err := db.db.QueryContext(ctx, query, playerID)
|
row := db.db.QueryRowContext(ctx, query, playerID)
|
||||||
if err != nil {
|
if err := row.Err(); err != nil {
|
||||||
return 0, errors.Wrapf(err, "Failed to run db query [%s]", query)
|
return 0, errors.Wrapf(err, "Failed to run db query [%s]", query)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
if rows.Next() {
|
|
||||||
var killsNum int
|
var killsNum int
|
||||||
|
|
||||||
err = rows.Scan(&killsNum)
|
err := row.Scan(&killsNum)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, errors.Wrap(err, "Failed to fetch data base")
|
return 0, errors.Wrap(err, "Failed to fetch data base")
|
||||||
}
|
}
|
||||||
|
|
||||||
return killsNum, nil
|
return killsNum, nil
|
||||||
}
|
|
||||||
|
|
||||||
return 0, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *dbLayer) createPlayer(ctx context.Context, name string, lastOnline time.Time) (*Player, error) {
|
func (db *dbLayer) createPlayer(ctx context.Context, name string, lastOnline time.Time) (*Player, error) {
|
||||||
|
19
handlers.go
19
handlers.go
@ -49,7 +49,7 @@ func (c *joinCommand) run(ctx context.Context) {
|
|||||||
log := getLogger(ctx)
|
log := getLogger(ctx)
|
||||||
pb := getDPlayersBoard(ctx)
|
pb := getDPlayersBoard(ctx)
|
||||||
|
|
||||||
mess := tgbotapi.NewMessage(cfg.ChatID, fmt.Sprintf("%s вошел в матрицу", c.name))
|
mess := tgbotapi.NewMessage(cfg.ChatID, fmt.Sprintf("%s подключился", c.name))
|
||||||
m, err := botApi.Send(mess)
|
m, err := botApi.Send(mess)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
@ -77,7 +77,9 @@ func (c *joinCommand) run(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = pb.getPlayerBoard(p.id).setOnline(true).updatePlayerInfo(ctx)
|
pb.getPlayerBoard(p.id).setOnline(true)
|
||||||
|
|
||||||
|
err = pb.update(ctx, achievementVeryLongOnline)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
}
|
}
|
||||||
@ -95,7 +97,7 @@ func (c *quitCommand) run(ctx context.Context) {
|
|||||||
log := getLogger(ctx)
|
log := getLogger(ctx)
|
||||||
pb := getDPlayersBoard(ctx)
|
pb := getDPlayersBoard(ctx)
|
||||||
|
|
||||||
mess := tgbotapi.NewMessage(cfg.ChatID, fmt.Sprintf("%s покинул матрицу", c.name))
|
mess := tgbotapi.NewMessage(cfg.ChatID, fmt.Sprintf("%s отключился", c.name))
|
||||||
m, err := botApi.Send(mess)
|
m, err := botApi.Send(mess)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
@ -115,7 +117,9 @@ func (c *quitCommand) run(ctx context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = pb.getPlayerBoard(p.id).setOnline(false).updatePlayerInfo(ctx)
|
pb.getPlayerBoard(p.id).setOnline(false)
|
||||||
|
|
||||||
|
err = pb.update(ctx, achievementVeryLongOnline)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
}
|
}
|
||||||
@ -143,7 +147,7 @@ func (c *deathCommand) run(ctx context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = pb.getPlayerBoard(p.id).updatePlayerInfo(ctx)
|
err = pb.update(ctx, achievementDeathless, achievementBestFeeder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
}
|
}
|
||||||
@ -182,7 +186,7 @@ func (c *killCommand) run(ctx context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = pb.getPlayerBoard(p.id).updatePlayerInfo(ctx)
|
err = pb.update(ctx, achievementMaxFrags, achievementPeaceable)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
}
|
}
|
||||||
@ -210,9 +214,8 @@ func (c *changeLevelCommand) run(ctx context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = pb.getPlayerBoard(p.id).updatePlayerInfo(ctx)
|
err = pb.update(ctx, achievementMaxLevel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
245
playersBoard.go
245
playersBoard.go
@ -3,17 +3,61 @@ package main
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api"
|
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api"
|
||||||
"github.com/hako/durafmt"
|
"github.com/hako/durafmt"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type achievement uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
_ achievement = iota
|
||||||
|
achievementBestFeeder
|
||||||
|
achievementVeryLongOnline
|
||||||
|
achievementDeathless
|
||||||
|
achievementPeaceable
|
||||||
|
achievementMaxFrags
|
||||||
|
achievementMaxLevel
|
||||||
|
)
|
||||||
|
|
||||||
|
func getEmojiByAchievement(ach achievement) string {
|
||||||
|
switch ach {
|
||||||
|
case achievementBestFeeder:
|
||||||
|
return "\xF0\x9F\x91\xBB"
|
||||||
|
case achievementVeryLongOnline:
|
||||||
|
return "\xF0\x9F\xA4\xAA"
|
||||||
|
case achievementDeathless:
|
||||||
|
return "\xF0\x9F\x98\x8E"
|
||||||
|
case achievementPeaceable:
|
||||||
|
return "\xF0\x9F\x98\x87"
|
||||||
|
case achievementMaxFrags:
|
||||||
|
return "\xF0\x9F\x98\x88"
|
||||||
|
case achievementMaxLevel:
|
||||||
|
return "\xF0\x9F\xA7\x99\xE2\x80\x8D\xE2\x99\x82\xEF\xB8\x8F"
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var allAchievement = []achievement{
|
||||||
|
achievementBestFeeder,
|
||||||
|
achievementVeryLongOnline,
|
||||||
|
achievementDeathless,
|
||||||
|
achievementPeaceable,
|
||||||
|
achievementMaxFrags,
|
||||||
|
achievementMaxLevel,
|
||||||
|
}
|
||||||
|
|
||||||
type playerInfo struct {
|
type playerInfo struct {
|
||||||
playerID string
|
playerID string
|
||||||
playerMessageID int
|
playerMessageID int
|
||||||
isOnline bool
|
isOnline bool
|
||||||
|
achievements []achievement
|
||||||
|
messageText string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *playerInfo) setOnline(v bool) *playerInfo {
|
func (p *playerInfo) setOnline(v bool) *playerInfo {
|
||||||
@ -33,23 +77,18 @@ func (p *playerInfo) updatePlayerInfo(ctx context.Context) error {
|
|||||||
conf := getConfig(ctx)
|
conf := getConfig(ctx)
|
||||||
db := getDB(ctx)
|
db := getDB(ctx)
|
||||||
|
|
||||||
|
lines := make([]string, 0, 10)
|
||||||
|
|
||||||
player, err := db.getPlayerByID(ctx, p.playerID)
|
player, err := db.getPlayerByID(ctx, p.playerID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
kills, err := db.getKillsByOPlayerID(ctx, player.id)
|
kills, err := db.getKillsByPlayerID(ctx, player.id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
test := `*%s* | %s
|
|
||||||
%s Уровень: *%s*
|
|
||||||
%s Смертей: *%d*
|
|
||||||
%s Время в игре: %s
|
|
||||||
%s Фрагов: %d
|
|
||||||
`
|
|
||||||
|
|
||||||
access := "\xE2\x9D\x8C offLine"
|
access := "\xE2\x9D\x8C offLine"
|
||||||
if p.isOnline {
|
if p.isOnline {
|
||||||
access = "\xE2\x9C\x85 onLine"
|
access = "\xE2\x9C\x85 onLine"
|
||||||
@ -67,42 +106,47 @@ func (p *playerInfo) updatePlayerInfo(ctx context.Context) error {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
test = fmt.Sprintf(test, player.name, access,
|
lines = append(lines, fmt.Sprintf("*%s* | %s", player.name, access))
|
||||||
emojiUp, level,
|
lines = append(lines, fmt.Sprintf("%s Уровень: *%s*", emojiUp, level))
|
||||||
emojiDeaths, player.deaths,
|
lines = append(lines, fmt.Sprintf("%s Смертей: *%d*", emojiDeaths, player.deaths))
|
||||||
emojiTime, d.Format(units),
|
lines = append(lines, fmt.Sprintf("%s Фрагов: *%d*", emojiGun, kills))
|
||||||
emojiGun, kills,
|
lines = append(lines, fmt.Sprintf("%s Время в игре: *%s*", emojiTime, d.Format(units)))
|
||||||
)
|
lines = append(lines, "-----")
|
||||||
|
|
||||||
if p.playerMessageID != 0 {
|
emojiAch := make([]string, 0, len(p.achievements))
|
||||||
mess := tgbotapi.NewEditMessageText(conf.ChatID, p.playerMessageID, test)
|
|
||||||
mess.ParseMode = tgbotapi.ModeMarkdown
|
|
||||||
|
|
||||||
ikm := tgbotapi.NewInlineKeyboardMarkup(
|
for _, a := range p.achievements {
|
||||||
tgbotapi.NewInlineKeyboardRow(
|
emojiAch = append(emojiAch, getEmojiByAchievement(a))
|
||||||
tgbotapi.NewInlineKeyboardButtonData("Подробнее", "additional"),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
mess.ReplyMarkup = &ikm
|
|
||||||
|
|
||||||
_, err := botApi.Send(mess)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "Failed to update message")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
lines = append(lines, strings.Join(emojiAch, " "))
|
||||||
}
|
|
||||||
|
|
||||||
mess := tgbotapi.NewMessage(conf.ChatID, test)
|
text := strings.Join(lines, "\n")
|
||||||
|
|
||||||
|
if text != p.messageText {
|
||||||
|
|
||||||
|
var c tgbotapi.Chattable
|
||||||
|
|
||||||
|
if p.playerMessageID == 0 {
|
||||||
|
mess := tgbotapi.NewMessage(conf.ChatID, text)
|
||||||
mess.ParseMode = tgbotapi.ModeMarkdown
|
mess.ParseMode = tgbotapi.ModeMarkdown
|
||||||
|
|
||||||
m, err := botApi.Send(mess)
|
c = mess
|
||||||
|
} else {
|
||||||
|
mess := tgbotapi.NewEditMessageText(conf.ChatID, p.playerMessageID, text)
|
||||||
|
mess.ParseMode = tgbotapi.ModeMarkdown
|
||||||
|
|
||||||
|
c = mess
|
||||||
|
}
|
||||||
|
|
||||||
|
m, err := botApi.Send(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "Failed to send message")
|
return errors.Wrap(err, "Failed to send message")
|
||||||
}
|
}
|
||||||
|
|
||||||
p.playerMessageID = m.MessageID
|
p.playerMessageID = m.MessageID
|
||||||
|
p.messageText = text
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -120,14 +164,32 @@ func (p *playerInfo) deletePlayerInfo(ctx context.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *playerInfo) setAchievement(ach achievement) {
|
||||||
|
for _, a := range p.achievements {
|
||||||
|
if a == ach {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p.achievements = append(p.achievements, ach)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *playerInfo) unsetAchievement(ach achievement) {
|
||||||
|
for i, a := range p.achievements {
|
||||||
|
if a == ach {
|
||||||
|
p.achievements = append(p.achievements[:i], p.achievements[:i+1]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type playersBoard struct {
|
type playersBoard struct {
|
||||||
mx sync.Mutex
|
mx sync.Mutex
|
||||||
players []playerInfo
|
players []*playerInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPlayersBoard() *playersBoard {
|
func newPlayersBoard() *playersBoard {
|
||||||
return &playersBoard{
|
return &playersBoard{
|
||||||
players: make([]playerInfo, 0),
|
players: make([]*playerInfo, 0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,19 +204,28 @@ func (pb *playersBoard) load(ctx context.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
pb.players = make([]playerInfo, 0, len(players))
|
pb.players = make([]*playerInfo, 0, len(players))
|
||||||
|
|
||||||
for _, p := range players {
|
for _, p := range players {
|
||||||
pi := playerInfo{
|
pi := &playerInfo{
|
||||||
playerID: p.id,
|
playerID: p.id,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := pi.updatePlayerInfo(ctx)
|
pb.players = append(pb.players, pi)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, a := range allAchievement {
|
||||||
|
err := pb.updateAchievements(ctx, a)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pb.players = append(pb.players, pi)
|
for _, p := range pb.players {
|
||||||
|
err := p.updatePlayerInfo(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -163,18 +234,110 @@ func (pb *playersBoard) load(ctx context.Context) error {
|
|||||||
func (pb *playersBoard) getPlayerBoard(playerID string) *playerInfo {
|
func (pb *playersBoard) getPlayerBoard(playerID string) *playerInfo {
|
||||||
for i := range pb.players {
|
for i := range pb.players {
|
||||||
if pb.players[i].playerID == playerID {
|
if pb.players[i].playerID == playerID {
|
||||||
return &pb.players[i]
|
return pb.players[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pb.mx.Lock()
|
pb.mx.Lock()
|
||||||
defer pb.mx.Unlock()
|
defer pb.mx.Unlock()
|
||||||
|
|
||||||
pb.players = append(pb.players, playerInfo{
|
pb.players = append(pb.players, &playerInfo{
|
||||||
playerID: playerID,
|
playerID: playerID,
|
||||||
})
|
})
|
||||||
|
|
||||||
return &pb.players[len(pb.players)-1]
|
return pb.players[len(pb.players)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pb *playersBoard) updateAchievements(ctx context.Context, ach achievement) error {
|
||||||
|
db := getDB(ctx)
|
||||||
|
|
||||||
|
var value int
|
||||||
|
|
||||||
|
playerIDs := make([]string, 0, len(pb.players))
|
||||||
|
|
||||||
|
setValue := func(v int, playerID string) {
|
||||||
|
if value < v {
|
||||||
|
value = v
|
||||||
|
|
||||||
|
playerIDs = []string{playerID}
|
||||||
|
} else if value == v {
|
||||||
|
playerIDs = append(playerIDs, playerID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range pb.players {
|
||||||
|
player, err := db.getPlayerByID(ctx, p.playerID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ach {
|
||||||
|
case achievementBestFeeder:
|
||||||
|
setValue(player.deaths, p.playerID)
|
||||||
|
|
||||||
|
case achievementVeryLongOnline:
|
||||||
|
setValue(int(player.onlineDuration/time.Second), p.playerID)
|
||||||
|
|
||||||
|
case achievementDeathless:
|
||||||
|
if player.deaths == 0 {
|
||||||
|
playerIDs = append(playerIDs, p.playerID)
|
||||||
|
}
|
||||||
|
|
||||||
|
case achievementPeaceable:
|
||||||
|
kills, err := db.getKillsByPlayerID(ctx, p.playerID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
setValue(int(^uint(0)>>1)-kills, p.playerID)
|
||||||
|
|
||||||
|
case achievementMaxFrags:
|
||||||
|
kills, err := db.getKillsByPlayerID(ctx, p.playerID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
setValue(kills, p.playerID)
|
||||||
|
|
||||||
|
case achievementMaxLevel:
|
||||||
|
setValue(player.level, p.playerID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mainLoop:
|
||||||
|
for _, p := range pb.players {
|
||||||
|
for _, pid := range playerIDs {
|
||||||
|
if p.playerID == pid {
|
||||||
|
p.setAchievement(ach)
|
||||||
|
continue mainLoop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p.unsetAchievement(ach)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pb *playersBoard) update(ctx context.Context, as ...achievement) error {
|
||||||
|
pb.mx.Lock()
|
||||||
|
defer pb.mx.Unlock()
|
||||||
|
|
||||||
|
for _, a := range as {
|
||||||
|
err := pb.updateAchievements(ctx, a)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range pb.players {
|
||||||
|
err := p.updatePlayerInfo(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pb *playersBoard) run(ctx context.Context) {
|
func (pb *playersBoard) run(ctx context.Context) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user