Skip to content

Commit

Permalink
feat: player event table
Browse files Browse the repository at this point in the history
  • Loading branch information
dd84ai committed Nov 4, 2023
1 parent 618d45a commit 8cc4500
Show file tree
Hide file tree
Showing 18 changed files with 217 additions and 31 deletions.
1 change: 1 addition & 0 deletions app/configurator/connection.go
Expand Up @@ -45,6 +45,7 @@ func (cg *Configurator) AutoMigrateSchema() *Configurator {
&models.TagRegion{},
&models.TagForumPostTrack{},
&models.TagForumPostIgnore{},
&models.TagPlayerEvent{},
&models.AlertNeutralPlayersEqualOrGreater{},
&models.AlertEnemiesEqualOrGreater{},
&models.AlertFriendsEqualOrGreater{},
Expand Down
4 changes: 4 additions & 0 deletions app/configurator/models/models.go
Expand Up @@ -25,6 +25,10 @@ type TagPlayerEnemy struct {
TagTemplate
}

type TagPlayerEvent struct {
TagTemplate
}

type TagSystem struct {
TagTemplate
}
Expand Down
14 changes: 13 additions & 1 deletion app/configurator/tags.go
Expand Up @@ -19,7 +19,8 @@ type taggable interface {
models.TagSystem |
models.TagRegion |
models.TagPlayerFriend |
models.TagPlayerEnemy
models.TagPlayerEnemy |
models.TagPlayerEvent
GetTag() types.Tag
}

Expand Down Expand Up @@ -52,6 +53,10 @@ type ConfiguratorPlayerEnemy = ConfiguratorTags[models.TagPlayerEnemy]

var NewConfiguratorPlayerEnemy = NewConfiguratorTags[models.TagPlayerEnemy]

type ConfiguratorPlayerEvent = ConfiguratorTags[models.TagPlayerEvent]

var NewConfiguratorPlayerEvent = NewConfiguratorTags[models.TagPlayerEvent]

func (c ConfiguratorTags[T]) TagsAdd(channelID types.DiscordChannelID, tags ...types.Tag) error {
objs := []T{}
for _, tag := range tags {
Expand Down Expand Up @@ -80,11 +85,18 @@ func (c ConfiguratorTags[T]) TagsAdd(channelID types.DiscordChannelID, tags ...t

func (c ConfiguratorTags[T]) TagsRemove(channelID types.DiscordChannelID, tags ...types.Tag) error {
errors := NewErrorAggregator()
TotalRowsAffected := 0
for _, tag := range tags {
result := c.db.Where("channel_id = ? AND tag = ?", channelID, tag).Delete(&T{})
logus.CheckWarn(result.Error, "unsuccesful result of c.db.Delete")
errors.Append(result.Error)
TotalRowsAffected += int(result.RowsAffected)
}

if TotalRowsAffected == 0 {
return ErrorZeroAffectedRows{}
}

return errors.TryToGetError()
}

Expand Down
9 changes: 9 additions & 0 deletions app/consoler/commands/root.go
Expand Up @@ -95,6 +95,15 @@ func CreateConsoler(
configurator.NewConfiguratorPlayerEnemy(configurator.NewConfigurator(channelInfo.GetDbpath())),
)

NewTagCommands(
playerGroup.GetChild(
playerGroup.CurrentCmd,
cmdgroup.Command("event"),
cmdgroup.ShortDesc("Player event commands"),
),
configurator.NewConfiguratorPlayerEvent(configurator.NewConfigurator(channelInfo.GetDbpath())),
)

alertGroup := root.GetChild(
root.CurrentCmd,
cmdgroup.Command("alert"),
Expand Down
10 changes: 8 additions & 2 deletions app/consoler/commands/tags.go
Expand Up @@ -61,14 +61,20 @@ func (t *tagCommands) CreateTagRemove() {

err := t.cfgTags.TagsRemove(t.GetChannelID(), types.Tag(strings.Join(args, " ")))
if err != nil {
printer.Println(cmd, "ERR msg="+err.Error())
if _, ok := err.(configurator.ErrorZeroAffectedRows); ok {
printer.Println(cmd, "ERR removed nothing, because inserted value did not match anything present in the list")
} else {
printer.Println(cmd, "ERR ="+err.Error())
}
return
}

printer.Println(cmd, "OK tags are removed"+strings.Join(args, " "))
printer.Println(cmd, "OK tags are removed: "+strings.Join(args, " "))
logus.Debug("executed Create Tag Remove with args", logus.Args(args))
},
}
t.CurrentCmd.AddCommand(command)

}

func (t *tagCommands) CreateTagClear() {
Expand Down
11 changes: 6 additions & 5 deletions app/consoler/consoler.go
Expand Up @@ -26,16 +26,12 @@ func NewConsoler(
dbpath types.Dbpath,
) *Consoler {
c := &Consoler{}
c.buffStdout = NewWriter()
c.buffStderr = NewWriter()

c.dbpath = dbpath
c.params = consoler_types.NewChannelParams("", dbpath)
configur := configurator.NewConfigurator(dbpath)

c.rootCmd = commands.CreateConsoler(c.params, configur)
c.rootCmd.SetOut(c.buffStdout)
c.rootCmd.SetErr(c.buffStderr)

return c
}

Expand All @@ -48,6 +44,11 @@ func (c *Consoler) Execute(
return c
}

c.buffStdout = NewWriter()
c.buffStderr = NewWriter()
c.rootCmd.SetOut(c.buffStdout)
c.rootCmd.SetErr(c.buffStderr)

c.params.SetChannelID(channelID)
c.rootCmd.SetArgs(strings.Split(cmd, " "))
c.rootCmd.Execute()
Expand Down
2 changes: 2 additions & 0 deletions app/consoler/printer/printer.go
Expand Up @@ -5,6 +5,7 @@ Those functions are capable to print back to user to Discord via Cobra
*/

import (
"darkbot/app/settings/logus"
"fmt"

"github.com/spf13/cobra"
Expand All @@ -15,5 +16,6 @@ func Print(Cmd *cobra.Command, msg string) {
}

func Println(Cmd *cobra.Command, msg string) {
logus.Debug(fmt.Sprintf("printer.Println msg=%s", msg))
Cmd.OutOrStdout().Write([]byte(fmt.Sprintf("%s\n", msg)))
}
15 changes: 10 additions & 5 deletions app/scrappy/fixtures.go
Expand Up @@ -6,14 +6,19 @@ import (
"darkbot/app/scrappy/player"
)

func FixtureNewStorageWithPlayers(players *player.PlayerStorage) *ScrappyStorage {
return &ScrappyStorage{playerStorage: players}
}

func FixtureMockedStorage() *ScrappyStorage {
func FixtureMockedStorage(opts ...storageParam) *ScrappyStorage {
return NewScrapyStorage(
base.FixtureBaseApiMock(),
player.FixturePlayerAPIMock(),
baseattack.FixtureBaseAttackAPIMock(),
opts...,
)
}

type storageParam func(storage *ScrappyStorage)

func WithPlayerStorage(playerStorage *player.PlayerStorage) storageParam {
return func(storage *ScrappyStorage) {
storage.playerStorage = playerStorage
}
}
6 changes: 5 additions & 1 deletion app/scrappy/main.go
Expand Up @@ -15,11 +15,15 @@ type ScrappyStorage struct {
baseAttackStorage *baseattack.BaseAttackStorage
}

func NewScrapyStorage(base_api base.IbaseAPI, player_api player.IPlayerAPI, base_attack baseattack.IbaseAttackAPI) *ScrappyStorage {
func NewScrapyStorage(base_api base.IbaseAPI, player_api player.IPlayerAPI, base_attack baseattack.IbaseAttackAPI, opts ...storageParam) *ScrappyStorage {
s := &ScrappyStorage{}
s.baseStorage = base.NewBaseStorage(base_api)
s.playerStorage = player.NewPlayerStorage(player_api)
s.baseAttackStorage = baseattack.NewBaseAttackStorage(base_attack)

for _, opt := range opts {
opt(s)
}
return s
}

Expand Down
6 changes: 6 additions & 0 deletions app/settings/logus/params.go
Expand Up @@ -173,3 +173,9 @@ func GormResult(result *gorm.DB) slogParam {
c.params["result.error_type"] = fmt.Sprintf("%T", result.Error)
}
}

func DiscordMessageID(value types.DiscordMessageID) slogParam {
return func(c *slogGroup) {
c.params["discord_msg_id"] = string(value)
}
}
2 changes: 2 additions & 0 deletions app/viewer/apis/apis.go
Expand Up @@ -12,6 +12,7 @@ type Players struct {
Regions configurator.ConfiguratorRegion
Enemies configurator.ConfiguratorPlayerEnemy
Friends configurator.ConfiguratorPlayerFriend
Events configurator.ConfiguratorPlayerEvent
}
type Alerts struct {
NeutralsGreaterThan configurator.CfgAlertNeutralPlayersGreaterThan
Expand Down Expand Up @@ -59,6 +60,7 @@ func NewAPI(ChannelID types.DiscordChannelID, dbpath types.Dbpath, opts ...apiPa
Regions: configurator.NewConfiguratorRegion(configur),
Enemies: configurator.NewConfiguratorPlayerEnemy(configur),
Friends: configurator.NewConfiguratorPlayerFriend(configur),
Events: configurator.NewConfiguratorPlayerEvent(configur),
},
Alerts: Alerts{
NeutralsGreaterThan: configurator.NewCfgAlertNeutralPlayersGreaterThan(configur),
Expand Down
3 changes: 2 additions & 1 deletion app/viewer/channel.go
Expand Up @@ -7,6 +7,7 @@ import (
"darkbot/app/viewer/apis"
"darkbot/app/viewer/views"
"darkbot/app/viewer/views/baseview"
"darkbot/app/viewer/views/eventview"
"darkbot/app/viewer/views/playerview"
"strings"
"time"
Expand All @@ -24,6 +25,7 @@ func NewChannelView(api *apis.API, channelID types.DiscordChannelID) ChannelView
view := ChannelView{api: api}
view.views = append(view.views, baseview.NewTemplateBase(api))
view.views = append(view.views, playerview.NewTemplatePlayers(api))
view.views = append(view.views, eventview.NewEventRenderer(api))
view.ChannelID = channelID

return view
Expand All @@ -41,7 +43,6 @@ func (v *ChannelView) Discover() error {
for _, msg := range msgs {
for _, view := range v.views {
view.DiscoverMessageID(msg.Content, msg.ID)
view.DiscoverMessageID(msg.Content, msg.ID)
}

}
Expand Down
88 changes: 88 additions & 0 deletions app/viewer/views/eventview/event.go
@@ -0,0 +1,88 @@
package eventview

import (
"darkbot/app/settings/logus"
"darkbot/app/settings/types"
"darkbot/app/viewer/apis"
"darkbot/app/viewer/views"
_ "embed"
"encoding/json"
"fmt"
"strings"
"time"
)

type EventRenderer struct {
main views.TemplateShared
api *apis.API
}

func NewEventRenderer(api *apis.API) *EventRenderer {
base := EventRenderer{}
base.api = api
base.main.Header = "#darkbot-event-view"
return &base
}

func (t *EventRenderer) DiscoverMessageID(content string, msgID types.DiscordMessageID) {
if strings.Contains(content, t.main.Header) {
t.main.MessageID = msgID
}
}

func (t *EventRenderer) MatchMessageID(messageID types.DiscordMessageID) bool {
return messageID == t.main.MessageID
}

func (t *EventRenderer) Send() {
t.main.Send(t.api)
}

type PlayerTemplate struct {
Time string
Name string
System string
}

func (t *EventRenderer) Render() error {
record, err := t.api.Scrappy.GetPlayerStorage().GetLatestRecord()
if logus.CheckWarn(err, "unable to get players") {
return err
}

logus.Debug("rendered events", logus.DiscordMessageID(t.main.MessageID))

eventTags, err := t.api.Players.Events.TagsList(t.api.ChannelID)
logus.CheckWarn(err, "failed to acquire player event list", logus.ChannelID(t.api.ChannelID))

if len(eventTags) > 0 {
var sb strings.Builder

sb.WriteString(fmt.Sprintf("**%s** %s\n", t.main.Header, time.Now().String()))
sb.WriteString("**Event table of players**\n")
sb.WriteString("```json\n")

for _, eventTag := range eventTags {
sb.WriteString(fmt.Sprintf(`"%s": `, eventTag))

matchedPlayers := []PlayerTemplate{}
for _, player := range record.List {
if views.TagContains(player.Name, []types.Tag{eventTag}) {
matchedPlayers = append(matchedPlayers, PlayerTemplate{Name: player.Name, Time: player.Time, System: player.System})
continue
}
}
result, err := json.Marshal(matchedPlayers)
logus.CheckError(err, "failed to marshal event matched players")
sb.WriteString(fmt.Sprintf("%s", string(result)))

sb.WriteString("\n")
}

sb.WriteString("```\n")
t.main.Content = sb.String()

}

return nil
}
39 changes: 39 additions & 0 deletions app/viewer/views/eventview/event_test.go
@@ -0,0 +1,39 @@
package eventview

import (
"darkbot/app/configurator"
"darkbot/app/scrappy"
"darkbot/app/scrappy/player"
"darkbot/app/scrappy/shared/records"
"darkbot/app/settings/logus"
"darkbot/app/settings/types"
"darkbot/app/viewer/apis"
"testing"

"github.com/stretchr/testify/assert"
)

func TestPlayerEvent(t *testing.T) {
configurator.FixtureMigrator(func(dbpath types.Dbpath) {
channelID, _ := configurator.FixtureChannel(dbpath)

configurator.NewConfiguratorPlayerEvent(configurator.NewConfigurator(dbpath)).TagsAdd(channelID, []types.Tag{"player1", "player2"}...)

players := player.NewPlayerStorage(player.FixturePlayerAPIMock())
storage := scrappy.FixtureMockedStorage(scrappy.WithPlayerStorage(players))
api := apis.NewAPI(channelID, dbpath, apis.WithStorage(storage))
record := records.NewStampedObjects[player.Player]()
record.Add(player.Player{Name: "player1", System: "system1", Region: "region1"})
record.Add(player.Player{Name: "player2", System: "system2", Region: "region2"})
record.Add(player.Player{Name: "player3", System: "system3", Region: "region3"})
record.Add(player.Player{Name: "player4", System: "system4", Region: "region4"})
players.Add(record)

playerView := NewEventRenderer(api)
playerView.Render()
logus.Debug(playerView.main.Content)
logus.Debug("test TestPlayerEvent is finished")

assert.NotEmpty(t, playerView.main.Content)
})
}

0 comments on commit 8cc4500

Please sign in to comment.